summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorFlorian Kriener <floriank@google.com>2016-02-29 12:01:45 +0100
committerFlorian Kriener <floriank@google.com>2016-03-01 11:49:43 +0100
commit0b098b759cf9a2a8659babaf8c3b74e1b48ca604 (patch)
tree4e979c7d4ae3cae2dd4c465eb41e906476a52c55 /source
parentb35dda27ecb4351ef33ab78fb316fac76c463c67 (diff)
downloaddng_sdk-0b098b759cf9a2a8659babaf8c3b74e1b48ca604.tar.gz
Convert line endings to Unix format
Line endings were inconsistent before, this commit normalized line endings to Unix format. Bug: 26535130 Change-Id: I9a08119a2bf374db1a9b402ec8d22ee1ae04bc6b
Diffstat (limited to 'source')
-rw-r--r--source/dng_1d_function.cpp390
-rw-r--r--source/dng_1d_function.h318
-rw-r--r--source/dng_1d_table.cpp390
-rw-r--r--source/dng_1d_table.h258
-rw-r--r--source/dng_abort_sniffer.cpp484
-rw-r--r--source/dng_abort_sniffer.h488
-rw-r--r--source/dng_area_task.cpp540
-rw-r--r--source/dng_area_task.h396
-rw-r--r--source/dng_assertions.h266
-rw-r--r--source/dng_auto_ptr.h528
-rw-r--r--source/dng_bad_pixels.cpp3716
-rw-r--r--source/dng_bad_pixels.h626
-rw-r--r--source/dng_bottlenecks.cpp144
-rw-r--r--source/dng_bottlenecks.h3430
-rw-r--r--source/dng_camera_profile.cpp2772
-rw-r--r--source/dng_camera_profile.h1756
-rw-r--r--source/dng_classes.h200
-rw-r--r--source/dng_color_space.cpp2144
-rw-r--r--source/dng_color_space.h702
-rw-r--r--source/dng_color_spec.cpp1134
-rw-r--r--source/dng_color_spec.h292
-rw-r--r--source/dng_date_time.h770
-rw-r--r--source/dng_errors.h116
-rw-r--r--source/dng_exceptions.cpp410
-rw-r--r--source/dng_exceptions.h602
-rw-r--r--source/dng_exif.cpp8780
-rw-r--r--source/dng_exif.h702
-rw-r--r--source/dng_fast_module.h62
-rw-r--r--source/dng_file_stream.cpp270
-rw-r--r--source/dng_file_stream.h154
-rw-r--r--source/dng_filter_task.h316
-rw-r--r--source/dng_fingerprint.cpp1188
-rw-r--r--source/dng_fingerprint.h794
-rw-r--r--source/dng_gain_map.cpp1208
-rw-r--r--source/dng_gain_map.h438
-rw-r--r--source/dng_globals.cpp56
-rw-r--r--source/dng_globals.h92
-rw-r--r--source/dng_hue_sat_map.cpp740
-rw-r--r--source/dng_ifd.cpp8566
-rw-r--r--source/dng_ifd.h610
-rw-r--r--source/dng_image.cpp1696
-rw-r--r--source/dng_image.h866
-rw-r--r--source/dng_image_writer.h2490
-rw-r--r--source/dng_info.cpp5050
-rw-r--r--source/dng_info.h326
-rw-r--r--source/dng_iptc.cpp1970
-rw-r--r--source/dng_iptc.h344
-rw-r--r--source/dng_jpeg_image.h184
-rw-r--r--source/dng_lens_correction.h1278
-rw-r--r--source/dng_linearization_info.h328
-rw-r--r--source/dng_lossless_jpeg.cpp7556
-rw-r--r--source/dng_lossless_jpeg.h138
-rw-r--r--source/dng_matrix.cpp2160
-rw-r--r--source/dng_matrix.h652
-rw-r--r--source/dng_memory_stream.h194
-rw-r--r--source/dng_misc_opcodes.h834
-rw-r--r--source/dng_mosaic_info.cpp3976
-rw-r--r--source/dng_mosaic_info.h400
-rw-r--r--source/dng_mutex.cpp788
-rw-r--r--source/dng_mutex.h354
-rw-r--r--source/dng_opcode_list.cpp548
-rw-r--r--source/dng_opcode_list.h332
-rw-r--r--source/dng_opcodes.cpp1108
-rw-r--r--source/dng_opcodes.h1014
-rw-r--r--source/dng_orientation.cpp466
-rw-r--r--source/dng_orientation.h378
-rw-r--r--source/dng_parse_utils.cpp6652
-rw-r--r--source/dng_parse_utils.h464
-rw-r--r--source/dng_point.cpp44
-rw-r--r--source/dng_point.h398
-rw-r--r--source/dng_preview.cpp1418
-rw-r--r--source/dng_preview.h490
-rw-r--r--source/dng_pthread.cpp2282
-rw-r--r--source/dng_pthread.h532
-rw-r--r--source/dng_rational.cpp300
-rw-r--r--source/dng_rational.h298
-rw-r--r--source/dng_read_image.h364
-rw-r--r--source/dng_rect.cpp336
-rw-r--r--source/dng_ref_counted_block.cpp374
-rw-r--r--source/dng_ref_counted_block.h582
-rw-r--r--source/dng_reference.cpp5562
-rw-r--r--source/dng_reference.h1042
-rw-r--r--source/dng_render.h624
-rw-r--r--source/dng_resample.h586
-rw-r--r--source/dng_sdk_limits.h156
-rw-r--r--source/dng_shared.h498
-rw-r--r--source/dng_simple_image.h164
-rw-r--r--source/dng_spline.cpp466
-rw-r--r--source/dng_spline.h168
-rw-r--r--source/dng_stream.cpp2442
-rw-r--r--source/dng_stream.h1396
-rw-r--r--source/dng_string.h330
-rw-r--r--source/dng_string_list.cpp326
-rw-r--r--source/dng_string_list.h172
-rw-r--r--source/dng_tag_codes.h1086
-rw-r--r--source/dng_tag_types.cpp132
-rw-r--r--source/dng_tag_types.h104
-rw-r--r--source/dng_tag_values.h986
-rw-r--r--source/dng_temperature.cpp518
-rw-r--r--source/dng_temperature.h194
-rw-r--r--source/dng_tile_iterator.cpp398
-rw-r--r--source/dng_tile_iterator.h152
-rw-r--r--source/dng_tone_curve.cpp276
-rw-r--r--source/dng_tone_curve.h130
-rw-r--r--source/dng_uncopyable.h96
-rw-r--r--source/dng_xmp.cpp8834
-rw-r--r--source/dng_xmp_sdk.cpp3358
-rw-r--r--source/dng_xy_coord.cpp178
-rw-r--r--source/dng_xy_coord.h374
109 files changed, 63780 insertions, 63780 deletions
diff --git a/source/dng_1d_function.cpp b/source/dng_1d_function.cpp
index 3ff79f4..02c983f 100644
--- a/source/dng_1d_function.cpp
+++ b/source/dng_1d_function.cpp
@@ -1,195 +1,195 @@
-/*****************************************************************************/
-// Copyright 2006 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_1d_function.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_1d_function.h"
-
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_1d_function::~dng_1d_function ()
- {
-
- }
-
-/*****************************************************************************/
-
-bool dng_1d_function::IsIdentity () const
- {
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-real64 dng_1d_function::EvaluateInverse (real64 y) const
- {
-
- const uint32 kMaxIterations = 30;
- const real64 kNearZero = 1.0e-10;
-
- real64 x0 = 0.0;
- real64 y0 = Evaluate (x0);
-
- real64 x1 = 1.0;
- real64 y1 = Evaluate (x1);
-
- for (uint32 iteration = 0; iteration < kMaxIterations; iteration++)
- {
-
- if (Abs_real64 (y1 - y0) < kNearZero)
- {
- break;
- }
-
- real64 x2 = Pin_real64 (0.0,
- x1 + (y - y1) * (x1 - x0) / (y1 - y0),
- 1.0);
-
- real64 y2 = Evaluate (x2);
-
- x0 = x1;
- y0 = y1;
-
- x1 = x2;
- y1 = y2;
-
- }
-
- return x1;
-
- }
-
-/*****************************************************************************/
-
-bool dng_1d_identity::IsIdentity () const
- {
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-real64 dng_1d_identity::Evaluate (real64 x) const
- {
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-real64 dng_1d_identity::EvaluateInverse (real64 x) const
- {
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_1d_identity::Get ()
- {
-
- static dng_1d_identity static_function;
-
- return static_function;
-
- }
-
-/*****************************************************************************/
-
-dng_1d_concatenate::dng_1d_concatenate (const dng_1d_function &function1,
- const dng_1d_function &function2)
-
- : fFunction1 (function1)
- , fFunction2 (function2)
-
- {
-
- }
-
-/*****************************************************************************/
-
-bool dng_1d_concatenate::IsIdentity () const
- {
-
- return fFunction1.IsIdentity () &&
- fFunction2.IsIdentity ();
-
- }
-
-/*****************************************************************************/
-
-real64 dng_1d_concatenate::Evaluate (real64 x) const
- {
-
- real64 y = Pin_real64 (0.0, fFunction1.Evaluate (x), 1.0);
-
- return fFunction2.Evaluate (y);
-
- }
-
-/*****************************************************************************/
-
-real64 dng_1d_concatenate::EvaluateInverse (real64 x) const
- {
-
- real64 y = fFunction2.EvaluateInverse (x);
-
- return fFunction1.EvaluateInverse (y);
-
- }
-
-/*****************************************************************************/
-
-dng_1d_inverse::dng_1d_inverse (const dng_1d_function &f)
-
- : fFunction (f)
-
- {
-
- }
-
-/*****************************************************************************/
-
-bool dng_1d_inverse::IsIdentity () const
- {
-
- return fFunction.IsIdentity ();
-
- }
-
-/*****************************************************************************/
-
-real64 dng_1d_inverse::Evaluate (real64 x) const
- {
-
- return fFunction.EvaluateInverse (x);
-
- }
-
-/*****************************************************************************/
-
-real64 dng_1d_inverse::EvaluateInverse (real64 y) const
- {
-
- return fFunction.Evaluate (y);
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_1d_function.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_1d_function.h"
+
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_1d_function::~dng_1d_function ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+bool dng_1d_function::IsIdentity () const
+ {
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_1d_function::EvaluateInverse (real64 y) const
+ {
+
+ const uint32 kMaxIterations = 30;
+ const real64 kNearZero = 1.0e-10;
+
+ real64 x0 = 0.0;
+ real64 y0 = Evaluate (x0);
+
+ real64 x1 = 1.0;
+ real64 y1 = Evaluate (x1);
+
+ for (uint32 iteration = 0; iteration < kMaxIterations; iteration++)
+ {
+
+ if (Abs_real64 (y1 - y0) < kNearZero)
+ {
+ break;
+ }
+
+ real64 x2 = Pin_real64 (0.0,
+ x1 + (y - y1) * (x1 - x0) / (y1 - y0),
+ 1.0);
+
+ real64 y2 = Evaluate (x2);
+
+ x0 = x1;
+ y0 = y1;
+
+ x1 = x2;
+ y1 = y2;
+
+ }
+
+ return x1;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_1d_identity::IsIdentity () const
+ {
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_1d_identity::Evaluate (real64 x) const
+ {
+
+ return x;
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_1d_identity::EvaluateInverse (real64 x) const
+ {
+
+ return x;
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_1d_identity::Get ()
+ {
+
+ static dng_1d_identity static_function;
+
+ return static_function;
+
+ }
+
+/*****************************************************************************/
+
+dng_1d_concatenate::dng_1d_concatenate (const dng_1d_function &function1,
+ const dng_1d_function &function2)
+
+ : fFunction1 (function1)
+ , fFunction2 (function2)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+bool dng_1d_concatenate::IsIdentity () const
+ {
+
+ return fFunction1.IsIdentity () &&
+ fFunction2.IsIdentity ();
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_1d_concatenate::Evaluate (real64 x) const
+ {
+
+ real64 y = Pin_real64 (0.0, fFunction1.Evaluate (x), 1.0);
+
+ return fFunction2.Evaluate (y);
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_1d_concatenate::EvaluateInverse (real64 x) const
+ {
+
+ real64 y = fFunction2.EvaluateInverse (x);
+
+ return fFunction1.EvaluateInverse (y);
+
+ }
+
+/*****************************************************************************/
+
+dng_1d_inverse::dng_1d_inverse (const dng_1d_function &f)
+
+ : fFunction (f)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+bool dng_1d_inverse::IsIdentity () const
+ {
+
+ return fFunction.IsIdentity ();
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_1d_inverse::Evaluate (real64 x) const
+ {
+
+ return fFunction.EvaluateInverse (x);
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_1d_inverse::EvaluateInverse (real64 y) const
+ {
+
+ return fFunction.Evaluate (y);
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_1d_function.h b/source/dng_1d_function.h
index aee59ca..a3c38db 100644
--- a/source/dng_1d_function.h
+++ b/source/dng_1d_function.h
@@ -1,159 +1,159 @@
-/*****************************************************************************/
-// Copyright 2006 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_1d_function.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Classes for a 1D floating-point to floating-point function abstraction.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_1d_function__
-#define __dng_1d_function__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief A 1D floating-point function.
-///
-/// The domain (input) is always from 0.0 to 1.0, while the range (output) can be an arbitrary interval.
-
-class dng_1d_function
- {
-
- public:
-
- virtual ~dng_1d_function ();
-
- /// Returns true if this function is the map x -> y such that x == y for all x . That is if Evaluate(x) == x for all x.
-
- virtual bool IsIdentity () const;
-
- /// Return the mapping for value x.
- /// This method must be implemented by a derived class of dng_1d_function and the derived class determines the
- /// lookup method and function used.
- /// \param x A value between 0.0 and 1.0 (inclusive).
- /// \retval Mapped value for x
-
- virtual real64 Evaluate (real64 x) const = 0;
-
- /// Return the reverse mapped value for y.
- /// This method can be implemented by derived classes. The default implementation uses Newton's method to solve
- /// for x such that Evaluate(x) == y.
- /// \param y A value to reverse map. Should be within the range of the function implemented by this dng_1d_function .
- /// \retval A value x such that Evaluate(x) == y (to very close approximation).
-
- virtual real64 EvaluateInverse (real64 y) const;
-
- };
-
-/*****************************************************************************/
-
-/// An identity (x -> y such that x == y for all x) mapping function.
-
-class dng_1d_identity: public dng_1d_function
- {
-
- public:
- /// Always returns true for this class.
-
- virtual bool IsIdentity () const;
-
- /// Always returns x for this class.
-
- virtual real64 Evaluate (real64 x) const;
-
- /// Always returns y for this class.
-
- virtual real64 EvaluateInverse (real64 y) const;
-
- /// This class is a singleton, and is entirely threadsafe. Use this method to get an instance of the class.
-
- static const dng_1d_function & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// A dng_1d_function that represents the composition (curry) of two other dng_1d_functions.
-
-class dng_1d_concatenate: public dng_1d_function
- {
-
- protected:
-
- const dng_1d_function &fFunction1;
-
- const dng_1d_function &fFunction2;
-
- public:
-
- /// Create a dng_1d_function which computes y = function2.Evaluate(function1.Evaluate(x)).
- /// Compose function1 and function2 to compute y = function2.Evaluate(function1.Evaluate(x)). The range of function1.Evaluate must be a subset of 0.0 to 1.0 inclusive,
- /// otherwise the result of function1(x) will be pinned (clipped) to 0.0 if <0.0 and to 1.0 if > 1.0 .
- /// \param function1 Inner function of composition.
- /// \param function2 Outer function of composition.
-
- dng_1d_concatenate (const dng_1d_function &function1,
- const dng_1d_function &function2);
-
- /// Only true if both function1 and function2 have IsIdentity equal to true.
-
- virtual bool IsIdentity () const;
-
- /// Return the composed mapping for value x.
- /// \param x A value between 0.0 and 1.0 (inclusive).
- /// \retval function2.Evaluate(function1.Evaluate(x)).
-
- virtual real64 Evaluate (real64 x) const;
-
- /// Return the reverse mapped value for y.
- /// Be careful using this method with compositions where the inner function does not have a range 0.0 to 1.0 . (Or better yet, do not use such functions.)
- /// \param y A value to reverse map. Should be within the range of function2.Evaluate.
- /// \retval A value x such that function2.Evaluate(function1.Evaluate(x)) == y (to very close approximation).
-
- virtual real64 EvaluateInverse (real64 y) const;
-
- };
-
-/*****************************************************************************/
-
-/// A dng_1d_function that represents the inverse of another dng_1d_function.
-
-class dng_1d_inverse: public dng_1d_function
- {
-
- protected:
-
- const dng_1d_function &fFunction;
-
- public:
-
- dng_1d_inverse (const dng_1d_function &f);
-
- virtual bool IsIdentity () const;
-
- virtual real64 Evaluate (real64 x) const;
-
- virtual real64 EvaluateInverse (real64 y) const;
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_1d_function.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Classes for a 1D floating-point to floating-point function abstraction.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_1d_function__
+#define __dng_1d_function__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief A 1D floating-point function.
+///
+/// The domain (input) is always from 0.0 to 1.0, while the range (output) can be an arbitrary interval.
+
+class dng_1d_function
+ {
+
+ public:
+
+ virtual ~dng_1d_function ();
+
+ /// Returns true if this function is the map x -> y such that x == y for all x . That is if Evaluate(x) == x for all x.
+
+ virtual bool IsIdentity () const;
+
+ /// Return the mapping for value x.
+ /// This method must be implemented by a derived class of dng_1d_function and the derived class determines the
+ /// lookup method and function used.
+ /// \param x A value between 0.0 and 1.0 (inclusive).
+ /// \retval Mapped value for x
+
+ virtual real64 Evaluate (real64 x) const = 0;
+
+ /// Return the reverse mapped value for y.
+ /// This method can be implemented by derived classes. The default implementation uses Newton's method to solve
+ /// for x such that Evaluate(x) == y.
+ /// \param y A value to reverse map. Should be within the range of the function implemented by this dng_1d_function .
+ /// \retval A value x such that Evaluate(x) == y (to very close approximation).
+
+ virtual real64 EvaluateInverse (real64 y) const;
+
+ };
+
+/*****************************************************************************/
+
+/// An identity (x -> y such that x == y for all x) mapping function.
+
+class dng_1d_identity: public dng_1d_function
+ {
+
+ public:
+ /// Always returns true for this class.
+
+ virtual bool IsIdentity () const;
+
+ /// Always returns x for this class.
+
+ virtual real64 Evaluate (real64 x) const;
+
+ /// Always returns y for this class.
+
+ virtual real64 EvaluateInverse (real64 y) const;
+
+ /// This class is a singleton, and is entirely threadsafe. Use this method to get an instance of the class.
+
+ static const dng_1d_function & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// A dng_1d_function that represents the composition (curry) of two other dng_1d_functions.
+
+class dng_1d_concatenate: public dng_1d_function
+ {
+
+ protected:
+
+ const dng_1d_function &fFunction1;
+
+ const dng_1d_function &fFunction2;
+
+ public:
+
+ /// Create a dng_1d_function which computes y = function2.Evaluate(function1.Evaluate(x)).
+ /// Compose function1 and function2 to compute y = function2.Evaluate(function1.Evaluate(x)). The range of function1.Evaluate must be a subset of 0.0 to 1.0 inclusive,
+ /// otherwise the result of function1(x) will be pinned (clipped) to 0.0 if <0.0 and to 1.0 if > 1.0 .
+ /// \param function1 Inner function of composition.
+ /// \param function2 Outer function of composition.
+
+ dng_1d_concatenate (const dng_1d_function &function1,
+ const dng_1d_function &function2);
+
+ /// Only true if both function1 and function2 have IsIdentity equal to true.
+
+ virtual bool IsIdentity () const;
+
+ /// Return the composed mapping for value x.
+ /// \param x A value between 0.0 and 1.0 (inclusive).
+ /// \retval function2.Evaluate(function1.Evaluate(x)).
+
+ virtual real64 Evaluate (real64 x) const;
+
+ /// Return the reverse mapped value for y.
+ /// Be careful using this method with compositions where the inner function does not have a range 0.0 to 1.0 . (Or better yet, do not use such functions.)
+ /// \param y A value to reverse map. Should be within the range of function2.Evaluate.
+ /// \retval A value x such that function2.Evaluate(function1.Evaluate(x)) == y (to very close approximation).
+
+ virtual real64 EvaluateInverse (real64 y) const;
+
+ };
+
+/*****************************************************************************/
+
+/// A dng_1d_function that represents the inverse of another dng_1d_function.
+
+class dng_1d_inverse: public dng_1d_function
+ {
+
+ protected:
+
+ const dng_1d_function &fFunction;
+
+ public:
+
+ dng_1d_inverse (const dng_1d_function &f);
+
+ virtual bool IsIdentity () const;
+
+ virtual real64 Evaluate (real64 x) const;
+
+ virtual real64 EvaluateInverse (real64 y) const;
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_1d_table.cpp b/source/dng_1d_table.cpp
index 267078e..6325cf0 100644
--- a/source/dng_1d_table.cpp
+++ b/source/dng_1d_table.cpp
@@ -1,195 +1,195 @@
-/*****************************************************************************/
-// Copyright 2006-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_1d_table.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_1d_table.h"
-
-#include "dng_1d_function.h"
-#include "dng_memory.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_1d_table::dng_1d_table ()
-
- : fBuffer ()
- , fTable (NULL)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_1d_table::~dng_1d_table ()
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_1d_table::SubDivide (const dng_1d_function &function,
- uint32 lower,
- uint32 upper,
- real32 maxDelta)
- {
-
- uint32 range = upper - lower;
-
- bool subDivide = (range > (kTableSize >> 8));
-
- if (!subDivide)
- {
-
- real32 delta = Abs_real32 (fTable [upper] -
- fTable [lower]);
-
- if (delta > maxDelta)
- {
-
- subDivide = true;
-
- }
-
- }
-
- if (subDivide)
- {
-
- uint32 middle = (lower + upper) >> 1;
-
- fTable [middle] = (real32) function.Evaluate (middle * (1.0 / (real64) kTableSize));
-
- if (range > 2)
- {
-
- SubDivide (function, lower, middle, maxDelta);
-
- SubDivide (function, middle, upper, maxDelta);
-
- }
-
- }
-
- else
- {
-
- real64 y0 = fTable [lower];
- real64 y1 = fTable [upper];
-
- real64 delta = (y1 - y0) / (real64) range;
-
- for (uint32 j = lower + 1; j < upper; j++)
- {
-
- y0 += delta;
-
- fTable [j] = (real32) y0;
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_1d_table::Initialize (dng_memory_allocator &allocator,
- const dng_1d_function &function,
- bool subSample)
- {
-
- fBuffer.Reset (allocator.Allocate ((kTableSize + 2) * sizeof (real32)));
-
- fTable = fBuffer->Buffer_real32 ();
-
- if (subSample)
- {
-
- fTable [0 ] = (real32) function.Evaluate (0.0);
- fTable [kTableSize] = (real32) function.Evaluate (1.0);
-
- real32 maxDelta = Max_real32 (Abs_real32 (fTable [kTableSize] -
- fTable [0 ]), 1.0f) *
- (1.0f / 256.0f);
-
- SubDivide (function,
- 0,
- kTableSize,
- maxDelta);
-
- }
-
- else
- {
-
- for (uint32 j = 0; j <= kTableSize; j++)
- {
-
- real64 x = j * (1.0 / (real64) kTableSize);
-
- real64 y = function.Evaluate (x);
-
- fTable [j] = (real32) y;
-
- }
-
- }
-
- fTable [kTableSize + 1] = fTable [kTableSize];
-
- }
-
-/*****************************************************************************/
-
-void dng_1d_table::Expand16 (uint16 *table16) const
- {
-
- real64 step = (real64) kTableSize / 65535.0;
-
- real64 y0 = fTable [0];
- real64 y1 = fTable [1];
-
- real64 base = y0 * 65535.0 + 0.5;
- real64 slope = (y1 - y0) * 65535.0;
-
- uint32 index = 1;
- real64 fract = 0.0;
-
- for (uint32 j = 0; j < 0x10000; j++)
- {
-
- table16 [j] = (uint16) (base + slope * fract);
-
- fract += step;
-
- if (fract > 1.0)
- {
-
- index += 1;
- fract -= 1.0;
-
- y0 = y1;
- y1 = fTable [index];
-
- base = y0 * 65535.0 + 0.5;
- slope = (y1 - y0) * 65535.0;
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_1d_table.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_1d_table.h"
+
+#include "dng_1d_function.h"
+#include "dng_memory.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_1d_table::dng_1d_table ()
+
+ : fBuffer ()
+ , fTable (NULL)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_1d_table::~dng_1d_table ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_1d_table::SubDivide (const dng_1d_function &function,
+ uint32 lower,
+ uint32 upper,
+ real32 maxDelta)
+ {
+
+ uint32 range = upper - lower;
+
+ bool subDivide = (range > (kTableSize >> 8));
+
+ if (!subDivide)
+ {
+
+ real32 delta = Abs_real32 (fTable [upper] -
+ fTable [lower]);
+
+ if (delta > maxDelta)
+ {
+
+ subDivide = true;
+
+ }
+
+ }
+
+ if (subDivide)
+ {
+
+ uint32 middle = (lower + upper) >> 1;
+
+ fTable [middle] = (real32) function.Evaluate (middle * (1.0 / (real64) kTableSize));
+
+ if (range > 2)
+ {
+
+ SubDivide (function, lower, middle, maxDelta);
+
+ SubDivide (function, middle, upper, maxDelta);
+
+ }
+
+ }
+
+ else
+ {
+
+ real64 y0 = fTable [lower];
+ real64 y1 = fTable [upper];
+
+ real64 delta = (y1 - y0) / (real64) range;
+
+ for (uint32 j = lower + 1; j < upper; j++)
+ {
+
+ y0 += delta;
+
+ fTable [j] = (real32) y0;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_1d_table::Initialize (dng_memory_allocator &allocator,
+ const dng_1d_function &function,
+ bool subSample)
+ {
+
+ fBuffer.Reset (allocator.Allocate ((kTableSize + 2) * sizeof (real32)));
+
+ fTable = fBuffer->Buffer_real32 ();
+
+ if (subSample)
+ {
+
+ fTable [0 ] = (real32) function.Evaluate (0.0);
+ fTable [kTableSize] = (real32) function.Evaluate (1.0);
+
+ real32 maxDelta = Max_real32 (Abs_real32 (fTable [kTableSize] -
+ fTable [0 ]), 1.0f) *
+ (1.0f / 256.0f);
+
+ SubDivide (function,
+ 0,
+ kTableSize,
+ maxDelta);
+
+ }
+
+ else
+ {
+
+ for (uint32 j = 0; j <= kTableSize; j++)
+ {
+
+ real64 x = j * (1.0 / (real64) kTableSize);
+
+ real64 y = function.Evaluate (x);
+
+ fTable [j] = (real32) y;
+
+ }
+
+ }
+
+ fTable [kTableSize + 1] = fTable [kTableSize];
+
+ }
+
+/*****************************************************************************/
+
+void dng_1d_table::Expand16 (uint16 *table16) const
+ {
+
+ real64 step = (real64) kTableSize / 65535.0;
+
+ real64 y0 = fTable [0];
+ real64 y1 = fTable [1];
+
+ real64 base = y0 * 65535.0 + 0.5;
+ real64 slope = (y1 - y0) * 65535.0;
+
+ uint32 index = 1;
+ real64 fract = 0.0;
+
+ for (uint32 j = 0; j < 0x10000; j++)
+ {
+
+ table16 [j] = (uint16) (base + slope * fract);
+
+ fract += step;
+
+ if (fract > 1.0)
+ {
+
+ index += 1;
+ fract -= 1.0;
+
+ y0 = y1;
+ y1 = fTable [index];
+
+ base = y0 * 65535.0 + 0.5;
+ slope = (y1 - y0) * 65535.0;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_1d_table.h b/source/dng_1d_table.h
index 087a84b..3ff7c87 100644
--- a/source/dng_1d_table.h
+++ b/source/dng_1d_table.h
@@ -1,129 +1,129 @@
-/*****************************************************************************/
-// Copyright 2006-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_1d_table.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Definition of a lookup table based 1D floating-point to floating-point function abstraction using linear interpolation.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_1d_table__
-#define __dng_1d_table__
-
-/*****************************************************************************/
-
-#include "dng_assertions.h"
-#include "dng_auto_ptr.h"
-#include "dng_classes.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief A 1D floating-point lookup table using linear interpolation.
-
-class dng_1d_table
- {
-
- public:
-
- /// Constants denoting size of table.
-
- enum
- {
- kTableBits = 12, //< Table is always a power of 2 in size. This is log2(kTableSize).
- kTableSize = (1 << kTableBits) //< Number of entries in table.
- };
-
- protected:
-
- AutoPtr<dng_memory_block> fBuffer;
-
- real32 *fTable;
-
- public:
-
- dng_1d_table ();
-
- virtual ~dng_1d_table ();
-
- /// Set up table, initialize entries using functiion.
- /// This method can throw an exception, e.g. if there is not enough memory.
- /// \param allocator Memory allocator from which table memory is allocated.
- /// \param function Table is initialized with values of finction.Evalluate(0.0) to function.Evaluate(1.0).
- /// \param subSample If true, only sample the function a limited number of times and interpolate.
-
- void Initialize (dng_memory_allocator &allocator,
- const dng_1d_function &function,
- bool subSample = false);
-
- /// Lookup and interpolate mapping for an input.
- /// \param x value from 0.0 to 1.0 used as input for mapping
- /// \retval Approximation of function.Evaluate(x)
-
- real32 Interpolate (real32 x) const
- {
-
- real32 y = x * (real32) kTableSize;
-
- int32 index = (int32) y;
-
- if (index < 0 || index > kTableSize)
- {
-
- ThrowBadFormat("Index out of range.");
-
- }
-
- DNG_ASSERT (index >= 0 && index <= kTableSize,
- "dng_1d_table::Interpolate parameter out of range");
-
- real32 z = (real32) index;
-
- real32 fract = y - z;
-
- return fTable [index ] * (1.0f - fract) +
- fTable [index + 1] * ( fract);
-
- }
-
- /// Direct access function for table data.
-
- const real32 * Table () const
- {
- return fTable;
- }
-
- /// Expand the table to a 16-bit to 16-bit table.
-
- void Expand16 (uint16 *table16) const;
-
- private:
-
- void SubDivide (const dng_1d_function &function,
- uint32 lower,
- uint32 upper,
- real32 maxDelta);
-
- // Hidden copy constructor and assignment operator.
-
- dng_1d_table (const dng_1d_table &table);
-
- dng_1d_table & operator= (const dng_1d_table &table);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_1d_table.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Definition of a lookup table based 1D floating-point to floating-point function abstraction using linear interpolation.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_1d_table__
+#define __dng_1d_table__
+
+/*****************************************************************************/
+
+#include "dng_assertions.h"
+#include "dng_auto_ptr.h"
+#include "dng_classes.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief A 1D floating-point lookup table using linear interpolation.
+
+class dng_1d_table
+ {
+
+ public:
+
+ /// Constants denoting size of table.
+
+ enum
+ {
+ kTableBits = 12, //< Table is always a power of 2 in size. This is log2(kTableSize).
+ kTableSize = (1 << kTableBits) //< Number of entries in table.
+ };
+
+ protected:
+
+ AutoPtr<dng_memory_block> fBuffer;
+
+ real32 *fTable;
+
+ public:
+
+ dng_1d_table ();
+
+ virtual ~dng_1d_table ();
+
+ /// Set up table, initialize entries using functiion.
+ /// This method can throw an exception, e.g. if there is not enough memory.
+ /// \param allocator Memory allocator from which table memory is allocated.
+ /// \param function Table is initialized with values of finction.Evalluate(0.0) to function.Evaluate(1.0).
+ /// \param subSample If true, only sample the function a limited number of times and interpolate.
+
+ void Initialize (dng_memory_allocator &allocator,
+ const dng_1d_function &function,
+ bool subSample = false);
+
+ /// Lookup and interpolate mapping for an input.
+ /// \param x value from 0.0 to 1.0 used as input for mapping
+ /// \retval Approximation of function.Evaluate(x)
+
+ real32 Interpolate (real32 x) const
+ {
+
+ real32 y = x * (real32) kTableSize;
+
+ int32 index = (int32) y;
+
+ if (index < 0 || index > kTableSize)
+ {
+
+ ThrowBadFormat("Index out of range.");
+
+ }
+
+ DNG_ASSERT (index >= 0 && index <= kTableSize,
+ "dng_1d_table::Interpolate parameter out of range");
+
+ real32 z = (real32) index;
+
+ real32 fract = y - z;
+
+ return fTable [index ] * (1.0f - fract) +
+ fTable [index + 1] * ( fract);
+
+ }
+
+ /// Direct access function for table data.
+
+ const real32 * Table () const
+ {
+ return fTable;
+ }
+
+ /// Expand the table to a 16-bit to 16-bit table.
+
+ void Expand16 (uint16 *table16) const;
+
+ private:
+
+ void SubDivide (const dng_1d_function &function,
+ uint32 lower,
+ uint32 upper,
+ real32 maxDelta);
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_1d_table (const dng_1d_table &table);
+
+ dng_1d_table & operator= (const dng_1d_table &table);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_abort_sniffer.cpp b/source/dng_abort_sniffer.cpp
index 4c65733..2b96dfc 100644
--- a/source/dng_abort_sniffer.cpp
+++ b/source/dng_abort_sniffer.cpp
@@ -1,242 +1,242 @@
-/*****************************************************************************/
-// Copyright 2006-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_abort_sniffer.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_abort_sniffer.h"
-
-#include "dng_mutex.h"
-
-/*****************************************************************************/
-
-#if qDNGThreadSafe
-
-/*****************************************************************************/
-
-class dng_priority_manager
- {
-
- private:
-
- dng_mutex fMutex;
-
- dng_condition fCondition;
-
- uint32 fCounter [dng_priority_count];
-
- public:
-
- dng_priority_manager ();
-
- void Increment (dng_priority priority);
-
- void Decrement (dng_priority priority);
-
- void Wait (dng_priority priority);
-
- private:
-
- dng_priority MinPriority ()
- {
-
- // Assumes mutex is locked.
-
- for (uint32 level = dng_priority_maximum;
- level > dng_priority_minimum;
- level--)
- {
-
- if (fCounter [level])
- {
- return (dng_priority) level;
- }
-
- }
-
- return dng_priority_minimum;
-
- }
-
- };
-
-/*****************************************************************************/
-
-dng_priority_manager::dng_priority_manager ()
-
- : fMutex ("dng_priority_manager::fMutex")
- , fCondition ()
-
- {
-
- for (uint32 level = dng_priority_minimum;
- level <= dng_priority_maximum;
- level++)
- {
-
- fCounter [level] = 0;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_priority_manager::Increment (dng_priority priority)
- {
-
- dng_lock_mutex lock (&fMutex);
-
- fCounter [priority] += 1;
-
- }
-
-/*****************************************************************************/
-
-void dng_priority_manager::Decrement (dng_priority priority)
- {
-
- dng_lock_mutex lock (&fMutex);
-
- dng_priority oldMin = MinPriority ();
-
- fCounter [priority] -= 1;
-
- dng_priority newMin = MinPriority ();
-
- if (newMin < oldMin)
- {
-
- fCondition.Broadcast ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_priority_manager::Wait (dng_priority priority)
- {
-
- if (priority < dng_priority_maximum)
- {
-
- dng_lock_mutex lock (&fMutex);
-
- while (priority < MinPriority ())
- {
-
- fCondition.Wait (fMutex);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-static dng_priority_manager gPriorityManager;
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
-
-dng_set_minimum_priority::dng_set_minimum_priority (dng_priority priority)
-
- : fPriority (priority)
-
- {
-
- #if qDNGThreadSafe
-
- gPriorityManager.Increment (fPriority);
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-dng_set_minimum_priority::~dng_set_minimum_priority ()
- {
-
- #if qDNGThreadSafe
-
- gPriorityManager.Decrement (fPriority);
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-dng_abort_sniffer::dng_abort_sniffer ()
-
- : fPriority (dng_priority_maximum)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_abort_sniffer::~dng_abort_sniffer ()
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_abort_sniffer::SniffForAbort (dng_abort_sniffer *sniffer)
- {
-
- if (sniffer)
- {
-
- #if qDNGThreadSafe
-
- gPriorityManager.Wait (sniffer->Priority ());
-
- #endif
-
- sniffer->Sniff ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_abort_sniffer::StartTask (const char * /* name */,
- real64 /* fract */)
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_abort_sniffer::EndTask ()
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_abort_sniffer::UpdateProgress (real64 /* fract */)
- {
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_abort_sniffer.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_abort_sniffer.h"
+
+#include "dng_mutex.h"
+
+/*****************************************************************************/
+
+#if qDNGThreadSafe
+
+/*****************************************************************************/
+
+class dng_priority_manager
+ {
+
+ private:
+
+ dng_mutex fMutex;
+
+ dng_condition fCondition;
+
+ uint32 fCounter [dng_priority_count];
+
+ public:
+
+ dng_priority_manager ();
+
+ void Increment (dng_priority priority);
+
+ void Decrement (dng_priority priority);
+
+ void Wait (dng_priority priority);
+
+ private:
+
+ dng_priority MinPriority ()
+ {
+
+ // Assumes mutex is locked.
+
+ for (uint32 level = dng_priority_maximum;
+ level > dng_priority_minimum;
+ level--)
+ {
+
+ if (fCounter [level])
+ {
+ return (dng_priority) level;
+ }
+
+ }
+
+ return dng_priority_minimum;
+
+ }
+
+ };
+
+/*****************************************************************************/
+
+dng_priority_manager::dng_priority_manager ()
+
+ : fMutex ("dng_priority_manager::fMutex")
+ , fCondition ()
+
+ {
+
+ for (uint32 level = dng_priority_minimum;
+ level <= dng_priority_maximum;
+ level++)
+ {
+
+ fCounter [level] = 0;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_priority_manager::Increment (dng_priority priority)
+ {
+
+ dng_lock_mutex lock (&fMutex);
+
+ fCounter [priority] += 1;
+
+ }
+
+/*****************************************************************************/
+
+void dng_priority_manager::Decrement (dng_priority priority)
+ {
+
+ dng_lock_mutex lock (&fMutex);
+
+ dng_priority oldMin = MinPriority ();
+
+ fCounter [priority] -= 1;
+
+ dng_priority newMin = MinPriority ();
+
+ if (newMin < oldMin)
+ {
+
+ fCondition.Broadcast ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_priority_manager::Wait (dng_priority priority)
+ {
+
+ if (priority < dng_priority_maximum)
+ {
+
+ dng_lock_mutex lock (&fMutex);
+
+ while (priority < MinPriority ())
+ {
+
+ fCondition.Wait (fMutex);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+static dng_priority_manager gPriorityManager;
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
+
+dng_set_minimum_priority::dng_set_minimum_priority (dng_priority priority)
+
+ : fPriority (priority)
+
+ {
+
+ #if qDNGThreadSafe
+
+ gPriorityManager.Increment (fPriority);
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+dng_set_minimum_priority::~dng_set_minimum_priority ()
+ {
+
+ #if qDNGThreadSafe
+
+ gPriorityManager.Decrement (fPriority);
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+dng_abort_sniffer::dng_abort_sniffer ()
+
+ : fPriority (dng_priority_maximum)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_abort_sniffer::~dng_abort_sniffer ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_abort_sniffer::SniffForAbort (dng_abort_sniffer *sniffer)
+ {
+
+ if (sniffer)
+ {
+
+ #if qDNGThreadSafe
+
+ gPriorityManager.Wait (sniffer->Priority ());
+
+ #endif
+
+ sniffer->Sniff ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_abort_sniffer::StartTask (const char * /* name */,
+ real64 /* fract */)
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_abort_sniffer::EndTask ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_abort_sniffer::UpdateProgress (real64 /* fract */)
+ {
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_abort_sniffer.h b/source/dng_abort_sniffer.h
index 3a2f553..9940262 100644
--- a/source/dng_abort_sniffer.h
+++ b/source/dng_abort_sniffer.h
@@ -1,244 +1,244 @@
-/*****************************************************************************/
-// Copyright 2006-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_abort_sniffer.h#2 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Classes supporting user cancellation and progress tracking.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_abort_sniffer__
-#define __dng_abort_sniffer__
-
-/*****************************************************************************/
-
-#include "dng_flags.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief Thread priority level.
-
-enum dng_priority
- {
-
- dng_priority_low,
- dng_priority_medium,
- dng_priority_high,
-
- dng_priority_count,
-
- dng_priority_minimum = dng_priority_low,
- dng_priority_maximum = dng_priority_high
-
- };
-
-/*****************************************************************************/
-
-/// \brief Convenience class for setting thread priority level to minimum.
-
-class dng_set_minimum_priority
- {
-
- private:
-
- dng_priority fPriority;
-
- public:
-
- dng_set_minimum_priority (dng_priority priority);
-
- ~dng_set_minimum_priority ();
-
- };
-
-/*****************************************************************************/
-
-/** \brief Class for signaling user cancellation and receiving progress updates.
- *
- * DNG SDK clients should derive a host application specific implementation
- * from this class.
- */
-
-class dng_abort_sniffer
- {
-
- friend class dng_sniffer_task;
-
- private:
-
- dng_priority fPriority;
-
- public:
-
- dng_abort_sniffer ();
-
- virtual ~dng_abort_sniffer ();
-
- /// Getter for priority level.
-
- dng_priority Priority () const
- {
- return fPriority;
- }
-
- /// Setter for priority level.
-
- void SetPriority (dng_priority priority)
- {
- fPriority = priority;
- }
-
- /// Check for pending user cancellation or other abort. ThrowUserCanceled
- /// will be called if one is pending. This static method is provided as a
- /// convenience for quickly testing for an abort and throwing an exception
- /// if one is pending.
- /// \param sniffer The dng_sniffer to test for a pending abort. Can be NULL,
- /// in which case there an abort is never signalled.
-
- static void SniffForAbort (dng_abort_sniffer *sniffer);
-
- // A way to call Sniff while bypassing the priority wait.
-
- void SniffNoPriorityWait ()
- {
- Sniff ();
- }
-
- // Specifies whether or not the sniffer may be called by multiple threads
- // in parallel. Default result is false. Subclass must override to return
- // true.
-
- virtual bool ThreadSafe () const
- {
- return false;
- }
-
- protected:
-
- /// Should be implemented by derived classes to check for an user
- /// cancellation.
-
- virtual void Sniff () = 0;
-
- /// Signals the start of a named task withn processing in the DNG SDK.
- /// Tasks may be nested.
- /// \param name of the task
- /// \param fract Percentage of total processing this task is expected to
- /// take. From 0.0 to 1.0 .
-
- virtual void StartTask (const char *name,
- real64 fract);
-
- /// Signals the end of the innermost task that has been started.
-
- virtual void EndTask ();
-
- /// Signals progress made on current task.
- /// \param fract percentage of processing completed on current task.
- /// From 0.0 to 1.0 .
-
- virtual void UpdateProgress (real64 fract);
-
- };
-
-/******************************************************************************/
-
-/// \brief Class to establish scope of a named subtask in DNG processing.
-///
-/// Instances of this class are intended to be stack allocated.
-
-class dng_sniffer_task
- {
-
- private:
-
- dng_abort_sniffer *fSniffer;
-
- public:
-
- /// Inform a sniffer of a subtask in DNG processing.
- /// \param sniffer The sniffer associated with the host on which this
- /// processing is occurring.
- /// \param name The name of this subtask as a NUL terminated string.
- /// \param fract Percentage of total processing this task is expected
- /// to take, from 0.0 to 1.0 .
-
- dng_sniffer_task (dng_abort_sniffer *sniffer,
- const char *name = NULL,
- real64 fract = 0.0)
-
- : fSniffer (sniffer)
-
- {
- if (fSniffer)
- fSniffer->StartTask (name, fract);
- }
-
- ~dng_sniffer_task ()
- {
- if (fSniffer)
- fSniffer->EndTask ();
- }
-
- /// Check for pending user cancellation or other abort. ThrowUserCanceled
- /// will be called if one is pending.
-
- void Sniff ()
- {
- dng_abort_sniffer::SniffForAbort (fSniffer);
- }
-
- /// Update progress on this subtask.
- /// \param fract Percentage of processing completed on current task,
- /// from 0.0 to 1.0 .
-
- void UpdateProgress (real64 fract)
- {
- if (fSniffer)
- fSniffer->UpdateProgress (fract);
- }
-
- /// Update progress on this subtask.
- /// \param done Amount of task completed in arbitrary integer units.
- /// \param total Total size of task in same arbitrary integer units as done.
-
- void UpdateProgress (uint32 done,
- uint32 total)
- {
- UpdateProgress ((real64) done /
- (real64) total);
- }
-
- /// Signal task completed for progress purposes.
-
- void Finish ()
- {
- UpdateProgress (1.0);
- }
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_sniffer_task (const dng_sniffer_task &task);
-
- dng_sniffer_task & operator= (const dng_sniffer_task &task);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_abort_sniffer.h#2 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Classes supporting user cancellation and progress tracking.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_abort_sniffer__
+#define __dng_abort_sniffer__
+
+/*****************************************************************************/
+
+#include "dng_flags.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief Thread priority level.
+
+enum dng_priority
+ {
+
+ dng_priority_low,
+ dng_priority_medium,
+ dng_priority_high,
+
+ dng_priority_count,
+
+ dng_priority_minimum = dng_priority_low,
+ dng_priority_maximum = dng_priority_high
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Convenience class for setting thread priority level to minimum.
+
+class dng_set_minimum_priority
+ {
+
+ private:
+
+ dng_priority fPriority;
+
+ public:
+
+ dng_set_minimum_priority (dng_priority priority);
+
+ ~dng_set_minimum_priority ();
+
+ };
+
+/*****************************************************************************/
+
+/** \brief Class for signaling user cancellation and receiving progress updates.
+ *
+ * DNG SDK clients should derive a host application specific implementation
+ * from this class.
+ */
+
+class dng_abort_sniffer
+ {
+
+ friend class dng_sniffer_task;
+
+ private:
+
+ dng_priority fPriority;
+
+ public:
+
+ dng_abort_sniffer ();
+
+ virtual ~dng_abort_sniffer ();
+
+ /// Getter for priority level.
+
+ dng_priority Priority () const
+ {
+ return fPriority;
+ }
+
+ /// Setter for priority level.
+
+ void SetPriority (dng_priority priority)
+ {
+ fPriority = priority;
+ }
+
+ /// Check for pending user cancellation or other abort. ThrowUserCanceled
+ /// will be called if one is pending. This static method is provided as a
+ /// convenience for quickly testing for an abort and throwing an exception
+ /// if one is pending.
+ /// \param sniffer The dng_sniffer to test for a pending abort. Can be NULL,
+ /// in which case there an abort is never signalled.
+
+ static void SniffForAbort (dng_abort_sniffer *sniffer);
+
+ // A way to call Sniff while bypassing the priority wait.
+
+ void SniffNoPriorityWait ()
+ {
+ Sniff ();
+ }
+
+ // Specifies whether or not the sniffer may be called by multiple threads
+ // in parallel. Default result is false. Subclass must override to return
+ // true.
+
+ virtual bool ThreadSafe () const
+ {
+ return false;
+ }
+
+ protected:
+
+ /// Should be implemented by derived classes to check for an user
+ /// cancellation.
+
+ virtual void Sniff () = 0;
+
+ /// Signals the start of a named task withn processing in the DNG SDK.
+ /// Tasks may be nested.
+ /// \param name of the task
+ /// \param fract Percentage of total processing this task is expected to
+ /// take. From 0.0 to 1.0 .
+
+ virtual void StartTask (const char *name,
+ real64 fract);
+
+ /// Signals the end of the innermost task that has been started.
+
+ virtual void EndTask ();
+
+ /// Signals progress made on current task.
+ /// \param fract percentage of processing completed on current task.
+ /// From 0.0 to 1.0 .
+
+ virtual void UpdateProgress (real64 fract);
+
+ };
+
+/******************************************************************************/
+
+/// \brief Class to establish scope of a named subtask in DNG processing.
+///
+/// Instances of this class are intended to be stack allocated.
+
+class dng_sniffer_task
+ {
+
+ private:
+
+ dng_abort_sniffer *fSniffer;
+
+ public:
+
+ /// Inform a sniffer of a subtask in DNG processing.
+ /// \param sniffer The sniffer associated with the host on which this
+ /// processing is occurring.
+ /// \param name The name of this subtask as a NUL terminated string.
+ /// \param fract Percentage of total processing this task is expected
+ /// to take, from 0.0 to 1.0 .
+
+ dng_sniffer_task (dng_abort_sniffer *sniffer,
+ const char *name = NULL,
+ real64 fract = 0.0)
+
+ : fSniffer (sniffer)
+
+ {
+ if (fSniffer)
+ fSniffer->StartTask (name, fract);
+ }
+
+ ~dng_sniffer_task ()
+ {
+ if (fSniffer)
+ fSniffer->EndTask ();
+ }
+
+ /// Check for pending user cancellation or other abort. ThrowUserCanceled
+ /// will be called if one is pending.
+
+ void Sniff ()
+ {
+ dng_abort_sniffer::SniffForAbort (fSniffer);
+ }
+
+ /// Update progress on this subtask.
+ /// \param fract Percentage of processing completed on current task,
+ /// from 0.0 to 1.0 .
+
+ void UpdateProgress (real64 fract)
+ {
+ if (fSniffer)
+ fSniffer->UpdateProgress (fract);
+ }
+
+ /// Update progress on this subtask.
+ /// \param done Amount of task completed in arbitrary integer units.
+ /// \param total Total size of task in same arbitrary integer units as done.
+
+ void UpdateProgress (uint32 done,
+ uint32 total)
+ {
+ UpdateProgress ((real64) done /
+ (real64) total);
+ }
+
+ /// Signal task completed for progress purposes.
+
+ void Finish ()
+ {
+ UpdateProgress (1.0);
+ }
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_sniffer_task (const dng_sniffer_task &task);
+
+ dng_sniffer_task & operator= (const dng_sniffer_task &task);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_area_task.cpp b/source/dng_area_task.cpp
index 25b100e..ecba698 100644
--- a/source/dng_area_task.cpp
+++ b/source/dng_area_task.cpp
@@ -1,270 +1,270 @@
-/*****************************************************************************/
-// Copyright 2006-2012 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_area_task.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_area_task.h"
-
-#include "dng_abort_sniffer.h"
-#include "dng_flags.h"
-#include "dng_sdk_limits.h"
-#include "dng_tile_iterator.h"
-#include "dng_utils.h"
-
-#if qImagecore
-extern bool gPrintTimings;
-#endif
-
-/*****************************************************************************/
-
-dng_area_task::dng_area_task ()
-
- : fMaxThreads (kMaxMPThreads)
-
- , fMinTaskArea (256 * 256)
-
- , fUnitCell (1, 1)
-
- , fMaxTileSize (256, 256)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_area_task::~dng_area_task ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_rect dng_area_task::RepeatingTile1 () const
- {
-
- return dng_rect ();
-
- }
-
-/*****************************************************************************/
-
-dng_rect dng_area_task::RepeatingTile2 () const
- {
-
- return dng_rect ();
-
- }
-
-/*****************************************************************************/
-
-dng_rect dng_area_task::RepeatingTile3 () const
- {
-
- return dng_rect ();
-
- }
-
-/*****************************************************************************/
-
-void dng_area_task::Start (uint32 /* threadCount */,
- const dng_point & /* tileSize */,
- dng_memory_allocator * /* allocator */,
- dng_abort_sniffer * /* sniffer */)
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_area_task::Finish (uint32 /* threadCount */)
- {
-
- }
-
-/*****************************************************************************/
-
-dng_point dng_area_task::FindTileSize (const dng_rect &area) const
- {
-
- dng_rect repeatingTile1 = RepeatingTile1 ();
- dng_rect repeatingTile2 = RepeatingTile2 ();
- dng_rect repeatingTile3 = RepeatingTile3 ();
-
- if (repeatingTile1.IsEmpty ())
- {
- repeatingTile1 = area;
- }
-
- if (repeatingTile2.IsEmpty ())
- {
- repeatingTile2 = area;
- }
-
- if (repeatingTile3.IsEmpty ())
- {
- repeatingTile3 = area;
- }
-
- uint32 repeatV = Min_uint32 (Min_uint32 (repeatingTile1.H (),
- repeatingTile2.H ()),
- repeatingTile3.H ());
-
- uint32 repeatH = Min_uint32 (Min_uint32 (repeatingTile1.W (),
- repeatingTile2.W ()),
- repeatingTile3.W ());
-
- dng_point maxTileSize = MaxTileSize ();
-
- dng_point tileSize;
-
- tileSize.v = Min_int32 (repeatV, maxTileSize.v);
- tileSize.h = Min_int32 (repeatH, maxTileSize.h);
-
- // What this is doing is, if the smallest repeating image tile is larger than the
- // maximum tile size, adjusting the tile size down so that the tiles are as small
- // as possible while still having the same number of tiles covering the
- // repeat area. This makes the areas more equal in size, making MP
- // algorithms work better.
-
- // The image core team did not understand this code, and disabled it.
- // Really stupid idea to turn off code you don't understand!
- // I'm undoing this removal, because I think the code is correct and useful.
-
- uint32 countV = (repeatV + tileSize.v - 1) / tileSize.v;
- uint32 countH = (repeatH + tileSize.h - 1) / tileSize.h;
-
- tileSize.v = (repeatV + countV - 1) / countV;
- tileSize.h = (repeatH + countH - 1) / countH;
-
- // Round up to unit cell size.
-
- dng_point unitCell = UnitCell ();
-
- if (unitCell.h != 1 || unitCell.v != 1)
- {
- tileSize.v = ((tileSize.v + unitCell.v - 1) / unitCell.v) * unitCell.v;
- tileSize.h = ((tileSize.h + unitCell.h - 1) / unitCell.h) * unitCell.h;
- }
-
- // But if that is larger than maximum tile size, round down to unit cell size.
-
- if (tileSize.v > maxTileSize.v)
- {
- tileSize.v = (maxTileSize.v / unitCell.v) * unitCell.v;
- }
-
- if (tileSize.h > maxTileSize.h)
- {
- tileSize.h = (maxTileSize.h / unitCell.h) * unitCell.h;
- }
-
- #if qImagecore
- if (gPrintTimings)
- {
- fprintf (stdout, "\nRender tile for below: %d x %d\n", (int32) tileSize.h, (int32) tileSize.v);
- }
- #endif
-
- return tileSize;
-
- }
-
-/*****************************************************************************/
-
-void dng_area_task::ProcessOnThread (uint32 threadIndex,
- const dng_rect &area,
- const dng_point &tileSize,
- dng_abort_sniffer *sniffer)
- {
-
- dng_rect repeatingTile1 = RepeatingTile1 ();
- dng_rect repeatingTile2 = RepeatingTile2 ();
- dng_rect repeatingTile3 = RepeatingTile3 ();
-
- if (repeatingTile1.IsEmpty ())
- {
- repeatingTile1 = area;
- }
-
- if (repeatingTile2.IsEmpty ())
- {
- repeatingTile2 = area;
- }
-
- if (repeatingTile3.IsEmpty ())
- {
- repeatingTile3 = area;
- }
-
- dng_rect tile1;
-
- dng_tile_iterator iter1 (repeatingTile3, area);
-
- while (iter1.GetOneTile (tile1))
- {
-
- dng_rect tile2;
-
- dng_tile_iterator iter2 (repeatingTile2, tile1);
-
- while (iter2.GetOneTile (tile2))
- {
-
- dng_rect tile3;
-
- dng_tile_iterator iter3 (repeatingTile1, tile2);
-
- while (iter3.GetOneTile (tile3))
- {
-
- dng_rect tile4;
-
- dng_tile_iterator iter4 (tileSize, tile3);
-
- while (iter4.GetOneTile (tile4))
- {
-
- dng_abort_sniffer::SniffForAbort (sniffer);
-
- Process (threadIndex, tile4, sniffer);
-
- }
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_area_task::Perform (dng_area_task &task,
- const dng_rect &area,
- dng_memory_allocator *allocator,
- dng_abort_sniffer *sniffer)
- {
-
- dng_point tileSize (task.FindTileSize (area));
-
- task.Start (1, tileSize, allocator, sniffer);
-
- task.ProcessOnThread (0, area, tileSize, sniffer);
-
- task.Finish (1);
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2012 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_area_task.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_area_task.h"
+
+#include "dng_abort_sniffer.h"
+#include "dng_flags.h"
+#include "dng_sdk_limits.h"
+#include "dng_tile_iterator.h"
+#include "dng_utils.h"
+
+#if qImagecore
+extern bool gPrintTimings;
+#endif
+
+/*****************************************************************************/
+
+dng_area_task::dng_area_task ()
+
+ : fMaxThreads (kMaxMPThreads)
+
+ , fMinTaskArea (256 * 256)
+
+ , fUnitCell (1, 1)
+
+ , fMaxTileSize (256, 256)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_area_task::~dng_area_task ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_rect dng_area_task::RepeatingTile1 () const
+ {
+
+ return dng_rect ();
+
+ }
+
+/*****************************************************************************/
+
+dng_rect dng_area_task::RepeatingTile2 () const
+ {
+
+ return dng_rect ();
+
+ }
+
+/*****************************************************************************/
+
+dng_rect dng_area_task::RepeatingTile3 () const
+ {
+
+ return dng_rect ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_area_task::Start (uint32 /* threadCount */,
+ const dng_point & /* tileSize */,
+ dng_memory_allocator * /* allocator */,
+ dng_abort_sniffer * /* sniffer */)
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_area_task::Finish (uint32 /* threadCount */)
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_point dng_area_task::FindTileSize (const dng_rect &area) const
+ {
+
+ dng_rect repeatingTile1 = RepeatingTile1 ();
+ dng_rect repeatingTile2 = RepeatingTile2 ();
+ dng_rect repeatingTile3 = RepeatingTile3 ();
+
+ if (repeatingTile1.IsEmpty ())
+ {
+ repeatingTile1 = area;
+ }
+
+ if (repeatingTile2.IsEmpty ())
+ {
+ repeatingTile2 = area;
+ }
+
+ if (repeatingTile3.IsEmpty ())
+ {
+ repeatingTile3 = area;
+ }
+
+ uint32 repeatV = Min_uint32 (Min_uint32 (repeatingTile1.H (),
+ repeatingTile2.H ()),
+ repeatingTile3.H ());
+
+ uint32 repeatH = Min_uint32 (Min_uint32 (repeatingTile1.W (),
+ repeatingTile2.W ()),
+ repeatingTile3.W ());
+
+ dng_point maxTileSize = MaxTileSize ();
+
+ dng_point tileSize;
+
+ tileSize.v = Min_int32 (repeatV, maxTileSize.v);
+ tileSize.h = Min_int32 (repeatH, maxTileSize.h);
+
+ // What this is doing is, if the smallest repeating image tile is larger than the
+ // maximum tile size, adjusting the tile size down so that the tiles are as small
+ // as possible while still having the same number of tiles covering the
+ // repeat area. This makes the areas more equal in size, making MP
+ // algorithms work better.
+
+ // The image core team did not understand this code, and disabled it.
+ // Really stupid idea to turn off code you don't understand!
+ // I'm undoing this removal, because I think the code is correct and useful.
+
+ uint32 countV = (repeatV + tileSize.v - 1) / tileSize.v;
+ uint32 countH = (repeatH + tileSize.h - 1) / tileSize.h;
+
+ tileSize.v = (repeatV + countV - 1) / countV;
+ tileSize.h = (repeatH + countH - 1) / countH;
+
+ // Round up to unit cell size.
+
+ dng_point unitCell = UnitCell ();
+
+ if (unitCell.h != 1 || unitCell.v != 1)
+ {
+ tileSize.v = ((tileSize.v + unitCell.v - 1) / unitCell.v) * unitCell.v;
+ tileSize.h = ((tileSize.h + unitCell.h - 1) / unitCell.h) * unitCell.h;
+ }
+
+ // But if that is larger than maximum tile size, round down to unit cell size.
+
+ if (tileSize.v > maxTileSize.v)
+ {
+ tileSize.v = (maxTileSize.v / unitCell.v) * unitCell.v;
+ }
+
+ if (tileSize.h > maxTileSize.h)
+ {
+ tileSize.h = (maxTileSize.h / unitCell.h) * unitCell.h;
+ }
+
+ #if qImagecore
+ if (gPrintTimings)
+ {
+ fprintf (stdout, "\nRender tile for below: %d x %d\n", (int32) tileSize.h, (int32) tileSize.v);
+ }
+ #endif
+
+ return tileSize;
+
+ }
+
+/*****************************************************************************/
+
+void dng_area_task::ProcessOnThread (uint32 threadIndex,
+ const dng_rect &area,
+ const dng_point &tileSize,
+ dng_abort_sniffer *sniffer)
+ {
+
+ dng_rect repeatingTile1 = RepeatingTile1 ();
+ dng_rect repeatingTile2 = RepeatingTile2 ();
+ dng_rect repeatingTile3 = RepeatingTile3 ();
+
+ if (repeatingTile1.IsEmpty ())
+ {
+ repeatingTile1 = area;
+ }
+
+ if (repeatingTile2.IsEmpty ())
+ {
+ repeatingTile2 = area;
+ }
+
+ if (repeatingTile3.IsEmpty ())
+ {
+ repeatingTile3 = area;
+ }
+
+ dng_rect tile1;
+
+ dng_tile_iterator iter1 (repeatingTile3, area);
+
+ while (iter1.GetOneTile (tile1))
+ {
+
+ dng_rect tile2;
+
+ dng_tile_iterator iter2 (repeatingTile2, tile1);
+
+ while (iter2.GetOneTile (tile2))
+ {
+
+ dng_rect tile3;
+
+ dng_tile_iterator iter3 (repeatingTile1, tile2);
+
+ while (iter3.GetOneTile (tile3))
+ {
+
+ dng_rect tile4;
+
+ dng_tile_iterator iter4 (tileSize, tile3);
+
+ while (iter4.GetOneTile (tile4))
+ {
+
+ dng_abort_sniffer::SniffForAbort (sniffer);
+
+ Process (threadIndex, tile4, sniffer);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_area_task::Perform (dng_area_task &task,
+ const dng_rect &area,
+ dng_memory_allocator *allocator,
+ dng_abort_sniffer *sniffer)
+ {
+
+ dng_point tileSize (task.FindTileSize (area));
+
+ task.Start (1, tileSize, allocator, sniffer);
+
+ task.ProcessOnThread (0, area, tileSize, sniffer);
+
+ task.Finish (1);
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_area_task.h b/source/dng_area_task.h
index 4824873..3fe957d 100644
--- a/source/dng_area_task.h
+++ b/source/dng_area_task.h
@@ -1,198 +1,198 @@
-/*****************************************************************************/
-// Copyright 2006 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_area_task.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Class to handle partitioning a rectangular image processing operation taking into account multiple processing resources and memory constraints.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_area_task__
-#define __dng_area_task__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_point.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief Abstract class for rectangular processing operations with support for partitioning across multiple processing resources and observing memory constraints.
-
-class dng_area_task
- {
-
- protected:
-
- uint32 fMaxThreads;
-
- uint32 fMinTaskArea;
-
- dng_point fUnitCell;
-
- dng_point fMaxTileSize;
-
- public:
-
- dng_area_task ();
-
- virtual ~dng_area_task ();
-
- /// Getter for the maximum number of threads (resources) that can be used for processing
- ///
- /// \retval Number of threads, minimum of 1, that can be used for this task.
-
- virtual uint32 MaxThreads () const
- {
- return fMaxThreads;
- }
-
- /// Getter for minimum area of a partitioned rectangle.
- /// Often it is not profitable to use more resources if it requires partitioning the input into chunks that are too small,
- /// as the overhead increases more than the speedup. This method can be ovreridden for a specific task to indicate the smallest
- /// area for partitioning. Default is 256x256 pixels.
- ///
- /// \retval Minimum area for a partitoned tile in order to give performant operation. (Partitions can be smaller due to small inputs and edge cases.)
-
- virtual uint32 MinTaskArea () const
- {
- return fMinTaskArea;
- }
-
- /// Getter for dimensions of which partitioned tiles should be a multiple.
- /// Various methods of processing prefer certain alignments. The partitioning attempts to construct tiles such that the
- /// sizes are a multiple of the dimensions of this point.
- ///
- /// \retval a point giving preferred alignment in x and y
-
- virtual dng_point UnitCell () const
- {
- return fUnitCell;
- }
-
- /// Getter for maximum size of a tile for processing.
- /// Often processing will need to allocate temporary buffers or use other resources that are either fixed or in limited supply.
- /// The maximum tile size forces further partitioning if the tile is bigger than this size.
- ///
- /// \retval Maximum tile size allowed for this area task.
-
- virtual dng_point MaxTileSize () const
- {
- return fMaxTileSize;
- }
-
- /// Getter for RepeatingTile1.
- /// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to establish a set of 0 to 3 tile patterns for which
- /// the resulting partitions that the final Process method is called on will not cross tile boundaries in any of the
- /// tile patterns. This can be used for a processing routine that needs to read from two tiles and write to a third
- /// such that all the tiles are aligned and sized in a certain way. A RepeatingTile value is valid if it is non-empty.
- /// Higher numbered RepeatingTile patterns are only used if all lower ones are non-empty. A RepeatingTile pattern must
- /// be a multiple of UnitCell in size for all constraints of the partitionerr to be met.
-
- virtual dng_rect RepeatingTile1 () const;
-
- /// Getter for RepeatingTile2.
- /// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to establish a set of 0 to 3 tile patterns for which
- /// the resulting partitions that the final Process method is called on will not cross tile boundaries in any of the
- /// tile patterns. This can be used for a processing routine that needs to read from two tiles and write to a third
- /// such that all the tiles are aligned and sized in a certain way. A RepeatingTile value is valid if it is non-empty.
- /// Higher numbered RepeatingTile patterns are only used if all lower ones are non-empty. A RepeatingTile pattern must
- /// be a multiple of UnitCell in size for all constraints of the partitionerr to be met.
-
- virtual dng_rect RepeatingTile2 () const;
-
- /// Getter for RepeatingTile3.
- /// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to establish a set of 0 to 3 tile patterns for which
- /// the resulting partitions that the final Process method is called on will not cross tile boundaries in any of the
- /// tile patterns. This can be used for a processing routine that needs to read from two tiles and write to a third
- /// such that all the tiles are aligned and sized in a certain way. A RepeatingTile value is valid if it is non-empty.
- /// Higher numbered RepeatingTile patterns are only used if all lower ones are non-empty. A RepeatingTile pattern must
- /// be a multiple of UnitCell in size for all constraints of the partitionerr to be met.
-
- virtual dng_rect RepeatingTile3 () const;
-
- /// Task startup method called before any processing is done on partitions.
- /// The Start method is called before any processing is done and can be overridden to allocate temporary buffers, etc.
- ///
- /// \param threadCount Total number of threads that will be used for processing. Less than or equal to MaxThreads.
- /// \param tileSize Size of source tiles which will be processed. (Not all tiles will be this size due to edge conditions.)
- /// \param allocator dng_memory_allocator to use for allocating temporary buffers, etc.
- /// \param sniffer Sniffer to test for user cancellation and to set up progress.
-
- virtual void Start (uint32 threadCount,
- const dng_point &tileSize,
- dng_memory_allocator *allocator,
- dng_abort_sniffer *sniffer);
-
- /// Process one tile or fully partitioned area.
- /// This method is overridden by derived classes to implement the actual image processing. Note that the sniffer can be ignored if it is certain that a
- /// processing task will complete very quickly.
- /// This method should never be called directly but rather accessed via Process.
- /// There is no allocator parameter as all allocation should be done in Start.
- ///
- /// \param threadIndex 0 to threadCount - 1 index indicating which thread this is. (Can be used to get a thread-specific buffer allocated in the Start method.)
- /// \param tile Area to process.
- /// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates.
-
- virtual void Process (uint32 threadIndex,
- const dng_rect &tile,
- dng_abort_sniffer *sniffer) = 0;
-
- /// Task computation finalization and teardown method.
- /// Called after all resources have completed processing. Can be overridden to accumulate results and free resources allocated in Start.
- ///
- /// \param threadCount Number of threads used for processing. Same as value passed to Start.
-
- virtual void Finish (uint32 threadCount);
-
- /// Find tile size taking into account repeating tiles, unit cell, and maximum tile size.
- /// \param area Computation area for which to find tile size.
- /// \retval Tile size as height and width in point.
-
- dng_point FindTileSize (const dng_rect &area) const;
-
- /// Handle one resource's worth of partitioned tiles.
- /// Called after thread partitioning has already been done. Area may be further subdivided to handle maximum tile size, etc.
- /// It will be rare to override this method.
- ///
- /// \param threadIndex 0 to threadCount - 1 index indicating which thread this is.
- /// \param area Tile area partitioned to this resource.
- /// \param tileSize
- /// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates.
-
- void ProcessOnThread (uint32 threadIndex,
- const dng_rect &area,
- const dng_point &tileSize,
- dng_abort_sniffer *sniffer);
-
- /// Default resource partitioner that assumes a single resource to be used for processing.
- /// Implementations that are aware of multiple processing resources should override (replace) this method.
- /// This is usually done in dng_host::PerformAreaTask .
- /// \param task The task to perform.
- /// \param area The area on which mage processing should be performed.
- /// \param allocator dng_memory_allocator to use for allocating temporary buffers, etc.
- /// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates.
-
- static void Perform (dng_area_task &task,
- const dng_rect &area,
- dng_memory_allocator *allocator,
- dng_abort_sniffer *sniffer);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_area_task.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Class to handle partitioning a rectangular image processing operation taking into account multiple processing resources and memory constraints.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_area_task__
+#define __dng_area_task__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_point.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief Abstract class for rectangular processing operations with support for partitioning across multiple processing resources and observing memory constraints.
+
+class dng_area_task
+ {
+
+ protected:
+
+ uint32 fMaxThreads;
+
+ uint32 fMinTaskArea;
+
+ dng_point fUnitCell;
+
+ dng_point fMaxTileSize;
+
+ public:
+
+ dng_area_task ();
+
+ virtual ~dng_area_task ();
+
+ /// Getter for the maximum number of threads (resources) that can be used for processing
+ ///
+ /// \retval Number of threads, minimum of 1, that can be used for this task.
+
+ virtual uint32 MaxThreads () const
+ {
+ return fMaxThreads;
+ }
+
+ /// Getter for minimum area of a partitioned rectangle.
+ /// Often it is not profitable to use more resources if it requires partitioning the input into chunks that are too small,
+ /// as the overhead increases more than the speedup. This method can be ovreridden for a specific task to indicate the smallest
+ /// area for partitioning. Default is 256x256 pixels.
+ ///
+ /// \retval Minimum area for a partitoned tile in order to give performant operation. (Partitions can be smaller due to small inputs and edge cases.)
+
+ virtual uint32 MinTaskArea () const
+ {
+ return fMinTaskArea;
+ }
+
+ /// Getter for dimensions of which partitioned tiles should be a multiple.
+ /// Various methods of processing prefer certain alignments. The partitioning attempts to construct tiles such that the
+ /// sizes are a multiple of the dimensions of this point.
+ ///
+ /// \retval a point giving preferred alignment in x and y
+
+ virtual dng_point UnitCell () const
+ {
+ return fUnitCell;
+ }
+
+ /// Getter for maximum size of a tile for processing.
+ /// Often processing will need to allocate temporary buffers or use other resources that are either fixed or in limited supply.
+ /// The maximum tile size forces further partitioning if the tile is bigger than this size.
+ ///
+ /// \retval Maximum tile size allowed for this area task.
+
+ virtual dng_point MaxTileSize () const
+ {
+ return fMaxTileSize;
+ }
+
+ /// Getter for RepeatingTile1.
+ /// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to establish a set of 0 to 3 tile patterns for which
+ /// the resulting partitions that the final Process method is called on will not cross tile boundaries in any of the
+ /// tile patterns. This can be used for a processing routine that needs to read from two tiles and write to a third
+ /// such that all the tiles are aligned and sized in a certain way. A RepeatingTile value is valid if it is non-empty.
+ /// Higher numbered RepeatingTile patterns are only used if all lower ones are non-empty. A RepeatingTile pattern must
+ /// be a multiple of UnitCell in size for all constraints of the partitionerr to be met.
+
+ virtual dng_rect RepeatingTile1 () const;
+
+ /// Getter for RepeatingTile2.
+ /// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to establish a set of 0 to 3 tile patterns for which
+ /// the resulting partitions that the final Process method is called on will not cross tile boundaries in any of the
+ /// tile patterns. This can be used for a processing routine that needs to read from two tiles and write to a third
+ /// such that all the tiles are aligned and sized in a certain way. A RepeatingTile value is valid if it is non-empty.
+ /// Higher numbered RepeatingTile patterns are only used if all lower ones are non-empty. A RepeatingTile pattern must
+ /// be a multiple of UnitCell in size for all constraints of the partitionerr to be met.
+
+ virtual dng_rect RepeatingTile2 () const;
+
+ /// Getter for RepeatingTile3.
+ /// RepeatingTile1, RepeatingTile2, and RepeatingTile3 are used to establish a set of 0 to 3 tile patterns for which
+ /// the resulting partitions that the final Process method is called on will not cross tile boundaries in any of the
+ /// tile patterns. This can be used for a processing routine that needs to read from two tiles and write to a third
+ /// such that all the tiles are aligned and sized in a certain way. A RepeatingTile value is valid if it is non-empty.
+ /// Higher numbered RepeatingTile patterns are only used if all lower ones are non-empty. A RepeatingTile pattern must
+ /// be a multiple of UnitCell in size for all constraints of the partitionerr to be met.
+
+ virtual dng_rect RepeatingTile3 () const;
+
+ /// Task startup method called before any processing is done on partitions.
+ /// The Start method is called before any processing is done and can be overridden to allocate temporary buffers, etc.
+ ///
+ /// \param threadCount Total number of threads that will be used for processing. Less than or equal to MaxThreads.
+ /// \param tileSize Size of source tiles which will be processed. (Not all tiles will be this size due to edge conditions.)
+ /// \param allocator dng_memory_allocator to use for allocating temporary buffers, etc.
+ /// \param sniffer Sniffer to test for user cancellation and to set up progress.
+
+ virtual void Start (uint32 threadCount,
+ const dng_point &tileSize,
+ dng_memory_allocator *allocator,
+ dng_abort_sniffer *sniffer);
+
+ /// Process one tile or fully partitioned area.
+ /// This method is overridden by derived classes to implement the actual image processing. Note that the sniffer can be ignored if it is certain that a
+ /// processing task will complete very quickly.
+ /// This method should never be called directly but rather accessed via Process.
+ /// There is no allocator parameter as all allocation should be done in Start.
+ ///
+ /// \param threadIndex 0 to threadCount - 1 index indicating which thread this is. (Can be used to get a thread-specific buffer allocated in the Start method.)
+ /// \param tile Area to process.
+ /// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates.
+
+ virtual void Process (uint32 threadIndex,
+ const dng_rect &tile,
+ dng_abort_sniffer *sniffer) = 0;
+
+ /// Task computation finalization and teardown method.
+ /// Called after all resources have completed processing. Can be overridden to accumulate results and free resources allocated in Start.
+ ///
+ /// \param threadCount Number of threads used for processing. Same as value passed to Start.
+
+ virtual void Finish (uint32 threadCount);
+
+ /// Find tile size taking into account repeating tiles, unit cell, and maximum tile size.
+ /// \param area Computation area for which to find tile size.
+ /// \retval Tile size as height and width in point.
+
+ dng_point FindTileSize (const dng_rect &area) const;
+
+ /// Handle one resource's worth of partitioned tiles.
+ /// Called after thread partitioning has already been done. Area may be further subdivided to handle maximum tile size, etc.
+ /// It will be rare to override this method.
+ ///
+ /// \param threadIndex 0 to threadCount - 1 index indicating which thread this is.
+ /// \param area Tile area partitioned to this resource.
+ /// \param tileSize
+ /// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates.
+
+ void ProcessOnThread (uint32 threadIndex,
+ const dng_rect &area,
+ const dng_point &tileSize,
+ dng_abort_sniffer *sniffer);
+
+ /// Default resource partitioner that assumes a single resource to be used for processing.
+ /// Implementations that are aware of multiple processing resources should override (replace) this method.
+ /// This is usually done in dng_host::PerformAreaTask .
+ /// \param task The task to perform.
+ /// \param area The area on which mage processing should be performed.
+ /// \param allocator dng_memory_allocator to use for allocating temporary buffers, etc.
+ /// \param sniffer dng_abort_sniffer to use to check for user cancellation and progress updates.
+
+ static void Perform (dng_area_task &task,
+ const dng_rect &area,
+ dng_memory_allocator *allocator,
+ dng_abort_sniffer *sniffer);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_assertions.h b/source/dng_assertions.h
index 3c45957..dc998fa 100644
--- a/source/dng_assertions.h
+++ b/source/dng_assertions.h
@@ -1,133 +1,133 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_assertions.h#3 $ */
-/* $DateTime: 2012/09/05 12:31:51 $ */
-/* $Change: 847652 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Conditionally compiled assertion check support.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_assertions__
-#define __dng_assertions__
-
-/*****************************************************************************/
-
-#include "dng_exceptions.h"
-#include "dng_flags.h"
-
-/*****************************************************************************/
-
-#if qDNGDebug
-
-/// Platform-specific function to display an assert.
-
-void dng_show_message (const char *s);
-
-/// Show a formatted error message.
-
-void dng_show_message_f (const char *fmt, ...);
-
-#endif
-
-/*****************************************************************************/
-
-#ifndef DNG_ASSERT
-
-#if qDNGDebug
-
-/// Conditionally compiled macro to check an assertion and display a message if
-/// it fails and assertions are compiled in via qDNGDebug
-/// \param x Predicate which must be true.
-/// \param y String to display if x is not true.
-
-#define DNG_ASSERT(x,y) { if (!(x)) dng_show_message (y); }
-
-#else
-
-/// Conditionally compiled macro to check an assertion and display a message if
-/// it fails and assertions are compiled in via qDNGDebug
-/// \param x Predicate which must be true.
-/// \param y String to display if x is not true.
-
-#define DNG_ASSERT(x,y)
-
-#endif
-#endif
-
-/*****************************************************************************/
-
-#ifndef DNG_REQUIRE
-
-#if qDNGDebug
-
-/// Conditionally compiled macro to check an assertion, display a message, and throw
-/// an exception if it fails and assertions are compiled in via qDNGDebug
-/// \param condition Predicate which must be true.
-/// \param msg String to display if condition is not true.
-
-#define DNG_REQUIRE(condition,msg) \
- do \
- { \
- \
- if (!(condition)) \
- { \
- \
- DNG_ASSERT(condition, msg); \
- \
- ThrowProgramError (msg); \
- \
- } \
- \
- } \
- while (0)
-
-#else
-
-/// Conditionally compiled macro to check an assertion, display a message, and throw
-/// an exception if it fails and assertions are compiled in via qDNGDebug
-/// \param condition Predicate which must be true.
-/// \param msg String to display if condition is not true.
-
-#define DNG_REQUIRE(condition,msg) \
- do \
- { \
- \
- if (!(condition)) \
- { \
- \
- ThrowProgramError (msg); \
- \
- } \
- \
- } \
- while (0)
-
-#endif
-#endif
-
-/*****************************************************************************/
-
-#ifndef DNG_REPORT
-
-/// Macro to display an informational message
-/// \param x String to display.
-
-#define DNG_REPORT(x) DNG_ASSERT (false, x)
-
-#endif
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_assertions.h#3 $ */
+/* $DateTime: 2012/09/05 12:31:51 $ */
+/* $Change: 847652 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Conditionally compiled assertion check support.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_assertions__
+#define __dng_assertions__
+
+/*****************************************************************************/
+
+#include "dng_exceptions.h"
+#include "dng_flags.h"
+
+/*****************************************************************************/
+
+#if qDNGDebug
+
+/// Platform-specific function to display an assert.
+
+void dng_show_message (const char *s);
+
+/// Show a formatted error message.
+
+void dng_show_message_f (const char *fmt, ...);
+
+#endif
+
+/*****************************************************************************/
+
+#ifndef DNG_ASSERT
+
+#if qDNGDebug
+
+/// Conditionally compiled macro to check an assertion and display a message if
+/// it fails and assertions are compiled in via qDNGDebug
+/// \param x Predicate which must be true.
+/// \param y String to display if x is not true.
+
+#define DNG_ASSERT(x,y) { if (!(x)) dng_show_message (y); }
+
+#else
+
+/// Conditionally compiled macro to check an assertion and display a message if
+/// it fails and assertions are compiled in via qDNGDebug
+/// \param x Predicate which must be true.
+/// \param y String to display if x is not true.
+
+#define DNG_ASSERT(x,y)
+
+#endif
+#endif
+
+/*****************************************************************************/
+
+#ifndef DNG_REQUIRE
+
+#if qDNGDebug
+
+/// Conditionally compiled macro to check an assertion, display a message, and throw
+/// an exception if it fails and assertions are compiled in via qDNGDebug
+/// \param condition Predicate which must be true.
+/// \param msg String to display if condition is not true.
+
+#define DNG_REQUIRE(condition,msg) \
+ do \
+ { \
+ \
+ if (!(condition)) \
+ { \
+ \
+ DNG_ASSERT(condition, msg); \
+ \
+ ThrowProgramError (msg); \
+ \
+ } \
+ \
+ } \
+ while (0)
+
+#else
+
+/// Conditionally compiled macro to check an assertion, display a message, and throw
+/// an exception if it fails and assertions are compiled in via qDNGDebug
+/// \param condition Predicate which must be true.
+/// \param msg String to display if condition is not true.
+
+#define DNG_REQUIRE(condition,msg) \
+ do \
+ { \
+ \
+ if (!(condition)) \
+ { \
+ \
+ ThrowProgramError (msg); \
+ \
+ } \
+ \
+ } \
+ while (0)
+
+#endif
+#endif
+
+/*****************************************************************************/
+
+#ifndef DNG_REPORT
+
+/// Macro to display an informational message
+/// \param x String to display.
+
+#define DNG_REPORT(x) DNG_ASSERT (false, x)
+
+#endif
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_auto_ptr.h b/source/dng_auto_ptr.h
index cb15138..6d70fe6 100644
--- a/source/dng_auto_ptr.h
+++ b/source/dng_auto_ptr.h
@@ -1,264 +1,264 @@
-/*****************************************************************************/
-// Copyright 2006 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_auto_ptr.h#2 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Class to implement std::auto_ptr like functionality even on platforms which do not
- * have a full Standard C++ library.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_auto_ptr__
-#define __dng_auto_ptr__
-
-#include "dng_memory.h"
-
-#include <memory>
-#include <stddef.h>
-#include <stdlib.h>
-
-/*****************************************************************************/
-
-// The following template has similar functionality to the STL auto_ptr, without
-// requiring all the weight of STL.
-
-/*****************************************************************************/
-
-/// \brief A class intended to be used in stack scope to hold a pointer from new. The
-/// held pointer will be deleted automatically if the scope is left without calling
-/// Release on the AutoPtr first.
-
-template<class T>
-class AutoPtr
- {
-
- private:
-
- T *p_;
-
- public:
-
- /// Construct an AutoPtr with no referent.
-
- AutoPtr () : p_ (0) { }
-
- /// Construct an AutoPtr which owns the argument pointer.
- /// \param p pointer which constructed AutoPtr takes ownership of. p will be
- /// deleted on destruction or Reset unless Release is called first.
-
- explicit AutoPtr (T *p) : p_( p ) { }
-
- /// Reset is called on destruction.
-
- ~AutoPtr ();
-
- /// Call Reset with a pointer from new. Uses T's default constructor.
-
- void Alloc ();
-
- /// Return the owned pointer of this AutoPtr, NULL if none. No change in
- /// ownership or other effects occur.
-
- T *Get () const { return p_; }
-
- /// Return the owned pointer of this AutoPtr, NULL if none. The AutoPtr gives
- /// up ownership and takes NULL as its value.
-
- T *Release ();
-
- /// If a pointer is owned, it is deleted. Ownership is taken of passed in
- /// pointer.
- /// \param p pointer which constructed AutoPtr takes ownership of. p will be
- /// deleted on destruction or Reset unless Release is called first.
-
- void Reset (T *p);
-
- /// If a pointer is owned, it is deleted and the AutoPtr takes NULL as its
- /// value.
-
- void Reset ();
-
- /// Allows members of the owned pointer to be accessed directly. It is an
- /// error to call this if the AutoPtr has NULL as its value.
-
- T *operator-> () const { return p_; }
-
- /// Returns a reference to the object that the owned pointer points to. It is
- /// an error to call this if the AutoPtr has NULL as its value.
-
- T &operator* () const { return *p_; }
-
- /// Swap with another auto ptr.
-
- friend inline void Swap (AutoPtr< T > &x, AutoPtr< T > &y)
- {
- T* temp = x.p_;
- x.p_ = y.p_;
- y.p_ = temp;
- }
-
- private:
-
- // Hidden copy constructor and assignment operator. I don't think the STL
- // "feature" of grabbing ownership of the pointer is a good idea.
-
- AutoPtr (AutoPtr<T> &rhs);
-
- AutoPtr<T> & operator= (AutoPtr<T> &rhs);
-
- };
-
-/*****************************************************************************/
-
-template<class T>
-AutoPtr<T>::~AutoPtr ()
- {
-
- delete p_;
- p_ = 0;
-
- }
-
-/*****************************************************************************/
-
-template<class T>
-T *AutoPtr<T>::Release ()
- {
- T *result = p_;
- p_ = 0;
- return result;
- }
-
-/*****************************************************************************/
-
-template<class T>
-void AutoPtr<T>::Reset (T *p)
- {
-
- if (p_ != p)
- {
- if (p_ != 0)
- delete p_;
- p_ = p;
- }
-
- }
-
-/*****************************************************************************/
-
-template<class T>
-void AutoPtr<T>::Reset ()
- {
-
- if (p_ != 0)
- {
- delete p_;
- p_ = 0;
- }
-
- }
-
-/*****************************************************************************/
-
-template<class T>
-void AutoPtr<T>::Alloc ()
- {
- this->Reset (new T);
- }
-
-/*****************************************************************************/
-
-/// \brief A class that provides a variable-length array that automatically
-/// deletes the underlying memory on scope exit.
-///
-/// T is not required to be movable. The class is implemented using
-/// dng_std_vector but purposely does not use any member functions that require
-/// T to be movable.
-
-template<typename T>
-class AutoArray
- {
-
- public:
- /// Construct an AutoArray that refers to a null pointer.
-
- AutoArray () { }
-
- /// Construct an AutoArray containing 'count' elements, which are
- /// default-constructed. If an out-of-memory condition occurs, a
- /// dng_exception with error code dng_error_memory is thrown.
-
- explicit AutoArray (size_t count)
- : vector_(new dng_std_vector<T>(count))
- {
- }
-
- /// Changes the size of the AutoArray to 'count' elements. The new
- /// elements are default-constructed. The previously existing elements
- /// of the array are destroyed. If an out-of-memory condition occurs, a
- /// dng_exception with error code dng_error_memory is thrown.
-
- void Reset (size_t count)
- {
- vector_.reset(new dng_std_vector<T>(count));
- }
-
- /// Allows indexing into the AutoArray. The index 'i' must be
- /// non-negative and smaller than size of the array (the value that was
- /// passed to the constructor or to Reset()).
-
- T &operator[] (ptrdiff_t i)
- {
- return (*vector_) [i];
- }
- const T &operator[] (ptrdiff_t i) const
- {
- return (*vector_) [i];
- }
-
- /// Return a pointer to the beginning of the array.
-
- T *Get ()
- {
- if (vector_)
- return vector_->data();
- else
- return nullptr;
- }
- const T *Get () const
- {
- if (vector_)
- return vector_->data();
- else
- return nullptr;
- }
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- AutoArray (const AutoArray &);
-
- const AutoArray & operator= (const AutoArray &);
-
- private:
-
- std::unique_ptr<dng_std_vector<T> > vector_;
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_auto_ptr.h#2 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Class to implement std::auto_ptr like functionality even on platforms which do not
+ * have a full Standard C++ library.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_auto_ptr__
+#define __dng_auto_ptr__
+
+#include "dng_memory.h"
+
+#include <memory>
+#include <stddef.h>
+#include <stdlib.h>
+
+/*****************************************************************************/
+
+// The following template has similar functionality to the STL auto_ptr, without
+// requiring all the weight of STL.
+
+/*****************************************************************************/
+
+/// \brief A class intended to be used in stack scope to hold a pointer from new. The
+/// held pointer will be deleted automatically if the scope is left without calling
+/// Release on the AutoPtr first.
+
+template<class T>
+class AutoPtr
+ {
+
+ private:
+
+ T *p_;
+
+ public:
+
+ /// Construct an AutoPtr with no referent.
+
+ AutoPtr () : p_ (0) { }
+
+ /// Construct an AutoPtr which owns the argument pointer.
+ /// \param p pointer which constructed AutoPtr takes ownership of. p will be
+ /// deleted on destruction or Reset unless Release is called first.
+
+ explicit AutoPtr (T *p) : p_( p ) { }
+
+ /// Reset is called on destruction.
+
+ ~AutoPtr ();
+
+ /// Call Reset with a pointer from new. Uses T's default constructor.
+
+ void Alloc ();
+
+ /// Return the owned pointer of this AutoPtr, NULL if none. No change in
+ /// ownership or other effects occur.
+
+ T *Get () const { return p_; }
+
+ /// Return the owned pointer of this AutoPtr, NULL if none. The AutoPtr gives
+ /// up ownership and takes NULL as its value.
+
+ T *Release ();
+
+ /// If a pointer is owned, it is deleted. Ownership is taken of passed in
+ /// pointer.
+ /// \param p pointer which constructed AutoPtr takes ownership of. p will be
+ /// deleted on destruction or Reset unless Release is called first.
+
+ void Reset (T *p);
+
+ /// If a pointer is owned, it is deleted and the AutoPtr takes NULL as its
+ /// value.
+
+ void Reset ();
+
+ /// Allows members of the owned pointer to be accessed directly. It is an
+ /// error to call this if the AutoPtr has NULL as its value.
+
+ T *operator-> () const { return p_; }
+
+ /// Returns a reference to the object that the owned pointer points to. It is
+ /// an error to call this if the AutoPtr has NULL as its value.
+
+ T &operator* () const { return *p_; }
+
+ /// Swap with another auto ptr.
+
+ friend inline void Swap (AutoPtr< T > &x, AutoPtr< T > &y)
+ {
+ T* temp = x.p_;
+ x.p_ = y.p_;
+ y.p_ = temp;
+ }
+
+ private:
+
+ // Hidden copy constructor and assignment operator. I don't think the STL
+ // "feature" of grabbing ownership of the pointer is a good idea.
+
+ AutoPtr (AutoPtr<T> &rhs);
+
+ AutoPtr<T> & operator= (AutoPtr<T> &rhs);
+
+ };
+
+/*****************************************************************************/
+
+template<class T>
+AutoPtr<T>::~AutoPtr ()
+ {
+
+ delete p_;
+ p_ = 0;
+
+ }
+
+/*****************************************************************************/
+
+template<class T>
+T *AutoPtr<T>::Release ()
+ {
+ T *result = p_;
+ p_ = 0;
+ return result;
+ }
+
+/*****************************************************************************/
+
+template<class T>
+void AutoPtr<T>::Reset (T *p)
+ {
+
+ if (p_ != p)
+ {
+ if (p_ != 0)
+ delete p_;
+ p_ = p;
+ }
+
+ }
+
+/*****************************************************************************/
+
+template<class T>
+void AutoPtr<T>::Reset ()
+ {
+
+ if (p_ != 0)
+ {
+ delete p_;
+ p_ = 0;
+ }
+
+ }
+
+/*****************************************************************************/
+
+template<class T>
+void AutoPtr<T>::Alloc ()
+ {
+ this->Reset (new T);
+ }
+
+/*****************************************************************************/
+
+/// \brief A class that provides a variable-length array that automatically
+/// deletes the underlying memory on scope exit.
+///
+/// T is not required to be movable. The class is implemented using
+/// dng_std_vector but purposely does not use any member functions that require
+/// T to be movable.
+
+template<typename T>
+class AutoArray
+ {
+
+ public:
+ /// Construct an AutoArray that refers to a null pointer.
+
+ AutoArray () { }
+
+ /// Construct an AutoArray containing 'count' elements, which are
+ /// default-constructed. If an out-of-memory condition occurs, a
+ /// dng_exception with error code dng_error_memory is thrown.
+
+ explicit AutoArray (size_t count)
+ : vector_(new dng_std_vector<T>(count))
+ {
+ }
+
+ /// Changes the size of the AutoArray to 'count' elements. The new
+ /// elements are default-constructed. The previously existing elements
+ /// of the array are destroyed. If an out-of-memory condition occurs, a
+ /// dng_exception with error code dng_error_memory is thrown.
+
+ void Reset (size_t count)
+ {
+ vector_.reset(new dng_std_vector<T>(count));
+ }
+
+ /// Allows indexing into the AutoArray. The index 'i' must be
+ /// non-negative and smaller than size of the array (the value that was
+ /// passed to the constructor or to Reset()).
+
+ T &operator[] (ptrdiff_t i)
+ {
+ return (*vector_) [i];
+ }
+ const T &operator[] (ptrdiff_t i) const
+ {
+ return (*vector_) [i];
+ }
+
+ /// Return a pointer to the beginning of the array.
+
+ T *Get ()
+ {
+ if (vector_)
+ return vector_->data();
+ else
+ return nullptr;
+ }
+ const T *Get () const
+ {
+ if (vector_)
+ return vector_->data();
+ else
+ return nullptr;
+ }
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ AutoArray (const AutoArray &);
+
+ const AutoArray & operator= (const AutoArray &);
+
+ private:
+
+ std::unique_ptr<dng_std_vector<T> > vector_;
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_bad_pixels.cpp b/source/dng_bad_pixels.cpp
index 36c1991..52bde0d 100644
--- a/source/dng_bad_pixels.cpp
+++ b/source/dng_bad_pixels.cpp
@@ -1,1858 +1,1858 @@
-/*****************************************************************************/
-// 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_bad_pixels.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_bad_pixels.h"
-
-#include "dng_filter_task.h"
-#include "dng_globals.h"
-#include "dng_host.h"
-#include "dng_image.h"
-#include "dng_negative.h"
-#include "dng_safe_arithmetic.h"
-
-#include <algorithm>
-
-/*****************************************************************************/
-
-dng_opcode_FixBadPixelsConstant::dng_opcode_FixBadPixelsConstant
- (uint32 constant,
- uint32 bayerPhase)
-
- : dng_filter_opcode (dngOpcode_FixBadPixelsConstant,
- dngVersion_1_3_0_0,
- 0)
-
- , fConstant (constant)
- , fBayerPhase (bayerPhase)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_opcode_FixBadPixelsConstant::dng_opcode_FixBadPixelsConstant
- (dng_stream &stream)
-
- : dng_filter_opcode (dngOpcode_FixBadPixelsConstant,
- stream,
- "FixBadPixelsConstant")
-
- , fConstant (0)
- , fBayerPhase (0)
-
- {
-
- if (stream.Get_uint32 () != 8)
- {
- ThrowBadFormat ();
- }
-
- fConstant = stream.Get_uint32 ();
- fBayerPhase = stream.Get_uint32 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Constant: %u\n", (unsigned) fConstant);
-
- printf ("Bayer Phase: %u\n", (unsigned) fBayerPhase);
-
- }
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsConstant::PutData (dng_stream &stream) const
- {
-
- stream.Put_uint32 (8);
-
- stream.Put_uint32 (fConstant );
- stream.Put_uint32 (fBayerPhase);
-
- }
-
-/*****************************************************************************/
-
-dng_point dng_opcode_FixBadPixelsConstant::SrcRepeat ()
- {
-
- return dng_point (2, 2);
-
- }
-
-/*****************************************************************************/
-
-dng_rect dng_opcode_FixBadPixelsConstant::SrcArea (const dng_rect &dstArea,
- const dng_rect & /* imageBounds */)
- {
-
- dng_rect srcArea = dstArea;
-
- srcArea.t -= 2;
- srcArea.l -= 2;
-
- srcArea.b += 2;
- srcArea.r += 2;
-
- return srcArea;
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsConstant::Prepare (dng_negative & /* negative */,
- uint32 /* threadCount */,
- const dng_point & /* tileSize */,
- const dng_rect & /* imageBounds */,
- uint32 imagePlanes,
- uint32 bufferPixelType,
- dng_memory_allocator & /* allocator */)
- {
-
- // This opcode is restricted to single channel images.
-
- if (imagePlanes != 1)
- {
-
- ThrowBadFormat ();
-
- }
-
- // This opcode is restricted to 16-bit images.
-
- if (bufferPixelType != ttShort)
- {
-
- ThrowBadFormat ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsConstant::ProcessArea (dng_negative & /* negative */,
- uint32 /* threadIndex */,
- dng_pixel_buffer &srcBuffer,
- dng_pixel_buffer &dstBuffer,
- const dng_rect &dstArea,
- const dng_rect & /* imageBounds */)
- {
-
- dstBuffer.CopyArea (srcBuffer,
- dstArea,
- 0,
- dstBuffer.fPlanes);
-
- uint16 badPixel = (uint16) fConstant;
-
- for (int32 dstRow = dstArea.t; dstRow < dstArea.b; dstRow++)
- {
-
- const uint16 *sPtr = srcBuffer.ConstPixel_uint16 (dstRow, dstArea.l, 0);
- uint16 *dPtr = dstBuffer.DirtyPixel_uint16 (dstRow, dstArea.l, 0);
-
- for (int32 dstCol = dstArea.l; dstCol < dstArea.r; dstCol++)
- {
-
- if (*sPtr == badPixel)
- {
-
- uint32 count = 0;
- uint32 total = 0;
-
- uint16 value;
-
- if (IsGreen (dstRow, dstCol)) // Green pixel
- {
-
- value = sPtr [-srcBuffer.fRowStep - 1];
-
- if (value != badPixel)
- {
- count += 1;
- total += value;
- }
-
- value = sPtr [-srcBuffer.fRowStep + 1];
-
- if (value != badPixel)
- {
- count += 1;
- total += value;
- }
-
- value = sPtr [srcBuffer.fRowStep - 1];
-
- if (value != badPixel)
- {
- count += 1;
- total += value;
- }
-
- value = sPtr [srcBuffer.fRowStep + 1];
-
- if (value != badPixel)
- {
- count += 1;
- total += value;
- }
-
- }
-
- else // Red/blue pixel.
- {
-
- value = sPtr [-srcBuffer.fRowStep * 2];
-
- if (value != badPixel)
- {
- count += 1;
- total += value;
- }
-
- value = sPtr [srcBuffer.fRowStep * 2];
-
- if (value != badPixel)
- {
- count += 1;
- total += value;
- }
-
- value = sPtr [-2];
-
- if (value != badPixel)
- {
- count += 1;
- total += value;
- }
-
- value = sPtr [2];
-
- if (value != badPixel)
- {
- count += 1;
- total += value;
- }
-
- }
-
- if (count == 4) // Most common case.
- {
-
- *dPtr = (uint16) ((total + 2) >> 2);
-
- }
-
- else if (count > 0)
- {
-
- *dPtr = (uint16) ((total + (count >> 1)) / count);
-
- }
-
- }
-
- sPtr++;
- dPtr++;
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_bad_pixel_list::dng_bad_pixel_list ()
-
- : fBadPoints ()
- , fBadRects ()
-
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_bad_pixel_list::AddPoint (const dng_point &pt)
- {
-
- fBadPoints.push_back (pt);
-
- }
-
-/*****************************************************************************/
-
-void dng_bad_pixel_list::AddRect (const dng_rect &r)
- {
-
- fBadRects.push_back (r);
-
- }
-
-/*****************************************************************************/
-
-static bool SortBadPoints (const dng_point &a,
- const dng_point &b)
- {
-
- if (a.v < b.v)
- return true;
-
- if (a.v > b.v)
- return false;
-
- return a.h < b.h;
-
- }
-
-/*****************************************************************************/
-
-static bool SortBadRects (const dng_rect &a,
- const dng_rect &b)
- {
-
- if (a.t < b.t)
- return true;
-
- if (a.t > b.t)
- return false;
-
- if (a.l < b.l)
- return true;
-
- if (a.l > b.l)
- return false;
-
- if (a.b < b.b)
- return true;
-
- if (a.b > b.b)
- return false;
-
- return a.r < b.r;
-
- }
-
-/*****************************************************************************/
-
-void dng_bad_pixel_list::Sort ()
- {
-
- if (PointCount () > 1)
- {
-
- std::sort (fBadPoints.begin (),
- fBadPoints.end (),
- SortBadPoints);
-
- }
-
- if (RectCount () > 1)
- {
-
- std::sort (fBadRects.begin (),
- fBadRects.end (),
- SortBadRects);
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_bad_pixel_list::IsPointIsolated (uint32 index,
- uint32 radius) const
- {
-
- dng_point pt = Point (index);
-
- // Search backward through bad point list.
-
- for (int32 j = index - 1; j >= 0; j--)
- {
-
- const dng_point &pt2 = Point (j);
-
- if (pt2.v < pt.v - (int32) radius)
- {
- break;
- }
-
- if (Abs_int32 (pt2.h - pt.h) <= radius)
- {
- return false;
- }
-
- }
-
- // Search forward through bad point list.
-
- for (uint32 k = index + 1; k < PointCount (); k++)
- {
-
- const dng_point &pt2 = Point (k);
-
- if (pt2.v > pt.v + (int32) radius)
- {
- break;
- }
-
- if (Abs_int32 (pt2.h - pt.h) <= radius)
- {
- return false;
- }
-
- }
-
- // Search through bad rectangle list.
-
- dng_rect testRect (pt.v - radius,
- pt.h - radius,
- pt.v + radius + 1,
- pt.h + radius + 1);
-
- for (uint32 n = 0; n < RectCount (); n++)
- {
-
- if ((testRect & Rect (n)).NotEmpty ())
- {
- return false;
- }
-
- }
-
- // Did not find point anywhere, so bad pixel is isolated.
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool dng_bad_pixel_list::IsRectIsolated (uint32 index,
- uint32 radius) const
- {
-
- dng_rect testRect = Rect (index);
-
- testRect.t -= radius;
- testRect.l -= radius;
- testRect.b += radius;
- testRect.r += radius;
-
- for (uint32 n = 0; n < RectCount (); n++)
- {
-
- if (n != index)
- {
-
- if ((testRect & Rect (n)).NotEmpty ())
- {
- return false;
- }
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool dng_bad_pixel_list::IsPointValid (const dng_point &pt,
- const dng_rect &imageBounds,
- uint32 index) const
- {
-
- // The point must be in the image bounds to be valid.
-
- if (pt.v < imageBounds.t ||
- pt.h < imageBounds.l ||
- pt.v >= imageBounds.b ||
- pt.h >= imageBounds.r)
- {
- return false;
- }
-
- // Only search the bad point list if we have a starting search index.
-
- if (index != kNoIndex)
- {
-
- // Search backward through bad point list.
-
- for (int32 j = index - 1; j >= 0; j--)
- {
-
- const dng_point &pt2 = Point (j);
-
- if (pt2.v < pt.v)
- {
- break;
- }
-
- if (pt2 == pt)
- {
- return false;
- }
-
- }
-
- // Search forward through bad point list.
-
- for (uint32 k = index + 1; k < PointCount (); k++)
- {
-
- const dng_point &pt2 = Point (k);
-
- if (pt2.v > pt.v)
- {
- break;
- }
-
- if (pt2 == pt)
- {
- return false;
- }
-
- }
-
- }
-
- // Search through bad rectangle list.
-
- for (uint32 n = 0; n < RectCount (); n++)
- {
-
- const dng_rect &r = Rect (n);
-
- if (pt.v >= r.t &&
- pt.h >= r.l &&
- pt.v < r.b &&
- pt.h < r.r)
- {
- return false;
- }
-
- }
-
- // Did not find point anywhere, so pixel is valid.
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-dng_opcode_FixBadPixelsList::dng_opcode_FixBadPixelsList
- (AutoPtr<dng_bad_pixel_list> &list,
- uint32 bayerPhase)
-
-
- : dng_filter_opcode (dngOpcode_FixBadPixelsList,
- dngVersion_1_3_0_0,
- 0)
-
- , fList ()
-
- , fBayerPhase (bayerPhase)
-
- {
-
- fList.Reset (list.Release ());
-
- fList->Sort ();
-
- }
-
-/*****************************************************************************/
-
-dng_opcode_FixBadPixelsList::dng_opcode_FixBadPixelsList (dng_stream &stream)
-
- : dng_filter_opcode (dngOpcode_FixBadPixelsList,
- stream,
- "FixBadPixelsList")
-
- , fList ()
-
- , fBayerPhase (0)
-
- {
-
- uint32 size = stream.Get_uint32 ();
-
- fBayerPhase = stream.Get_uint32 ();
-
- uint32 pCount = stream.Get_uint32 ();
- uint32 rCount = stream.Get_uint32 ();
- uint32 expectedSize =
- SafeUint32Add(12, SafeUint32Add(SafeUint32Mult(pCount, 8), SafeUint32Mult(rCount, 16)));
- if (size != expectedSize)
- {
- ThrowBadFormat ();
- }
-
- fList.Reset (new dng_bad_pixel_list);
-
- uint32 index;
-
- for (index = 0; index < pCount; index++)
- {
-
- dng_point pt;
-
- pt.v = stream.Get_int32 ();
- pt.h = stream.Get_int32 ();
-
- fList->AddPoint (pt);
-
- }
-
- for (index = 0; index < rCount; index++)
- {
-
- dng_rect r;
-
- r.t = stream.Get_int32 ();
- r.l = stream.Get_int32 ();
- r.b = stream.Get_int32 ();
- r.r = stream.Get_int32 ();
-
- fList->AddRect (r);
-
- }
-
- fList->Sort ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Bayer Phase: %u\n", (unsigned) fBayerPhase);
-
- printf ("Bad Pixels: %u\n", (unsigned) pCount);
-
- for (index = 0; index < pCount && index < gDumpLineLimit; index++)
- {
- printf (" Pixel [%u]: v=%d, h=%d\n",
- (unsigned) index,
- (int) fList->Point (index).v,
- (int) fList->Point (index).h);
- }
-
- if (pCount > gDumpLineLimit)
- {
- printf (" ... %u bad pixels skipped\n", (unsigned) (pCount - gDumpLineLimit));
- }
-
- printf ("Bad Rects: %u\n", (unsigned) rCount);
-
- for (index = 0; index < rCount && index < gDumpLineLimit; index++)
- {
- printf (" Rect [%u]: t=%d, l=%d, b=%d, r=%d\n",
- (unsigned) index,
- (int) fList->Rect (index).t,
- (int) fList->Rect (index).l,
- (int) fList->Rect (index).b,
- (int) fList->Rect (index).r);
- }
-
- if (rCount > gDumpLineLimit)
- {
- printf (" ... %u bad rects skipped\n", (unsigned) (rCount - gDumpLineLimit));
- }
-
- }
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsList::PutData (dng_stream &stream) const
- {
-
- uint32 pCount = fList->PointCount ();
- uint32 rCount = fList->RectCount ();
-
- stream.Put_uint32 (12 + pCount * 8 + rCount * 16);
-
- stream.Put_uint32 (fBayerPhase);
-
- stream.Put_uint32 (pCount);
- stream.Put_uint32 (rCount);
-
- uint32 index;
-
- for (index = 0; index < pCount; index++)
- {
-
- const dng_point &pt (fList->Point (index));
-
- stream.Put_int32 (pt.v);
- stream.Put_int32 (pt.h);
-
- }
-
- for (index = 0; index < rCount; index++)
- {
-
- const dng_rect &r (fList->Rect (index));
-
- stream.Put_int32 (r.t);
- stream.Put_int32 (r.l);
- stream.Put_int32 (r.b);
- stream.Put_int32 (r.r);
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_rect dng_opcode_FixBadPixelsList::SrcArea (const dng_rect &dstArea,
- const dng_rect & /* imageBounds */)
- {
-
- int32 padding = 0;
-
- if (fList->PointCount ())
- {
- padding += kBadPointPadding;
- }
-
- if (fList->RectCount ())
- {
- padding += kBadRectPadding;
- }
-
- dng_rect srcArea = dstArea;
-
- srcArea.t -= padding;
- srcArea.l -= padding;
-
- srcArea.b += padding;
- srcArea.r += padding;
-
- return srcArea;
-
- }
-
-/*****************************************************************************/
-
-dng_point dng_opcode_FixBadPixelsList::SrcRepeat ()
- {
-
- return dng_point (2, 2);
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsList::Prepare (dng_negative & /* negative */,
- uint32 /* threadCount */,
- const dng_point & /* tileSize */,
- const dng_rect & /* imageBounds */,
- uint32 imagePlanes,
- uint32 bufferPixelType,
- dng_memory_allocator & /* allocator */)
- {
-
- // This opcode is restricted to single channel images.
-
- if (imagePlanes != 1)
- {
-
- ThrowBadFormat ();
-
- }
-
- // This opcode is restricted to 16-bit images.
-
- if (bufferPixelType != ttShort)
- {
-
- ThrowBadFormat ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsList::FixIsolatedPixel (dng_pixel_buffer &buffer,
- dng_point &badPoint)
- {
-
- uint16 *p0 = buffer.DirtyPixel_uint16 (badPoint.v - 2, badPoint.h - 2, 0);
- uint16 *p1 = buffer.DirtyPixel_uint16 (badPoint.v - 1, badPoint.h - 2, 0);
- uint16 *p2 = buffer.DirtyPixel_uint16 (badPoint.v , badPoint.h - 2, 0);
- uint16 *p3 = buffer.DirtyPixel_uint16 (badPoint.v + 1, badPoint.h - 2, 0);
- uint16 *p4 = buffer.DirtyPixel_uint16 (badPoint.v + 2, badPoint.h - 2, 0);
-
- uint32 est0;
- uint32 est1;
- uint32 est2;
- uint32 est3;
-
- uint32 grad0;
- uint32 grad1;
- uint32 grad2;
- uint32 grad3;
-
- if (IsGreen (badPoint.v, badPoint.h)) // Green pixel
- {
-
- // g00 b01 g02 b03 g04
- // r10 g11 r12 g13 r14
- // g20 b21 g22 b23 g24
- // r30 g31 r32 g33 r34
- // g40 b41 g42 b43 g44
-
- int32 b01 = p0 [1];
- int32 g02 = p0 [2];
- int32 b03 = p0 [3];
-
- int32 r10 = p1 [0];
- int32 g11 = p1 [1];
- int32 r12 = p1 [2];
- int32 g13 = p1 [3];
- int32 r14 = p1 [4];
-
- int32 g20 = p2 [0];
- int32 b21 = p2 [1];
- int32 b23 = p2 [3];
- int32 g24 = p2 [4];
-
- int32 r30 = p3 [0];
- int32 g31 = p3 [1];
- int32 r32 = p3 [2];
- int32 g33 = p3 [3];
- int32 r34 = p3 [4];
-
- int32 b41 = p4 [1];
- int32 g42 = p4 [2];
- int32 b43 = p4 [3];
-
- est0 = g02 + g42;
-
- grad0 = Abs_int32 (g02 - g42) +
- Abs_int32 (g11 - g31) +
- Abs_int32 (g13 - g33) +
- Abs_int32 (b01 - b21) +
- Abs_int32 (b03 - b23) +
- Abs_int32 (b21 - b41) +
- Abs_int32 (b23 - b43);
-
- est1 = g11 + g33;
-
- grad1 = Abs_int32 (g11 - g33) +
- Abs_int32 (g02 - g24) +
- Abs_int32 (g20 - g42) +
- Abs_int32 (b01 - b23) +
- Abs_int32 (r10 - r32) +
- Abs_int32 (r12 - r34) +
- Abs_int32 (b21 - b43);
-
- est2 = g20 + g24;
-
- grad2 = Abs_int32 (g20 - g24) +
- Abs_int32 (g11 - g13) +
- Abs_int32 (g31 - g33) +
- Abs_int32 (r10 - r12) +
- Abs_int32 (r30 - r32) +
- Abs_int32 (r12 - r14) +
- Abs_int32 (r32 - r34);
-
- est3 = g13 + g31;
-
- grad3 = Abs_int32 (g13 - g31) +
- Abs_int32 (g02 - g20) +
- Abs_int32 (g24 - g42) +
- Abs_int32 (b03 - b21) +
- Abs_int32 (r14 - r32) +
- Abs_int32 (r12 - r30) +
- Abs_int32 (b23 - b41);
-
- }
-
- else // Red/blue pixel
- {
-
- // b00 g01 b02 g03 b04
- // g10 r11 g12 r13 g14
- // b20 g21 b22 g23 b24
- // g30 r31 g32 r33 g34
- // b40 g41 b42 g43 b44
-
- int32 b00 = p0 [0];
- int32 g01 = p0 [1];
- int32 b02 = p0 [2];
- int32 g03 = p0 [3];
- int32 b04 = p0 [4];
-
- int32 g10 = p1 [0];
- int32 r11 = p1 [1];
- int32 g12 = p1 [2];
- int32 r13 = p1 [3];
- int32 g14 = p1 [4];
-
- int32 b20 = p2 [0];
- int32 g21 = p2 [1];
- int32 g23 = p2 [3];
- int32 b24 = p2 [4];
-
- int32 g30 = p3 [0];
- int32 r31 = p3 [1];
- int32 g32 = p3 [2];
- int32 r33 = p3 [3];
- int32 g34 = p3 [4];
-
- int32 b40 = p4 [0];
- int32 g41 = p4 [1];
- int32 b42 = p4 [2];
- int32 g43 = p4 [3];
- int32 b44 = p4 [4];
-
- est0 = b02 + b42;
-
- grad0 = Abs_int32 (b02 - b42) +
- Abs_int32 (g12 - g32) +
- Abs_int32 (g01 - g21) +
- Abs_int32 (g21 - g41) +
- Abs_int32 (g03 - g23) +
- Abs_int32 (g23 - g43) +
- Abs_int32 (r11 - r31) +
- Abs_int32 (r13 - r33);
-
- est1 = b00 + b44;
-
- grad1 = Abs_int32 (b00 - b44) +
- Abs_int32 (r11 - r33) +
- Abs_int32 (g01 - g23) +
- Abs_int32 (g10 - g32) +
- Abs_int32 (g12 - g34) +
- Abs_int32 (g21 - g43) +
- Abs_int32 (b02 - b24) +
- Abs_int32 (b20 - b42);
-
- est2 = b20 + b24;
-
- grad2 = Abs_int32 (b20 - b24) +
- Abs_int32 (g21 - g23) +
- Abs_int32 (g10 - g12) +
- Abs_int32 (g12 - g14) +
- Abs_int32 (g30 - g32) +
- Abs_int32 (g32 - g34) +
- Abs_int32 (r11 - r13) +
- Abs_int32 (r31 - r33);
-
- est3 = b04 + b40;
-
- grad3 = Abs_int32 (b04 - b40) +
- Abs_int32 (r13 - r31) +
- Abs_int32 (g03 - g21) +
- Abs_int32 (g14 - g32) +
- Abs_int32 (g12 - g30) +
- Abs_int32 (g23 - g41) +
- Abs_int32 (b02 - b20) +
- Abs_int32 (b24 - b42);
-
- }
-
- uint32 minGrad = Min_uint32 (grad0, grad1);
-
- minGrad = Min_uint32 (minGrad, grad2);
- minGrad = Min_uint32 (minGrad, grad3);
-
- uint32 limit = (minGrad * 3) >> 1;
-
- uint32 total = 0;
- uint32 count = 0;
-
- if (grad0 <= limit)
- {
- total += est0;
- count += 2;
- }
-
- if (grad1 <= limit)
- {
- total += est1;
- count += 2;
- }
-
- if (grad2 <= limit)
- {
- total += est2;
- count += 2;
- }
-
- if (grad3 <= limit)
- {
- total += est3;
- count += 2;
- }
-
- uint32 estimate = (total + (count >> 1)) / count;
-
- p2 [2] = (uint16) estimate;
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsList::FixClusteredPixel (dng_pixel_buffer &buffer,
- uint32 pointIndex,
- const dng_rect &imageBounds)
- {
-
- const uint32 kNumSets = 3;
- const uint32 kSetSize = 4;
-
- static const int32 kOffset [kNumSets] [kSetSize] [2] =
- {
- {
- { -1, 1 },
- { -1, -1 },
- { 1, -1 },
- { 1, 1 }
- },
- {
- { -2, 0 },
- { 2, 0 },
- { 0, -2 },
- { 0, 2 }
- },
- {
- { -2, -2 },
- { -2, 2 },
- { 2, -2 },
- { 2, 2 }
- }
- };
-
- dng_point badPoint = fList->Point (pointIndex);
-
- bool isGreen = IsGreen (badPoint.v, badPoint.h);
-
- uint16 *p = buffer.DirtyPixel_uint16 (badPoint.v, badPoint.h, 0);
-
- for (uint32 set = 0; set < kNumSets; set++)
- {
-
- if (!isGreen && (kOffset [set] [0] [0] & 1) == 1)
- {
- continue;
- }
-
- uint32 total = 0;
- uint32 count = 0;
-
- for (uint32 entry = 0; entry < kSetSize; entry++)
- {
-
- dng_point offset (kOffset [set] [entry] [0],
- kOffset [set] [entry] [1]);
-
- if (fList->IsPointValid (badPoint + offset,
- imageBounds,
- pointIndex))
- {
-
- total += p [offset.v * buffer.fRowStep +
- offset.h * buffer.fColStep];
-
- count++;
-
- }
-
- }
-
- if (count)
- {
-
- uint32 estimate = (total + (count >> 1)) / count;
-
- p [0] = (uint16) estimate;
-
- return;
-
- }
-
- }
-
- // Unable to patch bad pixel. Leave pixel as is.
-
- #if qDNGValidate
-
- char s [256];
-
- sprintf (s, "Unable to repair bad pixel, row %d, column %d",
- (int) badPoint.v,
- (int) badPoint.h);
-
- ReportWarning (s);
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsList::FixSingleColumn (dng_pixel_buffer &buffer,
- const dng_rect &badRect)
- {
-
- int32 cs = buffer.fColStep;
-
- for (int32 row = badRect.t; row < badRect.b; row++)
- {
-
- uint16 *p0 = buffer.DirtyPixel_uint16 (row - 4, badRect.l - 4, 0);
- uint16 *p1 = buffer.DirtyPixel_uint16 (row - 3, badRect.l - 4, 0);
- uint16 *p2 = buffer.DirtyPixel_uint16 (row - 2, badRect.l - 4, 0);
- uint16 *p3 = buffer.DirtyPixel_uint16 (row - 1, badRect.l - 4, 0);
- uint16 *p4 = buffer.DirtyPixel_uint16 (row , badRect.l - 4, 0);
- uint16 *p5 = buffer.DirtyPixel_uint16 (row + 1, badRect.l - 4, 0);
- uint16 *p6 = buffer.DirtyPixel_uint16 (row + 2, badRect.l - 4, 0);
- uint16 *p7 = buffer.DirtyPixel_uint16 (row + 3, badRect.l - 4, 0);
- uint16 *p8 = buffer.DirtyPixel_uint16 (row + 4, badRect.l - 4, 0);
-
- uint32 est0;
- uint32 est1;
- uint32 est2;
- uint32 est3;
- uint32 est4;
- uint32 est5;
- uint32 est6;
-
- uint32 grad0;
- uint32 grad1;
- uint32 grad2;
- uint32 grad3;
- uint32 grad4;
- uint32 grad5;
- uint32 grad6;
-
- uint32 lower = 0;
- uint32 upper = 0x0FFFF;
-
- if (IsGreen (row, badRect.l)) // Green pixel
- {
-
- // g00 b01 g02 b03 g04 b05 g06 b07 g08
- // r10 g11 r12 g13 r14 g15 r16 g17 r18
- // g20 b21 g22 b23 g24 b25 g26 b27 g28
- // r30 g31 r32 g33 r34 g35 r36 g37 r38
- // g40 b41 g42 b43 g44 b45 g46 b47 g48
- // r50 g51 r52 g53 r54 g55 r56 g57 r58
- // g60 b61 g62 b63 g64 b65 g66 b67 g68
- // r70 g71 r72 g73 r74 g75 r76 g77 r78
- // g80 b81 g82 b83 g84 b85 g86 b87 g88
-
- int32 b03 = p0 [3 * cs];
- int32 b05 = p0 [5 * cs];
-
- int32 g11 = p1 [1 * cs];
- int32 g13 = p1 [3 * cs];
- int32 g15 = p1 [5 * cs];
- int32 g17 = p1 [7 * cs];
-
- int32 g22 = p2 [2 * cs];
- int32 b23 = p2 [3 * cs];
- int32 b25 = p2 [5 * cs];
- int32 g26 = p2 [6 * cs];
-
- int32 r30 = p3 [0 * cs];
- int32 g31 = p3 [1 * cs];
- int32 r32 = p3 [2 * cs];
- int32 g33 = p3 [3 * cs];
- int32 g35 = p3 [5 * cs];
- int32 r36 = p3 [6 * cs];
- int32 g37 = p3 [7 * cs];
- int32 r38 = p3 [8 * cs];
-
- int32 g40 = p4 [0 * cs];
- int32 g42 = p4 [2 * cs];
- int32 b43 = p4 [3 * cs];
- int32 b45 = p4 [5 * cs];
- int32 g46 = p4 [6 * cs];
- int32 g48 = p4 [8 * cs];
-
- int32 r50 = p5 [0 * cs];
- int32 g51 = p5 [1 * cs];
- int32 r52 = p5 [2 * cs];
- int32 g53 = p5 [3 * cs];
- int32 g55 = p5 [5 * cs];
- int32 r56 = p5 [6 * cs];
- int32 g57 = p5 [7 * cs];
- int32 r58 = p5 [8 * cs];
-
- int32 g62 = p6 [2 * cs];
- int32 b63 = p6 [3 * cs];
- int32 b65 = p6 [5 * cs];
- int32 g66 = p6 [6 * cs];
-
- int32 g71 = p7 [1 * cs];
- int32 g73 = p7 [3 * cs];
- int32 g75 = p7 [5 * cs];
- int32 g77 = p7 [7 * cs];
-
- int32 b83 = p8 [3 * cs];
- int32 b85 = p8 [5 * cs];
-
- // In case there is some green split, make an estimate of
- // of the local difference between the greens, and adjust
- // the estimated green values for the difference
- // between the two types of green pixels when estimating
- // across green types.
-
- int32 split = ((g22 + g62 + g26 + g66) * 4 +
- (g42 + g46 ) * 8 -
- (g11 + g13 + g15 + g17) -
- (g31 + g33 + g35 + g37) * 3 -
- (g51 + g53 + g55 + g57) * 3 -
- (g71 + g73 + g75 + g77) + 16) >> 5;
-
- est0 = g13 + g75 + split * 2;
-
- grad0 = Abs_int32 (g13 - g75) +
- Abs_int32 (g15 - g46) +
- Abs_int32 (g22 - g53) +
- Abs_int32 (g35 - g66) +
- Abs_int32 (g42 - g73) +
- Abs_int32 (b03 - b65) +
- Abs_int32 (b23 - b85);
-
- est1 = g33 + g55 + split * 2;
-
- grad1 = Abs_int32 (g33 - g55) +
- Abs_int32 (g22 - g55) +
- Abs_int32 (g33 - g66) +
- Abs_int32 (g13 - g35) +
- Abs_int32 (g53 - g75) +
- Abs_int32 (b23 - b45) +
- Abs_int32 (b43 - b65);
-
- est2 = g31 + g57 + split * 2;
-
- grad2 = Abs_int32 (g31 - g57) +
- Abs_int32 (g33 - g46) +
- Abs_int32 (g35 - g48) +
- Abs_int32 (g40 - g53) +
- Abs_int32 (g42 - g55) +
- Abs_int32 (r30 - r56) +
- Abs_int32 (r32 - r58);
-
- est3 = g42 + g46;
-
- grad3 = Abs_int32 (g42 - g46) * 2 +
- Abs_int32 (g33 - g35) +
- Abs_int32 (g53 - g55) +
- Abs_int32 (b23 - b25) +
- Abs_int32 (b43 - b45) +
- Abs_int32 (b63 - b65);
-
- est4 = g37 + g51 + split * 2;
-
- grad4 = Abs_int32 (g37 - g51) +
- Abs_int32 (g35 - g42) +
- Abs_int32 (g33 - g40) +
- Abs_int32 (g48 - g55) +
- Abs_int32 (g46 - g53) +
- Abs_int32 (r38 - r52) +
- Abs_int32 (r36 - r50);
-
- est5 = g35 + g53 + split * 2;
-
- grad5 = Abs_int32 (g35 - g53) +
- Abs_int32 (g26 - g53) +
- Abs_int32 (g35 - g62) +
- Abs_int32 (g15 - g33) +
- Abs_int32 (g55 - g73) +
- Abs_int32 (b25 - b43) +
- Abs_int32 (b45 - b63);
-
- est6 = g15 + g73 + split * 2;
-
- grad6 = Abs_int32 (g15 - g73) +
- Abs_int32 (g13 - g42) +
- Abs_int32 (g26 - g55) +
- Abs_int32 (g33 - g62) +
- Abs_int32 (g46 - g75) +
- Abs_int32 (b05 - b63) +
- Abs_int32 (b25 - b83);
-
- lower = Min_uint32 (Min_uint32 (g33, g35),
- Min_uint32 (g53, g55));
-
- upper = Max_uint32 (Max_uint32 (g33, g35),
- Max_uint32 (g53, g55));
-
- lower = Pin_int32 (0, lower + split, 65535);
- upper = Pin_int32 (0, upper + split, 65535);
-
- }
-
- else // Red/blue pixel
- {
-
- // b00 g01 b02 g03 b04 g05 b06 g07 b08
- // g10 r11 g12 r13 g14 r15 g16 r17 g18
- // b20 g21 b22 g23 b24 g25 b26 g27 b28
- // g30 r31 g32 r33 g34 r35 g36 r37 g38
- // b40 g41 b42 g43 b44 g45 b46 g47 b48
- // g50 r51 g52 r53 g54 r55 g56 r57 g58
- // b60 g61 b62 g63 b64 g65 b66 g67 b68
- // g70 r71 g72 r73 g74 r75 g76 r77 g78
- // b80 g81 b82 g83 b84 g85 b86 g87 b88
-
- int32 b02 = p0 [2 * cs];
- int32 g03 = p0 [3 * cs];
- int32 g05 = p0 [5 * cs];
- int32 b06 = p0 [6 * cs];
-
- int32 r13 = p1 [3 * cs];
- int32 r15 = p1 [5 * cs];
-
- int32 b20 = p2 [0 * cs];
- int32 b22 = p2 [2 * cs];
- int32 g23 = p2 [3 * cs];
- int32 g25 = p2 [5 * cs];
- int32 b26 = p2 [6 * cs];
- int32 b28 = p2 [8 * cs];
-
- int32 r31 = p3 [1 * cs];
- int32 g32 = p3 [2 * cs];
- int32 r33 = p3 [3 * cs];
- int32 r35 = p3 [5 * cs];
- int32 g36 = p3 [6 * cs];
- int32 r37 = p3 [7 * cs];
-
- int32 g41 = p4 [1 * cs];
- int32 b42 = p4 [2 * cs];
- int32 g43 = p4 [3 * cs];
- int32 g45 = p4 [5 * cs];
- int32 b46 = p4 [6 * cs];
- int32 g47 = p4 [7 * cs];
-
- int32 r51 = p5 [1 * cs];
- int32 g52 = p5 [2 * cs];
- int32 r53 = p5 [3 * cs];
- int32 r55 = p5 [5 * cs];
- int32 g56 = p5 [6 * cs];
- int32 r57 = p5 [7 * cs];
-
- int32 b60 = p6 [0 * cs];
- int32 b62 = p6 [2 * cs];
- int32 g63 = p6 [3 * cs];
- int32 g65 = p6 [5 * cs];
- int32 b66 = p6 [6 * cs];
- int32 b68 = p6 [8 * cs];
-
- int32 r73 = p7 [3 * cs];
- int32 r75 = p7 [5 * cs];
-
- int32 b82 = p8 [2 * cs];
- int32 g83 = p8 [3 * cs];
- int32 g85 = p8 [5 * cs];
- int32 b86 = p8 [6 * cs];
-
- est0 = b02 + b86;
-
- grad0 = Abs_int32 (b02 - b86) +
- Abs_int32 (r13 - r55) +
- Abs_int32 (r33 - r75) +
- Abs_int32 (g03 - g45) +
- Abs_int32 (g23 - g65) +
- Abs_int32 (g43 - g85);
-
- est1 = b22 + b66;
-
- grad1 = Abs_int32 (b22 - b66) +
- Abs_int32 (r13 - r35) +
- Abs_int32 (r33 - r55) +
- Abs_int32 (r53 - r75) +
- Abs_int32 (g23 - g45) +
- Abs_int32 (g43 - g65);
-
- est2 = b20 + b68;
-
- grad2 = Abs_int32 (b20 - b68) +
- Abs_int32 (r31 - r55) +
- Abs_int32 (r33 - r57) +
- Abs_int32 (g23 - g47) +
- Abs_int32 (g32 - g56) +
- Abs_int32 (g41 - g65);
-
- est3 = b42 + b46;
-
- grad3 = Abs_int32 (b42 - b46) +
- Abs_int32 (r33 - r35) +
- Abs_int32 (r53 - r55) +
- Abs_int32 (g32 - g36) +
- Abs_int32 (g43 - g43) +
- Abs_int32 (g52 - g56);
-
- est4 = b28 + b60;
-
- grad4 = Abs_int32 (b28 - b60) +
- Abs_int32 (r37 - r53) +
- Abs_int32 (r35 - r51) +
- Abs_int32 (g25 - g41) +
- Abs_int32 (g36 - g52) +
- Abs_int32 (g47 - g63);
-
- est5 = b26 + b62;
-
- grad5 = Abs_int32 (b26 - b62) +
- Abs_int32 (r15 - r33) +
- Abs_int32 (r35 - r53) +
- Abs_int32 (r55 - r73) +
- Abs_int32 (g25 - g43) +
- Abs_int32 (g45 - g63);
-
- est6 = b06 + b82;
-
- grad6 = Abs_int32 (b06 - b82) +
- Abs_int32 (r15 - r53) +
- Abs_int32 (r35 - r73) +
- Abs_int32 (g05 - g43) +
- Abs_int32 (g25 - g63) +
- Abs_int32 (g45 - g83);
-
- lower = Min_uint32 (b42, b46);
- upper = Max_uint32 (b42, b46);
-
- }
-
- uint32 minGrad = Min_uint32 (grad0, grad1);
-
- minGrad = Min_uint32 (minGrad, grad2);
- minGrad = Min_uint32 (minGrad, grad3);
- minGrad = Min_uint32 (minGrad, grad4);
- minGrad = Min_uint32 (minGrad, grad5);
- minGrad = Min_uint32 (minGrad, grad6);
-
- uint32 limit = (minGrad * 3) >> 1;
-
- uint32 total = 0;
- uint32 count = 0;
-
- if (grad0 <= limit)
- {
- total += est0;
- count += 2;
- }
-
- if (grad1 <= limit)
- {
- total += est1;
- count += 2;
- }
-
- if (grad2 <= limit)
- {
- total += est2;
- count += 2;
- }
-
- if (grad3 <= limit)
- {
- total += est3;
- count += 2;
- }
-
- if (grad4 <= limit)
- {
- total += est4;
- count += 2;
- }
-
- if (grad5 <= limit)
- {
- total += est5;
- count += 2;
- }
-
- if (grad6 <= limit)
- {
- total += est6;
- count += 2;
- }
-
- uint32 estimate = (total + (count >> 1)) / count;
-
- p4 [4] = (uint16) Pin_uint32 (lower, estimate, upper);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsList::FixSingleRow (dng_pixel_buffer &buffer,
- const dng_rect &badRect)
- {
-
- dng_pixel_buffer tBuffer = buffer;
-
- tBuffer.fArea = Transpose (buffer.fArea);
-
- tBuffer.fRowStep = buffer.fColStep;
- tBuffer.fColStep = buffer.fRowStep;
-
- dng_rect tBadRect = Transpose (badRect);
-
- FixSingleColumn (tBuffer, tBadRect);
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsList::FixClusteredRect (dng_pixel_buffer &buffer,
- const dng_rect &badRect,
- const dng_rect &imageBounds)
- {
-
- const uint32 kNumSets = 8;
- const uint32 kSetSize = 8;
-
- static const int32 kOffset [kNumSets] [kSetSize] [2] =
- {
- {
- { -1, 1 },
- { -1, -1 },
- { 1, -1 },
- { 1, 1 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }
- },
- {
- { -2, 0 },
- { 2, 0 },
- { 0, -2 },
- { 0, 2 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }
- },
- {
- { -2, -2 },
- { -2, 2 },
- { 2, -2 },
- { 2, 2 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }
- },
- {
- { -1, -3 },
- { -3, -1 },
- { 1, -3 },
- { 3, -1 },
- { -1, 3 },
- { -3, 1 },
- { 1, 3 },
- { 3, 1 }
- },
- {
- { -4, 0 },
- { 4, 0 },
- { 0, -4 },
- { 0, 4 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }
- },
- {
- { -3, -3 },
- { -3, 3 },
- { 3, -3 },
- { 3, 3 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }
- },
- {
- { -2, -4 },
- { -4, -2 },
- { 2, -4 },
- { 4, -2 },
- { -2, 4 },
- { -4, 2 },
- { 2, 4 },
- { 4, 2 }
- },
- {
- { -4, -4 },
- { -4, 4 },
- { 4, -4 },
- { 4, 4 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 },
- { 0, 0 }
- }
- };
-
- bool didFail = false;
-
- for (int32 row = badRect.t; row < badRect.b; row++)
- {
-
- for (int32 col = badRect.l; col < badRect.r; col++)
- {
-
- uint16 *p = buffer.DirtyPixel_uint16 (row, col, 0);
-
- bool isGreen = IsGreen (row, col);
-
- bool didFixPixel = false;
-
- for (uint32 set = 0; set < kNumSets && !didFixPixel; set++)
- {
-
- if (!isGreen && (kOffset [set] [0] [0] & 1) == 1)
- {
- continue;
- }
-
- uint32 total = 0;
- uint32 count = 0;
-
- for (uint32 entry = 0; entry < kSetSize; entry++)
- {
-
- dng_point offset (kOffset [set] [entry] [0],
- kOffset [set] [entry] [1]);
-
- if (offset.v == 0 &&
- offset.h == 0)
- {
- break;
- }
-
- if (fList->IsPointValid (dng_point (row, col) + offset,
- imageBounds))
- {
-
- total += p [offset.v * buffer.fRowStep +
- offset.h * buffer.fColStep];
-
- count++;
-
- }
-
- }
-
- if (count)
- {
-
- uint32 estimate = (total + (count >> 1)) / count;
-
- p [0] = (uint16) estimate;
-
- didFixPixel = true;
-
- }
-
- }
-
- if (!didFixPixel)
- {
-
- didFail = true;
-
- }
-
- }
-
- }
-
- #if qDNGValidate
-
- if (didFail)
- {
-
- ReportWarning ("Unable to repair bad rectangle");
-
- }
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_FixBadPixelsList::ProcessArea (dng_negative & /* negative */,
- uint32 /* threadIndex */,
- dng_pixel_buffer &srcBuffer,
- dng_pixel_buffer &dstBuffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds)
- {
-
- uint32 pointCount = fList->PointCount ();
- uint32 rectCount = fList->RectCount ();
-
- dng_rect fixArea = dstArea;
-
- if (rectCount)
- {
- fixArea.t -= kBadRectPadding;
- fixArea.l -= kBadRectPadding;
- fixArea.b += kBadRectPadding;
- fixArea.r += kBadRectPadding;
- }
-
- bool didFixPoint = false;
-
- if (pointCount)
- {
-
- for (uint32 pointIndex = 0; pointIndex < pointCount; pointIndex++)
- {
-
- dng_point badPoint = fList->Point (pointIndex);
-
- if (badPoint.v >= fixArea.t &&
- badPoint.h >= fixArea.l &&
- badPoint.v < fixArea.b &&
- badPoint.h < fixArea.r)
- {
-
- bool isIsolated = fList->IsPointIsolated (pointIndex,
- kBadPointPadding);
-
- if (isIsolated &&
- badPoint.v >= imageBounds.t + kBadPointPadding &&
- badPoint.h >= imageBounds.l + kBadPointPadding &&
- badPoint.v < imageBounds.b - kBadPointPadding &&
- badPoint.h < imageBounds.r - kBadPointPadding)
- {
-
- FixIsolatedPixel (srcBuffer,
- badPoint);
-
- }
-
- else
- {
-
- FixClusteredPixel (srcBuffer,
- pointIndex,
- imageBounds);
-
- }
-
- didFixPoint = true;
-
- }
-
- }
-
- }
-
- if (rectCount)
- {
-
- if (didFixPoint)
- {
-
- srcBuffer.RepeatSubArea (imageBounds,
- SrcRepeat ().v,
- SrcRepeat ().h);
-
- }
-
- for (uint32 rectIndex = 0; rectIndex < rectCount; rectIndex++)
- {
-
- dng_rect badRect = fList->Rect (rectIndex);
-
- dng_rect overlap = dstArea & badRect;
-
- if (overlap.NotEmpty ())
- {
-
- bool isIsolated = fList->IsRectIsolated (rectIndex,
- kBadRectPadding);
-
- if (isIsolated &&
- badRect.r == badRect.l + 1 &&
- badRect.l >= imageBounds.l + SrcRepeat ().h &&
- badRect.r <= imageBounds.r - SrcRepeat ().v)
- {
-
- FixSingleColumn (srcBuffer,
- overlap);
-
- }
-
- else if (isIsolated &&
- badRect.b == badRect.t + 1 &&
- badRect.t >= imageBounds.t + SrcRepeat ().h &&
- badRect.b <= imageBounds.b - SrcRepeat ().v)
- {
-
- FixSingleRow (srcBuffer,
- overlap);
-
- }
-
- else
- {
-
- FixClusteredRect (srcBuffer,
- overlap,
- imageBounds);
-
- }
-
- }
-
- }
-
- }
-
- dstBuffer.CopyArea (srcBuffer,
- dstArea,
- 0,
- dstBuffer.fPlanes);
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// 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_bad_pixels.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_bad_pixels.h"
+
+#include "dng_filter_task.h"
+#include "dng_globals.h"
+#include "dng_host.h"
+#include "dng_image.h"
+#include "dng_negative.h"
+#include "dng_safe_arithmetic.h"
+
+#include <algorithm>
+
+/*****************************************************************************/
+
+dng_opcode_FixBadPixelsConstant::dng_opcode_FixBadPixelsConstant
+ (uint32 constant,
+ uint32 bayerPhase)
+
+ : dng_filter_opcode (dngOpcode_FixBadPixelsConstant,
+ dngVersion_1_3_0_0,
+ 0)
+
+ , fConstant (constant)
+ , fBayerPhase (bayerPhase)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_opcode_FixBadPixelsConstant::dng_opcode_FixBadPixelsConstant
+ (dng_stream &stream)
+
+ : dng_filter_opcode (dngOpcode_FixBadPixelsConstant,
+ stream,
+ "FixBadPixelsConstant")
+
+ , fConstant (0)
+ , fBayerPhase (0)
+
+ {
+
+ if (stream.Get_uint32 () != 8)
+ {
+ ThrowBadFormat ();
+ }
+
+ fConstant = stream.Get_uint32 ();
+ fBayerPhase = stream.Get_uint32 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Constant: %u\n", (unsigned) fConstant);
+
+ printf ("Bayer Phase: %u\n", (unsigned) fBayerPhase);
+
+ }
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsConstant::PutData (dng_stream &stream) const
+ {
+
+ stream.Put_uint32 (8);
+
+ stream.Put_uint32 (fConstant );
+ stream.Put_uint32 (fBayerPhase);
+
+ }
+
+/*****************************************************************************/
+
+dng_point dng_opcode_FixBadPixelsConstant::SrcRepeat ()
+ {
+
+ return dng_point (2, 2);
+
+ }
+
+/*****************************************************************************/
+
+dng_rect dng_opcode_FixBadPixelsConstant::SrcArea (const dng_rect &dstArea,
+ const dng_rect & /* imageBounds */)
+ {
+
+ dng_rect srcArea = dstArea;
+
+ srcArea.t -= 2;
+ srcArea.l -= 2;
+
+ srcArea.b += 2;
+ srcArea.r += 2;
+
+ return srcArea;
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsConstant::Prepare (dng_negative & /* negative */,
+ uint32 /* threadCount */,
+ const dng_point & /* tileSize */,
+ const dng_rect & /* imageBounds */,
+ uint32 imagePlanes,
+ uint32 bufferPixelType,
+ dng_memory_allocator & /* allocator */)
+ {
+
+ // This opcode is restricted to single channel images.
+
+ if (imagePlanes != 1)
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ // This opcode is restricted to 16-bit images.
+
+ if (bufferPixelType != ttShort)
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsConstant::ProcessArea (dng_negative & /* negative */,
+ uint32 /* threadIndex */,
+ dng_pixel_buffer &srcBuffer,
+ dng_pixel_buffer &dstBuffer,
+ const dng_rect &dstArea,
+ const dng_rect & /* imageBounds */)
+ {
+
+ dstBuffer.CopyArea (srcBuffer,
+ dstArea,
+ 0,
+ dstBuffer.fPlanes);
+
+ uint16 badPixel = (uint16) fConstant;
+
+ for (int32 dstRow = dstArea.t; dstRow < dstArea.b; dstRow++)
+ {
+
+ const uint16 *sPtr = srcBuffer.ConstPixel_uint16 (dstRow, dstArea.l, 0);
+ uint16 *dPtr = dstBuffer.DirtyPixel_uint16 (dstRow, dstArea.l, 0);
+
+ for (int32 dstCol = dstArea.l; dstCol < dstArea.r; dstCol++)
+ {
+
+ if (*sPtr == badPixel)
+ {
+
+ uint32 count = 0;
+ uint32 total = 0;
+
+ uint16 value;
+
+ if (IsGreen (dstRow, dstCol)) // Green pixel
+ {
+
+ value = sPtr [-srcBuffer.fRowStep - 1];
+
+ if (value != badPixel)
+ {
+ count += 1;
+ total += value;
+ }
+
+ value = sPtr [-srcBuffer.fRowStep + 1];
+
+ if (value != badPixel)
+ {
+ count += 1;
+ total += value;
+ }
+
+ value = sPtr [srcBuffer.fRowStep - 1];
+
+ if (value != badPixel)
+ {
+ count += 1;
+ total += value;
+ }
+
+ value = sPtr [srcBuffer.fRowStep + 1];
+
+ if (value != badPixel)
+ {
+ count += 1;
+ total += value;
+ }
+
+ }
+
+ else // Red/blue pixel.
+ {
+
+ value = sPtr [-srcBuffer.fRowStep * 2];
+
+ if (value != badPixel)
+ {
+ count += 1;
+ total += value;
+ }
+
+ value = sPtr [srcBuffer.fRowStep * 2];
+
+ if (value != badPixel)
+ {
+ count += 1;
+ total += value;
+ }
+
+ value = sPtr [-2];
+
+ if (value != badPixel)
+ {
+ count += 1;
+ total += value;
+ }
+
+ value = sPtr [2];
+
+ if (value != badPixel)
+ {
+ count += 1;
+ total += value;
+ }
+
+ }
+
+ if (count == 4) // Most common case.
+ {
+
+ *dPtr = (uint16) ((total + 2) >> 2);
+
+ }
+
+ else if (count > 0)
+ {
+
+ *dPtr = (uint16) ((total + (count >> 1)) / count);
+
+ }
+
+ }
+
+ sPtr++;
+ dPtr++;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_bad_pixel_list::dng_bad_pixel_list ()
+
+ : fBadPoints ()
+ , fBadRects ()
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_bad_pixel_list::AddPoint (const dng_point &pt)
+ {
+
+ fBadPoints.push_back (pt);
+
+ }
+
+/*****************************************************************************/
+
+void dng_bad_pixel_list::AddRect (const dng_rect &r)
+ {
+
+ fBadRects.push_back (r);
+
+ }
+
+/*****************************************************************************/
+
+static bool SortBadPoints (const dng_point &a,
+ const dng_point &b)
+ {
+
+ if (a.v < b.v)
+ return true;
+
+ if (a.v > b.v)
+ return false;
+
+ return a.h < b.h;
+
+ }
+
+/*****************************************************************************/
+
+static bool SortBadRects (const dng_rect &a,
+ const dng_rect &b)
+ {
+
+ if (a.t < b.t)
+ return true;
+
+ if (a.t > b.t)
+ return false;
+
+ if (a.l < b.l)
+ return true;
+
+ if (a.l > b.l)
+ return false;
+
+ if (a.b < b.b)
+ return true;
+
+ if (a.b > b.b)
+ return false;
+
+ return a.r < b.r;
+
+ }
+
+/*****************************************************************************/
+
+void dng_bad_pixel_list::Sort ()
+ {
+
+ if (PointCount () > 1)
+ {
+
+ std::sort (fBadPoints.begin (),
+ fBadPoints.end (),
+ SortBadPoints);
+
+ }
+
+ if (RectCount () > 1)
+ {
+
+ std::sort (fBadRects.begin (),
+ fBadRects.end (),
+ SortBadRects);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_bad_pixel_list::IsPointIsolated (uint32 index,
+ uint32 radius) const
+ {
+
+ dng_point pt = Point (index);
+
+ // Search backward through bad point list.
+
+ for (int32 j = index - 1; j >= 0; j--)
+ {
+
+ const dng_point &pt2 = Point (j);
+
+ if (pt2.v < pt.v - (int32) radius)
+ {
+ break;
+ }
+
+ if (Abs_int32 (pt2.h - pt.h) <= radius)
+ {
+ return false;
+ }
+
+ }
+
+ // Search forward through bad point list.
+
+ for (uint32 k = index + 1; k < PointCount (); k++)
+ {
+
+ const dng_point &pt2 = Point (k);
+
+ if (pt2.v > pt.v + (int32) radius)
+ {
+ break;
+ }
+
+ if (Abs_int32 (pt2.h - pt.h) <= radius)
+ {
+ return false;
+ }
+
+ }
+
+ // Search through bad rectangle list.
+
+ dng_rect testRect (pt.v - radius,
+ pt.h - radius,
+ pt.v + radius + 1,
+ pt.h + radius + 1);
+
+ for (uint32 n = 0; n < RectCount (); n++)
+ {
+
+ if ((testRect & Rect (n)).NotEmpty ())
+ {
+ return false;
+ }
+
+ }
+
+ // Did not find point anywhere, so bad pixel is isolated.
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_bad_pixel_list::IsRectIsolated (uint32 index,
+ uint32 radius) const
+ {
+
+ dng_rect testRect = Rect (index);
+
+ testRect.t -= radius;
+ testRect.l -= radius;
+ testRect.b += radius;
+ testRect.r += radius;
+
+ for (uint32 n = 0; n < RectCount (); n++)
+ {
+
+ if (n != index)
+ {
+
+ if ((testRect & Rect (n)).NotEmpty ())
+ {
+ return false;
+ }
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_bad_pixel_list::IsPointValid (const dng_point &pt,
+ const dng_rect &imageBounds,
+ uint32 index) const
+ {
+
+ // The point must be in the image bounds to be valid.
+
+ if (pt.v < imageBounds.t ||
+ pt.h < imageBounds.l ||
+ pt.v >= imageBounds.b ||
+ pt.h >= imageBounds.r)
+ {
+ return false;
+ }
+
+ // Only search the bad point list if we have a starting search index.
+
+ if (index != kNoIndex)
+ {
+
+ // Search backward through bad point list.
+
+ for (int32 j = index - 1; j >= 0; j--)
+ {
+
+ const dng_point &pt2 = Point (j);
+
+ if (pt2.v < pt.v)
+ {
+ break;
+ }
+
+ if (pt2 == pt)
+ {
+ return false;
+ }
+
+ }
+
+ // Search forward through bad point list.
+
+ for (uint32 k = index + 1; k < PointCount (); k++)
+ {
+
+ const dng_point &pt2 = Point (k);
+
+ if (pt2.v > pt.v)
+ {
+ break;
+ }
+
+ if (pt2 == pt)
+ {
+ return false;
+ }
+
+ }
+
+ }
+
+ // Search through bad rectangle list.
+
+ for (uint32 n = 0; n < RectCount (); n++)
+ {
+
+ const dng_rect &r = Rect (n);
+
+ if (pt.v >= r.t &&
+ pt.h >= r.l &&
+ pt.v < r.b &&
+ pt.h < r.r)
+ {
+ return false;
+ }
+
+ }
+
+ // Did not find point anywhere, so pixel is valid.
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+dng_opcode_FixBadPixelsList::dng_opcode_FixBadPixelsList
+ (AutoPtr<dng_bad_pixel_list> &list,
+ uint32 bayerPhase)
+
+
+ : dng_filter_opcode (dngOpcode_FixBadPixelsList,
+ dngVersion_1_3_0_0,
+ 0)
+
+ , fList ()
+
+ , fBayerPhase (bayerPhase)
+
+ {
+
+ fList.Reset (list.Release ());
+
+ fList->Sort ();
+
+ }
+
+/*****************************************************************************/
+
+dng_opcode_FixBadPixelsList::dng_opcode_FixBadPixelsList (dng_stream &stream)
+
+ : dng_filter_opcode (dngOpcode_FixBadPixelsList,
+ stream,
+ "FixBadPixelsList")
+
+ , fList ()
+
+ , fBayerPhase (0)
+
+ {
+
+ uint32 size = stream.Get_uint32 ();
+
+ fBayerPhase = stream.Get_uint32 ();
+
+ uint32 pCount = stream.Get_uint32 ();
+ uint32 rCount = stream.Get_uint32 ();
+ uint32 expectedSize =
+ SafeUint32Add(12, SafeUint32Add(SafeUint32Mult(pCount, 8), SafeUint32Mult(rCount, 16)));
+ if (size != expectedSize)
+ {
+ ThrowBadFormat ();
+ }
+
+ fList.Reset (new dng_bad_pixel_list);
+
+ uint32 index;
+
+ for (index = 0; index < pCount; index++)
+ {
+
+ dng_point pt;
+
+ pt.v = stream.Get_int32 ();
+ pt.h = stream.Get_int32 ();
+
+ fList->AddPoint (pt);
+
+ }
+
+ for (index = 0; index < rCount; index++)
+ {
+
+ dng_rect r;
+
+ r.t = stream.Get_int32 ();
+ r.l = stream.Get_int32 ();
+ r.b = stream.Get_int32 ();
+ r.r = stream.Get_int32 ();
+
+ fList->AddRect (r);
+
+ }
+
+ fList->Sort ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Bayer Phase: %u\n", (unsigned) fBayerPhase);
+
+ printf ("Bad Pixels: %u\n", (unsigned) pCount);
+
+ for (index = 0; index < pCount && index < gDumpLineLimit; index++)
+ {
+ printf (" Pixel [%u]: v=%d, h=%d\n",
+ (unsigned) index,
+ (int) fList->Point (index).v,
+ (int) fList->Point (index).h);
+ }
+
+ if (pCount > gDumpLineLimit)
+ {
+ printf (" ... %u bad pixels skipped\n", (unsigned) (pCount - gDumpLineLimit));
+ }
+
+ printf ("Bad Rects: %u\n", (unsigned) rCount);
+
+ for (index = 0; index < rCount && index < gDumpLineLimit; index++)
+ {
+ printf (" Rect [%u]: t=%d, l=%d, b=%d, r=%d\n",
+ (unsigned) index,
+ (int) fList->Rect (index).t,
+ (int) fList->Rect (index).l,
+ (int) fList->Rect (index).b,
+ (int) fList->Rect (index).r);
+ }
+
+ if (rCount > gDumpLineLimit)
+ {
+ printf (" ... %u bad rects skipped\n", (unsigned) (rCount - gDumpLineLimit));
+ }
+
+ }
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsList::PutData (dng_stream &stream) const
+ {
+
+ uint32 pCount = fList->PointCount ();
+ uint32 rCount = fList->RectCount ();
+
+ stream.Put_uint32 (12 + pCount * 8 + rCount * 16);
+
+ stream.Put_uint32 (fBayerPhase);
+
+ stream.Put_uint32 (pCount);
+ stream.Put_uint32 (rCount);
+
+ uint32 index;
+
+ for (index = 0; index < pCount; index++)
+ {
+
+ const dng_point &pt (fList->Point (index));
+
+ stream.Put_int32 (pt.v);
+ stream.Put_int32 (pt.h);
+
+ }
+
+ for (index = 0; index < rCount; index++)
+ {
+
+ const dng_rect &r (fList->Rect (index));
+
+ stream.Put_int32 (r.t);
+ stream.Put_int32 (r.l);
+ stream.Put_int32 (r.b);
+ stream.Put_int32 (r.r);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_rect dng_opcode_FixBadPixelsList::SrcArea (const dng_rect &dstArea,
+ const dng_rect & /* imageBounds */)
+ {
+
+ int32 padding = 0;
+
+ if (fList->PointCount ())
+ {
+ padding += kBadPointPadding;
+ }
+
+ if (fList->RectCount ())
+ {
+ padding += kBadRectPadding;
+ }
+
+ dng_rect srcArea = dstArea;
+
+ srcArea.t -= padding;
+ srcArea.l -= padding;
+
+ srcArea.b += padding;
+ srcArea.r += padding;
+
+ return srcArea;
+
+ }
+
+/*****************************************************************************/
+
+dng_point dng_opcode_FixBadPixelsList::SrcRepeat ()
+ {
+
+ return dng_point (2, 2);
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsList::Prepare (dng_negative & /* negative */,
+ uint32 /* threadCount */,
+ const dng_point & /* tileSize */,
+ const dng_rect & /* imageBounds */,
+ uint32 imagePlanes,
+ uint32 bufferPixelType,
+ dng_memory_allocator & /* allocator */)
+ {
+
+ // This opcode is restricted to single channel images.
+
+ if (imagePlanes != 1)
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ // This opcode is restricted to 16-bit images.
+
+ if (bufferPixelType != ttShort)
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsList::FixIsolatedPixel (dng_pixel_buffer &buffer,
+ dng_point &badPoint)
+ {
+
+ uint16 *p0 = buffer.DirtyPixel_uint16 (badPoint.v - 2, badPoint.h - 2, 0);
+ uint16 *p1 = buffer.DirtyPixel_uint16 (badPoint.v - 1, badPoint.h - 2, 0);
+ uint16 *p2 = buffer.DirtyPixel_uint16 (badPoint.v , badPoint.h - 2, 0);
+ uint16 *p3 = buffer.DirtyPixel_uint16 (badPoint.v + 1, badPoint.h - 2, 0);
+ uint16 *p4 = buffer.DirtyPixel_uint16 (badPoint.v + 2, badPoint.h - 2, 0);
+
+ uint32 est0;
+ uint32 est1;
+ uint32 est2;
+ uint32 est3;
+
+ uint32 grad0;
+ uint32 grad1;
+ uint32 grad2;
+ uint32 grad3;
+
+ if (IsGreen (badPoint.v, badPoint.h)) // Green pixel
+ {
+
+ // g00 b01 g02 b03 g04
+ // r10 g11 r12 g13 r14
+ // g20 b21 g22 b23 g24
+ // r30 g31 r32 g33 r34
+ // g40 b41 g42 b43 g44
+
+ int32 b01 = p0 [1];
+ int32 g02 = p0 [2];
+ int32 b03 = p0 [3];
+
+ int32 r10 = p1 [0];
+ int32 g11 = p1 [1];
+ int32 r12 = p1 [2];
+ int32 g13 = p1 [3];
+ int32 r14 = p1 [4];
+
+ int32 g20 = p2 [0];
+ int32 b21 = p2 [1];
+ int32 b23 = p2 [3];
+ int32 g24 = p2 [4];
+
+ int32 r30 = p3 [0];
+ int32 g31 = p3 [1];
+ int32 r32 = p3 [2];
+ int32 g33 = p3 [3];
+ int32 r34 = p3 [4];
+
+ int32 b41 = p4 [1];
+ int32 g42 = p4 [2];
+ int32 b43 = p4 [3];
+
+ est0 = g02 + g42;
+
+ grad0 = Abs_int32 (g02 - g42) +
+ Abs_int32 (g11 - g31) +
+ Abs_int32 (g13 - g33) +
+ Abs_int32 (b01 - b21) +
+ Abs_int32 (b03 - b23) +
+ Abs_int32 (b21 - b41) +
+ Abs_int32 (b23 - b43);
+
+ est1 = g11 + g33;
+
+ grad1 = Abs_int32 (g11 - g33) +
+ Abs_int32 (g02 - g24) +
+ Abs_int32 (g20 - g42) +
+ Abs_int32 (b01 - b23) +
+ Abs_int32 (r10 - r32) +
+ Abs_int32 (r12 - r34) +
+ Abs_int32 (b21 - b43);
+
+ est2 = g20 + g24;
+
+ grad2 = Abs_int32 (g20 - g24) +
+ Abs_int32 (g11 - g13) +
+ Abs_int32 (g31 - g33) +
+ Abs_int32 (r10 - r12) +
+ Abs_int32 (r30 - r32) +
+ Abs_int32 (r12 - r14) +
+ Abs_int32 (r32 - r34);
+
+ est3 = g13 + g31;
+
+ grad3 = Abs_int32 (g13 - g31) +
+ Abs_int32 (g02 - g20) +
+ Abs_int32 (g24 - g42) +
+ Abs_int32 (b03 - b21) +
+ Abs_int32 (r14 - r32) +
+ Abs_int32 (r12 - r30) +
+ Abs_int32 (b23 - b41);
+
+ }
+
+ else // Red/blue pixel
+ {
+
+ // b00 g01 b02 g03 b04
+ // g10 r11 g12 r13 g14
+ // b20 g21 b22 g23 b24
+ // g30 r31 g32 r33 g34
+ // b40 g41 b42 g43 b44
+
+ int32 b00 = p0 [0];
+ int32 g01 = p0 [1];
+ int32 b02 = p0 [2];
+ int32 g03 = p0 [3];
+ int32 b04 = p0 [4];
+
+ int32 g10 = p1 [0];
+ int32 r11 = p1 [1];
+ int32 g12 = p1 [2];
+ int32 r13 = p1 [3];
+ int32 g14 = p1 [4];
+
+ int32 b20 = p2 [0];
+ int32 g21 = p2 [1];
+ int32 g23 = p2 [3];
+ int32 b24 = p2 [4];
+
+ int32 g30 = p3 [0];
+ int32 r31 = p3 [1];
+ int32 g32 = p3 [2];
+ int32 r33 = p3 [3];
+ int32 g34 = p3 [4];
+
+ int32 b40 = p4 [0];
+ int32 g41 = p4 [1];
+ int32 b42 = p4 [2];
+ int32 g43 = p4 [3];
+ int32 b44 = p4 [4];
+
+ est0 = b02 + b42;
+
+ grad0 = Abs_int32 (b02 - b42) +
+ Abs_int32 (g12 - g32) +
+ Abs_int32 (g01 - g21) +
+ Abs_int32 (g21 - g41) +
+ Abs_int32 (g03 - g23) +
+ Abs_int32 (g23 - g43) +
+ Abs_int32 (r11 - r31) +
+ Abs_int32 (r13 - r33);
+
+ est1 = b00 + b44;
+
+ grad1 = Abs_int32 (b00 - b44) +
+ Abs_int32 (r11 - r33) +
+ Abs_int32 (g01 - g23) +
+ Abs_int32 (g10 - g32) +
+ Abs_int32 (g12 - g34) +
+ Abs_int32 (g21 - g43) +
+ Abs_int32 (b02 - b24) +
+ Abs_int32 (b20 - b42);
+
+ est2 = b20 + b24;
+
+ grad2 = Abs_int32 (b20 - b24) +
+ Abs_int32 (g21 - g23) +
+ Abs_int32 (g10 - g12) +
+ Abs_int32 (g12 - g14) +
+ Abs_int32 (g30 - g32) +
+ Abs_int32 (g32 - g34) +
+ Abs_int32 (r11 - r13) +
+ Abs_int32 (r31 - r33);
+
+ est3 = b04 + b40;
+
+ grad3 = Abs_int32 (b04 - b40) +
+ Abs_int32 (r13 - r31) +
+ Abs_int32 (g03 - g21) +
+ Abs_int32 (g14 - g32) +
+ Abs_int32 (g12 - g30) +
+ Abs_int32 (g23 - g41) +
+ Abs_int32 (b02 - b20) +
+ Abs_int32 (b24 - b42);
+
+ }
+
+ uint32 minGrad = Min_uint32 (grad0, grad1);
+
+ minGrad = Min_uint32 (minGrad, grad2);
+ minGrad = Min_uint32 (minGrad, grad3);
+
+ uint32 limit = (minGrad * 3) >> 1;
+
+ uint32 total = 0;
+ uint32 count = 0;
+
+ if (grad0 <= limit)
+ {
+ total += est0;
+ count += 2;
+ }
+
+ if (grad1 <= limit)
+ {
+ total += est1;
+ count += 2;
+ }
+
+ if (grad2 <= limit)
+ {
+ total += est2;
+ count += 2;
+ }
+
+ if (grad3 <= limit)
+ {
+ total += est3;
+ count += 2;
+ }
+
+ uint32 estimate = (total + (count >> 1)) / count;
+
+ p2 [2] = (uint16) estimate;
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsList::FixClusteredPixel (dng_pixel_buffer &buffer,
+ uint32 pointIndex,
+ const dng_rect &imageBounds)
+ {
+
+ const uint32 kNumSets = 3;
+ const uint32 kSetSize = 4;
+
+ static const int32 kOffset [kNumSets] [kSetSize] [2] =
+ {
+ {
+ { -1, 1 },
+ { -1, -1 },
+ { 1, -1 },
+ { 1, 1 }
+ },
+ {
+ { -2, 0 },
+ { 2, 0 },
+ { 0, -2 },
+ { 0, 2 }
+ },
+ {
+ { -2, -2 },
+ { -2, 2 },
+ { 2, -2 },
+ { 2, 2 }
+ }
+ };
+
+ dng_point badPoint = fList->Point (pointIndex);
+
+ bool isGreen = IsGreen (badPoint.v, badPoint.h);
+
+ uint16 *p = buffer.DirtyPixel_uint16 (badPoint.v, badPoint.h, 0);
+
+ for (uint32 set = 0; set < kNumSets; set++)
+ {
+
+ if (!isGreen && (kOffset [set] [0] [0] & 1) == 1)
+ {
+ continue;
+ }
+
+ uint32 total = 0;
+ uint32 count = 0;
+
+ for (uint32 entry = 0; entry < kSetSize; entry++)
+ {
+
+ dng_point offset (kOffset [set] [entry] [0],
+ kOffset [set] [entry] [1]);
+
+ if (fList->IsPointValid (badPoint + offset,
+ imageBounds,
+ pointIndex))
+ {
+
+ total += p [offset.v * buffer.fRowStep +
+ offset.h * buffer.fColStep];
+
+ count++;
+
+ }
+
+ }
+
+ if (count)
+ {
+
+ uint32 estimate = (total + (count >> 1)) / count;
+
+ p [0] = (uint16) estimate;
+
+ return;
+
+ }
+
+ }
+
+ // Unable to patch bad pixel. Leave pixel as is.
+
+ #if qDNGValidate
+
+ char s [256];
+
+ sprintf (s, "Unable to repair bad pixel, row %d, column %d",
+ (int) badPoint.v,
+ (int) badPoint.h);
+
+ ReportWarning (s);
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsList::FixSingleColumn (dng_pixel_buffer &buffer,
+ const dng_rect &badRect)
+ {
+
+ int32 cs = buffer.fColStep;
+
+ for (int32 row = badRect.t; row < badRect.b; row++)
+ {
+
+ uint16 *p0 = buffer.DirtyPixel_uint16 (row - 4, badRect.l - 4, 0);
+ uint16 *p1 = buffer.DirtyPixel_uint16 (row - 3, badRect.l - 4, 0);
+ uint16 *p2 = buffer.DirtyPixel_uint16 (row - 2, badRect.l - 4, 0);
+ uint16 *p3 = buffer.DirtyPixel_uint16 (row - 1, badRect.l - 4, 0);
+ uint16 *p4 = buffer.DirtyPixel_uint16 (row , badRect.l - 4, 0);
+ uint16 *p5 = buffer.DirtyPixel_uint16 (row + 1, badRect.l - 4, 0);
+ uint16 *p6 = buffer.DirtyPixel_uint16 (row + 2, badRect.l - 4, 0);
+ uint16 *p7 = buffer.DirtyPixel_uint16 (row + 3, badRect.l - 4, 0);
+ uint16 *p8 = buffer.DirtyPixel_uint16 (row + 4, badRect.l - 4, 0);
+
+ uint32 est0;
+ uint32 est1;
+ uint32 est2;
+ uint32 est3;
+ uint32 est4;
+ uint32 est5;
+ uint32 est6;
+
+ uint32 grad0;
+ uint32 grad1;
+ uint32 grad2;
+ uint32 grad3;
+ uint32 grad4;
+ uint32 grad5;
+ uint32 grad6;
+
+ uint32 lower = 0;
+ uint32 upper = 0x0FFFF;
+
+ if (IsGreen (row, badRect.l)) // Green pixel
+ {
+
+ // g00 b01 g02 b03 g04 b05 g06 b07 g08
+ // r10 g11 r12 g13 r14 g15 r16 g17 r18
+ // g20 b21 g22 b23 g24 b25 g26 b27 g28
+ // r30 g31 r32 g33 r34 g35 r36 g37 r38
+ // g40 b41 g42 b43 g44 b45 g46 b47 g48
+ // r50 g51 r52 g53 r54 g55 r56 g57 r58
+ // g60 b61 g62 b63 g64 b65 g66 b67 g68
+ // r70 g71 r72 g73 r74 g75 r76 g77 r78
+ // g80 b81 g82 b83 g84 b85 g86 b87 g88
+
+ int32 b03 = p0 [3 * cs];
+ int32 b05 = p0 [5 * cs];
+
+ int32 g11 = p1 [1 * cs];
+ int32 g13 = p1 [3 * cs];
+ int32 g15 = p1 [5 * cs];
+ int32 g17 = p1 [7 * cs];
+
+ int32 g22 = p2 [2 * cs];
+ int32 b23 = p2 [3 * cs];
+ int32 b25 = p2 [5 * cs];
+ int32 g26 = p2 [6 * cs];
+
+ int32 r30 = p3 [0 * cs];
+ int32 g31 = p3 [1 * cs];
+ int32 r32 = p3 [2 * cs];
+ int32 g33 = p3 [3 * cs];
+ int32 g35 = p3 [5 * cs];
+ int32 r36 = p3 [6 * cs];
+ int32 g37 = p3 [7 * cs];
+ int32 r38 = p3 [8 * cs];
+
+ int32 g40 = p4 [0 * cs];
+ int32 g42 = p4 [2 * cs];
+ int32 b43 = p4 [3 * cs];
+ int32 b45 = p4 [5 * cs];
+ int32 g46 = p4 [6 * cs];
+ int32 g48 = p4 [8 * cs];
+
+ int32 r50 = p5 [0 * cs];
+ int32 g51 = p5 [1 * cs];
+ int32 r52 = p5 [2 * cs];
+ int32 g53 = p5 [3 * cs];
+ int32 g55 = p5 [5 * cs];
+ int32 r56 = p5 [6 * cs];
+ int32 g57 = p5 [7 * cs];
+ int32 r58 = p5 [8 * cs];
+
+ int32 g62 = p6 [2 * cs];
+ int32 b63 = p6 [3 * cs];
+ int32 b65 = p6 [5 * cs];
+ int32 g66 = p6 [6 * cs];
+
+ int32 g71 = p7 [1 * cs];
+ int32 g73 = p7 [3 * cs];
+ int32 g75 = p7 [5 * cs];
+ int32 g77 = p7 [7 * cs];
+
+ int32 b83 = p8 [3 * cs];
+ int32 b85 = p8 [5 * cs];
+
+ // In case there is some green split, make an estimate of
+ // of the local difference between the greens, and adjust
+ // the estimated green values for the difference
+ // between the two types of green pixels when estimating
+ // across green types.
+
+ int32 split = ((g22 + g62 + g26 + g66) * 4 +
+ (g42 + g46 ) * 8 -
+ (g11 + g13 + g15 + g17) -
+ (g31 + g33 + g35 + g37) * 3 -
+ (g51 + g53 + g55 + g57) * 3 -
+ (g71 + g73 + g75 + g77) + 16) >> 5;
+
+ est0 = g13 + g75 + split * 2;
+
+ grad0 = Abs_int32 (g13 - g75) +
+ Abs_int32 (g15 - g46) +
+ Abs_int32 (g22 - g53) +
+ Abs_int32 (g35 - g66) +
+ Abs_int32 (g42 - g73) +
+ Abs_int32 (b03 - b65) +
+ Abs_int32 (b23 - b85);
+
+ est1 = g33 + g55 + split * 2;
+
+ grad1 = Abs_int32 (g33 - g55) +
+ Abs_int32 (g22 - g55) +
+ Abs_int32 (g33 - g66) +
+ Abs_int32 (g13 - g35) +
+ Abs_int32 (g53 - g75) +
+ Abs_int32 (b23 - b45) +
+ Abs_int32 (b43 - b65);
+
+ est2 = g31 + g57 + split * 2;
+
+ grad2 = Abs_int32 (g31 - g57) +
+ Abs_int32 (g33 - g46) +
+ Abs_int32 (g35 - g48) +
+ Abs_int32 (g40 - g53) +
+ Abs_int32 (g42 - g55) +
+ Abs_int32 (r30 - r56) +
+ Abs_int32 (r32 - r58);
+
+ est3 = g42 + g46;
+
+ grad3 = Abs_int32 (g42 - g46) * 2 +
+ Abs_int32 (g33 - g35) +
+ Abs_int32 (g53 - g55) +
+ Abs_int32 (b23 - b25) +
+ Abs_int32 (b43 - b45) +
+ Abs_int32 (b63 - b65);
+
+ est4 = g37 + g51 + split * 2;
+
+ grad4 = Abs_int32 (g37 - g51) +
+ Abs_int32 (g35 - g42) +
+ Abs_int32 (g33 - g40) +
+ Abs_int32 (g48 - g55) +
+ Abs_int32 (g46 - g53) +
+ Abs_int32 (r38 - r52) +
+ Abs_int32 (r36 - r50);
+
+ est5 = g35 + g53 + split * 2;
+
+ grad5 = Abs_int32 (g35 - g53) +
+ Abs_int32 (g26 - g53) +
+ Abs_int32 (g35 - g62) +
+ Abs_int32 (g15 - g33) +
+ Abs_int32 (g55 - g73) +
+ Abs_int32 (b25 - b43) +
+ Abs_int32 (b45 - b63);
+
+ est6 = g15 + g73 + split * 2;
+
+ grad6 = Abs_int32 (g15 - g73) +
+ Abs_int32 (g13 - g42) +
+ Abs_int32 (g26 - g55) +
+ Abs_int32 (g33 - g62) +
+ Abs_int32 (g46 - g75) +
+ Abs_int32 (b05 - b63) +
+ Abs_int32 (b25 - b83);
+
+ lower = Min_uint32 (Min_uint32 (g33, g35),
+ Min_uint32 (g53, g55));
+
+ upper = Max_uint32 (Max_uint32 (g33, g35),
+ Max_uint32 (g53, g55));
+
+ lower = Pin_int32 (0, lower + split, 65535);
+ upper = Pin_int32 (0, upper + split, 65535);
+
+ }
+
+ else // Red/blue pixel
+ {
+
+ // b00 g01 b02 g03 b04 g05 b06 g07 b08
+ // g10 r11 g12 r13 g14 r15 g16 r17 g18
+ // b20 g21 b22 g23 b24 g25 b26 g27 b28
+ // g30 r31 g32 r33 g34 r35 g36 r37 g38
+ // b40 g41 b42 g43 b44 g45 b46 g47 b48
+ // g50 r51 g52 r53 g54 r55 g56 r57 g58
+ // b60 g61 b62 g63 b64 g65 b66 g67 b68
+ // g70 r71 g72 r73 g74 r75 g76 r77 g78
+ // b80 g81 b82 g83 b84 g85 b86 g87 b88
+
+ int32 b02 = p0 [2 * cs];
+ int32 g03 = p0 [3 * cs];
+ int32 g05 = p0 [5 * cs];
+ int32 b06 = p0 [6 * cs];
+
+ int32 r13 = p1 [3 * cs];
+ int32 r15 = p1 [5 * cs];
+
+ int32 b20 = p2 [0 * cs];
+ int32 b22 = p2 [2 * cs];
+ int32 g23 = p2 [3 * cs];
+ int32 g25 = p2 [5 * cs];
+ int32 b26 = p2 [6 * cs];
+ int32 b28 = p2 [8 * cs];
+
+ int32 r31 = p3 [1 * cs];
+ int32 g32 = p3 [2 * cs];
+ int32 r33 = p3 [3 * cs];
+ int32 r35 = p3 [5 * cs];
+ int32 g36 = p3 [6 * cs];
+ int32 r37 = p3 [7 * cs];
+
+ int32 g41 = p4 [1 * cs];
+ int32 b42 = p4 [2 * cs];
+ int32 g43 = p4 [3 * cs];
+ int32 g45 = p4 [5 * cs];
+ int32 b46 = p4 [6 * cs];
+ int32 g47 = p4 [7 * cs];
+
+ int32 r51 = p5 [1 * cs];
+ int32 g52 = p5 [2 * cs];
+ int32 r53 = p5 [3 * cs];
+ int32 r55 = p5 [5 * cs];
+ int32 g56 = p5 [6 * cs];
+ int32 r57 = p5 [7 * cs];
+
+ int32 b60 = p6 [0 * cs];
+ int32 b62 = p6 [2 * cs];
+ int32 g63 = p6 [3 * cs];
+ int32 g65 = p6 [5 * cs];
+ int32 b66 = p6 [6 * cs];
+ int32 b68 = p6 [8 * cs];
+
+ int32 r73 = p7 [3 * cs];
+ int32 r75 = p7 [5 * cs];
+
+ int32 b82 = p8 [2 * cs];
+ int32 g83 = p8 [3 * cs];
+ int32 g85 = p8 [5 * cs];
+ int32 b86 = p8 [6 * cs];
+
+ est0 = b02 + b86;
+
+ grad0 = Abs_int32 (b02 - b86) +
+ Abs_int32 (r13 - r55) +
+ Abs_int32 (r33 - r75) +
+ Abs_int32 (g03 - g45) +
+ Abs_int32 (g23 - g65) +
+ Abs_int32 (g43 - g85);
+
+ est1 = b22 + b66;
+
+ grad1 = Abs_int32 (b22 - b66) +
+ Abs_int32 (r13 - r35) +
+ Abs_int32 (r33 - r55) +
+ Abs_int32 (r53 - r75) +
+ Abs_int32 (g23 - g45) +
+ Abs_int32 (g43 - g65);
+
+ est2 = b20 + b68;
+
+ grad2 = Abs_int32 (b20 - b68) +
+ Abs_int32 (r31 - r55) +
+ Abs_int32 (r33 - r57) +
+ Abs_int32 (g23 - g47) +
+ Abs_int32 (g32 - g56) +
+ Abs_int32 (g41 - g65);
+
+ est3 = b42 + b46;
+
+ grad3 = Abs_int32 (b42 - b46) +
+ Abs_int32 (r33 - r35) +
+ Abs_int32 (r53 - r55) +
+ Abs_int32 (g32 - g36) +
+ Abs_int32 (g43 - g43) +
+ Abs_int32 (g52 - g56);
+
+ est4 = b28 + b60;
+
+ grad4 = Abs_int32 (b28 - b60) +
+ Abs_int32 (r37 - r53) +
+ Abs_int32 (r35 - r51) +
+ Abs_int32 (g25 - g41) +
+ Abs_int32 (g36 - g52) +
+ Abs_int32 (g47 - g63);
+
+ est5 = b26 + b62;
+
+ grad5 = Abs_int32 (b26 - b62) +
+ Abs_int32 (r15 - r33) +
+ Abs_int32 (r35 - r53) +
+ Abs_int32 (r55 - r73) +
+ Abs_int32 (g25 - g43) +
+ Abs_int32 (g45 - g63);
+
+ est6 = b06 + b82;
+
+ grad6 = Abs_int32 (b06 - b82) +
+ Abs_int32 (r15 - r53) +
+ Abs_int32 (r35 - r73) +
+ Abs_int32 (g05 - g43) +
+ Abs_int32 (g25 - g63) +
+ Abs_int32 (g45 - g83);
+
+ lower = Min_uint32 (b42, b46);
+ upper = Max_uint32 (b42, b46);
+
+ }
+
+ uint32 minGrad = Min_uint32 (grad0, grad1);
+
+ minGrad = Min_uint32 (minGrad, grad2);
+ minGrad = Min_uint32 (minGrad, grad3);
+ minGrad = Min_uint32 (minGrad, grad4);
+ minGrad = Min_uint32 (minGrad, grad5);
+ minGrad = Min_uint32 (minGrad, grad6);
+
+ uint32 limit = (minGrad * 3) >> 1;
+
+ uint32 total = 0;
+ uint32 count = 0;
+
+ if (grad0 <= limit)
+ {
+ total += est0;
+ count += 2;
+ }
+
+ if (grad1 <= limit)
+ {
+ total += est1;
+ count += 2;
+ }
+
+ if (grad2 <= limit)
+ {
+ total += est2;
+ count += 2;
+ }
+
+ if (grad3 <= limit)
+ {
+ total += est3;
+ count += 2;
+ }
+
+ if (grad4 <= limit)
+ {
+ total += est4;
+ count += 2;
+ }
+
+ if (grad5 <= limit)
+ {
+ total += est5;
+ count += 2;
+ }
+
+ if (grad6 <= limit)
+ {
+ total += est6;
+ count += 2;
+ }
+
+ uint32 estimate = (total + (count >> 1)) / count;
+
+ p4 [4] = (uint16) Pin_uint32 (lower, estimate, upper);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsList::FixSingleRow (dng_pixel_buffer &buffer,
+ const dng_rect &badRect)
+ {
+
+ dng_pixel_buffer tBuffer = buffer;
+
+ tBuffer.fArea = Transpose (buffer.fArea);
+
+ tBuffer.fRowStep = buffer.fColStep;
+ tBuffer.fColStep = buffer.fRowStep;
+
+ dng_rect tBadRect = Transpose (badRect);
+
+ FixSingleColumn (tBuffer, tBadRect);
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsList::FixClusteredRect (dng_pixel_buffer &buffer,
+ const dng_rect &badRect,
+ const dng_rect &imageBounds)
+ {
+
+ const uint32 kNumSets = 8;
+ const uint32 kSetSize = 8;
+
+ static const int32 kOffset [kNumSets] [kSetSize] [2] =
+ {
+ {
+ { -1, 1 },
+ { -1, -1 },
+ { 1, -1 },
+ { 1, 1 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }
+ },
+ {
+ { -2, 0 },
+ { 2, 0 },
+ { 0, -2 },
+ { 0, 2 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }
+ },
+ {
+ { -2, -2 },
+ { -2, 2 },
+ { 2, -2 },
+ { 2, 2 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }
+ },
+ {
+ { -1, -3 },
+ { -3, -1 },
+ { 1, -3 },
+ { 3, -1 },
+ { -1, 3 },
+ { -3, 1 },
+ { 1, 3 },
+ { 3, 1 }
+ },
+ {
+ { -4, 0 },
+ { 4, 0 },
+ { 0, -4 },
+ { 0, 4 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }
+ },
+ {
+ { -3, -3 },
+ { -3, 3 },
+ { 3, -3 },
+ { 3, 3 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }
+ },
+ {
+ { -2, -4 },
+ { -4, -2 },
+ { 2, -4 },
+ { 4, -2 },
+ { -2, 4 },
+ { -4, 2 },
+ { 2, 4 },
+ { 4, 2 }
+ },
+ {
+ { -4, -4 },
+ { -4, 4 },
+ { 4, -4 },
+ { 4, 4 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }
+ }
+ };
+
+ bool didFail = false;
+
+ for (int32 row = badRect.t; row < badRect.b; row++)
+ {
+
+ for (int32 col = badRect.l; col < badRect.r; col++)
+ {
+
+ uint16 *p = buffer.DirtyPixel_uint16 (row, col, 0);
+
+ bool isGreen = IsGreen (row, col);
+
+ bool didFixPixel = false;
+
+ for (uint32 set = 0; set < kNumSets && !didFixPixel; set++)
+ {
+
+ if (!isGreen && (kOffset [set] [0] [0] & 1) == 1)
+ {
+ continue;
+ }
+
+ uint32 total = 0;
+ uint32 count = 0;
+
+ for (uint32 entry = 0; entry < kSetSize; entry++)
+ {
+
+ dng_point offset (kOffset [set] [entry] [0],
+ kOffset [set] [entry] [1]);
+
+ if (offset.v == 0 &&
+ offset.h == 0)
+ {
+ break;
+ }
+
+ if (fList->IsPointValid (dng_point (row, col) + offset,
+ imageBounds))
+ {
+
+ total += p [offset.v * buffer.fRowStep +
+ offset.h * buffer.fColStep];
+
+ count++;
+
+ }
+
+ }
+
+ if (count)
+ {
+
+ uint32 estimate = (total + (count >> 1)) / count;
+
+ p [0] = (uint16) estimate;
+
+ didFixPixel = true;
+
+ }
+
+ }
+
+ if (!didFixPixel)
+ {
+
+ didFail = true;
+
+ }
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (didFail)
+ {
+
+ ReportWarning ("Unable to repair bad rectangle");
+
+ }
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_FixBadPixelsList::ProcessArea (dng_negative & /* negative */,
+ uint32 /* threadIndex */,
+ dng_pixel_buffer &srcBuffer,
+ dng_pixel_buffer &dstBuffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds)
+ {
+
+ uint32 pointCount = fList->PointCount ();
+ uint32 rectCount = fList->RectCount ();
+
+ dng_rect fixArea = dstArea;
+
+ if (rectCount)
+ {
+ fixArea.t -= kBadRectPadding;
+ fixArea.l -= kBadRectPadding;
+ fixArea.b += kBadRectPadding;
+ fixArea.r += kBadRectPadding;
+ }
+
+ bool didFixPoint = false;
+
+ if (pointCount)
+ {
+
+ for (uint32 pointIndex = 0; pointIndex < pointCount; pointIndex++)
+ {
+
+ dng_point badPoint = fList->Point (pointIndex);
+
+ if (badPoint.v >= fixArea.t &&
+ badPoint.h >= fixArea.l &&
+ badPoint.v < fixArea.b &&
+ badPoint.h < fixArea.r)
+ {
+
+ bool isIsolated = fList->IsPointIsolated (pointIndex,
+ kBadPointPadding);
+
+ if (isIsolated &&
+ badPoint.v >= imageBounds.t + kBadPointPadding &&
+ badPoint.h >= imageBounds.l + kBadPointPadding &&
+ badPoint.v < imageBounds.b - kBadPointPadding &&
+ badPoint.h < imageBounds.r - kBadPointPadding)
+ {
+
+ FixIsolatedPixel (srcBuffer,
+ badPoint);
+
+ }
+
+ else
+ {
+
+ FixClusteredPixel (srcBuffer,
+ pointIndex,
+ imageBounds);
+
+ }
+
+ didFixPoint = true;
+
+ }
+
+ }
+
+ }
+
+ if (rectCount)
+ {
+
+ if (didFixPoint)
+ {
+
+ srcBuffer.RepeatSubArea (imageBounds,
+ SrcRepeat ().v,
+ SrcRepeat ().h);
+
+ }
+
+ for (uint32 rectIndex = 0; rectIndex < rectCount; rectIndex++)
+ {
+
+ dng_rect badRect = fList->Rect (rectIndex);
+
+ dng_rect overlap = dstArea & badRect;
+
+ if (overlap.NotEmpty ())
+ {
+
+ bool isIsolated = fList->IsRectIsolated (rectIndex,
+ kBadRectPadding);
+
+ if (isIsolated &&
+ badRect.r == badRect.l + 1 &&
+ badRect.l >= imageBounds.l + SrcRepeat ().h &&
+ badRect.r <= imageBounds.r - SrcRepeat ().v)
+ {
+
+ FixSingleColumn (srcBuffer,
+ overlap);
+
+ }
+
+ else if (isIsolated &&
+ badRect.b == badRect.t + 1 &&
+ badRect.t >= imageBounds.t + SrcRepeat ().h &&
+ badRect.b <= imageBounds.b - SrcRepeat ().v)
+ {
+
+ FixSingleRow (srcBuffer,
+ overlap);
+
+ }
+
+ else
+ {
+
+ FixClusteredRect (srcBuffer,
+ overlap,
+ imageBounds);
+
+ }
+
+ }
+
+ }
+
+ }
+
+ dstBuffer.CopyArea (srcBuffer,
+ dstArea,
+ 0,
+ dstBuffer.fPlanes);
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_bad_pixels.h b/source/dng_bad_pixels.h
index d8e5cdf..3d7c02e 100644
--- a/source/dng_bad_pixels.h
+++ b/source/dng_bad_pixels.h
@@ -1,313 +1,313 @@
-/*****************************************************************************/
-// 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_bad_pixels.h#3 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Opcodes to fix defective pixels, including individual pixels and regions (such as
- * defective rows and columns).
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_bad_pixels__
-#define __dng_bad_pixels__
-
-/*****************************************************************************/
-
-#include "dng_memory.h"
-#include "dng_opcodes.h"
-
-#include <vector>
-
-/*****************************************************************************/
-
-/// \brief An opcode to fix individual bad pixels that are marked with a constant
-/// value (e.g., 0) in a Bayer image.
-
-class dng_opcode_FixBadPixelsConstant: public dng_filter_opcode
- {
-
- private:
-
- uint32 fConstant;
-
- uint32 fBayerPhase;
-
- public:
-
- /// Construct an opcode to fix an individual bad pixels that are marked with
- /// a constant value in a Bayer image.
- /// \param constant The constant value that indicates a bad pixel.
- /// \param bayerPhase The phase of the Bayer mosaic pattern (0, 1, 2, 3).
-
- dng_opcode_FixBadPixelsConstant (uint32 constant,
- uint32 bayerPhase);
-
- dng_opcode_FixBadPixelsConstant (dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual dng_point SrcRepeat ();
-
- virtual dng_rect SrcArea (const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- 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 &srcBuffer,
- dng_pixel_buffer &dstBuffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- protected:
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
- bool IsGreen (int32 row, int32 col) const
- {
- return (((uint32) row + (uint32) col + fBayerPhase + (fBayerPhase >> 1)) & 1) == 0;
- }
-
- };
-
-/*****************************************************************************/
-
-/// \brief A list of bad pixels and rectangles (usually single rows or columns).
-
-class dng_bad_pixel_list
- {
-
- public:
-
- enum
- {
- kNoIndex = 0xFFFFFFFF
- };
-
- private:
-
- // List of bad single pixels.
-
- dng_std_vector<dng_point> fBadPoints;
-
- // List of bad rectangles (usually single rows or columns).
-
- dng_std_vector<dng_rect> fBadRects;
-
- public:
-
- /// Create an empty bad pixel list.
-
- dng_bad_pixel_list ();
-
- /// Returns the number of bad single pixels.
-
- uint32 PointCount () const
- {
- return (uint32) fBadPoints.size ();
- }
-
- /// Retrieves the bad single pixel coordinate via the specified list index.
- ///
- /// \param index The list index from which to retrieve the bad single pixel
- /// coordinate.
-
- const dng_point & Point (uint32 index) const
- {
- return fBadPoints [index];
- }
-
- /// Returns the number of bad rectangles.
-
- uint32 RectCount () const
- {
- return (uint32) fBadRects.size ();
- }
-
- /// Retrieves the bad rectangle via the specified list index.
- ///
- /// \param index The list index from which to retrieve the bad rectangle
- /// coordinates.
-
- const dng_rect & Rect (uint32 index) const
- {
- return fBadRects [index];
- }
-
- /// Returns true iff there are zero bad single pixels and zero bad
- /// rectangles.
-
- bool IsEmpty () const
- {
- return PointCount () == 0 &&
- RectCount () == 0;
- }
-
- /// Returns true iff there is at least one bad single pixel or at least one
- /// bad rectangle.
-
- bool NotEmpty () const
- {
- return !IsEmpty ();
- }
-
- /// Add the specified coordinate to the list of bad single pixels.
- ///
- /// \param pt The bad single pixel to add.
-
- void AddPoint (const dng_point &pt);
-
- /// Add the specified rectangle to the list of bad rectangles.
- ///
- /// \param pt The bad rectangle to add.
-
- void AddRect (const dng_rect &r);
-
- /// Sort the bad single pixels and bad rectangles by coordinates (top to
- /// bottom, then left to right).
-
- void Sort ();
-
- /// Returns true iff the specified bad single pixel is isolated, i.e., there
- /// is no other bad single pixel or bad rectangle that lies within radius
- /// pixels of this bad single pixel.
- ///
- /// \param index The index of the bad single pixel to test.
- /// \param radius The pixel radius to test for isolation.
-
- bool IsPointIsolated (uint32 index,
- uint32 radius) const;
-
- /// Returns true iff the specified bad rectangle is isolated, i.e., there
- /// is no other bad single pixel or bad rectangle that lies within radius
- /// pixels of this bad rectangle.
- ///
- /// \param index The index of the bad rectangle to test.
- /// \param radius The pixel radius to test for isolation.
-
- bool IsRectIsolated (uint32 index,
- uint32 radius) const;
-
- /// Returns true iff the specified point is valid, i.e., lies within the
- /// specified image bounds, is different from all other bad single pixels,
- /// and is not contained in any bad rectangle. The second and third
- /// conditions are only checked if provided with a starting search index.
- ///
- /// \param pt The point to test for validity.
- /// \param imageBounds The pt must lie within imageBounds to be valid.
- /// \index The search index to use (or kNoIndex, to avoid a search) for
- /// checking for validity.
-
- bool IsPointValid (const dng_point &pt,
- const dng_rect &imageBounds,
- uint32 index = kNoIndex) const;
-
- };
-
-/*****************************************************************************/
-
-/// \brief An opcode to fix lists of bad pixels (indicated by position) in a Bayer
-/// image.
-
-class dng_opcode_FixBadPixelsList: public dng_filter_opcode
- {
-
- protected:
-
- enum
- {
- kBadPointPadding = 2,
- kBadRectPadding = 4
- };
-
- private:
-
- AutoPtr<dng_bad_pixel_list> fList;
-
- uint32 fBayerPhase;
-
- public:
-
- /// Construct an opcode to fix lists of bad pixels (indicated by position) in
- /// a Bayer image.
- /// \param list The list of bad pixels to fix.
- /// \param bayerPhase The phase of the Bayer mosaic pattern (0, 1, 2, 3).
-
- dng_opcode_FixBadPixelsList (AutoPtr<dng_bad_pixel_list> &list,
- uint32 bayerPhase);
-
- dng_opcode_FixBadPixelsList (dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual dng_point SrcRepeat ();
-
- virtual dng_rect SrcArea (const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- 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 &srcBuffer,
- dng_pixel_buffer &dstBuffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- protected:
-
- bool IsGreen (int32 row, int32 col) const
- {
- return ((row + col + fBayerPhase + (fBayerPhase >> 1)) & 1) == 0;
- }
-
- virtual void FixIsolatedPixel (dng_pixel_buffer &buffer,
- dng_point &badPoint);
-
- virtual void FixClusteredPixel (dng_pixel_buffer &buffer,
- uint32 pointIndex,
- const dng_rect &imageBounds);
-
- virtual void FixSingleColumn (dng_pixel_buffer &buffer,
- const dng_rect &badRect);
-
- virtual void FixSingleRow (dng_pixel_buffer &buffer,
- const dng_rect &badRect);
-
- virtual void FixClusteredRect (dng_pixel_buffer &buffer,
- const dng_rect &badRect,
- const dng_rect &imageBounds);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// 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_bad_pixels.h#3 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Opcodes to fix defective pixels, including individual pixels and regions (such as
+ * defective rows and columns).
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_bad_pixels__
+#define __dng_bad_pixels__
+
+/*****************************************************************************/
+
+#include "dng_memory.h"
+#include "dng_opcodes.h"
+
+#include <vector>
+
+/*****************************************************************************/
+
+/// \brief An opcode to fix individual bad pixels that are marked with a constant
+/// value (e.g., 0) in a Bayer image.
+
+class dng_opcode_FixBadPixelsConstant: public dng_filter_opcode
+ {
+
+ private:
+
+ uint32 fConstant;
+
+ uint32 fBayerPhase;
+
+ public:
+
+ /// Construct an opcode to fix an individual bad pixels that are marked with
+ /// a constant value in a Bayer image.
+ /// \param constant The constant value that indicates a bad pixel.
+ /// \param bayerPhase The phase of the Bayer mosaic pattern (0, 1, 2, 3).
+
+ dng_opcode_FixBadPixelsConstant (uint32 constant,
+ uint32 bayerPhase);
+
+ dng_opcode_FixBadPixelsConstant (dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual dng_point SrcRepeat ();
+
+ virtual dng_rect SrcArea (const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ 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 &srcBuffer,
+ dng_pixel_buffer &dstBuffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ protected:
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+ bool IsGreen (int32 row, int32 col) const
+ {
+ return (((uint32) row + (uint32) col + fBayerPhase + (fBayerPhase >> 1)) & 1) == 0;
+ }
+
+ };
+
+/*****************************************************************************/
+
+/// \brief A list of bad pixels and rectangles (usually single rows or columns).
+
+class dng_bad_pixel_list
+ {
+
+ public:
+
+ enum
+ {
+ kNoIndex = 0xFFFFFFFF
+ };
+
+ private:
+
+ // List of bad single pixels.
+
+ dng_std_vector<dng_point> fBadPoints;
+
+ // List of bad rectangles (usually single rows or columns).
+
+ dng_std_vector<dng_rect> fBadRects;
+
+ public:
+
+ /// Create an empty bad pixel list.
+
+ dng_bad_pixel_list ();
+
+ /// Returns the number of bad single pixels.
+
+ uint32 PointCount () const
+ {
+ return (uint32) fBadPoints.size ();
+ }
+
+ /// Retrieves the bad single pixel coordinate via the specified list index.
+ ///
+ /// \param index The list index from which to retrieve the bad single pixel
+ /// coordinate.
+
+ const dng_point & Point (uint32 index) const
+ {
+ return fBadPoints [index];
+ }
+
+ /// Returns the number of bad rectangles.
+
+ uint32 RectCount () const
+ {
+ return (uint32) fBadRects.size ();
+ }
+
+ /// Retrieves the bad rectangle via the specified list index.
+ ///
+ /// \param index The list index from which to retrieve the bad rectangle
+ /// coordinates.
+
+ const dng_rect & Rect (uint32 index) const
+ {
+ return fBadRects [index];
+ }
+
+ /// Returns true iff there are zero bad single pixels and zero bad
+ /// rectangles.
+
+ bool IsEmpty () const
+ {
+ return PointCount () == 0 &&
+ RectCount () == 0;
+ }
+
+ /// Returns true iff there is at least one bad single pixel or at least one
+ /// bad rectangle.
+
+ bool NotEmpty () const
+ {
+ return !IsEmpty ();
+ }
+
+ /// Add the specified coordinate to the list of bad single pixels.
+ ///
+ /// \param pt The bad single pixel to add.
+
+ void AddPoint (const dng_point &pt);
+
+ /// Add the specified rectangle to the list of bad rectangles.
+ ///
+ /// \param pt The bad rectangle to add.
+
+ void AddRect (const dng_rect &r);
+
+ /// Sort the bad single pixels and bad rectangles by coordinates (top to
+ /// bottom, then left to right).
+
+ void Sort ();
+
+ /// Returns true iff the specified bad single pixel is isolated, i.e., there
+ /// is no other bad single pixel or bad rectangle that lies within radius
+ /// pixels of this bad single pixel.
+ ///
+ /// \param index The index of the bad single pixel to test.
+ /// \param radius The pixel radius to test for isolation.
+
+ bool IsPointIsolated (uint32 index,
+ uint32 radius) const;
+
+ /// Returns true iff the specified bad rectangle is isolated, i.e., there
+ /// is no other bad single pixel or bad rectangle that lies within radius
+ /// pixels of this bad rectangle.
+ ///
+ /// \param index The index of the bad rectangle to test.
+ /// \param radius The pixel radius to test for isolation.
+
+ bool IsRectIsolated (uint32 index,
+ uint32 radius) const;
+
+ /// Returns true iff the specified point is valid, i.e., lies within the
+ /// specified image bounds, is different from all other bad single pixels,
+ /// and is not contained in any bad rectangle. The second and third
+ /// conditions are only checked if provided with a starting search index.
+ ///
+ /// \param pt The point to test for validity.
+ /// \param imageBounds The pt must lie within imageBounds to be valid.
+ /// \index The search index to use (or kNoIndex, to avoid a search) for
+ /// checking for validity.
+
+ bool IsPointValid (const dng_point &pt,
+ const dng_rect &imageBounds,
+ uint32 index = kNoIndex) const;
+
+ };
+
+/*****************************************************************************/
+
+/// \brief An opcode to fix lists of bad pixels (indicated by position) in a Bayer
+/// image.
+
+class dng_opcode_FixBadPixelsList: public dng_filter_opcode
+ {
+
+ protected:
+
+ enum
+ {
+ kBadPointPadding = 2,
+ kBadRectPadding = 4
+ };
+
+ private:
+
+ AutoPtr<dng_bad_pixel_list> fList;
+
+ uint32 fBayerPhase;
+
+ public:
+
+ /// Construct an opcode to fix lists of bad pixels (indicated by position) in
+ /// a Bayer image.
+ /// \param list The list of bad pixels to fix.
+ /// \param bayerPhase The phase of the Bayer mosaic pattern (0, 1, 2, 3).
+
+ dng_opcode_FixBadPixelsList (AutoPtr<dng_bad_pixel_list> &list,
+ uint32 bayerPhase);
+
+ dng_opcode_FixBadPixelsList (dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual dng_point SrcRepeat ();
+
+ virtual dng_rect SrcArea (const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ 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 &srcBuffer,
+ dng_pixel_buffer &dstBuffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ protected:
+
+ bool IsGreen (int32 row, int32 col) const
+ {
+ return ((row + col + fBayerPhase + (fBayerPhase >> 1)) & 1) == 0;
+ }
+
+ virtual void FixIsolatedPixel (dng_pixel_buffer &buffer,
+ dng_point &badPoint);
+
+ virtual void FixClusteredPixel (dng_pixel_buffer &buffer,
+ uint32 pointIndex,
+ const dng_rect &imageBounds);
+
+ virtual void FixSingleColumn (dng_pixel_buffer &buffer,
+ const dng_rect &badRect);
+
+ virtual void FixSingleRow (dng_pixel_buffer &buffer,
+ const dng_rect &badRect);
+
+ virtual void FixClusteredRect (dng_pixel_buffer &buffer,
+ const dng_rect &badRect,
+ const dng_rect &imageBounds);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_bottlenecks.cpp b/source/dng_bottlenecks.cpp
index 44fdb7a..150acde 100644
--- a/source/dng_bottlenecks.cpp
+++ b/source/dng_bottlenecks.cpp
@@ -1,72 +1,72 @@
-/*****************************************************************************/
-// Copyright 2006-2009 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_bottlenecks.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_bottlenecks.h"
-
-#include "dng_reference.h"
-
-/*****************************************************************************/
-
-dng_suite gDNGSuite =
- {
- RefZeroBytes,
- RefCopyBytes,
- RefSwapBytes16,
- RefSwapBytes32,
- RefSetArea8,
- RefSetArea16,
- RefSetArea32,
- RefCopyArea8,
- RefCopyArea16,
- RefCopyArea32,
- RefCopyArea8_16,
- RefCopyArea8_S16,
- RefCopyArea8_32,
- RefCopyArea16_S16,
- RefCopyArea16_32,
- RefCopyArea8_R32,
- RefCopyArea16_R32,
- RefCopyAreaS16_R32,
- RefCopyAreaR32_8,
- RefCopyAreaR32_16,
- RefCopyAreaR32_S16,
- RefRepeatArea8,
- RefRepeatArea16,
- RefRepeatArea32,
- RefShiftRight16,
- RefBilinearRow16,
- RefBilinearRow32,
- RefBaselineABCtoRGB,
- RefBaselineABCDtoRGB,
- RefBaselineHueSatMap,
- RefBaselineRGBtoGray,
- RefBaselineRGBtoRGB,
- RefBaseline1DTable,
- RefBaselineRGBTone,
- RefResampleDown16,
- RefResampleDown32,
- RefResampleAcross16,
- RefResampleAcross32,
- RefEqualBytes,
- RefEqualArea8,
- RefEqualArea16,
- RefEqualArea32,
- RefVignetteMask16,
- RefVignette16,
- RefVignette32,
- RefMapArea16
- };
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2009 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_bottlenecks.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_bottlenecks.h"
+
+#include "dng_reference.h"
+
+/*****************************************************************************/
+
+dng_suite gDNGSuite =
+ {
+ RefZeroBytes,
+ RefCopyBytes,
+ RefSwapBytes16,
+ RefSwapBytes32,
+ RefSetArea8,
+ RefSetArea16,
+ RefSetArea32,
+ RefCopyArea8,
+ RefCopyArea16,
+ RefCopyArea32,
+ RefCopyArea8_16,
+ RefCopyArea8_S16,
+ RefCopyArea8_32,
+ RefCopyArea16_S16,
+ RefCopyArea16_32,
+ RefCopyArea8_R32,
+ RefCopyArea16_R32,
+ RefCopyAreaS16_R32,
+ RefCopyAreaR32_8,
+ RefCopyAreaR32_16,
+ RefCopyAreaR32_S16,
+ RefRepeatArea8,
+ RefRepeatArea16,
+ RefRepeatArea32,
+ RefShiftRight16,
+ RefBilinearRow16,
+ RefBilinearRow32,
+ RefBaselineABCtoRGB,
+ RefBaselineABCDtoRGB,
+ RefBaselineHueSatMap,
+ RefBaselineRGBtoGray,
+ RefBaselineRGBtoRGB,
+ RefBaseline1DTable,
+ RefBaselineRGBTone,
+ RefResampleDown16,
+ RefResampleDown32,
+ RefResampleAcross16,
+ RefResampleAcross32,
+ RefEqualBytes,
+ RefEqualArea8,
+ RefEqualArea16,
+ RefEqualArea32,
+ RefVignetteMask16,
+ RefVignette16,
+ RefVignette32,
+ RefMapArea16
+ };
+
+/*****************************************************************************/
diff --git a/source/dng_bottlenecks.h b/source/dng_bottlenecks.h
index ff8cbb0..ea72928 100644
--- a/source/dng_bottlenecks.h
+++ b/source/dng_bottlenecks.h
@@ -1,1715 +1,1715 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_bottlenecks.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Indirection mechanism for performance-critical routines that might be replaced
- * with hand-optimized or hardware-specific implementations.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_bottlenecks__
-#define __dng_bottlenecks__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-typedef void (ZeroBytesProc)
- (void *dPtr,
- uint32 count);
-
-typedef void (CopyBytesProc)
- (const void *sPtr,
- void *dPtr,
- uint32 count);
-
-/*****************************************************************************/
-
-typedef void (SwapBytes16Proc)
- (uint16 *dPtr,
- uint32 count);
-
-typedef void (SwapBytes32Proc)
- (uint32 *dPtr,
- uint32 count);
-
-/*****************************************************************************/
-
-typedef void (SetArea8Proc)
- (uint8 *dPtr,
- uint8 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep);
-
-typedef void (SetArea16Proc)
- (uint16 *dPtr,
- uint16 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep);
-
-typedef void (SetArea32Proc)
- (uint32 *dPtr,
- uint32 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep);
-
-/*****************************************************************************/
-
-typedef void (CopyArea8Proc)
- (const uint8 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef void (CopyArea16Proc)
- (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef void (CopyArea32Proc)
- (const uint32 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef void (CopyArea8_16Proc)
- (const uint8 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef void (CopyArea8_S16Proc)
- (const uint8 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef void (CopyArea8_32Proc)
- (const uint8 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef void (CopyArea16_S16Proc)
- (const uint16 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef void (CopyArea16_32Proc)
- (const uint16 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef void (CopyArea8_R32Proc)
- (const uint8 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-typedef void (CopyArea16_R32Proc)
- (const uint16 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-typedef void (CopyAreaS16_R32Proc)
- (const int16 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-typedef void (CopyAreaR32_8Proc)
- (const real32 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-typedef void (CopyAreaR32_16Proc)
- (const real32 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-typedef void (CopyAreaR32_S16Proc)
- (const real32 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-/*****************************************************************************/
-
-typedef void (RepeatArea8Proc)
- (const uint8 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH);
-
-typedef void (RepeatArea16Proc)
- (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH);
-
-typedef void (RepeatArea32Proc)
- (const uint32 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH);
-
-/*****************************************************************************/
-
-typedef void (ShiftRight16Proc)
- (uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 shift);
-
-/*****************************************************************************/
-
-typedef void (BilinearRow16Proc)
- (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 cols,
- uint32 patPhase,
- uint32 patCount,
- const uint32 * kernCounts,
- const int32 * const * kernOffsets,
- const uint16 * const * kernWeights,
- uint32 sShift);
-
-typedef void (BilinearRow32Proc)
- (const real32 *sPtr,
- real32 *dPtr,
- uint32 cols,
- uint32 patPhase,
- uint32 patCount,
- const uint32 * kernCounts,
- const int32 * const * kernOffsets,
- const real32 * const * kernWeights,
- uint32 sShift);
-
-/*****************************************************************************/
-
-typedef void (BaselineABCtoRGBProc)
- (const real32 *sPtrA,
- const real32 *sPtrB,
- const real32 *sPtrC,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_vector &cameraWhite,
- const dng_matrix &cameraToRGB);
-
-typedef void (BaselineABCDtoRGBProc)
- (const real32 *sPtrA,
- const real32 *sPtrB,
- const real32 *sPtrC,
- const real32 *sPtrD,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_vector &cameraWhite,
- const dng_matrix &cameraToRGB);
-
-/*****************************************************************************/
-
-typedef void (BaselineHueSatMapProc)
- (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_hue_sat_map &lut,
- const dng_1d_table *encodeTable,
- const dng_1d_table *decodeTable);
-
-/*****************************************************************************/
-
-typedef void (BaselineGrayToRGBProc)
- (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrG,
- uint32 count,
- const dng_matrix &matrix);
-
-typedef void (BaselineRGBtoRGBProc)
- (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_matrix &matrix);
-
-/*****************************************************************************/
-
-typedef void (Baseline1DTableProc)
- (const real32 *sPtr,
- real32 *dPtr,
- uint32 count,
- const dng_1d_table &table);
-
-/*****************************************************************************/
-
-typedef void (BaselineRGBToneProc)
- (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_1d_table &table);
-
-/*****************************************************************************/
-
-typedef void (ResampleDown16Proc)
- (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 sCount,
- int32 sRowStep,
- const int16 *wPtr,
- uint32 wCount,
- uint32 pixelRange);
-
-typedef void (ResampleDown32Proc)
- (const real32 *sPtr,
- real32 *dPtr,
- uint32 sCount,
- int32 sRowStep,
- const real32 *wPtr,
- uint32 wCount);
-
-/*****************************************************************************/
-
-typedef void (ResampleAcross16Proc)
- (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 dCount,
- const int32 *coord,
- const int16 *wPtr,
- uint32 wCount,
- uint32 wStep,
- uint32 pixelRange);
-
-typedef void (ResampleAcross32Proc)
- (const real32 *sPtr,
- real32 *dPtr,
- uint32 dCount,
- const int32 *coord,
- const real32 *wPtr,
- uint32 wCount,
- uint32 wStep);
-
-/*****************************************************************************/
-
-typedef bool (EqualBytesProc)
- (const void *sPtr,
- const void *dPtr,
- uint32 count);
-
-typedef bool (EqualArea8Proc)
- (const uint8 *sPtr,
- const uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef bool (EqualArea16Proc)
- (const uint16 *sPtr,
- const uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-typedef bool (EqualArea32Proc)
- (const uint32 *sPtr,
- const uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-/*****************************************************************************/
-
-typedef void (VignetteMask16Proc)
- (uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- int32 rowStep,
- int64 offsetH,
- int64 offsetV,
- int64 stepH,
- int64 stepV,
- uint32 tBits,
- const uint16 *table);
-
-typedef void (Vignette16Proc)
- (int16 *sPtr,
- const uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sPlaneStep,
- int32 mRowStep,
- uint32 mBits);
-
-/*****************************************************************************/
-
-typedef void (Vignette32Proc)
- (real32 *sPtr,
- const uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sPlaneStep,
- int32 mRowStep,
- uint32 mBits);
-
-/*****************************************************************************/
-
-typedef void (MapArea16Proc)
- (uint16 *dPtr,
- uint32 count0,
- uint32 count1,
- uint32 count2,
- int32 step0,
- int32 step1,
- int32 step2,
- const uint16 *map);
-
-/*****************************************************************************/
-
-struct dng_suite
- {
- ZeroBytesProc *ZeroBytes;
- CopyBytesProc *CopyBytes;
- SwapBytes16Proc *SwapBytes16;
- SwapBytes32Proc *SwapBytes32;
- SetArea8Proc *SetArea8;
- SetArea16Proc *SetArea16;
- SetArea32Proc *SetArea32;
- CopyArea8Proc *CopyArea8;
- CopyArea16Proc *CopyArea16;
- CopyArea32Proc *CopyArea32;
- CopyArea8_16Proc *CopyArea8_16;
- CopyArea8_S16Proc *CopyArea8_S16;
- CopyArea8_32Proc *CopyArea8_32;
- CopyArea16_S16Proc *CopyArea16_S16;
- CopyArea16_32Proc *CopyArea16_32;
- CopyArea8_R32Proc *CopyArea8_R32;
- CopyArea16_R32Proc *CopyArea16_R32;
- CopyAreaS16_R32Proc *CopyAreaS16_R32;
- CopyAreaR32_8Proc *CopyAreaR32_8;
- CopyAreaR32_16Proc *CopyAreaR32_16;
- CopyAreaR32_S16Proc *CopyAreaR32_S16;
- RepeatArea8Proc *RepeatArea8;
- RepeatArea16Proc *RepeatArea16;
- RepeatArea32Proc *RepeatArea32;
- ShiftRight16Proc *ShiftRight16;
- BilinearRow16Proc *BilinearRow16;
- BilinearRow32Proc *BilinearRow32;
- BaselineABCtoRGBProc *BaselineABCtoRGB;
- BaselineABCDtoRGBProc *BaselineABCDtoRGB;
- BaselineHueSatMapProc *BaselineHueSatMap;
- BaselineGrayToRGBProc *BaselineRGBtoGray;
- BaselineRGBtoRGBProc *BaselineRGBtoRGB;
- Baseline1DTableProc *Baseline1DTable;
- BaselineRGBToneProc *BaselineRGBTone;
- ResampleDown16Proc *ResampleDown16;
- ResampleDown32Proc *ResampleDown32;
- ResampleAcross16Proc *ResampleAcross16;
- ResampleAcross32Proc *ResampleAcross32;
- EqualBytesProc *EqualBytes;
- EqualArea8Proc *EqualArea8;
- EqualArea16Proc *EqualArea16;
- EqualArea32Proc *EqualArea32;
- VignetteMask16Proc *VignetteMask16;
- Vignette16Proc *Vignette16;
- Vignette32Proc *Vignette32;
- MapArea16Proc *MapArea16;
- };
-
-/*****************************************************************************/
-
-extern dng_suite gDNGSuite;
-
-/*****************************************************************************/
-
-inline void DoZeroBytes (void *dPtr,
- uint32 count)
- {
-
- (gDNGSuite.ZeroBytes) (dPtr,
- count);
-
- }
-
-inline void DoCopyBytes (const void *sPtr,
- void *dPtr,
- uint32 count)
- {
-
- (gDNGSuite.CopyBytes) (sPtr,
- dPtr,
- count);
-
- }
-
-/*****************************************************************************/
-
-inline void DoSwapBytes16 (uint16 *dPtr,
- uint32 count)
- {
-
- (gDNGSuite.SwapBytes16) (dPtr,
- count);
-
- }
-
-inline void DoSwapBytes32 (uint32 *dPtr,
- uint32 count)
- {
-
- (gDNGSuite.SwapBytes32) (dPtr,
- count);
-
- }
-
-/*****************************************************************************/
-
-inline void DoSetArea8 (uint8 *dPtr,
- uint8 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep)
- {
-
- (gDNGSuite.SetArea8) (dPtr,
- value,
- rows,
- cols,
- planes,
- rowStep,
- colStep,
- planeStep);
-
- }
-
-inline void DoSetArea16 (uint16 *dPtr,
- uint16 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep)
- {
-
- (gDNGSuite.SetArea16) (dPtr,
- value,
- rows,
- cols,
- planes,
- rowStep,
- colStep,
- planeStep);
-
- }
-
-inline void DoSetArea32 (uint32 *dPtr,
- uint32 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep)
- {
-
- (gDNGSuite.SetArea32) (dPtr,
- value,
- rows,
- cols,
- planes,
- rowStep,
- colStep,
- planeStep);
-
- }
-
-/*****************************************************************************/
-
-inline void DoCopyArea8 (const uint8 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- (gDNGSuite.CopyArea8) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline void DoCopyArea16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- (gDNGSuite.CopyArea16) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline void DoCopyArea32 (const uint32 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- (gDNGSuite.CopyArea32) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline void DoCopyArea8_16 (const uint8 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- (gDNGSuite.CopyArea8_16) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline void DoCopyArea8_S16 (const uint8 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- (gDNGSuite.CopyArea8_S16) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline void DoCopyArea8_32 (const uint8 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- (gDNGSuite.CopyArea8_32) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline void DoCopyArea16_S16 (const uint16 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- (gDNGSuite.CopyArea16_S16) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline void DoCopyArea16_32 (const uint16 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- (gDNGSuite.CopyArea16_32) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline void DoCopyArea8_R32 (const uint8 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- (gDNGSuite.CopyArea8_R32) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep,
- pixelRange);
-
- }
-
-inline void DoCopyArea16_R32 (const uint16 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- (gDNGSuite.CopyArea16_R32) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep,
- pixelRange);
-
- }
-
-inline void DoCopyAreaS16_R32 (const int16 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- (gDNGSuite.CopyAreaS16_R32) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep,
- pixelRange);
-
- }
-
-inline void DoCopyAreaR32_8 (const real32 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- (gDNGSuite.CopyAreaR32_8) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep,
- pixelRange);
-
- }
-
-inline void DoCopyAreaR32_16 (const real32 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- (gDNGSuite.CopyAreaR32_16) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep,
- pixelRange);
-
- }
-
-inline void DoCopyAreaR32_S16 (const real32 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- (gDNGSuite.CopyAreaR32_S16) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep,
- pixelRange);
-
- }
-
-/*****************************************************************************/
-
-inline void DoRepeatArea8 (const uint8 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH)
- {
-
- (gDNGSuite.RepeatArea8) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- rowStep,
- colStep,
- planeStep,
- repeatV,
- repeatH,
- phaseV,
- phaseH);
-
- }
-
-inline void DoRepeatArea16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH)
- {
-
- (gDNGSuite.RepeatArea16) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- rowStep,
- colStep,
- planeStep,
- repeatV,
- repeatH,
- phaseV,
- phaseH);
-
- }
-
-inline void DoRepeatArea32 (const uint32 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH)
- {
-
- (gDNGSuite.RepeatArea32) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- rowStep,
- colStep,
- planeStep,
- repeatV,
- repeatH,
- phaseV,
- phaseH);
-
- }
-
-/*****************************************************************************/
-
-inline void DoShiftRight16 (uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 shift)
- {
-
- (gDNGSuite.ShiftRight16) (dPtr,
- rows,
- cols,
- planes,
- rowStep,
- colStep,
- planeStep,
- shift);
-
- }
-
-/*****************************************************************************/
-
-inline void DoBilinearRow16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 cols,
- uint32 patPhase,
- uint32 patCount,
- const uint32 * kernCounts,
- const int32 * const * kernOffsets,
- const uint16 * const * kernWeights,
- uint32 sShift)
- {
-
- (gDNGSuite.BilinearRow16) (sPtr,
- dPtr,
- cols,
- patPhase,
- patCount,
- kernCounts,
- kernOffsets,
- kernWeights,
- sShift);
-
- }
-
-inline void DoBilinearRow32 (const real32 *sPtr,
- real32 *dPtr,
- uint32 cols,
- uint32 patPhase,
- uint32 patCount,
- const uint32 * kernCounts,
- const int32 * const * kernOffsets,
- const real32 * const * kernWeights,
- uint32 sShift)
- {
-
- (gDNGSuite.BilinearRow32) (sPtr,
- dPtr,
- cols,
- patPhase,
- patCount,
- kernCounts,
- kernOffsets,
- kernWeights,
- sShift);
-
- }
-
-/*****************************************************************************/
-
-inline void DoBaselineABCtoRGB (const real32 *sPtrA,
- const real32 *sPtrB,
- const real32 *sPtrC,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_vector &cameraWhite,
- const dng_matrix &cameraToRGB)
- {
-
- (gDNGSuite.BaselineABCtoRGB) (sPtrA,
- sPtrB,
- sPtrC,
- dPtrR,
- dPtrG,
- dPtrB,
- count,
- cameraWhite,
- cameraToRGB);
-
- }
-
-inline void DoBaselineABCDtoRGB (const real32 *sPtrA,
- const real32 *sPtrB,
- const real32 *sPtrC,
- const real32 *sPtrD,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_vector &cameraWhite,
- const dng_matrix &cameraToRGB)
- {
-
- (gDNGSuite.BaselineABCDtoRGB) (sPtrA,
- sPtrB,
- sPtrC,
- sPtrD,
- dPtrR,
- dPtrG,
- dPtrB,
- count,
- cameraWhite,
- cameraToRGB);
-
- }
-
-/*****************************************************************************/
-
-inline void DoBaselineHueSatMap (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_hue_sat_map &lut,
- const dng_1d_table *encodeTable,
- const dng_1d_table *decodeTable)
- {
-
- (gDNGSuite.BaselineHueSatMap) (sPtrR,
- sPtrG,
- sPtrB,
- dPtrR,
- dPtrG,
- dPtrB,
- count,
- lut,
- encodeTable,
- decodeTable);
-
- }
-
-/*****************************************************************************/
-
-inline void DoBaselineRGBtoGray (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrG,
- uint32 count,
- const dng_matrix &matrix)
- {
-
- (gDNGSuite.BaselineRGBtoGray) (sPtrR,
- sPtrG,
- sPtrB,
- dPtrG,
- count,
- matrix);
-
- }
-
-inline void DoBaselineRGBtoRGB (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_matrix &matrix)
- {
-
- (gDNGSuite.BaselineRGBtoRGB) (sPtrR,
- sPtrG,
- sPtrB,
- dPtrR,
- dPtrG,
- dPtrB,
- count,
- matrix);
-
- }
-
-/*****************************************************************************/
-
-inline void DoBaseline1DTable (const real32 *sPtr,
- real32 *dPtr,
- uint32 count,
- const dng_1d_table &table)
- {
-
- (gDNGSuite.Baseline1DTable) (sPtr,
- dPtr,
- count,
- table);
-
- }
-
-/*****************************************************************************/
-
-inline void DoBaselineRGBTone (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_1d_table &table)
- {
-
- (gDNGSuite.BaselineRGBTone) (sPtrR,
- sPtrG,
- sPtrB,
- dPtrR,
- dPtrG,
- dPtrB,
- count,
- table);
-
- }
-
-/*****************************************************************************/
-
-inline void DoResampleDown16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 sCount,
- int32 sRowStep,
- const int16 *wPtr,
- uint32 wCount,
- uint32 pixelRange)
- {
-
- (gDNGSuite.ResampleDown16) (sPtr,
- dPtr,
- sCount,
- sRowStep,
- wPtr,
- wCount,
- pixelRange);
-
- }
-
-inline void DoResampleDown32 (const real32 *sPtr,
- real32 *dPtr,
- uint32 sCount,
- int32 sRowStep,
- const real32 *wPtr,
- uint32 wCount)
- {
-
- (gDNGSuite.ResampleDown32) (sPtr,
- dPtr,
- sCount,
- sRowStep,
- wPtr,
- wCount);
-
- }
-
-/*****************************************************************************/
-
-inline void DoResampleAcross16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 dCount,
- const int32 *coord,
- const int16 *wPtr,
- uint32 wCount,
- uint32 wStep,
- uint32 pixelRange)
- {
-
- (gDNGSuite.ResampleAcross16) (sPtr,
- dPtr,
- dCount,
- coord,
- wPtr,
- wCount,
- wStep,
- pixelRange);
-
- }
-
-inline void DoResampleAcross32 (const real32 *sPtr,
- real32 *dPtr,
- uint32 dCount,
- const int32 *coord,
- const real32 *wPtr,
- uint32 wCount,
- uint32 wStep)
- {
-
- (gDNGSuite.ResampleAcross32) (sPtr,
- dPtr,
- dCount,
- coord,
- wPtr,
- wCount,
- wStep);
-
- }
-
-/*****************************************************************************/
-
-inline bool DoEqualBytes (const void *sPtr,
- const void *dPtr,
- uint32 count)
- {
-
- return (gDNGSuite.EqualBytes) (sPtr,
- dPtr,
- count);
-
- }
-
-inline bool DoEqualArea8 (const uint8 *sPtr,
- const uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- return (gDNGSuite.EqualArea8) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline bool DoEqualArea16 (const uint16 *sPtr,
- const uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- return (gDNGSuite.EqualArea16) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-inline bool DoEqualArea32 (const uint32 *sPtr,
- const uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- return (gDNGSuite.EqualArea32) (sPtr,
- dPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sColStep,
- sPlaneStep,
- dRowStep,
- dColStep,
- dPlaneStep);
-
- }
-
-/*****************************************************************************/
-
-inline void DoVignetteMask16 (uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- int32 rowStep,
- int64 offsetH,
- int64 offsetV,
- int64 stepH,
- int64 stepV,
- uint32 tBits,
- const uint16 *table)
- {
-
- (gDNGSuite.VignetteMask16) (mPtr,
- rows,
- cols,
- rowStep,
- offsetH,
- offsetV,
- stepH,
- stepV,
- tBits,
- table);
-
- }
-
-/*****************************************************************************/
-
-inline void DoVignette16 (int16 *sPtr,
- const uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sPlaneStep,
- int32 mRowStep,
- uint32 mBits)
- {
-
- (gDNGSuite.Vignette16) (sPtr,
- mPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sPlaneStep,
- mRowStep,
- mBits);
-
- }
-
-/*****************************************************************************/
-
-inline void DoVignette32 (real32 *sPtr,
- const uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sPlaneStep,
- int32 mRowStep,
- uint32 mBits)
- {
-
- (gDNGSuite.Vignette32) (sPtr,
- mPtr,
- rows,
- cols,
- planes,
- sRowStep,
- sPlaneStep,
- mRowStep,
- mBits);
-
- }
-
-/*****************************************************************************/
-
-inline void DoMapArea16 (uint16 *dPtr,
- uint32 count0,
- uint32 count1,
- uint32 count2,
- int32 step0,
- int32 step1,
- int32 step2,
- const uint16 *map)
- {
-
- (gDNGSuite.MapArea16) (dPtr,
- count0,
- count1,
- count2,
- step0,
- step1,
- step2,
- map);
-
- }
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_bottlenecks.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Indirection mechanism for performance-critical routines that might be replaced
+ * with hand-optimized or hardware-specific implementations.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_bottlenecks__
+#define __dng_bottlenecks__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+typedef void (ZeroBytesProc)
+ (void *dPtr,
+ uint32 count);
+
+typedef void (CopyBytesProc)
+ (const void *sPtr,
+ void *dPtr,
+ uint32 count);
+
+/*****************************************************************************/
+
+typedef void (SwapBytes16Proc)
+ (uint16 *dPtr,
+ uint32 count);
+
+typedef void (SwapBytes32Proc)
+ (uint32 *dPtr,
+ uint32 count);
+
+/*****************************************************************************/
+
+typedef void (SetArea8Proc)
+ (uint8 *dPtr,
+ uint8 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep);
+
+typedef void (SetArea16Proc)
+ (uint16 *dPtr,
+ uint16 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep);
+
+typedef void (SetArea32Proc)
+ (uint32 *dPtr,
+ uint32 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep);
+
+/*****************************************************************************/
+
+typedef void (CopyArea8Proc)
+ (const uint8 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef void (CopyArea16Proc)
+ (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef void (CopyArea32Proc)
+ (const uint32 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef void (CopyArea8_16Proc)
+ (const uint8 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef void (CopyArea8_S16Proc)
+ (const uint8 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef void (CopyArea8_32Proc)
+ (const uint8 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef void (CopyArea16_S16Proc)
+ (const uint16 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef void (CopyArea16_32Proc)
+ (const uint16 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef void (CopyArea8_R32Proc)
+ (const uint8 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+typedef void (CopyArea16_R32Proc)
+ (const uint16 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+typedef void (CopyAreaS16_R32Proc)
+ (const int16 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+typedef void (CopyAreaR32_8Proc)
+ (const real32 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+typedef void (CopyAreaR32_16Proc)
+ (const real32 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+typedef void (CopyAreaR32_S16Proc)
+ (const real32 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+/*****************************************************************************/
+
+typedef void (RepeatArea8Proc)
+ (const uint8 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH);
+
+typedef void (RepeatArea16Proc)
+ (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH);
+
+typedef void (RepeatArea32Proc)
+ (const uint32 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH);
+
+/*****************************************************************************/
+
+typedef void (ShiftRight16Proc)
+ (uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 shift);
+
+/*****************************************************************************/
+
+typedef void (BilinearRow16Proc)
+ (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 cols,
+ uint32 patPhase,
+ uint32 patCount,
+ const uint32 * kernCounts,
+ const int32 * const * kernOffsets,
+ const uint16 * const * kernWeights,
+ uint32 sShift);
+
+typedef void (BilinearRow32Proc)
+ (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 cols,
+ uint32 patPhase,
+ uint32 patCount,
+ const uint32 * kernCounts,
+ const int32 * const * kernOffsets,
+ const real32 * const * kernWeights,
+ uint32 sShift);
+
+/*****************************************************************************/
+
+typedef void (BaselineABCtoRGBProc)
+ (const real32 *sPtrA,
+ const real32 *sPtrB,
+ const real32 *sPtrC,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_vector &cameraWhite,
+ const dng_matrix &cameraToRGB);
+
+typedef void (BaselineABCDtoRGBProc)
+ (const real32 *sPtrA,
+ const real32 *sPtrB,
+ const real32 *sPtrC,
+ const real32 *sPtrD,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_vector &cameraWhite,
+ const dng_matrix &cameraToRGB);
+
+/*****************************************************************************/
+
+typedef void (BaselineHueSatMapProc)
+ (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_hue_sat_map &lut,
+ const dng_1d_table *encodeTable,
+ const dng_1d_table *decodeTable);
+
+/*****************************************************************************/
+
+typedef void (BaselineGrayToRGBProc)
+ (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrG,
+ uint32 count,
+ const dng_matrix &matrix);
+
+typedef void (BaselineRGBtoRGBProc)
+ (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_matrix &matrix);
+
+/*****************************************************************************/
+
+typedef void (Baseline1DTableProc)
+ (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 count,
+ const dng_1d_table &table);
+
+/*****************************************************************************/
+
+typedef void (BaselineRGBToneProc)
+ (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_1d_table &table);
+
+/*****************************************************************************/
+
+typedef void (ResampleDown16Proc)
+ (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 sCount,
+ int32 sRowStep,
+ const int16 *wPtr,
+ uint32 wCount,
+ uint32 pixelRange);
+
+typedef void (ResampleDown32Proc)
+ (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 sCount,
+ int32 sRowStep,
+ const real32 *wPtr,
+ uint32 wCount);
+
+/*****************************************************************************/
+
+typedef void (ResampleAcross16Proc)
+ (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 dCount,
+ const int32 *coord,
+ const int16 *wPtr,
+ uint32 wCount,
+ uint32 wStep,
+ uint32 pixelRange);
+
+typedef void (ResampleAcross32Proc)
+ (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 dCount,
+ const int32 *coord,
+ const real32 *wPtr,
+ uint32 wCount,
+ uint32 wStep);
+
+/*****************************************************************************/
+
+typedef bool (EqualBytesProc)
+ (const void *sPtr,
+ const void *dPtr,
+ uint32 count);
+
+typedef bool (EqualArea8Proc)
+ (const uint8 *sPtr,
+ const uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef bool (EqualArea16Proc)
+ (const uint16 *sPtr,
+ const uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+typedef bool (EqualArea32Proc)
+ (const uint32 *sPtr,
+ const uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+/*****************************************************************************/
+
+typedef void (VignetteMask16Proc)
+ (uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ int32 rowStep,
+ int64 offsetH,
+ int64 offsetV,
+ int64 stepH,
+ int64 stepV,
+ uint32 tBits,
+ const uint16 *table);
+
+typedef void (Vignette16Proc)
+ (int16 *sPtr,
+ const uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sPlaneStep,
+ int32 mRowStep,
+ uint32 mBits);
+
+/*****************************************************************************/
+
+typedef void (Vignette32Proc)
+ (real32 *sPtr,
+ const uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sPlaneStep,
+ int32 mRowStep,
+ uint32 mBits);
+
+/*****************************************************************************/
+
+typedef void (MapArea16Proc)
+ (uint16 *dPtr,
+ uint32 count0,
+ uint32 count1,
+ uint32 count2,
+ int32 step0,
+ int32 step1,
+ int32 step2,
+ const uint16 *map);
+
+/*****************************************************************************/
+
+struct dng_suite
+ {
+ ZeroBytesProc *ZeroBytes;
+ CopyBytesProc *CopyBytes;
+ SwapBytes16Proc *SwapBytes16;
+ SwapBytes32Proc *SwapBytes32;
+ SetArea8Proc *SetArea8;
+ SetArea16Proc *SetArea16;
+ SetArea32Proc *SetArea32;
+ CopyArea8Proc *CopyArea8;
+ CopyArea16Proc *CopyArea16;
+ CopyArea32Proc *CopyArea32;
+ CopyArea8_16Proc *CopyArea8_16;
+ CopyArea8_S16Proc *CopyArea8_S16;
+ CopyArea8_32Proc *CopyArea8_32;
+ CopyArea16_S16Proc *CopyArea16_S16;
+ CopyArea16_32Proc *CopyArea16_32;
+ CopyArea8_R32Proc *CopyArea8_R32;
+ CopyArea16_R32Proc *CopyArea16_R32;
+ CopyAreaS16_R32Proc *CopyAreaS16_R32;
+ CopyAreaR32_8Proc *CopyAreaR32_8;
+ CopyAreaR32_16Proc *CopyAreaR32_16;
+ CopyAreaR32_S16Proc *CopyAreaR32_S16;
+ RepeatArea8Proc *RepeatArea8;
+ RepeatArea16Proc *RepeatArea16;
+ RepeatArea32Proc *RepeatArea32;
+ ShiftRight16Proc *ShiftRight16;
+ BilinearRow16Proc *BilinearRow16;
+ BilinearRow32Proc *BilinearRow32;
+ BaselineABCtoRGBProc *BaselineABCtoRGB;
+ BaselineABCDtoRGBProc *BaselineABCDtoRGB;
+ BaselineHueSatMapProc *BaselineHueSatMap;
+ BaselineGrayToRGBProc *BaselineRGBtoGray;
+ BaselineRGBtoRGBProc *BaselineRGBtoRGB;
+ Baseline1DTableProc *Baseline1DTable;
+ BaselineRGBToneProc *BaselineRGBTone;
+ ResampleDown16Proc *ResampleDown16;
+ ResampleDown32Proc *ResampleDown32;
+ ResampleAcross16Proc *ResampleAcross16;
+ ResampleAcross32Proc *ResampleAcross32;
+ EqualBytesProc *EqualBytes;
+ EqualArea8Proc *EqualArea8;
+ EqualArea16Proc *EqualArea16;
+ EqualArea32Proc *EqualArea32;
+ VignetteMask16Proc *VignetteMask16;
+ Vignette16Proc *Vignette16;
+ Vignette32Proc *Vignette32;
+ MapArea16Proc *MapArea16;
+ };
+
+/*****************************************************************************/
+
+extern dng_suite gDNGSuite;
+
+/*****************************************************************************/
+
+inline void DoZeroBytes (void *dPtr,
+ uint32 count)
+ {
+
+ (gDNGSuite.ZeroBytes) (dPtr,
+ count);
+
+ }
+
+inline void DoCopyBytes (const void *sPtr,
+ void *dPtr,
+ uint32 count)
+ {
+
+ (gDNGSuite.CopyBytes) (sPtr,
+ dPtr,
+ count);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoSwapBytes16 (uint16 *dPtr,
+ uint32 count)
+ {
+
+ (gDNGSuite.SwapBytes16) (dPtr,
+ count);
+
+ }
+
+inline void DoSwapBytes32 (uint32 *dPtr,
+ uint32 count)
+ {
+
+ (gDNGSuite.SwapBytes32) (dPtr,
+ count);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoSetArea8 (uint8 *dPtr,
+ uint8 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep)
+ {
+
+ (gDNGSuite.SetArea8) (dPtr,
+ value,
+ rows,
+ cols,
+ planes,
+ rowStep,
+ colStep,
+ planeStep);
+
+ }
+
+inline void DoSetArea16 (uint16 *dPtr,
+ uint16 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep)
+ {
+
+ (gDNGSuite.SetArea16) (dPtr,
+ value,
+ rows,
+ cols,
+ planes,
+ rowStep,
+ colStep,
+ planeStep);
+
+ }
+
+inline void DoSetArea32 (uint32 *dPtr,
+ uint32 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep)
+ {
+
+ (gDNGSuite.SetArea32) (dPtr,
+ value,
+ rows,
+ cols,
+ planes,
+ rowStep,
+ colStep,
+ planeStep);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoCopyArea8 (const uint8 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ (gDNGSuite.CopyArea8) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline void DoCopyArea16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ (gDNGSuite.CopyArea16) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline void DoCopyArea32 (const uint32 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ (gDNGSuite.CopyArea32) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline void DoCopyArea8_16 (const uint8 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ (gDNGSuite.CopyArea8_16) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline void DoCopyArea8_S16 (const uint8 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ (gDNGSuite.CopyArea8_S16) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline void DoCopyArea8_32 (const uint8 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ (gDNGSuite.CopyArea8_32) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline void DoCopyArea16_S16 (const uint16 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ (gDNGSuite.CopyArea16_S16) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline void DoCopyArea16_32 (const uint16 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ (gDNGSuite.CopyArea16_32) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline void DoCopyArea8_R32 (const uint8 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ (gDNGSuite.CopyArea8_R32) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep,
+ pixelRange);
+
+ }
+
+inline void DoCopyArea16_R32 (const uint16 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ (gDNGSuite.CopyArea16_R32) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep,
+ pixelRange);
+
+ }
+
+inline void DoCopyAreaS16_R32 (const int16 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ (gDNGSuite.CopyAreaS16_R32) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep,
+ pixelRange);
+
+ }
+
+inline void DoCopyAreaR32_8 (const real32 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ (gDNGSuite.CopyAreaR32_8) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep,
+ pixelRange);
+
+ }
+
+inline void DoCopyAreaR32_16 (const real32 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ (gDNGSuite.CopyAreaR32_16) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep,
+ pixelRange);
+
+ }
+
+inline void DoCopyAreaR32_S16 (const real32 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ (gDNGSuite.CopyAreaR32_S16) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep,
+ pixelRange);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoRepeatArea8 (const uint8 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH)
+ {
+
+ (gDNGSuite.RepeatArea8) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ rowStep,
+ colStep,
+ planeStep,
+ repeatV,
+ repeatH,
+ phaseV,
+ phaseH);
+
+ }
+
+inline void DoRepeatArea16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH)
+ {
+
+ (gDNGSuite.RepeatArea16) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ rowStep,
+ colStep,
+ planeStep,
+ repeatV,
+ repeatH,
+ phaseV,
+ phaseH);
+
+ }
+
+inline void DoRepeatArea32 (const uint32 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH)
+ {
+
+ (gDNGSuite.RepeatArea32) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ rowStep,
+ colStep,
+ planeStep,
+ repeatV,
+ repeatH,
+ phaseV,
+ phaseH);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoShiftRight16 (uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 shift)
+ {
+
+ (gDNGSuite.ShiftRight16) (dPtr,
+ rows,
+ cols,
+ planes,
+ rowStep,
+ colStep,
+ planeStep,
+ shift);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoBilinearRow16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 cols,
+ uint32 patPhase,
+ uint32 patCount,
+ const uint32 * kernCounts,
+ const int32 * const * kernOffsets,
+ const uint16 * const * kernWeights,
+ uint32 sShift)
+ {
+
+ (gDNGSuite.BilinearRow16) (sPtr,
+ dPtr,
+ cols,
+ patPhase,
+ patCount,
+ kernCounts,
+ kernOffsets,
+ kernWeights,
+ sShift);
+
+ }
+
+inline void DoBilinearRow32 (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 cols,
+ uint32 patPhase,
+ uint32 patCount,
+ const uint32 * kernCounts,
+ const int32 * const * kernOffsets,
+ const real32 * const * kernWeights,
+ uint32 sShift)
+ {
+
+ (gDNGSuite.BilinearRow32) (sPtr,
+ dPtr,
+ cols,
+ patPhase,
+ patCount,
+ kernCounts,
+ kernOffsets,
+ kernWeights,
+ sShift);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoBaselineABCtoRGB (const real32 *sPtrA,
+ const real32 *sPtrB,
+ const real32 *sPtrC,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_vector &cameraWhite,
+ const dng_matrix &cameraToRGB)
+ {
+
+ (gDNGSuite.BaselineABCtoRGB) (sPtrA,
+ sPtrB,
+ sPtrC,
+ dPtrR,
+ dPtrG,
+ dPtrB,
+ count,
+ cameraWhite,
+ cameraToRGB);
+
+ }
+
+inline void DoBaselineABCDtoRGB (const real32 *sPtrA,
+ const real32 *sPtrB,
+ const real32 *sPtrC,
+ const real32 *sPtrD,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_vector &cameraWhite,
+ const dng_matrix &cameraToRGB)
+ {
+
+ (gDNGSuite.BaselineABCDtoRGB) (sPtrA,
+ sPtrB,
+ sPtrC,
+ sPtrD,
+ dPtrR,
+ dPtrG,
+ dPtrB,
+ count,
+ cameraWhite,
+ cameraToRGB);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoBaselineHueSatMap (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_hue_sat_map &lut,
+ const dng_1d_table *encodeTable,
+ const dng_1d_table *decodeTable)
+ {
+
+ (gDNGSuite.BaselineHueSatMap) (sPtrR,
+ sPtrG,
+ sPtrB,
+ dPtrR,
+ dPtrG,
+ dPtrB,
+ count,
+ lut,
+ encodeTable,
+ decodeTable);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoBaselineRGBtoGray (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrG,
+ uint32 count,
+ const dng_matrix &matrix)
+ {
+
+ (gDNGSuite.BaselineRGBtoGray) (sPtrR,
+ sPtrG,
+ sPtrB,
+ dPtrG,
+ count,
+ matrix);
+
+ }
+
+inline void DoBaselineRGBtoRGB (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_matrix &matrix)
+ {
+
+ (gDNGSuite.BaselineRGBtoRGB) (sPtrR,
+ sPtrG,
+ sPtrB,
+ dPtrR,
+ dPtrG,
+ dPtrB,
+ count,
+ matrix);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoBaseline1DTable (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 count,
+ const dng_1d_table &table)
+ {
+
+ (gDNGSuite.Baseline1DTable) (sPtr,
+ dPtr,
+ count,
+ table);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoBaselineRGBTone (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_1d_table &table)
+ {
+
+ (gDNGSuite.BaselineRGBTone) (sPtrR,
+ sPtrG,
+ sPtrB,
+ dPtrR,
+ dPtrG,
+ dPtrB,
+ count,
+ table);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoResampleDown16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 sCount,
+ int32 sRowStep,
+ const int16 *wPtr,
+ uint32 wCount,
+ uint32 pixelRange)
+ {
+
+ (gDNGSuite.ResampleDown16) (sPtr,
+ dPtr,
+ sCount,
+ sRowStep,
+ wPtr,
+ wCount,
+ pixelRange);
+
+ }
+
+inline void DoResampleDown32 (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 sCount,
+ int32 sRowStep,
+ const real32 *wPtr,
+ uint32 wCount)
+ {
+
+ (gDNGSuite.ResampleDown32) (sPtr,
+ dPtr,
+ sCount,
+ sRowStep,
+ wPtr,
+ wCount);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoResampleAcross16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 dCount,
+ const int32 *coord,
+ const int16 *wPtr,
+ uint32 wCount,
+ uint32 wStep,
+ uint32 pixelRange)
+ {
+
+ (gDNGSuite.ResampleAcross16) (sPtr,
+ dPtr,
+ dCount,
+ coord,
+ wPtr,
+ wCount,
+ wStep,
+ pixelRange);
+
+ }
+
+inline void DoResampleAcross32 (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 dCount,
+ const int32 *coord,
+ const real32 *wPtr,
+ uint32 wCount,
+ uint32 wStep)
+ {
+
+ (gDNGSuite.ResampleAcross32) (sPtr,
+ dPtr,
+ dCount,
+ coord,
+ wPtr,
+ wCount,
+ wStep);
+
+ }
+
+/*****************************************************************************/
+
+inline bool DoEqualBytes (const void *sPtr,
+ const void *dPtr,
+ uint32 count)
+ {
+
+ return (gDNGSuite.EqualBytes) (sPtr,
+ dPtr,
+ count);
+
+ }
+
+inline bool DoEqualArea8 (const uint8 *sPtr,
+ const uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ return (gDNGSuite.EqualArea8) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline bool DoEqualArea16 (const uint16 *sPtr,
+ const uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ return (gDNGSuite.EqualArea16) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+inline bool DoEqualArea32 (const uint32 *sPtr,
+ const uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ return (gDNGSuite.EqualArea32) (sPtr,
+ dPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sColStep,
+ sPlaneStep,
+ dRowStep,
+ dColStep,
+ dPlaneStep);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoVignetteMask16 (uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ int32 rowStep,
+ int64 offsetH,
+ int64 offsetV,
+ int64 stepH,
+ int64 stepV,
+ uint32 tBits,
+ const uint16 *table)
+ {
+
+ (gDNGSuite.VignetteMask16) (mPtr,
+ rows,
+ cols,
+ rowStep,
+ offsetH,
+ offsetV,
+ stepH,
+ stepV,
+ tBits,
+ table);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoVignette16 (int16 *sPtr,
+ const uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sPlaneStep,
+ int32 mRowStep,
+ uint32 mBits)
+ {
+
+ (gDNGSuite.Vignette16) (sPtr,
+ mPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sPlaneStep,
+ mRowStep,
+ mBits);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoVignette32 (real32 *sPtr,
+ const uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sPlaneStep,
+ int32 mRowStep,
+ uint32 mBits)
+ {
+
+ (gDNGSuite.Vignette32) (sPtr,
+ mPtr,
+ rows,
+ cols,
+ planes,
+ sRowStep,
+ sPlaneStep,
+ mRowStep,
+ mBits);
+
+ }
+
+/*****************************************************************************/
+
+inline void DoMapArea16 (uint16 *dPtr,
+ uint32 count0,
+ uint32 count1,
+ uint32 count2,
+ int32 step0,
+ int32 step1,
+ int32 step2,
+ const uint16 *map)
+ {
+
+ (gDNGSuite.MapArea16) (dPtr,
+ count0,
+ count1,
+ count2,
+ step0,
+ step1,
+ step2,
+ map);
+
+ }
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_camera_profile.cpp b/source/dng_camera_profile.cpp
index f14b812..06f423b 100644
--- a/source/dng_camera_profile.cpp
+++ b/source/dng_camera_profile.cpp
@@ -1,1386 +1,1386 @@
-/*****************************************************************************/
-// Copyright 2006-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_camera_profile.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-#include "dng_camera_profile.h"
-
-#include "dng_1d_table.h"
-#include "dng_assertions.h"
-#include "dng_color_space.h"
-#include "dng_host.h"
-#include "dng_exceptions.h"
-#include "dng_image_writer.h"
-#include "dng_info.h"
-#include "dng_parse_utils.h"
-#include "dng_tag_codes.h"
-#include "dng_tag_types.h"
-#include "dng_temperature.h"
-#include "dng_xy_coord.h"
-
-/*****************************************************************************/
-
-const char * kProfileName_Embedded = "Embedded";
-
-const char * kAdobeCalibrationSignature = "com.adobe";
-
-/*****************************************************************************/
-
-dng_camera_profile::dng_camera_profile ()
-
- : fName ()
- , fCalibrationIlluminant1 (lsUnknown)
- , fCalibrationIlluminant2 (lsUnknown)
- , fColorMatrix1 ()
- , fColorMatrix2 ()
- , fForwardMatrix1 ()
- , fForwardMatrix2 ()
- , fReductionMatrix1 ()
- , fReductionMatrix2 ()
- , fFingerprint ()
- , fCopyright ()
- , fEmbedPolicy (pepAllowCopying)
- , fHueSatDeltas1 ()
- , fHueSatDeltas2 ()
- , fHueSatMapEncoding (encoding_Linear)
- , fLookTable ()
- , fLookTableEncoding (encoding_Linear)
- , fBaselineExposureOffset (0, 100)
- , fDefaultBlackRender (defaultBlackRender_Auto)
- , fToneCurve ()
- , fProfileCalibrationSignature ()
- , fUniqueCameraModelRestriction ()
- , fWasReadFromDNG (false)
- , fWasReadFromDisk (false)
- , fWasBuiltinMatrix (false)
- , fWasStubbed (false)
-
- {
-
- fToneCurve.SetInvalid ();
-
- }
-
-/*****************************************************************************/
-
-dng_camera_profile::~dng_camera_profile ()
- {
-
- }
-
-/*****************************************************************************/
-
-real64 dng_camera_profile::IlluminantToTemperature (uint32 light)
- {
-
- switch (light)
- {
-
- case lsStandardLightA:
- case lsTungsten:
- {
- return 2850.0;
- }
-
- case lsISOStudioTungsten:
- {
- return 3200.0;
- }
-
- case lsD50:
- {
- return 5000.0;
- }
-
- case lsD55:
- case lsDaylight:
- case lsFineWeather:
- case lsFlash:
- case lsStandardLightB:
- {
- return 5500.0;
- }
-
- case lsD65:
- case lsStandardLightC:
- case lsCloudyWeather:
- {
- return 6500.0;
- }
-
- case lsD75:
- case lsShade:
- {
- return 7500.0;
- }
-
- case lsDaylightFluorescent:
- {
- return (5700.0 + 7100.0) * 0.5;
- }
-
- case lsDayWhiteFluorescent:
- {
- return (4600.0 + 5500.0) * 0.5;
- }
-
- case lsCoolWhiteFluorescent:
- case lsFluorescent:
- {
- return (3800.0 + 4500.0) * 0.5;
- }
-
- case lsWhiteFluorescent:
- {
- return (3250.0 + 3800.0) * 0.5;
- }
-
- case lsWarmWhiteFluorescent:
- {
- return (2600.0 + 3250.0) * 0.5;
- }
-
- default:
- {
- return 0.0;
- }
-
- }
-
- }
-
-/******************************************************************************/
-
-void dng_camera_profile::NormalizeColorMatrix (dng_matrix &m)
- {
-
- if (m.NotEmpty ())
- {
-
- // Find scale factor to normalize the matrix.
-
- dng_vector coord = m * PCStoXYZ ();
-
- real64 maxCoord = coord.MaxEntry ();
-
- if (maxCoord > 0.0 && (maxCoord < 0.99 || maxCoord > 1.01))
- {
-
- m.Scale (1.0 / maxCoord);
-
- }
-
- // Round to four decimal places.
-
- m.Round (10000);
-
- }
-
- }
-
-/******************************************************************************/
-
-void dng_camera_profile::SetColorMatrix1 (const dng_matrix &m)
- {
-
- fColorMatrix1 = m;
-
- NormalizeColorMatrix (fColorMatrix1);
-
- ClearFingerprint ();
-
- }
-
-/******************************************************************************/
-
-void dng_camera_profile::SetColorMatrix2 (const dng_matrix &m)
- {
-
- fColorMatrix2 = m;
-
- NormalizeColorMatrix (fColorMatrix2);
-
- ClearFingerprint ();
-
- }
-
-/******************************************************************************/
-
-// Make sure the forward matrix maps to exactly the PCS.
-
-void dng_camera_profile::NormalizeForwardMatrix (dng_matrix &m)
- {
-
- if (m.NotEmpty ())
- {
-
- dng_vector cameraOne;
-
- cameraOne.SetIdentity (m.Cols ());
-
- dng_vector xyz = m * cameraOne;
-
- m = PCStoXYZ ().AsDiagonal () *
- Invert (xyz.AsDiagonal ()) *
- m;
-
- }
-
- }
-
-/******************************************************************************/
-
-void dng_camera_profile::SetForwardMatrix1 (const dng_matrix &m)
- {
-
- fForwardMatrix1 = m;
-
- fForwardMatrix1.Round (10000);
-
- ClearFingerprint ();
-
- }
-
-/******************************************************************************/
-
-void dng_camera_profile::SetForwardMatrix2 (const dng_matrix &m)
- {
-
- fForwardMatrix2 = m;
-
- fForwardMatrix2.Round (10000);
-
- ClearFingerprint ();
-
- }
-
-/*****************************************************************************/
-
-void dng_camera_profile::SetReductionMatrix1 (const dng_matrix &m)
- {
-
- fReductionMatrix1 = m;
-
- fReductionMatrix1.Round (10000);
-
- ClearFingerprint ();
-
- }
-
-/******************************************************************************/
-
-void dng_camera_profile::SetReductionMatrix2 (const dng_matrix &m)
- {
-
- fReductionMatrix2 = m;
-
- fReductionMatrix2.Round (10000);
-
- ClearFingerprint ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_camera_profile::HasColorMatrix1 () const
- {
-
- return fColorMatrix1.Cols () == 3 &&
- fColorMatrix1.Rows () > 1;
-
- }
-
-/*****************************************************************************/
-
-bool dng_camera_profile::HasColorMatrix2 () const
- {
-
- return fColorMatrix2.Cols () == 3 &&
- fColorMatrix2.Rows () == fColorMatrix1.Rows ();
-
- }
-
-/*****************************************************************************/
-
-void dng_camera_profile::SetHueSatDeltas1 (const dng_hue_sat_map &deltas1)
- {
-
- fHueSatDeltas1 = deltas1;
-
- ClearFingerprint ();
-
- }
-
-/*****************************************************************************/
-
-void dng_camera_profile::SetHueSatDeltas2 (const dng_hue_sat_map &deltas2)
- {
-
- fHueSatDeltas2 = deltas2;
-
- ClearFingerprint ();
-
- }
-
-/*****************************************************************************/
-
-void dng_camera_profile::SetLookTable (const dng_hue_sat_map &table)
- {
-
- fLookTable = table;
-
- ClearFingerprint ();
-
- }
-
-/*****************************************************************************/
-
-static void FingerprintMatrix (dng_md5_printer_stream &printer,
- const dng_matrix &matrix)
- {
-
- tag_matrix tag (0, matrix);
-
- // Tag's Put routine doesn't write the header, only the data
-
- tag.Put (printer);
-
- }
-
-/*****************************************************************************/
-
-static void FingerprintHueSatMap (dng_md5_printer_stream &printer,
- const dng_hue_sat_map &map)
- {
-
- if (map.IsNull ())
- return;
-
- uint32 hues;
- uint32 sats;
- uint32 vals;
-
- map.GetDivisions (hues, sats, vals);
-
- printer.Put_uint32 (hues);
- printer.Put_uint32 (sats);
- printer.Put_uint32 (vals);
-
- for (uint32 val = 0; val < vals; val++)
- for (uint32 hue = 0; hue < hues; hue++)
- for (uint32 sat = 0; sat < sats; sat++)
- {
-
- dng_hue_sat_map::HSBModify modify;
-
- map.GetDelta (hue, sat, val, modify);
-
- printer.Put_real32 (modify.fHueShift);
- printer.Put_real32 (modify.fSatScale);
- printer.Put_real32 (modify.fValScale);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_camera_profile::CalculateFingerprint () const
- {
-
- DNG_ASSERT (!fWasStubbed, "CalculateFingerprint on stubbed profile");
-
- dng_md5_printer_stream printer;
-
- // MD5 hash is always calculated on little endian data.
-
- printer.SetLittleEndian ();
-
- // The data that we fingerprint closely matches that saved
- // by the profile_tag_set class in dng_image_writer.cpp, with
- // the exception of the fingerprint itself.
-
- if (HasColorMatrix1 ())
- {
-
- uint32 colorChannels = ColorMatrix1 ().Rows ();
-
- printer.Put_uint16 ((uint16) fCalibrationIlluminant1);
-
- FingerprintMatrix (printer, fColorMatrix1);
-
- if (fForwardMatrix1.Rows () == fColorMatrix1.Cols () &&
- fForwardMatrix1.Cols () == fColorMatrix1.Rows ())
- {
-
- FingerprintMatrix (printer, fForwardMatrix1);
-
- }
-
- if (colorChannels > 3 && fReductionMatrix1.Rows () *
- fReductionMatrix1.Cols () == colorChannels * 3)
- {
-
- FingerprintMatrix (printer, fReductionMatrix1);
-
- }
-
- if (HasColorMatrix2 ())
- {
-
- printer.Put_uint16 ((uint16) fCalibrationIlluminant2);
-
- FingerprintMatrix (printer, fColorMatrix2);
-
- if (fForwardMatrix2.Rows () == fColorMatrix2.Cols () &&
- fForwardMatrix2.Cols () == fColorMatrix2.Rows ())
- {
-
- FingerprintMatrix (printer, fForwardMatrix2);
-
- }
-
- if (colorChannels > 3 && fReductionMatrix2.Rows () *
- fReductionMatrix2.Cols () == colorChannels * 3)
- {
-
- FingerprintMatrix (printer, fReductionMatrix2);
-
- }
-
- }
-
- printer.Put (fName.Get (),
- fName.Length ());
-
- printer.Put (fProfileCalibrationSignature.Get (),
- fProfileCalibrationSignature.Length ());
-
- printer.Put_uint32 (fEmbedPolicy);
-
- printer.Put (fCopyright.Get (),
- fCopyright.Length ());
-
- bool haveHueSat1 = HueSatDeltas1 ().IsValid ();
-
- bool haveHueSat2 = HueSatDeltas2 ().IsValid () &&
- HasColorMatrix2 ();
-
- if (haveHueSat1)
- {
-
- FingerprintHueSatMap (printer, fHueSatDeltas1);
-
- }
-
- if (haveHueSat2)
- {
-
- FingerprintHueSatMap (printer, fHueSatDeltas2);
-
- }
-
- if (haveHueSat1 || haveHueSat2)
- {
-
- if (fHueSatMapEncoding != 0)
- {
-
- printer.Put_uint32 (fHueSatMapEncoding);
-
- }
-
- }
-
- if (fLookTable.IsValid ())
- {
-
- FingerprintHueSatMap (printer, fLookTable);
-
- if (fLookTableEncoding != 0)
- {
-
- printer.Put_uint32 (fLookTableEncoding);
-
- }
-
- }
-
- if (fBaselineExposureOffset.IsValid ())
- {
-
- if (fBaselineExposureOffset.As_real64 () != 0.0)
- {
-
- printer.Put_real64 (fBaselineExposureOffset.As_real64 ());
-
- }
-
- }
-
- if (fDefaultBlackRender != 0)
- {
-
- printer.Put_int32 (fDefaultBlackRender);
-
- }
-
- if (fToneCurve.IsValid ())
- {
-
- for (uint32 i = 0; i < fToneCurve.fCoord.size (); i++)
- {
-
- printer.Put_real32 ((real32) fToneCurve.fCoord [i].h);
- printer.Put_real32 ((real32) fToneCurve.fCoord [i].v);
-
- }
-
- }
-
- }
-
- fFingerprint = printer.Result ();
-
- }
-
-/******************************************************************************/
-
-bool dng_camera_profile::ValidForwardMatrix (const dng_matrix &m)
- {
-
- const real64 kThreshold = 0.01;
-
- if (m.NotEmpty ())
- {
-
- dng_vector cameraOne;
-
- cameraOne.SetIdentity (m.Cols ());
-
- dng_vector xyz = m * cameraOne;
-
- dng_vector pcs = PCStoXYZ ();
-
- if (Abs_real64 (xyz [0] - pcs [0]) > kThreshold ||
- Abs_real64 (xyz [1] - pcs [1]) > kThreshold ||
- Abs_real64 (xyz [2] - pcs [2]) > kThreshold)
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/******************************************************************************/
-
-bool dng_camera_profile::IsValid (uint32 channels) const
- {
-
- // For Monochrome images, we ignore the camera profile.
-
- if (channels == 1)
- {
-
- return true;
-
- }
-
- // ColorMatrix1 is required for all color images.
-
- if (fColorMatrix1.Cols () != 3 ||
- fColorMatrix1.Rows () != channels)
- {
-
- #if qDNGValidate
-
- ReportError ("ColorMatrix1 is wrong size");
-
- #endif
-
- return false;
-
- }
-
- // ColorMatrix2 is optional, but it must be valid if present.
-
- if (fColorMatrix2.Cols () != 0 ||
- fColorMatrix2.Rows () != 0)
- {
-
- if (fColorMatrix2.Cols () != 3 ||
- fColorMatrix2.Rows () != channels)
- {
-
- #if qDNGValidate
-
- ReportError ("ColorMatrix2 is wrong size");
-
- #endif
-
- return false;
-
- }
-
- }
-
- // ForwardMatrix1 is optional, but it must be valid if present.
-
- if (fForwardMatrix1.Cols () != 0 ||
- fForwardMatrix1.Rows () != 0)
- {
-
- if (fForwardMatrix1.Rows () != 3 ||
- fForwardMatrix1.Cols () != channels)
- {
-
- #if qDNGValidate
-
- ReportError ("ForwardMatrix1 is wrong size");
-
- #endif
-
- return false;
-
- }
-
- // Make sure ForwardMatrix1 does a valid mapping.
-
- if (!ValidForwardMatrix (fForwardMatrix1))
- {
-
- #if qDNGValidate
-
- ReportError ("ForwardMatrix1 does not map equal camera values to XYZ D50");
-
- #endif
-
- return false;
-
- }
-
- }
-
- // ForwardMatrix2 is optional, but it must be valid if present.
-
- if (fForwardMatrix2.Cols () != 0 ||
- fForwardMatrix2.Rows () != 0)
- {
-
- if (fForwardMatrix2.Rows () != 3 ||
- fForwardMatrix2.Cols () != channels)
- {
-
- #if qDNGValidate
-
- ReportError ("ForwardMatrix2 is wrong size");
-
- #endif
-
- return false;
-
- }
-
- // Make sure ForwardMatrix2 does a valid mapping.
-
- if (!ValidForwardMatrix (fForwardMatrix2))
- {
-
- #if qDNGValidate
-
- ReportError ("ForwardMatrix2 does not map equal camera values to XYZ D50");
-
- #endif
-
- return false;
-
- }
-
- }
-
- // ReductionMatrix1 is optional, but it must be valid if present.
-
- if (fReductionMatrix1.Cols () != 0 ||
- fReductionMatrix1.Rows () != 0)
- {
-
- if (fReductionMatrix1.Cols () != channels ||
- fReductionMatrix1.Rows () != 3)
- {
-
- #if qDNGValidate
-
- ReportError ("ReductionMatrix1 is wrong size");
-
- #endif
-
- return false;
-
- }
-
- }
-
- // ReductionMatrix2 is optional, but it must be valid if present.
-
- if (fReductionMatrix2.Cols () != 0 ||
- fReductionMatrix2.Rows () != 0)
- {
-
- if (fReductionMatrix2.Cols () != channels ||
- fReductionMatrix2.Rows () != 3)
- {
-
- #if qDNGValidate
-
- ReportError ("ReductionMatrix2 is wrong size");
-
- #endif
-
- return false;
-
- }
-
- }
-
- // Make sure ColorMatrix1 is invertable.
-
- try
- {
-
- if (fReductionMatrix1.NotEmpty ())
- {
-
- (void) Invert (fColorMatrix1,
- fReductionMatrix1);
-
- }
-
- else
- {
-
- (void) Invert (fColorMatrix1);
-
- }
-
- }
-
- catch (...)
- {
-
- #if qDNGValidate
-
- ReportError ("ColorMatrix1 is not invertable");
-
- #endif
-
- return false;
-
- }
-
- // Make sure ColorMatrix2 is invertable.
-
- if (fColorMatrix2.NotEmpty ())
- {
-
- try
- {
-
- if (fReductionMatrix2.NotEmpty ())
- {
-
- (void) Invert (fColorMatrix2,
- fReductionMatrix2);
-
- }
-
- else
- {
-
- (void) Invert (fColorMatrix2);
-
- }
-
- }
-
- catch (...)
- {
-
- #if qDNGValidate
-
- ReportError ("ColorMatrix2 is not invertable");
-
- #endif
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool dng_camera_profile::EqualData (const dng_camera_profile &profile) const
- {
-
- return fCalibrationIlluminant1 == profile.fCalibrationIlluminant1 &&
- fCalibrationIlluminant2 == profile.fCalibrationIlluminant2 &&
- fColorMatrix1 == profile.fColorMatrix1 &&
- fColorMatrix2 == profile.fColorMatrix2 &&
- fForwardMatrix1 == profile.fForwardMatrix1 &&
- fForwardMatrix2 == profile.fForwardMatrix2 &&
- fReductionMatrix1 == profile.fReductionMatrix1 &&
- fReductionMatrix2 == profile.fReductionMatrix2 &&
- fHueSatDeltas1 == profile.fHueSatDeltas1 &&
- fHueSatDeltas2 == profile.fHueSatDeltas2 &&
- fHueSatMapEncoding == profile.fHueSatMapEncoding &&
- fLookTable == profile.fLookTable &&
- fLookTableEncoding == profile.fLookTableEncoding &&
- fDefaultBlackRender == profile.fDefaultBlackRender &&
- fToneCurve == profile.fToneCurve &&
- fBaselineExposureOffset.As_real64 () == profile.fBaselineExposureOffset.As_real64 () &&
- fProfileCalibrationSignature == profile.fProfileCalibrationSignature;
-
- }
-
-/*****************************************************************************/
-
-void dng_camera_profile::ReadHueSatMap (dng_stream &stream,
- dng_hue_sat_map &hueSatMap,
- uint32 hues,
- uint32 sats,
- uint32 vals,
- bool skipSat0)
- {
-
- hueSatMap.SetDivisions (hues, sats, vals);
-
- for (uint32 val = 0; val < vals; val++)
- {
-
- for (uint32 hue = 0; hue < hues; hue++)
- {
-
- for (uint32 sat = skipSat0 ? 1 : 0; sat < sats; sat++)
- {
-
- dng_hue_sat_map::HSBModify modify;
-
- modify.fHueShift = stream.Get_real32 ();
- modify.fSatScale = stream.Get_real32 ();
- modify.fValScale = stream.Get_real32 ();
-
- hueSatMap.SetDelta (hue, sat, val, modify);
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-void dng_camera_profile::Parse (dng_stream &stream,
- dng_camera_profile_info &profileInfo)
- {
-
- SetUniqueCameraModelRestriction (profileInfo.fUniqueCameraModel.Get ());
-
- if (profileInfo.fProfileName.NotEmpty ())
- {
-
- SetName (profileInfo.fProfileName.Get ());
-
- }
-
- SetCopyright (profileInfo.fProfileCopyright.Get ());
-
- SetEmbedPolicy (profileInfo.fEmbedPolicy);
-
- SetCalibrationIlluminant1 (profileInfo.fCalibrationIlluminant1);
-
- SetColorMatrix1 (profileInfo.fColorMatrix1);
-
- if (profileInfo.fForwardMatrix1.NotEmpty ())
- {
-
- SetForwardMatrix1 (profileInfo.fForwardMatrix1);
-
- }
-
- if (profileInfo.fReductionMatrix1.NotEmpty ())
- {
-
- SetReductionMatrix1 (profileInfo.fReductionMatrix1);
-
- }
-
- if (profileInfo.fColorMatrix2.NotEmpty ())
- {
-
- SetCalibrationIlluminant2 (profileInfo.fCalibrationIlluminant2);
-
- SetColorMatrix2 (profileInfo.fColorMatrix2);
-
- if (profileInfo.fForwardMatrix2.NotEmpty ())
- {
-
- SetForwardMatrix2 (profileInfo.fForwardMatrix2);
-
- }
-
- if (profileInfo.fReductionMatrix2.NotEmpty ())
- {
-
- SetReductionMatrix2 (profileInfo.fReductionMatrix2);
-
- }
-
- }
-
- SetProfileCalibrationSignature (profileInfo.fProfileCalibrationSignature.Get ());
-
- if (profileInfo.fHueSatDeltas1Offset != 0 &&
- profileInfo.fHueSatDeltas1Count != 0)
- {
-
- TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
-
- stream.SetReadPosition (profileInfo.fHueSatDeltas1Offset);
-
- bool skipSat0 = (profileInfo.fHueSatDeltas1Count == profileInfo.fProfileHues *
- (profileInfo.fProfileSats - 1) *
- profileInfo.fProfileVals * 3);
-
- ReadHueSatMap (stream,
- fHueSatDeltas1,
- profileInfo.fProfileHues,
- profileInfo.fProfileSats,
- profileInfo.fProfileVals,
- skipSat0);
-
- }
-
- if (profileInfo.fHueSatDeltas2Offset != 0 &&
- profileInfo.fHueSatDeltas2Count != 0)
- {
-
- TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
-
- stream.SetReadPosition (profileInfo.fHueSatDeltas2Offset);
-
- bool skipSat0 = (profileInfo.fHueSatDeltas2Count == profileInfo.fProfileHues *
- (profileInfo.fProfileSats - 1) *
- profileInfo.fProfileVals * 3);
-
- ReadHueSatMap (stream,
- fHueSatDeltas2,
- profileInfo.fProfileHues,
- profileInfo.fProfileSats,
- profileInfo.fProfileVals,
- skipSat0);
-
- }
-
- if (profileInfo.fLookTableOffset != 0 &&
- profileInfo.fLookTableCount != 0)
- {
-
- TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
-
- stream.SetReadPosition (profileInfo.fLookTableOffset);
-
- bool skipSat0 = (profileInfo.fLookTableCount == profileInfo.fLookTableHues *
- (profileInfo.fLookTableSats - 1) *
- profileInfo.fLookTableVals * 3);
-
- ReadHueSatMap (stream,
- fLookTable,
- profileInfo.fLookTableHues,
- profileInfo.fLookTableSats,
- profileInfo.fLookTableVals,
- skipSat0);
-
- }
-
- if ((profileInfo.fToneCurveCount & 1) == 0)
- {
-
- TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
-
- stream.SetReadPosition (profileInfo.fToneCurveOffset);
-
- uint32 points = profileInfo.fToneCurveCount / 2;
-
- fToneCurve.fCoord.resize (points);
-
- for (size_t i = 0; i < points; i++)
- {
-
- dng_point_real64 point;
-
- point.h = stream.Get_real32 ();
- point.v = stream.Get_real32 ();
-
- fToneCurve.fCoord [i] = point;
-
- }
-
- }
-
- SetHueSatMapEncoding (profileInfo.fHueSatMapEncoding);
-
- SetLookTableEncoding (profileInfo.fLookTableEncoding);
-
- SetBaselineExposureOffset (profileInfo.fBaselineExposureOffset.As_real64 ());
-
- SetDefaultBlackRender (profileInfo.fDefaultBlackRender);
-
- }
-
-/*****************************************************************************/
-
-bool dng_camera_profile::ParseExtended (dng_stream &stream)
- {
-
- try
- {
-
- dng_camera_profile_info profileInfo;
-
- if (!profileInfo.ParseExtended (stream))
- {
- return false;
- }
-
- Parse (stream, profileInfo);
-
- return true;
-
- }
-
- catch (...)
- {
-
- // Eat parsing errors.
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-void dng_camera_profile::SetFourColorBayer ()
- {
-
- uint32 j;
-
- if (!IsValid (3))
- {
- ThrowProgramError ();
- }
-
- if (fColorMatrix1.NotEmpty ())
- {
-
- dng_matrix m (4, 3);
-
- for (j = 0; j < 3; j++)
- {
- m [0] [j] = fColorMatrix1 [0] [j];
- m [1] [j] = fColorMatrix1 [1] [j];
- m [2] [j] = fColorMatrix1 [2] [j];
- m [3] [j] = fColorMatrix1 [1] [j];
- }
-
- fColorMatrix1 = m;
-
- }
-
- if (fColorMatrix2.NotEmpty ())
- {
-
- dng_matrix m (4, 3);
-
- for (j = 0; j < 3; j++)
- {
- m [0] [j] = fColorMatrix2 [0] [j];
- m [1] [j] = fColorMatrix2 [1] [j];
- m [2] [j] = fColorMatrix2 [2] [j];
- m [3] [j] = fColorMatrix2 [1] [j];
- }
-
- fColorMatrix2 = m;
-
- }
-
- fReductionMatrix1.Clear ();
- fReductionMatrix2.Clear ();
-
- fForwardMatrix1.Clear ();
- fForwardMatrix2.Clear ();
-
- }
-
-/*****************************************************************************/
-
-dng_hue_sat_map * dng_camera_profile::HueSatMapForWhite (const dng_xy_coord &white) const
- {
-
- if (fHueSatDeltas1.IsValid ())
- {
-
- // If we only have the first table, just use it for any color temperature.
-
- if (!fHueSatDeltas2.IsValid ())
- {
-
- return new dng_hue_sat_map (fHueSatDeltas1);
-
- }
-
- // Else we need to interpolate based on color temperature.
-
- real64 temperature1 = CalibrationTemperature1 ();
- real64 temperature2 = CalibrationTemperature2 ();
-
- if (temperature1 <= 0.0 ||
- temperature2 <= 0.0 ||
- temperature1 == temperature2)
- {
-
- return new dng_hue_sat_map (fHueSatDeltas1);
-
- }
-
- bool reverseOrder = temperature1 > temperature2;
-
- if (reverseOrder)
- {
- real64 temp = temperature1;
- temperature1 = temperature2;
- temperature2 = temp;
- }
-
- // Convert to temperature/offset space.
-
- dng_temperature td (white);
-
- // Find fraction to weight the first calibration.
-
- real64 g;
-
- if (td.Temperature () <= temperature1)
- g = 1.0;
-
- else if (td.Temperature () >= temperature2)
- g = 0.0;
-
- else
- {
-
- real64 invT = 1.0 / td.Temperature ();
-
- g = (invT - (1.0 / temperature2)) /
- ((1.0 / temperature1) - (1.0 / temperature2));
-
- }
-
- // Fix up if we swapped the order.
-
- if (reverseOrder)
- {
- g = 1.0 - g;
- }
-
- // Do the interpolation.
-
- return dng_hue_sat_map::Interpolate (HueSatDeltas1 (),
- HueSatDeltas2 (),
- g);
-
- }
-
- return NULL;
-
- }
-
-/*****************************************************************************/
-
-void dng_camera_profile::Stub ()
- {
-
- (void) Fingerprint ();
-
- dng_hue_sat_map nullTable;
-
- fHueSatDeltas1 = nullTable;
- fHueSatDeltas2 = nullTable;
-
- fLookTable = nullTable;
-
- fToneCurve.SetInvalid ();
-
- fWasStubbed = true;
-
- }
-
-/*****************************************************************************/
-
-void SplitCameraProfileName (const dng_string &name,
- dng_string &baseName,
- int32 &version)
- {
-
- baseName = name;
-
- version = 0;
-
- uint32 len = baseName.Length ();
-
- if (len > 5 && baseName.EndsWith (" beta"))
- {
-
- baseName.Truncate (len - 5);
-
- version += -10;
-
- }
-
- else if (len > 7)
- {
-
- char lastChar = name.Get () [len - 1];
-
- if (lastChar >= '0' && lastChar <= '9')
- {
-
- dng_string temp = name;
-
- temp.Truncate (len - 1);
-
- if (temp.EndsWith (" beta "))
- {
-
- baseName.Truncate (len - 7);
-
- version += ((int32) (lastChar - '0')) - 10;
-
- }
-
- }
-
- }
-
- len = baseName.Length ();
-
- if (len > 3)
- {
-
- char lastChar = name.Get () [len - 1];
-
- if (lastChar >= '0' && lastChar <= '9')
- {
-
- dng_string temp = name;
-
- temp.Truncate (len - 1);
-
- if (temp.EndsWith (" v"))
- {
-
- baseName.Truncate (len - 3);
-
- version += ((int32) (lastChar - '0')) * 100;
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void BuildHueSatMapEncodingTable (dng_memory_allocator &allocator,
- uint32 encoding,
- AutoPtr<dng_1d_table> &encodeTable,
- AutoPtr<dng_1d_table> &decodeTable,
- bool subSample)
- {
-
- encodeTable.Reset ();
- decodeTable.Reset ();
-
- switch (encoding)
- {
-
- case encoding_Linear:
- {
-
- break;
-
- }
-
- case encoding_sRGB:
- {
-
- encodeTable.Reset (new dng_1d_table);
- decodeTable.Reset (new dng_1d_table);
-
- const dng_1d_function & curve = dng_function_GammaEncode_sRGB::Get ();
-
- encodeTable->Initialize (allocator,
- curve,
- subSample);
-
- const dng_1d_inverse inverse (curve);
-
- decodeTable->Initialize (allocator,
- inverse,
- subSample);
-
- break;
-
- }
-
- default:
- {
-
- DNG_REPORT ("Unsupported hue sat map / look table encoding.");
-
- break;
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_camera_profile.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+#include "dng_camera_profile.h"
+
+#include "dng_1d_table.h"
+#include "dng_assertions.h"
+#include "dng_color_space.h"
+#include "dng_host.h"
+#include "dng_exceptions.h"
+#include "dng_image_writer.h"
+#include "dng_info.h"
+#include "dng_parse_utils.h"
+#include "dng_tag_codes.h"
+#include "dng_tag_types.h"
+#include "dng_temperature.h"
+#include "dng_xy_coord.h"
+
+/*****************************************************************************/
+
+const char * kProfileName_Embedded = "Embedded";
+
+const char * kAdobeCalibrationSignature = "com.adobe";
+
+/*****************************************************************************/
+
+dng_camera_profile::dng_camera_profile ()
+
+ : fName ()
+ , fCalibrationIlluminant1 (lsUnknown)
+ , fCalibrationIlluminant2 (lsUnknown)
+ , fColorMatrix1 ()
+ , fColorMatrix2 ()
+ , fForwardMatrix1 ()
+ , fForwardMatrix2 ()
+ , fReductionMatrix1 ()
+ , fReductionMatrix2 ()
+ , fFingerprint ()
+ , fCopyright ()
+ , fEmbedPolicy (pepAllowCopying)
+ , fHueSatDeltas1 ()
+ , fHueSatDeltas2 ()
+ , fHueSatMapEncoding (encoding_Linear)
+ , fLookTable ()
+ , fLookTableEncoding (encoding_Linear)
+ , fBaselineExposureOffset (0, 100)
+ , fDefaultBlackRender (defaultBlackRender_Auto)
+ , fToneCurve ()
+ , fProfileCalibrationSignature ()
+ , fUniqueCameraModelRestriction ()
+ , fWasReadFromDNG (false)
+ , fWasReadFromDisk (false)
+ , fWasBuiltinMatrix (false)
+ , fWasStubbed (false)
+
+ {
+
+ fToneCurve.SetInvalid ();
+
+ }
+
+/*****************************************************************************/
+
+dng_camera_profile::~dng_camera_profile ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_camera_profile::IlluminantToTemperature (uint32 light)
+ {
+
+ switch (light)
+ {
+
+ case lsStandardLightA:
+ case lsTungsten:
+ {
+ return 2850.0;
+ }
+
+ case lsISOStudioTungsten:
+ {
+ return 3200.0;
+ }
+
+ case lsD50:
+ {
+ return 5000.0;
+ }
+
+ case lsD55:
+ case lsDaylight:
+ case lsFineWeather:
+ case lsFlash:
+ case lsStandardLightB:
+ {
+ return 5500.0;
+ }
+
+ case lsD65:
+ case lsStandardLightC:
+ case lsCloudyWeather:
+ {
+ return 6500.0;
+ }
+
+ case lsD75:
+ case lsShade:
+ {
+ return 7500.0;
+ }
+
+ case lsDaylightFluorescent:
+ {
+ return (5700.0 + 7100.0) * 0.5;
+ }
+
+ case lsDayWhiteFluorescent:
+ {
+ return (4600.0 + 5500.0) * 0.5;
+ }
+
+ case lsCoolWhiteFluorescent:
+ case lsFluorescent:
+ {
+ return (3800.0 + 4500.0) * 0.5;
+ }
+
+ case lsWhiteFluorescent:
+ {
+ return (3250.0 + 3800.0) * 0.5;
+ }
+
+ case lsWarmWhiteFluorescent:
+ {
+ return (2600.0 + 3250.0) * 0.5;
+ }
+
+ default:
+ {
+ return 0.0;
+ }
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void dng_camera_profile::NormalizeColorMatrix (dng_matrix &m)
+ {
+
+ if (m.NotEmpty ())
+ {
+
+ // Find scale factor to normalize the matrix.
+
+ dng_vector coord = m * PCStoXYZ ();
+
+ real64 maxCoord = coord.MaxEntry ();
+
+ if (maxCoord > 0.0 && (maxCoord < 0.99 || maxCoord > 1.01))
+ {
+
+ m.Scale (1.0 / maxCoord);
+
+ }
+
+ // Round to four decimal places.
+
+ m.Round (10000);
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void dng_camera_profile::SetColorMatrix1 (const dng_matrix &m)
+ {
+
+ fColorMatrix1 = m;
+
+ NormalizeColorMatrix (fColorMatrix1);
+
+ ClearFingerprint ();
+
+ }
+
+/******************************************************************************/
+
+void dng_camera_profile::SetColorMatrix2 (const dng_matrix &m)
+ {
+
+ fColorMatrix2 = m;
+
+ NormalizeColorMatrix (fColorMatrix2);
+
+ ClearFingerprint ();
+
+ }
+
+/******************************************************************************/
+
+// Make sure the forward matrix maps to exactly the PCS.
+
+void dng_camera_profile::NormalizeForwardMatrix (dng_matrix &m)
+ {
+
+ if (m.NotEmpty ())
+ {
+
+ dng_vector cameraOne;
+
+ cameraOne.SetIdentity (m.Cols ());
+
+ dng_vector xyz = m * cameraOne;
+
+ m = PCStoXYZ ().AsDiagonal () *
+ Invert (xyz.AsDiagonal ()) *
+ m;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void dng_camera_profile::SetForwardMatrix1 (const dng_matrix &m)
+ {
+
+ fForwardMatrix1 = m;
+
+ fForwardMatrix1.Round (10000);
+
+ ClearFingerprint ();
+
+ }
+
+/******************************************************************************/
+
+void dng_camera_profile::SetForwardMatrix2 (const dng_matrix &m)
+ {
+
+ fForwardMatrix2 = m;
+
+ fForwardMatrix2.Round (10000);
+
+ ClearFingerprint ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_camera_profile::SetReductionMatrix1 (const dng_matrix &m)
+ {
+
+ fReductionMatrix1 = m;
+
+ fReductionMatrix1.Round (10000);
+
+ ClearFingerprint ();
+
+ }
+
+/******************************************************************************/
+
+void dng_camera_profile::SetReductionMatrix2 (const dng_matrix &m)
+ {
+
+ fReductionMatrix2 = m;
+
+ fReductionMatrix2.Round (10000);
+
+ ClearFingerprint ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_camera_profile::HasColorMatrix1 () const
+ {
+
+ return fColorMatrix1.Cols () == 3 &&
+ fColorMatrix1.Rows () > 1;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_camera_profile::HasColorMatrix2 () const
+ {
+
+ return fColorMatrix2.Cols () == 3 &&
+ fColorMatrix2.Rows () == fColorMatrix1.Rows ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_camera_profile::SetHueSatDeltas1 (const dng_hue_sat_map &deltas1)
+ {
+
+ fHueSatDeltas1 = deltas1;
+
+ ClearFingerprint ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_camera_profile::SetHueSatDeltas2 (const dng_hue_sat_map &deltas2)
+ {
+
+ fHueSatDeltas2 = deltas2;
+
+ ClearFingerprint ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_camera_profile::SetLookTable (const dng_hue_sat_map &table)
+ {
+
+ fLookTable = table;
+
+ ClearFingerprint ();
+
+ }
+
+/*****************************************************************************/
+
+static void FingerprintMatrix (dng_md5_printer_stream &printer,
+ const dng_matrix &matrix)
+ {
+
+ tag_matrix tag (0, matrix);
+
+ // Tag's Put routine doesn't write the header, only the data
+
+ tag.Put (printer);
+
+ }
+
+/*****************************************************************************/
+
+static void FingerprintHueSatMap (dng_md5_printer_stream &printer,
+ const dng_hue_sat_map &map)
+ {
+
+ if (map.IsNull ())
+ return;
+
+ uint32 hues;
+ uint32 sats;
+ uint32 vals;
+
+ map.GetDivisions (hues, sats, vals);
+
+ printer.Put_uint32 (hues);
+ printer.Put_uint32 (sats);
+ printer.Put_uint32 (vals);
+
+ for (uint32 val = 0; val < vals; val++)
+ for (uint32 hue = 0; hue < hues; hue++)
+ for (uint32 sat = 0; sat < sats; sat++)
+ {
+
+ dng_hue_sat_map::HSBModify modify;
+
+ map.GetDelta (hue, sat, val, modify);
+
+ printer.Put_real32 (modify.fHueShift);
+ printer.Put_real32 (modify.fSatScale);
+ printer.Put_real32 (modify.fValScale);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_camera_profile::CalculateFingerprint () const
+ {
+
+ DNG_ASSERT (!fWasStubbed, "CalculateFingerprint on stubbed profile");
+
+ dng_md5_printer_stream printer;
+
+ // MD5 hash is always calculated on little endian data.
+
+ printer.SetLittleEndian ();
+
+ // The data that we fingerprint closely matches that saved
+ // by the profile_tag_set class in dng_image_writer.cpp, with
+ // the exception of the fingerprint itself.
+
+ if (HasColorMatrix1 ())
+ {
+
+ uint32 colorChannels = ColorMatrix1 ().Rows ();
+
+ printer.Put_uint16 ((uint16) fCalibrationIlluminant1);
+
+ FingerprintMatrix (printer, fColorMatrix1);
+
+ if (fForwardMatrix1.Rows () == fColorMatrix1.Cols () &&
+ fForwardMatrix1.Cols () == fColorMatrix1.Rows ())
+ {
+
+ FingerprintMatrix (printer, fForwardMatrix1);
+
+ }
+
+ if (colorChannels > 3 && fReductionMatrix1.Rows () *
+ fReductionMatrix1.Cols () == colorChannels * 3)
+ {
+
+ FingerprintMatrix (printer, fReductionMatrix1);
+
+ }
+
+ if (HasColorMatrix2 ())
+ {
+
+ printer.Put_uint16 ((uint16) fCalibrationIlluminant2);
+
+ FingerprintMatrix (printer, fColorMatrix2);
+
+ if (fForwardMatrix2.Rows () == fColorMatrix2.Cols () &&
+ fForwardMatrix2.Cols () == fColorMatrix2.Rows ())
+ {
+
+ FingerprintMatrix (printer, fForwardMatrix2);
+
+ }
+
+ if (colorChannels > 3 && fReductionMatrix2.Rows () *
+ fReductionMatrix2.Cols () == colorChannels * 3)
+ {
+
+ FingerprintMatrix (printer, fReductionMatrix2);
+
+ }
+
+ }
+
+ printer.Put (fName.Get (),
+ fName.Length ());
+
+ printer.Put (fProfileCalibrationSignature.Get (),
+ fProfileCalibrationSignature.Length ());
+
+ printer.Put_uint32 (fEmbedPolicy);
+
+ printer.Put (fCopyright.Get (),
+ fCopyright.Length ());
+
+ bool haveHueSat1 = HueSatDeltas1 ().IsValid ();
+
+ bool haveHueSat2 = HueSatDeltas2 ().IsValid () &&
+ HasColorMatrix2 ();
+
+ if (haveHueSat1)
+ {
+
+ FingerprintHueSatMap (printer, fHueSatDeltas1);
+
+ }
+
+ if (haveHueSat2)
+ {
+
+ FingerprintHueSatMap (printer, fHueSatDeltas2);
+
+ }
+
+ if (haveHueSat1 || haveHueSat2)
+ {
+
+ if (fHueSatMapEncoding != 0)
+ {
+
+ printer.Put_uint32 (fHueSatMapEncoding);
+
+ }
+
+ }
+
+ if (fLookTable.IsValid ())
+ {
+
+ FingerprintHueSatMap (printer, fLookTable);
+
+ if (fLookTableEncoding != 0)
+ {
+
+ printer.Put_uint32 (fLookTableEncoding);
+
+ }
+
+ }
+
+ if (fBaselineExposureOffset.IsValid ())
+ {
+
+ if (fBaselineExposureOffset.As_real64 () != 0.0)
+ {
+
+ printer.Put_real64 (fBaselineExposureOffset.As_real64 ());
+
+ }
+
+ }
+
+ if (fDefaultBlackRender != 0)
+ {
+
+ printer.Put_int32 (fDefaultBlackRender);
+
+ }
+
+ if (fToneCurve.IsValid ())
+ {
+
+ for (uint32 i = 0; i < fToneCurve.fCoord.size (); i++)
+ {
+
+ printer.Put_real32 ((real32) fToneCurve.fCoord [i].h);
+ printer.Put_real32 ((real32) fToneCurve.fCoord [i].v);
+
+ }
+
+ }
+
+ }
+
+ fFingerprint = printer.Result ();
+
+ }
+
+/******************************************************************************/
+
+bool dng_camera_profile::ValidForwardMatrix (const dng_matrix &m)
+ {
+
+ const real64 kThreshold = 0.01;
+
+ if (m.NotEmpty ())
+ {
+
+ dng_vector cameraOne;
+
+ cameraOne.SetIdentity (m.Cols ());
+
+ dng_vector xyz = m * cameraOne;
+
+ dng_vector pcs = PCStoXYZ ();
+
+ if (Abs_real64 (xyz [0] - pcs [0]) > kThreshold ||
+ Abs_real64 (xyz [1] - pcs [1]) > kThreshold ||
+ Abs_real64 (xyz [2] - pcs [2]) > kThreshold)
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+bool dng_camera_profile::IsValid (uint32 channels) const
+ {
+
+ // For Monochrome images, we ignore the camera profile.
+
+ if (channels == 1)
+ {
+
+ return true;
+
+ }
+
+ // ColorMatrix1 is required for all color images.
+
+ if (fColorMatrix1.Cols () != 3 ||
+ fColorMatrix1.Rows () != channels)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ColorMatrix1 is wrong size");
+
+ #endif
+
+ return false;
+
+ }
+
+ // ColorMatrix2 is optional, but it must be valid if present.
+
+ if (fColorMatrix2.Cols () != 0 ||
+ fColorMatrix2.Rows () != 0)
+ {
+
+ if (fColorMatrix2.Cols () != 3 ||
+ fColorMatrix2.Rows () != channels)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ColorMatrix2 is wrong size");
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // ForwardMatrix1 is optional, but it must be valid if present.
+
+ if (fForwardMatrix1.Cols () != 0 ||
+ fForwardMatrix1.Rows () != 0)
+ {
+
+ if (fForwardMatrix1.Rows () != 3 ||
+ fForwardMatrix1.Cols () != channels)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ForwardMatrix1 is wrong size");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Make sure ForwardMatrix1 does a valid mapping.
+
+ if (!ValidForwardMatrix (fForwardMatrix1))
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ForwardMatrix1 does not map equal camera values to XYZ D50");
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // ForwardMatrix2 is optional, but it must be valid if present.
+
+ if (fForwardMatrix2.Cols () != 0 ||
+ fForwardMatrix2.Rows () != 0)
+ {
+
+ if (fForwardMatrix2.Rows () != 3 ||
+ fForwardMatrix2.Cols () != channels)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ForwardMatrix2 is wrong size");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Make sure ForwardMatrix2 does a valid mapping.
+
+ if (!ValidForwardMatrix (fForwardMatrix2))
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ForwardMatrix2 does not map equal camera values to XYZ D50");
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // ReductionMatrix1 is optional, but it must be valid if present.
+
+ if (fReductionMatrix1.Cols () != 0 ||
+ fReductionMatrix1.Rows () != 0)
+ {
+
+ if (fReductionMatrix1.Cols () != channels ||
+ fReductionMatrix1.Rows () != 3)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ReductionMatrix1 is wrong size");
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // ReductionMatrix2 is optional, but it must be valid if present.
+
+ if (fReductionMatrix2.Cols () != 0 ||
+ fReductionMatrix2.Rows () != 0)
+ {
+
+ if (fReductionMatrix2.Cols () != channels ||
+ fReductionMatrix2.Rows () != 3)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ReductionMatrix2 is wrong size");
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // Make sure ColorMatrix1 is invertable.
+
+ try
+ {
+
+ if (fReductionMatrix1.NotEmpty ())
+ {
+
+ (void) Invert (fColorMatrix1,
+ fReductionMatrix1);
+
+ }
+
+ else
+ {
+
+ (void) Invert (fColorMatrix1);
+
+ }
+
+ }
+
+ catch (...)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ColorMatrix1 is not invertable");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Make sure ColorMatrix2 is invertable.
+
+ if (fColorMatrix2.NotEmpty ())
+ {
+
+ try
+ {
+
+ if (fReductionMatrix2.NotEmpty ())
+ {
+
+ (void) Invert (fColorMatrix2,
+ fReductionMatrix2);
+
+ }
+
+ else
+ {
+
+ (void) Invert (fColorMatrix2);
+
+ }
+
+ }
+
+ catch (...)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ColorMatrix2 is not invertable");
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_camera_profile::EqualData (const dng_camera_profile &profile) const
+ {
+
+ return fCalibrationIlluminant1 == profile.fCalibrationIlluminant1 &&
+ fCalibrationIlluminant2 == profile.fCalibrationIlluminant2 &&
+ fColorMatrix1 == profile.fColorMatrix1 &&
+ fColorMatrix2 == profile.fColorMatrix2 &&
+ fForwardMatrix1 == profile.fForwardMatrix1 &&
+ fForwardMatrix2 == profile.fForwardMatrix2 &&
+ fReductionMatrix1 == profile.fReductionMatrix1 &&
+ fReductionMatrix2 == profile.fReductionMatrix2 &&
+ fHueSatDeltas1 == profile.fHueSatDeltas1 &&
+ fHueSatDeltas2 == profile.fHueSatDeltas2 &&
+ fHueSatMapEncoding == profile.fHueSatMapEncoding &&
+ fLookTable == profile.fLookTable &&
+ fLookTableEncoding == profile.fLookTableEncoding &&
+ fDefaultBlackRender == profile.fDefaultBlackRender &&
+ fToneCurve == profile.fToneCurve &&
+ fBaselineExposureOffset.As_real64 () == profile.fBaselineExposureOffset.As_real64 () &&
+ fProfileCalibrationSignature == profile.fProfileCalibrationSignature;
+
+ }
+
+/*****************************************************************************/
+
+void dng_camera_profile::ReadHueSatMap (dng_stream &stream,
+ dng_hue_sat_map &hueSatMap,
+ uint32 hues,
+ uint32 sats,
+ uint32 vals,
+ bool skipSat0)
+ {
+
+ hueSatMap.SetDivisions (hues, sats, vals);
+
+ for (uint32 val = 0; val < vals; val++)
+ {
+
+ for (uint32 hue = 0; hue < hues; hue++)
+ {
+
+ for (uint32 sat = skipSat0 ? 1 : 0; sat < sats; sat++)
+ {
+
+ dng_hue_sat_map::HSBModify modify;
+
+ modify.fHueShift = stream.Get_real32 ();
+ modify.fSatScale = stream.Get_real32 ();
+ modify.fValScale = stream.Get_real32 ();
+
+ hueSatMap.SetDelta (hue, sat, val, modify);
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+void dng_camera_profile::Parse (dng_stream &stream,
+ dng_camera_profile_info &profileInfo)
+ {
+
+ SetUniqueCameraModelRestriction (profileInfo.fUniqueCameraModel.Get ());
+
+ if (profileInfo.fProfileName.NotEmpty ())
+ {
+
+ SetName (profileInfo.fProfileName.Get ());
+
+ }
+
+ SetCopyright (profileInfo.fProfileCopyright.Get ());
+
+ SetEmbedPolicy (profileInfo.fEmbedPolicy);
+
+ SetCalibrationIlluminant1 (profileInfo.fCalibrationIlluminant1);
+
+ SetColorMatrix1 (profileInfo.fColorMatrix1);
+
+ if (profileInfo.fForwardMatrix1.NotEmpty ())
+ {
+
+ SetForwardMatrix1 (profileInfo.fForwardMatrix1);
+
+ }
+
+ if (profileInfo.fReductionMatrix1.NotEmpty ())
+ {
+
+ SetReductionMatrix1 (profileInfo.fReductionMatrix1);
+
+ }
+
+ if (profileInfo.fColorMatrix2.NotEmpty ())
+ {
+
+ SetCalibrationIlluminant2 (profileInfo.fCalibrationIlluminant2);
+
+ SetColorMatrix2 (profileInfo.fColorMatrix2);
+
+ if (profileInfo.fForwardMatrix2.NotEmpty ())
+ {
+
+ SetForwardMatrix2 (profileInfo.fForwardMatrix2);
+
+ }
+
+ if (profileInfo.fReductionMatrix2.NotEmpty ())
+ {
+
+ SetReductionMatrix2 (profileInfo.fReductionMatrix2);
+
+ }
+
+ }
+
+ SetProfileCalibrationSignature (profileInfo.fProfileCalibrationSignature.Get ());
+
+ if (profileInfo.fHueSatDeltas1Offset != 0 &&
+ profileInfo.fHueSatDeltas1Count != 0)
+ {
+
+ TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
+
+ stream.SetReadPosition (profileInfo.fHueSatDeltas1Offset);
+
+ bool skipSat0 = (profileInfo.fHueSatDeltas1Count == profileInfo.fProfileHues *
+ (profileInfo.fProfileSats - 1) *
+ profileInfo.fProfileVals * 3);
+
+ ReadHueSatMap (stream,
+ fHueSatDeltas1,
+ profileInfo.fProfileHues,
+ profileInfo.fProfileSats,
+ profileInfo.fProfileVals,
+ skipSat0);
+
+ }
+
+ if (profileInfo.fHueSatDeltas2Offset != 0 &&
+ profileInfo.fHueSatDeltas2Count != 0)
+ {
+
+ TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
+
+ stream.SetReadPosition (profileInfo.fHueSatDeltas2Offset);
+
+ bool skipSat0 = (profileInfo.fHueSatDeltas2Count == profileInfo.fProfileHues *
+ (profileInfo.fProfileSats - 1) *
+ profileInfo.fProfileVals * 3);
+
+ ReadHueSatMap (stream,
+ fHueSatDeltas2,
+ profileInfo.fProfileHues,
+ profileInfo.fProfileSats,
+ profileInfo.fProfileVals,
+ skipSat0);
+
+ }
+
+ if (profileInfo.fLookTableOffset != 0 &&
+ profileInfo.fLookTableCount != 0)
+ {
+
+ TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
+
+ stream.SetReadPosition (profileInfo.fLookTableOffset);
+
+ bool skipSat0 = (profileInfo.fLookTableCount == profileInfo.fLookTableHues *
+ (profileInfo.fLookTableSats - 1) *
+ profileInfo.fLookTableVals * 3);
+
+ ReadHueSatMap (stream,
+ fLookTable,
+ profileInfo.fLookTableHues,
+ profileInfo.fLookTableSats,
+ profileInfo.fLookTableVals,
+ skipSat0);
+
+ }
+
+ if ((profileInfo.fToneCurveCount & 1) == 0)
+ {
+
+ TempBigEndian setEndianness (stream, profileInfo.fBigEndian);
+
+ stream.SetReadPosition (profileInfo.fToneCurveOffset);
+
+ uint32 points = profileInfo.fToneCurveCount / 2;
+
+ fToneCurve.fCoord.resize (points);
+
+ for (size_t i = 0; i < points; i++)
+ {
+
+ dng_point_real64 point;
+
+ point.h = stream.Get_real32 ();
+ point.v = stream.Get_real32 ();
+
+ fToneCurve.fCoord [i] = point;
+
+ }
+
+ }
+
+ SetHueSatMapEncoding (profileInfo.fHueSatMapEncoding);
+
+ SetLookTableEncoding (profileInfo.fLookTableEncoding);
+
+ SetBaselineExposureOffset (profileInfo.fBaselineExposureOffset.As_real64 ());
+
+ SetDefaultBlackRender (profileInfo.fDefaultBlackRender);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_camera_profile::ParseExtended (dng_stream &stream)
+ {
+
+ try
+ {
+
+ dng_camera_profile_info profileInfo;
+
+ if (!profileInfo.ParseExtended (stream))
+ {
+ return false;
+ }
+
+ Parse (stream, profileInfo);
+
+ return true;
+
+ }
+
+ catch (...)
+ {
+
+ // Eat parsing errors.
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_camera_profile::SetFourColorBayer ()
+ {
+
+ uint32 j;
+
+ if (!IsValid (3))
+ {
+ ThrowProgramError ();
+ }
+
+ if (fColorMatrix1.NotEmpty ())
+ {
+
+ dng_matrix m (4, 3);
+
+ for (j = 0; j < 3; j++)
+ {
+ m [0] [j] = fColorMatrix1 [0] [j];
+ m [1] [j] = fColorMatrix1 [1] [j];
+ m [2] [j] = fColorMatrix1 [2] [j];
+ m [3] [j] = fColorMatrix1 [1] [j];
+ }
+
+ fColorMatrix1 = m;
+
+ }
+
+ if (fColorMatrix2.NotEmpty ())
+ {
+
+ dng_matrix m (4, 3);
+
+ for (j = 0; j < 3; j++)
+ {
+ m [0] [j] = fColorMatrix2 [0] [j];
+ m [1] [j] = fColorMatrix2 [1] [j];
+ m [2] [j] = fColorMatrix2 [2] [j];
+ m [3] [j] = fColorMatrix2 [1] [j];
+ }
+
+ fColorMatrix2 = m;
+
+ }
+
+ fReductionMatrix1.Clear ();
+ fReductionMatrix2.Clear ();
+
+ fForwardMatrix1.Clear ();
+ fForwardMatrix2.Clear ();
+
+ }
+
+/*****************************************************************************/
+
+dng_hue_sat_map * dng_camera_profile::HueSatMapForWhite (const dng_xy_coord &white) const
+ {
+
+ if (fHueSatDeltas1.IsValid ())
+ {
+
+ // If we only have the first table, just use it for any color temperature.
+
+ if (!fHueSatDeltas2.IsValid ())
+ {
+
+ return new dng_hue_sat_map (fHueSatDeltas1);
+
+ }
+
+ // Else we need to interpolate based on color temperature.
+
+ real64 temperature1 = CalibrationTemperature1 ();
+ real64 temperature2 = CalibrationTemperature2 ();
+
+ if (temperature1 <= 0.0 ||
+ temperature2 <= 0.0 ||
+ temperature1 == temperature2)
+ {
+
+ return new dng_hue_sat_map (fHueSatDeltas1);
+
+ }
+
+ bool reverseOrder = temperature1 > temperature2;
+
+ if (reverseOrder)
+ {
+ real64 temp = temperature1;
+ temperature1 = temperature2;
+ temperature2 = temp;
+ }
+
+ // Convert to temperature/offset space.
+
+ dng_temperature td (white);
+
+ // Find fraction to weight the first calibration.
+
+ real64 g;
+
+ if (td.Temperature () <= temperature1)
+ g = 1.0;
+
+ else if (td.Temperature () >= temperature2)
+ g = 0.0;
+
+ else
+ {
+
+ real64 invT = 1.0 / td.Temperature ();
+
+ g = (invT - (1.0 / temperature2)) /
+ ((1.0 / temperature1) - (1.0 / temperature2));
+
+ }
+
+ // Fix up if we swapped the order.
+
+ if (reverseOrder)
+ {
+ g = 1.0 - g;
+ }
+
+ // Do the interpolation.
+
+ return dng_hue_sat_map::Interpolate (HueSatDeltas1 (),
+ HueSatDeltas2 (),
+ g);
+
+ }
+
+ return NULL;
+
+ }
+
+/*****************************************************************************/
+
+void dng_camera_profile::Stub ()
+ {
+
+ (void) Fingerprint ();
+
+ dng_hue_sat_map nullTable;
+
+ fHueSatDeltas1 = nullTable;
+ fHueSatDeltas2 = nullTable;
+
+ fLookTable = nullTable;
+
+ fToneCurve.SetInvalid ();
+
+ fWasStubbed = true;
+
+ }
+
+/*****************************************************************************/
+
+void SplitCameraProfileName (const dng_string &name,
+ dng_string &baseName,
+ int32 &version)
+ {
+
+ baseName = name;
+
+ version = 0;
+
+ uint32 len = baseName.Length ();
+
+ if (len > 5 && baseName.EndsWith (" beta"))
+ {
+
+ baseName.Truncate (len - 5);
+
+ version += -10;
+
+ }
+
+ else if (len > 7)
+ {
+
+ char lastChar = name.Get () [len - 1];
+
+ if (lastChar >= '0' && lastChar <= '9')
+ {
+
+ dng_string temp = name;
+
+ temp.Truncate (len - 1);
+
+ if (temp.EndsWith (" beta "))
+ {
+
+ baseName.Truncate (len - 7);
+
+ version += ((int32) (lastChar - '0')) - 10;
+
+ }
+
+ }
+
+ }
+
+ len = baseName.Length ();
+
+ if (len > 3)
+ {
+
+ char lastChar = name.Get () [len - 1];
+
+ if (lastChar >= '0' && lastChar <= '9')
+ {
+
+ dng_string temp = name;
+
+ temp.Truncate (len - 1);
+
+ if (temp.EndsWith (" v"))
+ {
+
+ baseName.Truncate (len - 3);
+
+ version += ((int32) (lastChar - '0')) * 100;
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void BuildHueSatMapEncodingTable (dng_memory_allocator &allocator,
+ uint32 encoding,
+ AutoPtr<dng_1d_table> &encodeTable,
+ AutoPtr<dng_1d_table> &decodeTable,
+ bool subSample)
+ {
+
+ encodeTable.Reset ();
+ decodeTable.Reset ();
+
+ switch (encoding)
+ {
+
+ case encoding_Linear:
+ {
+
+ break;
+
+ }
+
+ case encoding_sRGB:
+ {
+
+ encodeTable.Reset (new dng_1d_table);
+ decodeTable.Reset (new dng_1d_table);
+
+ const dng_1d_function & curve = dng_function_GammaEncode_sRGB::Get ();
+
+ encodeTable->Initialize (allocator,
+ curve,
+ subSample);
+
+ const dng_1d_inverse inverse (curve);
+
+ decodeTable->Initialize (allocator,
+ inverse,
+ subSample);
+
+ break;
+
+ }
+
+ default:
+ {
+
+ DNG_REPORT ("Unsupported hue sat map / look table encoding.");
+
+ break;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_camera_profile.h b/source/dng_camera_profile.h
index df14a8a..47de7e3 100644
--- a/source/dng_camera_profile.h
+++ b/source/dng_camera_profile.h
@@ -1,878 +1,878 @@
-/******************************************************************************/
-// Copyright 2006-2007 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_camera_profile.h#2 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Support for DNG camera color profile information.
- * Per the \ref spec_dng "DNG 1.1.0 specification", a DNG file can store up to
- * two sets of color profile information for a camera in the DNG file from that
- * camera. The second set is optional and when there are two sets, they represent
- * profiles made under different illumination.
- *
- * Profiling information is optionally separated into two parts. One part represents
- * a profile for a reference camera. (ColorMatrix1 and ColorMatrix2 here.) The
- * second is a per-camera calibration that takes into account unit-to-unit variation.
- * This is designed to allow replacing the reference color matrix with one of one's
- * own construction while maintaining any unit-specific calibration the camera
- * manufacturer may have provided.
- *
- * See Appendix 6 of the \ref spec_dng "DNG 1.1.0 specification" for more information.
- */
-
-#ifndef __dng_camera_profile__
-#define __dng_camera_profile__
-
-/******************************************************************************/
-
-#include "dng_auto_ptr.h"
-#include "dng_assertions.h"
-#include "dng_classes.h"
-#include "dng_fingerprint.h"
-#include "dng_hue_sat_map.h"
-#include "dng_matrix.h"
-#include "dng_string.h"
-#include "dng_tag_values.h"
-#include "dng_tone_curve.h"
-
-/******************************************************************************/
-
-extern const char * kProfileName_Embedded;
-
-extern const char * kAdobeCalibrationSignature;
-
-/******************************************************************************/
-
-/// \brief An ID for a camera profile consisting of a name and optional fingerprint.
-
-class dng_camera_profile_id
- {
-
- private:
-
- dng_string fName;
-
- dng_fingerprint fFingerprint;
-
- public:
-
- /// Construct an invalid camera profile ID (empty name and fingerprint).
-
- dng_camera_profile_id ()
-
- : fName ()
- , fFingerprint ()
-
- {
- }
-
- /// Construct a camera profile ID with the specified name and no fingerprint.
- /// \param name The name of the camera profile ID.
-
- dng_camera_profile_id (const char *name)
-
- : fName ()
- , fFingerprint ()
-
- {
- fName.Set (name);
- }
-
- /// Construct a camera profile ID with the specified name and no fingerprint.
- /// \param name The name of the camera profile ID.
-
- dng_camera_profile_id (const dng_string &name)
-
- : fName (name)
- , fFingerprint ()
-
- {
- }
-
- /// Construct a camera profile ID with the specified name and fingerprint.
- /// \param name The name of the camera profile ID.
- /// \param fingerprint The fingerprint of the camera profile ID.
-
- dng_camera_profile_id (const char *name,
- const dng_fingerprint &fingerprint)
-
- : fName ()
- , fFingerprint (fingerprint)
-
- {
- fName.Set (name);
- DNG_ASSERT (!fFingerprint.IsValid () || fName.NotEmpty (),
- "Cannot have profile fingerprint without name");
- }
-
- /// Construct a camera profile ID with the specified name and fingerprint.
- /// \param name The name of the camera profile ID.
- /// \param fingerprint The fingerprint of the camera profile ID.
-
- dng_camera_profile_id (const dng_string &name,
- const dng_fingerprint &fingerprint)
-
- : fName (name)
- , fFingerprint (fingerprint)
-
- {
- DNG_ASSERT (!fFingerprint.IsValid () || fName.NotEmpty (),
- "Cannot have profile fingerprint without name");
- }
-
- /// Getter for the name of the camera profile ID.
- /// \retval The name of the camera profile ID.
-
- const dng_string & Name () const
- {
- return fName;
- }
-
- /// Getter for the fingerprint of the camera profile ID.
- /// \retval The fingerprint of the camera profile ID.
-
- const dng_fingerprint & Fingerprint () const
- {
- return fFingerprint;
- }
-
- /// Test for equality of two camera profile IDs.
- /// \param The id of the camera profile ID to compare.
-
- bool operator== (const dng_camera_profile_id &id) const
- {
- return fName == id.fName &&
- fFingerprint == id.fFingerprint;
- }
-
- /// Test for inequality of two camera profile IDs.
- /// \param The id of the camera profile ID to compare.
-
- bool operator!= (const dng_camera_profile_id &id) const
- {
- return !(*this == id);
- }
-
- /// Returns true iff the camera profile ID is valid.
-
- bool IsValid () const
- {
- return fName.NotEmpty (); // Fingerprint is optional.
- }
-
- /// Resets the name and fingerprint, thereby making this camera profile ID
- /// invalid.
-
- void Clear ()
- {
- *this = dng_camera_profile_id ();
- }
-
- };
-
-/******************************************************************************/
-
-/// \brief Container for DNG camera color profile and calibration data.
-
-class dng_camera_profile
- {
-
- protected:
-
- // Name of this camera profile.
-
- dng_string fName;
-
- // Light sources for up to two calibrations. These use the EXIF
- // encodings for illuminant and are used to distinguish which
- // matrix to use.
-
- uint32 fCalibrationIlluminant1;
- uint32 fCalibrationIlluminant2;
-
- // Color matrices for up to two calibrations.
-
- // These matrices map XYZ values to non-white balanced camera values.
- // Adobe needs to go that direction in order to determine the clipping
- // points for highlight recovery logic based on the white point. If
- // cameras were all 3-color, the matrix could be stored as a forward matrix,
- // but we need the backwards matrix to deal with 4-color cameras.
-
- dng_matrix fColorMatrix1;
- dng_matrix fColorMatrix2;
-
- // These matrices map white balanced camera values to XYZ chromatically
- // adapted to D50 (the ICC profile PCS white point). If the matrices
- // exist, then this implies that white balancing should be done by scaling
- // camera values with a diagonal matrix.
-
- dng_matrix fForwardMatrix1;
- dng_matrix fForwardMatrix2;
-
- // Dimensionality reduction hints for more than three color cameras.
- // This is an optional matrix that maps the camera's color components
- // to 3 components. These are only used if the forward matrices don't
- // exist, and are used invert the color matrices.
-
- dng_matrix fReductionMatrix1;
- dng_matrix fReductionMatrix2;
-
- // MD5 hash for all data bits of the profile.
-
- mutable dng_fingerprint fFingerprint;
-
- // Copyright notice from creator of profile.
-
- dng_string fCopyright;
-
- // Rules for how this profile can be embedded and/or copied.
-
- uint32 fEmbedPolicy;
-
- // 2-D (or 3-D) hue/sat tables to modify colors.
-
- dng_hue_sat_map fHueSatDeltas1;
- dng_hue_sat_map fHueSatDeltas2;
-
- // Value (V of HSV) encoding for hue/sat tables.
-
- uint32 fHueSatMapEncoding;
-
- // 3-D hue/sat table to apply a "look".
-
- dng_hue_sat_map fLookTable;
-
- // Value (V of HSV) encoding for look table.
-
- uint32 fLookTableEncoding;
-
- // Baseline exposure offset. When using this profile, this offset value is
- // added to the BaselineExposure value for the negative to determine the
- // overall baseline exposure to apply.
-
- dng_srational fBaselineExposureOffset;
-
- // Default black rendering.
-
- uint32 fDefaultBlackRender;
-
- // The "as shot" tone curve for this profile. Check IsValid method
- // to tell if one exists in profile.
-
- dng_tone_curve fToneCurve;
-
- // If this string matches the fCameraCalibrationSignature of the
- // negative, then use the calibration matrix values from the negative.
-
- dng_string fProfileCalibrationSignature;
-
- // If non-empty, only allow use of this profile with camera having
- // same unique model name.
-
- dng_string fUniqueCameraModelRestriction;
-
- // Was this profile read from inside a DNG file? (If so, we wnat
- // to be sure to include it again when writing out an updated
- // DNG file)
-
- bool fWasReadFromDNG;
-
- // Was this profile read from disk (i.e., an external profile)? (If so, we
- // may need to refresh when changes are made externally to the profile
- // directory.)
-
- bool fWasReadFromDisk;
-
- // Was this profile a built-in "Matrix" profile? (If so, we may need to
- // refresh -- i.e., remove it from the list of available profiles -- when
- // changes are made externally to the profile directory.)
-
- bool fWasBuiltinMatrix;
-
- // Was this profile stubbed to save memory (and no longer valid
- // for building color conversion tables)?
-
- bool fWasStubbed;
-
- public:
-
- dng_camera_profile ();
-
- virtual ~dng_camera_profile ();
-
- // API for profile name:
-
- /// Setter for camera profile name.
- /// \param name Name to use for this camera profile.
-
- void SetName (const char *name)
- {
- fName.Set (name);
- ClearFingerprint ();
- }
-
- /// Getter for camera profile name.
- /// \retval Name of profile.
-
- const dng_string & Name () const
- {
- return fName;
- }
-
- /// Test if this name is embedded.
- /// \retval true if the name matches the name of the embedded camera profile.
-
- bool NameIsEmbedded () const
- {
- return fName.Matches (kProfileName_Embedded, true);
- }
-
- // API for calibration illuminants:
-
- /// Setter for first of up to two light sources used for calibration.
- /// Uses the EXIF encodings for illuminant and is used to distinguish which
- /// matrix to use.
- /// Corresponds to the DNG CalibrationIlluminant1 tag.
-
- void SetCalibrationIlluminant1 (uint32 light)
- {
- fCalibrationIlluminant1 = light;
- ClearFingerprint ();
- }
-
- /// Setter for second of up to two light sources used for calibration.
- /// Uses the EXIF encodings for illuminant and is used to distinguish which
- /// matrix to use.
- /// Corresponds to the DNG CalibrationIlluminant2 tag.
-
- void SetCalibrationIlluminant2 (uint32 light)
- {
- fCalibrationIlluminant2 = light;
- ClearFingerprint ();
- }
-
- /// Getter for first of up to two light sources used for calibration.
- /// Uses the EXIF encodings for illuminant and is used to distinguish which
- /// matrix to use.
- /// Corresponds to the DNG CalibrationIlluminant1 tag.
-
- uint32 CalibrationIlluminant1 () const
- {
- return fCalibrationIlluminant1;
- }
-
- /// Getter for second of up to two light sources used for calibration.
- /// Uses the EXIF encodings for illuminant and is used to distinguish which
- /// matrix to use.
- /// Corresponds to the DNG CalibrationIlluminant2 tag.
-
- uint32 CalibrationIlluminant2 () const
- {
- return fCalibrationIlluminant2;
- }
-
- /// Getter for first of up to two light sources used for calibration, returning
- /// result as color temperature.
-
- real64 CalibrationTemperature1 () const
- {
- return IlluminantToTemperature (CalibrationIlluminant1 ());
- }
-
- /// Getter for second of up to two light sources used for calibration, returning
- /// result as color temperature.
-
- real64 CalibrationTemperature2 () const
- {
- return IlluminantToTemperature (CalibrationIlluminant2 ());
- }
-
- // API for color matrices:
-
- /// Utility function to normalize the scale of the color matrix.
-
- static void NormalizeColorMatrix (dng_matrix &m);
-
- /// Setter for first of up to two color matrices used for reference camera calibrations.
- /// These matrices map XYZ values to camera values. The DNG SDK needs to map colors
- /// that direction in order to determine the clipping points for
- /// highlight recovery logic based on the white point. If cameras
- /// were all three-color, the matrix could be stored as a forward matrix.
- /// The inverse matrix is requried to support four-color cameras.
-
- void SetColorMatrix1 (const dng_matrix &m);
-
- /// Setter for second of up to two color matrices used for reference camera calibrations.
- /// These matrices map XYZ values to camera values. The DNG SDK needs to map colors
- /// that direction in order to determine the clipping points for
- /// highlight recovery logic based on the white point. If cameras
- /// were all three-color, the matrix could be stored as a forward matrix.
- /// The inverse matrix is requried to support four-color cameras.
-
- void SetColorMatrix2 (const dng_matrix &m);
-
- /// Predicate to test if first camera matrix is set
-
- bool HasColorMatrix1 () const;
-
- /// Predicate to test if second camera matrix is set
-
- bool HasColorMatrix2 () const;
-
- /// Getter for first of up to two color matrices used for calibrations.
-
- const dng_matrix & ColorMatrix1 () const
- {
- return fColorMatrix1;
- }
-
- /// Getter for second of up to two color matrices used for calibrations.
-
- const dng_matrix & ColorMatrix2 () const
- {
- return fColorMatrix2;
- }
-
- // API for forward matrices:
-
- /// Utility function to normalize the scale of the forward matrix.
-
- static void NormalizeForwardMatrix (dng_matrix &m);
-
- /// Setter for first of up to two forward matrices used for calibrations.
-
- void SetForwardMatrix1 (const dng_matrix &m);
-
- /// Setter for second of up to two forward matrices used for calibrations.
-
- void SetForwardMatrix2 (const dng_matrix &m);
-
- /// Getter for first of up to two forward matrices used for calibrations.
-
- const dng_matrix & ForwardMatrix1 () const
- {
- return fForwardMatrix1;
- }
-
- /// Getter for second of up to two forward matrices used for calibrations.
-
- const dng_matrix & ForwardMatrix2 () const
- {
- return fForwardMatrix2;
- }
-
- // API for reduction matrices:
-
- /// Setter for first of up to two dimensionality reduction hints for four-color cameras.
- /// This is an optional matrix that maps four components to three.
- /// See Appendix 6 of the \ref spec_dng "DNG 1.1.0 specification."
-
- void SetReductionMatrix1 (const dng_matrix &m);
-
- /// Setter for second of up to two dimensionality reduction hints for four-color cameras.
- /// This is an optional matrix that maps four components to three.
- /// See Appendix 6 of the \ref spec_dng "DNG 1.1.0 specification."
-
- void SetReductionMatrix2 (const dng_matrix &m);
-
- /// Getter for first of up to two dimensionality reduction hints for four color cameras.
-
- const dng_matrix & ReductionMatrix1 () const
- {
- return fReductionMatrix1;
- }
-
- /// Getter for second of up to two dimensionality reduction hints for four color cameras.
-
- const dng_matrix & ReductionMatrix2 () const
- {
- return fReductionMatrix2;
- }
-
- /// Getter function from profile fingerprint.
-
- const dng_fingerprint &Fingerprint () const
- {
-
- if (!fFingerprint.IsValid ())
- CalculateFingerprint ();
-
- return fFingerprint;
-
- }
-
- /// Getter for camera profile id.
- /// \retval ID of profile.
-
- dng_camera_profile_id ProfileID () const
- {
- return dng_camera_profile_id (Name (), Fingerprint ());
- }
-
- /// Setter for camera profile copyright.
- /// \param copyright Copyright string to use for this camera profile.
-
- void SetCopyright (const char *copyright)
- {
- fCopyright.Set (copyright);
- ClearFingerprint ();
- }
-
- /// Getter for camera profile copyright.
- /// \retval Copyright string for profile.
-
- const dng_string & Copyright () const
- {
- return fCopyright;
- }
-
- // Accessors for embed policy.
-
- /// Setter for camera profile embed policy.
- /// \param policy Policy to use for this camera profile.
-
- void SetEmbedPolicy (uint32 policy)
- {
- fEmbedPolicy = policy;
- ClearFingerprint ();
- }
-
- /// Getter for camera profile embed policy.
- /// \param Policy for profile.
-
- uint32 EmbedPolicy () const
- {
- return fEmbedPolicy;
- }
-
- /// Returns true iff the profile is legal to embed in a DNG, per the
- /// profile's embed policy.
-
- bool IsLegalToEmbed () const
- {
- return WasReadFromDNG () ||
- EmbedPolicy () == pepAllowCopying ||
- EmbedPolicy () == pepEmbedIfUsed ||
- EmbedPolicy () == pepNoRestrictions;
- }
-
- // Accessors for hue sat maps.
-
- /// Returns true iff the profile has a valid HueSatMap color table.
-
- bool HasHueSatDeltas () const
- {
- return fHueSatDeltas1.IsValid ();
- }
-
- /// Getter for first HueSatMap color table (for calibration illuminant 1).
-
- const dng_hue_sat_map & HueSatDeltas1 () const
- {
- return fHueSatDeltas1;
- }
-
- /// Setter for first HueSatMap color table (for calibration illuminant 1).
-
- void SetHueSatDeltas1 (const dng_hue_sat_map &deltas1);
-
- /// Getter for second HueSatMap color table (for calibration illuminant 2).
-
- const dng_hue_sat_map & HueSatDeltas2 () const
- {
- return fHueSatDeltas2;
- }
-
- /// Setter for second HueSatMap color table (for calibration illuminant 2).
-
- void SetHueSatDeltas2 (const dng_hue_sat_map &deltas2);
-
- // Accessors for hue sat map encoding.
-
- /// Returns the hue sat map encoding (see ProfileHueSatMapEncoding tag).
-
- uint32 HueSatMapEncoding () const
- {
- return fHueSatMapEncoding;
- }
-
- /// Sets the hue sat map encoding (see ProfileHueSatMapEncoding tag) to the
- /// specified encoding.
-
- void SetHueSatMapEncoding (uint32 encoding)
- {
- fHueSatMapEncoding = encoding;
- ClearFingerprint ();
- }
-
- // Accessors for look table.
-
- /// Returns true if the profile has a LookTable.
-
- bool HasLookTable () const
- {
- return fLookTable.IsValid ();
- }
-
- /// Getter for LookTable.
-
- const dng_hue_sat_map & LookTable () const
- {
- return fLookTable;
- }
-
- /// Setter for LookTable.
-
- void SetLookTable (const dng_hue_sat_map &table);
-
- // Accessors for look table encoding.
-
- /// Returns the LookTable encoding (see ProfileLookTableEncoding tag).
-
- uint32 LookTableEncoding () const
- {
- return fLookTableEncoding;
- }
-
- /// Sets the LookTable encoding (see ProfileLookTableEncoding tag) to the
- /// specified encoding.
-
- void SetLookTableEncoding (uint32 encoding)
- {
- fLookTableEncoding = encoding;
- ClearFingerprint ();
- }
-
- // Accessors for baseline exposure offset.
-
- /// Sets the baseline exposure offset of the profile (see
- /// BaselineExposureOffset tag) to the specified value.
-
- void SetBaselineExposureOffset (real64 exposureOffset)
- {
- fBaselineExposureOffset.Set_real64 (exposureOffset, 100);
- ClearFingerprint ();
- }
-
- /// Returns the baseline exposure offset of the profile (see
- /// BaselineExposureOffset tag).
-
- const dng_srational & BaselineExposureOffset () const
- {
- return fBaselineExposureOffset;
- }
-
- // Accessors for default black render.
-
- /// Sets the default black render of the profile (see DefaultBlackRender tag)
- /// to the specified option.
-
- void SetDefaultBlackRender (uint32 defaultBlackRender)
- {
- fDefaultBlackRender = defaultBlackRender;
- ClearFingerprint ();
- }
-
- /// Returns the default black render of the profile (see DefaultBlackRender
- /// tag).
-
- uint32 DefaultBlackRender () const
- {
- return fDefaultBlackRender;
- }
-
- // Accessors for tone curve.
-
- /// Returns the tone curve of the profile.
-
- const dng_tone_curve & ToneCurve () const
- {
- return fToneCurve;
- }
-
- /// Sets the tone curve of the profile to the specified curve.
-
- void SetToneCurve (const dng_tone_curve &curve)
- {
- fToneCurve = curve;
- ClearFingerprint ();
- }
-
- // Accessors for profile calibration signature.
-
- /// Sets the profile calibration signature (see ProfileCalibrationSignature
- /// tag) to the specified string.
-
- void SetProfileCalibrationSignature (const char *signature)
- {
- fProfileCalibrationSignature.Set (signature);
- }
-
- /// Returns the profile calibration signature (see ProfileCalibrationSignature
- /// tag) of the profile.
-
- const dng_string & ProfileCalibrationSignature () const
- {
- return fProfileCalibrationSignature;
- }
-
- /// Setter for camera unique model name to restrict use of this profile.
- /// \param camera Camera unique model name designating only camera this
- /// profile can be used with. (Empty string for no restriction.)
-
- void SetUniqueCameraModelRestriction (const char *camera)
- {
- fUniqueCameraModelRestriction.Set (camera);
- // Not included in fingerprint, so don't need ClearFingerprint ().
- }
-
- /// Getter for camera unique model name to restrict use of this profile.
- /// \retval Unique model name of only camera this profile can be used with
- /// or empty if no restriction.
-
- const dng_string & UniqueCameraModelRestriction () const
- {
- return fUniqueCameraModelRestriction;
- }
-
- // Accessors for was read from DNG flag.
-
- /// Sets internal flag to indicate this profile was originally read from a
- /// DNG file.
-
- void SetWasReadFromDNG (bool state = true)
- {
- fWasReadFromDNG = state;
- }
-
- /// Was this profile read from a DNG?
-
- bool WasReadFromDNG () const
- {
- return fWasReadFromDNG;
- }
-
- // Accessors for was read from disk flag.
-
- /// Sets internal flag to indicate this profile was originally read from
- /// disk.
-
- void SetWasReadFromDisk (bool state = true)
- {
- fWasReadFromDisk = state;
- }
-
- /// Was this profile read from disk?
-
- bool WasReadFromDisk () const
- {
- return fWasReadFromDisk;
- }
-
- // Accessors for was built-in matrix flag.
-
- /// Sets internal flag to indicate this profile was originally a built-in
- /// matrix profile.
-
- void SetWasBuiltinMatrix (bool state = true)
- {
- fWasBuiltinMatrix = state;
- }
-
- /// Was this profile a built-in matrix profile?
-
- bool WasBuiltinMatrix () const
- {
- return fWasBuiltinMatrix;
- }
-
- /// Determines if this a valid profile for this number of color channels?
- /// \retval true if the profile is valid.
-
- bool IsValid (uint32 channels) const;
-
- /// Predicate to check if two camera profiles are colorwise equal, thus ignores
- /// the profile name.
- /// \param profile Camera profile to compare to.
-
- bool EqualData (const dng_camera_profile &profile) const;
-
- /// Parse profile from dng_camera_profile_info data.
-
- void Parse (dng_stream &stream,
- dng_camera_profile_info &profileInfo);
-
- /// Parse from an extended profile stream, which is similar to stand alone
- /// TIFF file.
-
- bool ParseExtended (dng_stream &stream);
-
- /// Convert from a three-color to a four-color Bayer profile.
-
- virtual void SetFourColorBayer ();
-
- /// Find the hue/sat table to use for a given white point, if any.
- /// The calling routine owns the resulting table.
-
- dng_hue_sat_map * HueSatMapForWhite (const dng_xy_coord &white) const;
-
- /// Stub out the profile (free memory used by large tables).
-
- void Stub ();
-
- /// Was this profile stubbed?
-
- bool WasStubbed () const
- {
- return fWasStubbed;
- }
-
- protected:
-
- static real64 IlluminantToTemperature (uint32 light);
-
- void ClearFingerprint ()
- {
- fFingerprint.Clear ();
- }
-
- void CalculateFingerprint () const;
-
- static bool ValidForwardMatrix (const dng_matrix &m);
-
- static void ReadHueSatMap (dng_stream &stream,
- dng_hue_sat_map &hueSatMap,
- uint32 hues,
- uint32 sats,
- uint32 vals,
- bool skipSat0);
-
- };
-
-/******************************************************************************/
-
-void SplitCameraProfileName (const dng_string &name,
- dng_string &baseName,
- int32 &version);
-
-/*****************************************************************************/
-
-void BuildHueSatMapEncodingTable (dng_memory_allocator &allocator,
- uint32 encoding,
- AutoPtr<dng_1d_table> &encodeTable,
- AutoPtr<dng_1d_table> &decodeTable,
- bool subSample);
-
-/******************************************************************************/
-
-#endif
-
-/******************************************************************************/
+/******************************************************************************/
+// Copyright 2006-2007 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_camera_profile.h#2 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Support for DNG camera color profile information.
+ * Per the \ref spec_dng "DNG 1.1.0 specification", a DNG file can store up to
+ * two sets of color profile information for a camera in the DNG file from that
+ * camera. The second set is optional and when there are two sets, they represent
+ * profiles made under different illumination.
+ *
+ * Profiling information is optionally separated into two parts. One part represents
+ * a profile for a reference camera. (ColorMatrix1 and ColorMatrix2 here.) The
+ * second is a per-camera calibration that takes into account unit-to-unit variation.
+ * This is designed to allow replacing the reference color matrix with one of one's
+ * own construction while maintaining any unit-specific calibration the camera
+ * manufacturer may have provided.
+ *
+ * See Appendix 6 of the \ref spec_dng "DNG 1.1.0 specification" for more information.
+ */
+
+#ifndef __dng_camera_profile__
+#define __dng_camera_profile__
+
+/******************************************************************************/
+
+#include "dng_auto_ptr.h"
+#include "dng_assertions.h"
+#include "dng_classes.h"
+#include "dng_fingerprint.h"
+#include "dng_hue_sat_map.h"
+#include "dng_matrix.h"
+#include "dng_string.h"
+#include "dng_tag_values.h"
+#include "dng_tone_curve.h"
+
+/******************************************************************************/
+
+extern const char * kProfileName_Embedded;
+
+extern const char * kAdobeCalibrationSignature;
+
+/******************************************************************************/
+
+/// \brief An ID for a camera profile consisting of a name and optional fingerprint.
+
+class dng_camera_profile_id
+ {
+
+ private:
+
+ dng_string fName;
+
+ dng_fingerprint fFingerprint;
+
+ public:
+
+ /// Construct an invalid camera profile ID (empty name and fingerprint).
+
+ dng_camera_profile_id ()
+
+ : fName ()
+ , fFingerprint ()
+
+ {
+ }
+
+ /// Construct a camera profile ID with the specified name and no fingerprint.
+ /// \param name The name of the camera profile ID.
+
+ dng_camera_profile_id (const char *name)
+
+ : fName ()
+ , fFingerprint ()
+
+ {
+ fName.Set (name);
+ }
+
+ /// Construct a camera profile ID with the specified name and no fingerprint.
+ /// \param name The name of the camera profile ID.
+
+ dng_camera_profile_id (const dng_string &name)
+
+ : fName (name)
+ , fFingerprint ()
+
+ {
+ }
+
+ /// Construct a camera profile ID with the specified name and fingerprint.
+ /// \param name The name of the camera profile ID.
+ /// \param fingerprint The fingerprint of the camera profile ID.
+
+ dng_camera_profile_id (const char *name,
+ const dng_fingerprint &fingerprint)
+
+ : fName ()
+ , fFingerprint (fingerprint)
+
+ {
+ fName.Set (name);
+ DNG_ASSERT (!fFingerprint.IsValid () || fName.NotEmpty (),
+ "Cannot have profile fingerprint without name");
+ }
+
+ /// Construct a camera profile ID with the specified name and fingerprint.
+ /// \param name The name of the camera profile ID.
+ /// \param fingerprint The fingerprint of the camera profile ID.
+
+ dng_camera_profile_id (const dng_string &name,
+ const dng_fingerprint &fingerprint)
+
+ : fName (name)
+ , fFingerprint (fingerprint)
+
+ {
+ DNG_ASSERT (!fFingerprint.IsValid () || fName.NotEmpty (),
+ "Cannot have profile fingerprint without name");
+ }
+
+ /// Getter for the name of the camera profile ID.
+ /// \retval The name of the camera profile ID.
+
+ const dng_string & Name () const
+ {
+ return fName;
+ }
+
+ /// Getter for the fingerprint of the camera profile ID.
+ /// \retval The fingerprint of the camera profile ID.
+
+ const dng_fingerprint & Fingerprint () const
+ {
+ return fFingerprint;
+ }
+
+ /// Test for equality of two camera profile IDs.
+ /// \param The id of the camera profile ID to compare.
+
+ bool operator== (const dng_camera_profile_id &id) const
+ {
+ return fName == id.fName &&
+ fFingerprint == id.fFingerprint;
+ }
+
+ /// Test for inequality of two camera profile IDs.
+ /// \param The id of the camera profile ID to compare.
+
+ bool operator!= (const dng_camera_profile_id &id) const
+ {
+ return !(*this == id);
+ }
+
+ /// Returns true iff the camera profile ID is valid.
+
+ bool IsValid () const
+ {
+ return fName.NotEmpty (); // Fingerprint is optional.
+ }
+
+ /// Resets the name and fingerprint, thereby making this camera profile ID
+ /// invalid.
+
+ void Clear ()
+ {
+ *this = dng_camera_profile_id ();
+ }
+
+ };
+
+/******************************************************************************/
+
+/// \brief Container for DNG camera color profile and calibration data.
+
+class dng_camera_profile
+ {
+
+ protected:
+
+ // Name of this camera profile.
+
+ dng_string fName;
+
+ // Light sources for up to two calibrations. These use the EXIF
+ // encodings for illuminant and are used to distinguish which
+ // matrix to use.
+
+ uint32 fCalibrationIlluminant1;
+ uint32 fCalibrationIlluminant2;
+
+ // Color matrices for up to two calibrations.
+
+ // These matrices map XYZ values to non-white balanced camera values.
+ // Adobe needs to go that direction in order to determine the clipping
+ // points for highlight recovery logic based on the white point. If
+ // cameras were all 3-color, the matrix could be stored as a forward matrix,
+ // but we need the backwards matrix to deal with 4-color cameras.
+
+ dng_matrix fColorMatrix1;
+ dng_matrix fColorMatrix2;
+
+ // These matrices map white balanced camera values to XYZ chromatically
+ // adapted to D50 (the ICC profile PCS white point). If the matrices
+ // exist, then this implies that white balancing should be done by scaling
+ // camera values with a diagonal matrix.
+
+ dng_matrix fForwardMatrix1;
+ dng_matrix fForwardMatrix2;
+
+ // Dimensionality reduction hints for more than three color cameras.
+ // This is an optional matrix that maps the camera's color components
+ // to 3 components. These are only used if the forward matrices don't
+ // exist, and are used invert the color matrices.
+
+ dng_matrix fReductionMatrix1;
+ dng_matrix fReductionMatrix2;
+
+ // MD5 hash for all data bits of the profile.
+
+ mutable dng_fingerprint fFingerprint;
+
+ // Copyright notice from creator of profile.
+
+ dng_string fCopyright;
+
+ // Rules for how this profile can be embedded and/or copied.
+
+ uint32 fEmbedPolicy;
+
+ // 2-D (or 3-D) hue/sat tables to modify colors.
+
+ dng_hue_sat_map fHueSatDeltas1;
+ dng_hue_sat_map fHueSatDeltas2;
+
+ // Value (V of HSV) encoding for hue/sat tables.
+
+ uint32 fHueSatMapEncoding;
+
+ // 3-D hue/sat table to apply a "look".
+
+ dng_hue_sat_map fLookTable;
+
+ // Value (V of HSV) encoding for look table.
+
+ uint32 fLookTableEncoding;
+
+ // Baseline exposure offset. When using this profile, this offset value is
+ // added to the BaselineExposure value for the negative to determine the
+ // overall baseline exposure to apply.
+
+ dng_srational fBaselineExposureOffset;
+
+ // Default black rendering.
+
+ uint32 fDefaultBlackRender;
+
+ // The "as shot" tone curve for this profile. Check IsValid method
+ // to tell if one exists in profile.
+
+ dng_tone_curve fToneCurve;
+
+ // If this string matches the fCameraCalibrationSignature of the
+ // negative, then use the calibration matrix values from the negative.
+
+ dng_string fProfileCalibrationSignature;
+
+ // If non-empty, only allow use of this profile with camera having
+ // same unique model name.
+
+ dng_string fUniqueCameraModelRestriction;
+
+ // Was this profile read from inside a DNG file? (If so, we wnat
+ // to be sure to include it again when writing out an updated
+ // DNG file)
+
+ bool fWasReadFromDNG;
+
+ // Was this profile read from disk (i.e., an external profile)? (If so, we
+ // may need to refresh when changes are made externally to the profile
+ // directory.)
+
+ bool fWasReadFromDisk;
+
+ // Was this profile a built-in "Matrix" profile? (If so, we may need to
+ // refresh -- i.e., remove it from the list of available profiles -- when
+ // changes are made externally to the profile directory.)
+
+ bool fWasBuiltinMatrix;
+
+ // Was this profile stubbed to save memory (and no longer valid
+ // for building color conversion tables)?
+
+ bool fWasStubbed;
+
+ public:
+
+ dng_camera_profile ();
+
+ virtual ~dng_camera_profile ();
+
+ // API for profile name:
+
+ /// Setter for camera profile name.
+ /// \param name Name to use for this camera profile.
+
+ void SetName (const char *name)
+ {
+ fName.Set (name);
+ ClearFingerprint ();
+ }
+
+ /// Getter for camera profile name.
+ /// \retval Name of profile.
+
+ const dng_string & Name () const
+ {
+ return fName;
+ }
+
+ /// Test if this name is embedded.
+ /// \retval true if the name matches the name of the embedded camera profile.
+
+ bool NameIsEmbedded () const
+ {
+ return fName.Matches (kProfileName_Embedded, true);
+ }
+
+ // API for calibration illuminants:
+
+ /// Setter for first of up to two light sources used for calibration.
+ /// Uses the EXIF encodings for illuminant and is used to distinguish which
+ /// matrix to use.
+ /// Corresponds to the DNG CalibrationIlluminant1 tag.
+
+ void SetCalibrationIlluminant1 (uint32 light)
+ {
+ fCalibrationIlluminant1 = light;
+ ClearFingerprint ();
+ }
+
+ /// Setter for second of up to two light sources used for calibration.
+ /// Uses the EXIF encodings for illuminant and is used to distinguish which
+ /// matrix to use.
+ /// Corresponds to the DNG CalibrationIlluminant2 tag.
+
+ void SetCalibrationIlluminant2 (uint32 light)
+ {
+ fCalibrationIlluminant2 = light;
+ ClearFingerprint ();
+ }
+
+ /// Getter for first of up to two light sources used for calibration.
+ /// Uses the EXIF encodings for illuminant and is used to distinguish which
+ /// matrix to use.
+ /// Corresponds to the DNG CalibrationIlluminant1 tag.
+
+ uint32 CalibrationIlluminant1 () const
+ {
+ return fCalibrationIlluminant1;
+ }
+
+ /// Getter for second of up to two light sources used for calibration.
+ /// Uses the EXIF encodings for illuminant and is used to distinguish which
+ /// matrix to use.
+ /// Corresponds to the DNG CalibrationIlluminant2 tag.
+
+ uint32 CalibrationIlluminant2 () const
+ {
+ return fCalibrationIlluminant2;
+ }
+
+ /// Getter for first of up to two light sources used for calibration, returning
+ /// result as color temperature.
+
+ real64 CalibrationTemperature1 () const
+ {
+ return IlluminantToTemperature (CalibrationIlluminant1 ());
+ }
+
+ /// Getter for second of up to two light sources used for calibration, returning
+ /// result as color temperature.
+
+ real64 CalibrationTemperature2 () const
+ {
+ return IlluminantToTemperature (CalibrationIlluminant2 ());
+ }
+
+ // API for color matrices:
+
+ /// Utility function to normalize the scale of the color matrix.
+
+ static void NormalizeColorMatrix (dng_matrix &m);
+
+ /// Setter for first of up to two color matrices used for reference camera calibrations.
+ /// These matrices map XYZ values to camera values. The DNG SDK needs to map colors
+ /// that direction in order to determine the clipping points for
+ /// highlight recovery logic based on the white point. If cameras
+ /// were all three-color, the matrix could be stored as a forward matrix.
+ /// The inverse matrix is requried to support four-color cameras.
+
+ void SetColorMatrix1 (const dng_matrix &m);
+
+ /// Setter for second of up to two color matrices used for reference camera calibrations.
+ /// These matrices map XYZ values to camera values. The DNG SDK needs to map colors
+ /// that direction in order to determine the clipping points for
+ /// highlight recovery logic based on the white point. If cameras
+ /// were all three-color, the matrix could be stored as a forward matrix.
+ /// The inverse matrix is requried to support four-color cameras.
+
+ void SetColorMatrix2 (const dng_matrix &m);
+
+ /// Predicate to test if first camera matrix is set
+
+ bool HasColorMatrix1 () const;
+
+ /// Predicate to test if second camera matrix is set
+
+ bool HasColorMatrix2 () const;
+
+ /// Getter for first of up to two color matrices used for calibrations.
+
+ const dng_matrix & ColorMatrix1 () const
+ {
+ return fColorMatrix1;
+ }
+
+ /// Getter for second of up to two color matrices used for calibrations.
+
+ const dng_matrix & ColorMatrix2 () const
+ {
+ return fColorMatrix2;
+ }
+
+ // API for forward matrices:
+
+ /// Utility function to normalize the scale of the forward matrix.
+
+ static void NormalizeForwardMatrix (dng_matrix &m);
+
+ /// Setter for first of up to two forward matrices used for calibrations.
+
+ void SetForwardMatrix1 (const dng_matrix &m);
+
+ /// Setter for second of up to two forward matrices used for calibrations.
+
+ void SetForwardMatrix2 (const dng_matrix &m);
+
+ /// Getter for first of up to two forward matrices used for calibrations.
+
+ const dng_matrix & ForwardMatrix1 () const
+ {
+ return fForwardMatrix1;
+ }
+
+ /// Getter for second of up to two forward matrices used for calibrations.
+
+ const dng_matrix & ForwardMatrix2 () const
+ {
+ return fForwardMatrix2;
+ }
+
+ // API for reduction matrices:
+
+ /// Setter for first of up to two dimensionality reduction hints for four-color cameras.
+ /// This is an optional matrix that maps four components to three.
+ /// See Appendix 6 of the \ref spec_dng "DNG 1.1.0 specification."
+
+ void SetReductionMatrix1 (const dng_matrix &m);
+
+ /// Setter for second of up to two dimensionality reduction hints for four-color cameras.
+ /// This is an optional matrix that maps four components to three.
+ /// See Appendix 6 of the \ref spec_dng "DNG 1.1.0 specification."
+
+ void SetReductionMatrix2 (const dng_matrix &m);
+
+ /// Getter for first of up to two dimensionality reduction hints for four color cameras.
+
+ const dng_matrix & ReductionMatrix1 () const
+ {
+ return fReductionMatrix1;
+ }
+
+ /// Getter for second of up to two dimensionality reduction hints for four color cameras.
+
+ const dng_matrix & ReductionMatrix2 () const
+ {
+ return fReductionMatrix2;
+ }
+
+ /// Getter function from profile fingerprint.
+
+ const dng_fingerprint &Fingerprint () const
+ {
+
+ if (!fFingerprint.IsValid ())
+ CalculateFingerprint ();
+
+ return fFingerprint;
+
+ }
+
+ /// Getter for camera profile id.
+ /// \retval ID of profile.
+
+ dng_camera_profile_id ProfileID () const
+ {
+ return dng_camera_profile_id (Name (), Fingerprint ());
+ }
+
+ /// Setter for camera profile copyright.
+ /// \param copyright Copyright string to use for this camera profile.
+
+ void SetCopyright (const char *copyright)
+ {
+ fCopyright.Set (copyright);
+ ClearFingerprint ();
+ }
+
+ /// Getter for camera profile copyright.
+ /// \retval Copyright string for profile.
+
+ const dng_string & Copyright () const
+ {
+ return fCopyright;
+ }
+
+ // Accessors for embed policy.
+
+ /// Setter for camera profile embed policy.
+ /// \param policy Policy to use for this camera profile.
+
+ void SetEmbedPolicy (uint32 policy)
+ {
+ fEmbedPolicy = policy;
+ ClearFingerprint ();
+ }
+
+ /// Getter for camera profile embed policy.
+ /// \param Policy for profile.
+
+ uint32 EmbedPolicy () const
+ {
+ return fEmbedPolicy;
+ }
+
+ /// Returns true iff the profile is legal to embed in a DNG, per the
+ /// profile's embed policy.
+
+ bool IsLegalToEmbed () const
+ {
+ return WasReadFromDNG () ||
+ EmbedPolicy () == pepAllowCopying ||
+ EmbedPolicy () == pepEmbedIfUsed ||
+ EmbedPolicy () == pepNoRestrictions;
+ }
+
+ // Accessors for hue sat maps.
+
+ /// Returns true iff the profile has a valid HueSatMap color table.
+
+ bool HasHueSatDeltas () const
+ {
+ return fHueSatDeltas1.IsValid ();
+ }
+
+ /// Getter for first HueSatMap color table (for calibration illuminant 1).
+
+ const dng_hue_sat_map & HueSatDeltas1 () const
+ {
+ return fHueSatDeltas1;
+ }
+
+ /// Setter for first HueSatMap color table (for calibration illuminant 1).
+
+ void SetHueSatDeltas1 (const dng_hue_sat_map &deltas1);
+
+ /// Getter for second HueSatMap color table (for calibration illuminant 2).
+
+ const dng_hue_sat_map & HueSatDeltas2 () const
+ {
+ return fHueSatDeltas2;
+ }
+
+ /// Setter for second HueSatMap color table (for calibration illuminant 2).
+
+ void SetHueSatDeltas2 (const dng_hue_sat_map &deltas2);
+
+ // Accessors for hue sat map encoding.
+
+ /// Returns the hue sat map encoding (see ProfileHueSatMapEncoding tag).
+
+ uint32 HueSatMapEncoding () const
+ {
+ return fHueSatMapEncoding;
+ }
+
+ /// Sets the hue sat map encoding (see ProfileHueSatMapEncoding tag) to the
+ /// specified encoding.
+
+ void SetHueSatMapEncoding (uint32 encoding)
+ {
+ fHueSatMapEncoding = encoding;
+ ClearFingerprint ();
+ }
+
+ // Accessors for look table.
+
+ /// Returns true if the profile has a LookTable.
+
+ bool HasLookTable () const
+ {
+ return fLookTable.IsValid ();
+ }
+
+ /// Getter for LookTable.
+
+ const dng_hue_sat_map & LookTable () const
+ {
+ return fLookTable;
+ }
+
+ /// Setter for LookTable.
+
+ void SetLookTable (const dng_hue_sat_map &table);
+
+ // Accessors for look table encoding.
+
+ /// Returns the LookTable encoding (see ProfileLookTableEncoding tag).
+
+ uint32 LookTableEncoding () const
+ {
+ return fLookTableEncoding;
+ }
+
+ /// Sets the LookTable encoding (see ProfileLookTableEncoding tag) to the
+ /// specified encoding.
+
+ void SetLookTableEncoding (uint32 encoding)
+ {
+ fLookTableEncoding = encoding;
+ ClearFingerprint ();
+ }
+
+ // Accessors for baseline exposure offset.
+
+ /// Sets the baseline exposure offset of the profile (see
+ /// BaselineExposureOffset tag) to the specified value.
+
+ void SetBaselineExposureOffset (real64 exposureOffset)
+ {
+ fBaselineExposureOffset.Set_real64 (exposureOffset, 100);
+ ClearFingerprint ();
+ }
+
+ /// Returns the baseline exposure offset of the profile (see
+ /// BaselineExposureOffset tag).
+
+ const dng_srational & BaselineExposureOffset () const
+ {
+ return fBaselineExposureOffset;
+ }
+
+ // Accessors for default black render.
+
+ /// Sets the default black render of the profile (see DefaultBlackRender tag)
+ /// to the specified option.
+
+ void SetDefaultBlackRender (uint32 defaultBlackRender)
+ {
+ fDefaultBlackRender = defaultBlackRender;
+ ClearFingerprint ();
+ }
+
+ /// Returns the default black render of the profile (see DefaultBlackRender
+ /// tag).
+
+ uint32 DefaultBlackRender () const
+ {
+ return fDefaultBlackRender;
+ }
+
+ // Accessors for tone curve.
+
+ /// Returns the tone curve of the profile.
+
+ const dng_tone_curve & ToneCurve () const
+ {
+ return fToneCurve;
+ }
+
+ /// Sets the tone curve of the profile to the specified curve.
+
+ void SetToneCurve (const dng_tone_curve &curve)
+ {
+ fToneCurve = curve;
+ ClearFingerprint ();
+ }
+
+ // Accessors for profile calibration signature.
+
+ /// Sets the profile calibration signature (see ProfileCalibrationSignature
+ /// tag) to the specified string.
+
+ void SetProfileCalibrationSignature (const char *signature)
+ {
+ fProfileCalibrationSignature.Set (signature);
+ }
+
+ /// Returns the profile calibration signature (see ProfileCalibrationSignature
+ /// tag) of the profile.
+
+ const dng_string & ProfileCalibrationSignature () const
+ {
+ return fProfileCalibrationSignature;
+ }
+
+ /// Setter for camera unique model name to restrict use of this profile.
+ /// \param camera Camera unique model name designating only camera this
+ /// profile can be used with. (Empty string for no restriction.)
+
+ void SetUniqueCameraModelRestriction (const char *camera)
+ {
+ fUniqueCameraModelRestriction.Set (camera);
+ // Not included in fingerprint, so don't need ClearFingerprint ().
+ }
+
+ /// Getter for camera unique model name to restrict use of this profile.
+ /// \retval Unique model name of only camera this profile can be used with
+ /// or empty if no restriction.
+
+ const dng_string & UniqueCameraModelRestriction () const
+ {
+ return fUniqueCameraModelRestriction;
+ }
+
+ // Accessors for was read from DNG flag.
+
+ /// Sets internal flag to indicate this profile was originally read from a
+ /// DNG file.
+
+ void SetWasReadFromDNG (bool state = true)
+ {
+ fWasReadFromDNG = state;
+ }
+
+ /// Was this profile read from a DNG?
+
+ bool WasReadFromDNG () const
+ {
+ return fWasReadFromDNG;
+ }
+
+ // Accessors for was read from disk flag.
+
+ /// Sets internal flag to indicate this profile was originally read from
+ /// disk.
+
+ void SetWasReadFromDisk (bool state = true)
+ {
+ fWasReadFromDisk = state;
+ }
+
+ /// Was this profile read from disk?
+
+ bool WasReadFromDisk () const
+ {
+ return fWasReadFromDisk;
+ }
+
+ // Accessors for was built-in matrix flag.
+
+ /// Sets internal flag to indicate this profile was originally a built-in
+ /// matrix profile.
+
+ void SetWasBuiltinMatrix (bool state = true)
+ {
+ fWasBuiltinMatrix = state;
+ }
+
+ /// Was this profile a built-in matrix profile?
+
+ bool WasBuiltinMatrix () const
+ {
+ return fWasBuiltinMatrix;
+ }
+
+ /// Determines if this a valid profile for this number of color channels?
+ /// \retval true if the profile is valid.
+
+ bool IsValid (uint32 channels) const;
+
+ /// Predicate to check if two camera profiles are colorwise equal, thus ignores
+ /// the profile name.
+ /// \param profile Camera profile to compare to.
+
+ bool EqualData (const dng_camera_profile &profile) const;
+
+ /// Parse profile from dng_camera_profile_info data.
+
+ void Parse (dng_stream &stream,
+ dng_camera_profile_info &profileInfo);
+
+ /// Parse from an extended profile stream, which is similar to stand alone
+ /// TIFF file.
+
+ bool ParseExtended (dng_stream &stream);
+
+ /// Convert from a three-color to a four-color Bayer profile.
+
+ virtual void SetFourColorBayer ();
+
+ /// Find the hue/sat table to use for a given white point, if any.
+ /// The calling routine owns the resulting table.
+
+ dng_hue_sat_map * HueSatMapForWhite (const dng_xy_coord &white) const;
+
+ /// Stub out the profile (free memory used by large tables).
+
+ void Stub ();
+
+ /// Was this profile stubbed?
+
+ bool WasStubbed () const
+ {
+ return fWasStubbed;
+ }
+
+ protected:
+
+ static real64 IlluminantToTemperature (uint32 light);
+
+ void ClearFingerprint ()
+ {
+ fFingerprint.Clear ();
+ }
+
+ void CalculateFingerprint () const;
+
+ static bool ValidForwardMatrix (const dng_matrix &m);
+
+ static void ReadHueSatMap (dng_stream &stream,
+ dng_hue_sat_map &hueSatMap,
+ uint32 hues,
+ uint32 sats,
+ uint32 vals,
+ bool skipSat0);
+
+ };
+
+/******************************************************************************/
+
+void SplitCameraProfileName (const dng_string &name,
+ dng_string &baseName,
+ int32 &version);
+
+/*****************************************************************************/
+
+void BuildHueSatMapEncodingTable (dng_memory_allocator &allocator,
+ uint32 encoding,
+ AutoPtr<dng_1d_table> &encodeTable,
+ AutoPtr<dng_1d_table> &decodeTable,
+ bool subSample);
+
+/******************************************************************************/
+
+#endif
+
+/******************************************************************************/
diff --git a/source/dng_classes.h b/source/dng_classes.h
index be72c4a..1192bd8 100644
--- a/source/dng_classes.h
+++ b/source/dng_classes.h
@@ -1,100 +1,100 @@
-/*****************************************************************************/
-// Copyright 2006-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_classes.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*** \file
- * Forward class declarations to avoid having to include many .h files in most places.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_classes__
-#define __dng_classes__
-
-/*****************************************************************************/
-
-class dng_1d_function;
-class dng_1d_table;
-class dng_abort_sniffer;
-class dng_area_task;
-class dng_basic_tag_set;
-class dng_camera_profile;
-class dng_camera_profile_id;
-class dng_camera_profile_info;
-class dng_color_space;
-class dng_color_spec;
-class dng_date_time;
-class dng_date_time_info;
-class dng_exif;
-class dng_fingerprint;
-class dng_host;
-class dng_hue_sat_map;
-class dng_ifd;
-class dng_image;
-class dng_image_preview;
-class dng_image_writer;
-class dng_info;
-class dng_iptc;
-class dng_jpeg_image;
-class dng_jpeg_preview;
-class dng_linearization_info;
-class dng_matrix;
-class dng_matrix_3by3;
-class dng_matrix_4by3;
-class dng_md5_printer;
-class dng_memory_allocator;
-class dng_memory_block;
-class dng_memory_data;
-class dng_memory_stream;
-class dng_metadata;
-class dng_mosaic_info;
-class dng_mutex;
-class dng_noise_function;
-class dng_noise_profile;
-class dng_opcode;
-class dng_opcode_list;
-class dng_orientation;
-class dng_negative;
-class dng_pixel_buffer;
-class dng_point;
-class dng_point_real64;
-class dng_preview;
-class dng_preview_info;
-class dng_preview_list;
-class dng_raw_preview;
-class dng_read_image;
-class dng_rect;
-class dng_rect_real64;
-class dng_render;
-class dng_resolution;
-class dng_shared;
-class dng_spline_solver;
-class dng_srational;
-class dng_stream;
-class dng_string;
-class dng_string_list;
-class dng_tiff_directory;
-class dng_tile_buffer;
-class dng_time_zone;
-class dng_tone_curve;
-class dng_urational;
-class dng_vector;
-class dng_vector_3;
-class dng_xmp;
-class dng_xmp_sdk;
-class dng_xy_coord;
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_classes.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*** \file
+ * Forward class declarations to avoid having to include many .h files in most places.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_classes__
+#define __dng_classes__
+
+/*****************************************************************************/
+
+class dng_1d_function;
+class dng_1d_table;
+class dng_abort_sniffer;
+class dng_area_task;
+class dng_basic_tag_set;
+class dng_camera_profile;
+class dng_camera_profile_id;
+class dng_camera_profile_info;
+class dng_color_space;
+class dng_color_spec;
+class dng_date_time;
+class dng_date_time_info;
+class dng_exif;
+class dng_fingerprint;
+class dng_host;
+class dng_hue_sat_map;
+class dng_ifd;
+class dng_image;
+class dng_image_preview;
+class dng_image_writer;
+class dng_info;
+class dng_iptc;
+class dng_jpeg_image;
+class dng_jpeg_preview;
+class dng_linearization_info;
+class dng_matrix;
+class dng_matrix_3by3;
+class dng_matrix_4by3;
+class dng_md5_printer;
+class dng_memory_allocator;
+class dng_memory_block;
+class dng_memory_data;
+class dng_memory_stream;
+class dng_metadata;
+class dng_mosaic_info;
+class dng_mutex;
+class dng_noise_function;
+class dng_noise_profile;
+class dng_opcode;
+class dng_opcode_list;
+class dng_orientation;
+class dng_negative;
+class dng_pixel_buffer;
+class dng_point;
+class dng_point_real64;
+class dng_preview;
+class dng_preview_info;
+class dng_preview_list;
+class dng_raw_preview;
+class dng_read_image;
+class dng_rect;
+class dng_rect_real64;
+class dng_render;
+class dng_resolution;
+class dng_shared;
+class dng_spline_solver;
+class dng_srational;
+class dng_stream;
+class dng_string;
+class dng_string_list;
+class dng_tiff_directory;
+class dng_tile_buffer;
+class dng_time_zone;
+class dng_tone_curve;
+class dng_urational;
+class dng_vector;
+class dng_vector_3;
+class dng_xmp;
+class dng_xmp_sdk;
+class dng_xy_coord;
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_color_space.cpp b/source/dng_color_space.cpp
index 72d465f..a3f4c9a 100644
--- a/source/dng_color_space.cpp
+++ b/source/dng_color_space.cpp
@@ -1,1072 +1,1072 @@
-/*****************************************************************************/
-// Copyright 2006-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_color_space.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-#include "dng_color_space.h"
-
-#include "dng_1d_table.h"
-#include "dng_exceptions.h"
-#include "dng_flags.h"
-#include "dng_matrix.h"
-#include "dng_spline.h"
-#include "dng_utils.h"
-#include "dng_xy_coord.h"
-
-/*****************************************************************************/
-
-real64 dng_function_GammaEncode_sRGB::Evaluate (real64 x) const
- {
-
- if (x <= 0.0031308)
- return x * 12.92;
-
- else
- return 1.055 * pow (x, 1.0 / 2.4) - 0.055;
-
- }
-
-/*****************************************************************************/
-
-real64 dng_function_GammaEncode_sRGB::EvaluateInverse (real64 y) const
- {
-
- if (y <= 0.0031308 * 12.92)
- return y * (1.0 / 12.92);
-
- else
- return pow ((y + 0.055) * (1.0 / 1.055), 2.4);
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_function_GammaEncode_sRGB::Get ()
- {
-
- static dng_function_GammaEncode_sRGB static_function;
-
- return static_function;
-
- }
-
-/*****************************************************************************/
-
-real64 dng_function_GammaEncode_1_8::Evaluate (real64 x) const
- {
-
- const real64 gamma = 1.0 / 1.8;
-
- const real64 slope0 = 32.0;
-
- const real64 x1 = 8.2118790552e-4; // pow (slope0, 1.0 / (gamma - 1.0)) * 2.0
-
- const real64 y1 = 0.019310851; // pow (x1, gamma)
-
- const real64 slope1 = 13.064306598; // gamma * pow (x1, gamma - 1.0)
-
- if (x <= x1)
- return EvaluateSplineSegment (x,
- 0.0,
- 0.0,
- slope0,
- x1,
- y1,
- slope1);
-
- else
- return pow (x, gamma);
-
- }
-
-/*****************************************************************************/
-
-real64 dng_function_GammaEncode_1_8::EvaluateInverse (real64 y) const
- {
-
- if (y > 0.0 && y < 0.019310851)
- {
-
- return dng_1d_function::EvaluateInverse (y);
-
- }
-
- return pow (y, 1.8);
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_function_GammaEncode_1_8::Get ()
- {
-
- static dng_function_GammaEncode_1_8 static_function;
-
- return static_function;
-
- }
-
-/*****************************************************************************/
-
-real64 dng_function_GammaEncode_2_2::Evaluate (real64 x) const
- {
-
- const real64 gamma = 1.0 / 2.2;
-
- const real64 slope0 = 32.0;
-
- const real64 x1 = 0.0034800731; // pow (slope0, 1.0 / (gamma - 1.0)) * 2.0
-
- const real64 y1 = 0.0763027458; // pow (x1, gamma)
-
- const real64 slope1 = 9.9661890075; // gamma * pow (x1, gamma - 1.0)
-
- if (x <= x1)
- return EvaluateSplineSegment (x,
- 0.0,
- 0.0,
- slope0,
- x1,
- y1,
- slope1);
-
- else
- return pow (x, gamma);
-
- }
-
-/*****************************************************************************/
-
-real64 dng_function_GammaEncode_2_2::EvaluateInverse (real64 y) const
- {
-
- if (y > 0.0 && y < 0.0763027458)
- {
-
- return dng_1d_function::EvaluateInverse (y);
-
- }
-
- return pow (y, 2.2);
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_function_GammaEncode_2_2::Get ()
- {
-
- static dng_function_GammaEncode_2_2 static_function;
-
- return static_function;
-
- }
-
-/*****************************************************************************/
-
-dng_color_space::dng_color_space ()
-
- : fMatrixToPCS ()
- , fMatrixFromPCS ()
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_color_space::~dng_color_space ()
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_color_space::SetMonochrome ()
- {
-
- fMatrixToPCS = PCStoXYZ ().AsColumn ();
-
- dng_matrix m (1, 3);
-
- m [0] [0] = 0.0;
- m [0] [1] = 1.0;
- m [0] [2] = 0.0;
-
- fMatrixFromPCS = m;
-
- }
-
-/*****************************************************************************/
-
-void dng_color_space::SetMatrixToPCS (const dng_matrix_3by3 &M)
- {
-
- // The matrix values are often rounded, so adjust to
- // get them to convert device white exactly to the PCS.
-
- dng_vector_3 W1 = M * dng_vector_3 (1.0, 1.0, 1.0);
- dng_vector_3 W2 = PCStoXYZ ();
-
- real64 s0 = W2 [0] / W1 [0];
- real64 s1 = W2 [1] / W1 [1];
- real64 s2 = W2 [2] / W1 [2];
-
- dng_matrix_3by3 S (s0, 0, 0,
- 0, s1, 0,
- 0, 0, s2);
-
- fMatrixToPCS = S * M;
-
- // Find reverse matrix.
-
- fMatrixFromPCS = Invert (fMatrixToPCS);
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_color_space::GammaFunction () const
- {
-
- return dng_1d_identity::Get ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_color_space::ICCProfile (uint32 &size,
- const uint8 *&data) const
- {
-
- size = 0;
- data = NULL;
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-dng_space_sRGB::dng_space_sRGB ()
- {
-
- SetMatrixToPCS (dng_matrix_3by3 (0.4361, 0.3851, 0.1431,
- 0.2225, 0.7169, 0.0606,
- 0.0139, 0.0971, 0.7141));
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_space_sRGB::GammaFunction () const
- {
-
- return dng_function_GammaEncode_sRGB::Get ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_space_sRGB::ICCProfile (uint32 &size,
- const uint8 *&data) const
-
- {
-
- static const uint8 ksRGBProfileData [] =
- {
- 0x00, 0x00, 0x0C, 0x48, 0x4C, 0x69, 0x6E, 0x6F, 0x02, 0x10, 0x00, 0x00,
- 0x6D, 0x6E, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5A, 0x20,
- 0x07, 0xCE, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00,
- 0x61, 0x63, 0x73, 0x70, 0x4D, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
- 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x48, 0x50, 0x20, 0x20,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
- 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x33,
- 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x00, 0x6C,
- 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x14,
- 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14,
- 0x72, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x14,
- 0x67, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x00, 0x14,
- 0x62, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14,
- 0x64, 0x6D, 0x6E, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
- 0x64, 0x6D, 0x64, 0x64, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x88,
- 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x4C, 0x00, 0x00, 0x00, 0x86,
- 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xD4, 0x00, 0x00, 0x00, 0x24,
- 0x6C, 0x75, 0x6D, 0x69, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x14,
- 0x6D, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0C, 0x00, 0x00, 0x00, 0x24,
- 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x0C,
- 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3C, 0x00, 0x00, 0x08, 0x0C,
- 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3C, 0x00, 0x00, 0x08, 0x0C,
- 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3C, 0x00, 0x00, 0x08, 0x0C,
- 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
- 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39,
- 0x39, 0x38, 0x20, 0x48, 0x65, 0x77, 0x6C, 0x65, 0x74, 0x74, 0x2D, 0x50,
- 0x61, 0x63, 0x6B, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x61,
- 0x6E, 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43,
- 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32, 0x2E, 0x31, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47,
- 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32,
- 0x2E, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xF3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xCC,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xA2, 0x00, 0x00, 0x38, 0xF5,
- 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xB7, 0x85, 0x00, 0x00, 0x18, 0xDA,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xA0,
- 0x00, 0x00, 0x0F, 0x84, 0x00, 0x00, 0xB6, 0xCF, 0x64, 0x65, 0x73, 0x63,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
- 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x69,
- 0x65, 0x63, 0x2E, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
- 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x69, 0x65, 0x63, 0x2E,
- 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E,
- 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32, 0x2E,
- 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x52, 0x47,
- 0x42, 0x20, 0x63, 0x6F, 0x6C, 0x6F, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
- 0x63, 0x65, 0x20, 0x2D, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x49, 0x45, 0x43,
- 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32, 0x2E, 0x31, 0x20, 0x44,
- 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
- 0x6F, 0x6C, 0x6F, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
- 0x2D, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x2C, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63,
- 0x65, 0x20, 0x56, 0x69, 0x65, 0x77, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x6F,
- 0x6E, 0x64, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x49,
- 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32, 0x2E, 0x31, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x52,
- 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
- 0x77, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x6F, 0x6E, 0x64, 0x69, 0x74, 0x69,
- 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39,
- 0x36, 0x36, 0x2D, 0x32, 0x2E, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x65, 0x77,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA4, 0xFE, 0x00, 0x14, 0x5F, 0x2E,
- 0x00, 0x10, 0xCF, 0x14, 0x00, 0x03, 0xED, 0xCC, 0x00, 0x04, 0x13, 0x0B,
- 0x00, 0x03, 0x5C, 0x9E, 0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5A, 0x20,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00,
- 0x00, 0x57, 0x1F, 0xE7, 0x6D, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x8F,
- 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F,
- 0x00, 0x14, 0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2D,
- 0x00, 0x32, 0x00, 0x37, 0x00, 0x3B, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4A,
- 0x00, 0x4F, 0x00, 0x54, 0x00, 0x59, 0x00, 0x5E, 0x00, 0x63, 0x00, 0x68,
- 0x00, 0x6D, 0x00, 0x72, 0x00, 0x77, 0x00, 0x7C, 0x00, 0x81, 0x00, 0x86,
- 0x00, 0x8B, 0x00, 0x90, 0x00, 0x95, 0x00, 0x9A, 0x00, 0x9F, 0x00, 0xA4,
- 0x00, 0xA9, 0x00, 0xAE, 0x00, 0xB2, 0x00, 0xB7, 0x00, 0xBC, 0x00, 0xC1,
- 0x00, 0xC6, 0x00, 0xCB, 0x00, 0xD0, 0x00, 0xD5, 0x00, 0xDB, 0x00, 0xE0,
- 0x00, 0xE5, 0x00, 0xEB, 0x00, 0xF0, 0x00, 0xF6, 0x00, 0xFB, 0x01, 0x01,
- 0x01, 0x07, 0x01, 0x0D, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1F, 0x01, 0x25,
- 0x01, 0x2B, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3E, 0x01, 0x45, 0x01, 0x4C,
- 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67, 0x01, 0x6E, 0x01, 0x75,
- 0x01, 0x7C, 0x01, 0x83, 0x01, 0x8B, 0x01, 0x92, 0x01, 0x9A, 0x01, 0xA1,
- 0x01, 0xA9, 0x01, 0xB1, 0x01, 0xB9, 0x01, 0xC1, 0x01, 0xC9, 0x01, 0xD1,
- 0x01, 0xD9, 0x01, 0xE1, 0x01, 0xE9, 0x01, 0xF2, 0x01, 0xFA, 0x02, 0x03,
- 0x02, 0x0C, 0x02, 0x14, 0x02, 0x1D, 0x02, 0x26, 0x02, 0x2F, 0x02, 0x38,
- 0x02, 0x41, 0x02, 0x4B, 0x02, 0x54, 0x02, 0x5D, 0x02, 0x67, 0x02, 0x71,
- 0x02, 0x7A, 0x02, 0x84, 0x02, 0x8E, 0x02, 0x98, 0x02, 0xA2, 0x02, 0xAC,
- 0x02, 0xB6, 0x02, 0xC1, 0x02, 0xCB, 0x02, 0xD5, 0x02, 0xE0, 0x02, 0xEB,
- 0x02, 0xF5, 0x03, 0x00, 0x03, 0x0B, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2D,
- 0x03, 0x38, 0x03, 0x43, 0x03, 0x4F, 0x03, 0x5A, 0x03, 0x66, 0x03, 0x72,
- 0x03, 0x7E, 0x03, 0x8A, 0x03, 0x96, 0x03, 0xA2, 0x03, 0xAE, 0x03, 0xBA,
- 0x03, 0xC7, 0x03, 0xD3, 0x03, 0xE0, 0x03, 0xEC, 0x03, 0xF9, 0x04, 0x06,
- 0x04, 0x13, 0x04, 0x20, 0x04, 0x2D, 0x04, 0x3B, 0x04, 0x48, 0x04, 0x55,
- 0x04, 0x63, 0x04, 0x71, 0x04, 0x7E, 0x04, 0x8C, 0x04, 0x9A, 0x04, 0xA8,
- 0x04, 0xB6, 0x04, 0xC4, 0x04, 0xD3, 0x04, 0xE1, 0x04, 0xF0, 0x04, 0xFE,
- 0x05, 0x0D, 0x05, 0x1C, 0x05, 0x2B, 0x05, 0x3A, 0x05, 0x49, 0x05, 0x58,
- 0x05, 0x67, 0x05, 0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xA6, 0x05, 0xB5,
- 0x05, 0xC5, 0x05, 0xD5, 0x05, 0xE5, 0x05, 0xF6, 0x06, 0x06, 0x06, 0x16,
- 0x06, 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6A, 0x06, 0x7B,
- 0x06, 0x8C, 0x06, 0x9D, 0x06, 0xAF, 0x06, 0xC0, 0x06, 0xD1, 0x06, 0xE3,
- 0x06, 0xF5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2B, 0x07, 0x3D, 0x07, 0x4F,
- 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07, 0xAC, 0x07, 0xBF,
- 0x07, 0xD2, 0x07, 0xE5, 0x07, 0xF8, 0x08, 0x0B, 0x08, 0x1F, 0x08, 0x32,
- 0x08, 0x46, 0x08, 0x5A, 0x08, 0x6E, 0x08, 0x82, 0x08, 0x96, 0x08, 0xAA,
- 0x08, 0xBE, 0x08, 0xD2, 0x08, 0xE7, 0x08, 0xFB, 0x09, 0x10, 0x09, 0x25,
- 0x09, 0x3A, 0x09, 0x4F, 0x09, 0x64, 0x09, 0x79, 0x09, 0x8F, 0x09, 0xA4,
- 0x09, 0xBA, 0x09, 0xCF, 0x09, 0xE5, 0x09, 0xFB, 0x0A, 0x11, 0x0A, 0x27,
- 0x0A, 0x3D, 0x0A, 0x54, 0x0A, 0x6A, 0x0A, 0x81, 0x0A, 0x98, 0x0A, 0xAE,
- 0x0A, 0xC5, 0x0A, 0xDC, 0x0A, 0xF3, 0x0B, 0x0B, 0x0B, 0x22, 0x0B, 0x39,
- 0x0B, 0x51, 0x0B, 0x69, 0x0B, 0x80, 0x0B, 0x98, 0x0B, 0xB0, 0x0B, 0xC8,
- 0x0B, 0xE1, 0x0B, 0xF9, 0x0C, 0x12, 0x0C, 0x2A, 0x0C, 0x43, 0x0C, 0x5C,
- 0x0C, 0x75, 0x0C, 0x8E, 0x0C, 0xA7, 0x0C, 0xC0, 0x0C, 0xD9, 0x0C, 0xF3,
- 0x0D, 0x0D, 0x0D, 0x26, 0x0D, 0x40, 0x0D, 0x5A, 0x0D, 0x74, 0x0D, 0x8E,
- 0x0D, 0xA9, 0x0D, 0xC3, 0x0D, 0xDE, 0x0D, 0xF8, 0x0E, 0x13, 0x0E, 0x2E,
- 0x0E, 0x49, 0x0E, 0x64, 0x0E, 0x7F, 0x0E, 0x9B, 0x0E, 0xB6, 0x0E, 0xD2,
- 0x0E, 0xEE, 0x0F, 0x09, 0x0F, 0x25, 0x0F, 0x41, 0x0F, 0x5E, 0x0F, 0x7A,
- 0x0F, 0x96, 0x0F, 0xB3, 0x0F, 0xCF, 0x0F, 0xEC, 0x10, 0x09, 0x10, 0x26,
- 0x10, 0x43, 0x10, 0x61, 0x10, 0x7E, 0x10, 0x9B, 0x10, 0xB9, 0x10, 0xD7,
- 0x10, 0xF5, 0x11, 0x13, 0x11, 0x31, 0x11, 0x4F, 0x11, 0x6D, 0x11, 0x8C,
- 0x11, 0xAA, 0x11, 0xC9, 0x11, 0xE8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45,
- 0x12, 0x64, 0x12, 0x84, 0x12, 0xA3, 0x12, 0xC3, 0x12, 0xE3, 0x13, 0x03,
- 0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xA4, 0x13, 0xC5,
- 0x13, 0xE5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6A, 0x14, 0x8B,
- 0x14, 0xAD, 0x14, 0xCE, 0x14, 0xF0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56,
- 0x15, 0x78, 0x15, 0x9B, 0x15, 0xBD, 0x15, 0xE0, 0x16, 0x03, 0x16, 0x26,
- 0x16, 0x49, 0x16, 0x6C, 0x16, 0x8F, 0x16, 0xB2, 0x16, 0xD6, 0x16, 0xFA,
- 0x17, 0x1D, 0x17, 0x41, 0x17, 0x65, 0x17, 0x89, 0x17, 0xAE, 0x17, 0xD2,
- 0x17, 0xF7, 0x18, 0x1B, 0x18, 0x40, 0x18, 0x65, 0x18, 0x8A, 0x18, 0xAF,
- 0x18, 0xD5, 0x18, 0xFA, 0x19, 0x20, 0x19, 0x45, 0x19, 0x6B, 0x19, 0x91,
- 0x19, 0xB7, 0x19, 0xDD, 0x1A, 0x04, 0x1A, 0x2A, 0x1A, 0x51, 0x1A, 0x77,
- 0x1A, 0x9E, 0x1A, 0xC5, 0x1A, 0xEC, 0x1B, 0x14, 0x1B, 0x3B, 0x1B, 0x63,
- 0x1B, 0x8A, 0x1B, 0xB2, 0x1B, 0xDA, 0x1C, 0x02, 0x1C, 0x2A, 0x1C, 0x52,
- 0x1C, 0x7B, 0x1C, 0xA3, 0x1C, 0xCC, 0x1C, 0xF5, 0x1D, 0x1E, 0x1D, 0x47,
- 0x1D, 0x70, 0x1D, 0x99, 0x1D, 0xC3, 0x1D, 0xEC, 0x1E, 0x16, 0x1E, 0x40,
- 0x1E, 0x6A, 0x1E, 0x94, 0x1E, 0xBE, 0x1E, 0xE9, 0x1F, 0x13, 0x1F, 0x3E,
- 0x1F, 0x69, 0x1F, 0x94, 0x1F, 0xBF, 0x1F, 0xEA, 0x20, 0x15, 0x20, 0x41,
- 0x20, 0x6C, 0x20, 0x98, 0x20, 0xC4, 0x20, 0xF0, 0x21, 0x1C, 0x21, 0x48,
- 0x21, 0x75, 0x21, 0xA1, 0x21, 0xCE, 0x21, 0xFB, 0x22, 0x27, 0x22, 0x55,
- 0x22, 0x82, 0x22, 0xAF, 0x22, 0xDD, 0x23, 0x0A, 0x23, 0x38, 0x23, 0x66,
- 0x23, 0x94, 0x23, 0xC2, 0x23, 0xF0, 0x24, 0x1F, 0x24, 0x4D, 0x24, 0x7C,
- 0x24, 0xAB, 0x24, 0xDA, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97,
- 0x25, 0xC7, 0x25, 0xF7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xB7,
- 0x26, 0xE8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7A, 0x27, 0xAB, 0x27, 0xDC,
- 0x28, 0x0D, 0x28, 0x3F, 0x28, 0x71, 0x28, 0xA2, 0x28, 0xD4, 0x29, 0x06,
- 0x29, 0x38, 0x29, 0x6B, 0x29, 0x9D, 0x29, 0xD0, 0x2A, 0x02, 0x2A, 0x35,
- 0x2A, 0x68, 0x2A, 0x9B, 0x2A, 0xCF, 0x2B, 0x02, 0x2B, 0x36, 0x2B, 0x69,
- 0x2B, 0x9D, 0x2B, 0xD1, 0x2C, 0x05, 0x2C, 0x39, 0x2C, 0x6E, 0x2C, 0xA2,
- 0x2C, 0xD7, 0x2D, 0x0C, 0x2D, 0x41, 0x2D, 0x76, 0x2D, 0xAB, 0x2D, 0xE1,
- 0x2E, 0x16, 0x2E, 0x4C, 0x2E, 0x82, 0x2E, 0xB7, 0x2E, 0xEE, 0x2F, 0x24,
- 0x2F, 0x5A, 0x2F, 0x91, 0x2F, 0xC7, 0x2F, 0xFE, 0x30, 0x35, 0x30, 0x6C,
- 0x30, 0xA4, 0x30, 0xDB, 0x31, 0x12, 0x31, 0x4A, 0x31, 0x82, 0x31, 0xBA,
- 0x31, 0xF2, 0x32, 0x2A, 0x32, 0x63, 0x32, 0x9B, 0x32, 0xD4, 0x33, 0x0D,
- 0x33, 0x46, 0x33, 0x7F, 0x33, 0xB8, 0x33, 0xF1, 0x34, 0x2B, 0x34, 0x65,
- 0x34, 0x9E, 0x34, 0xD8, 0x35, 0x13, 0x35, 0x4D, 0x35, 0x87, 0x35, 0xC2,
- 0x35, 0xFD, 0x36, 0x37, 0x36, 0x72, 0x36, 0xAE, 0x36, 0xE9, 0x37, 0x24,
- 0x37, 0x60, 0x37, 0x9C, 0x37, 0xD7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8C,
- 0x38, 0xC8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7F, 0x39, 0xBC, 0x39, 0xF9,
- 0x3A, 0x36, 0x3A, 0x74, 0x3A, 0xB2, 0x3A, 0xEF, 0x3B, 0x2D, 0x3B, 0x6B,
- 0x3B, 0xAA, 0x3B, 0xE8, 0x3C, 0x27, 0x3C, 0x65, 0x3C, 0xA4, 0x3C, 0xE3,
- 0x3D, 0x22, 0x3D, 0x61, 0x3D, 0xA1, 0x3D, 0xE0, 0x3E, 0x20, 0x3E, 0x60,
- 0x3E, 0xA0, 0x3E, 0xE0, 0x3F, 0x21, 0x3F, 0x61, 0x3F, 0xA2, 0x3F, 0xE2,
- 0x40, 0x23, 0x40, 0x64, 0x40, 0xA6, 0x40, 0xE7, 0x41, 0x29, 0x41, 0x6A,
- 0x41, 0xAC, 0x41, 0xEE, 0x42, 0x30, 0x42, 0x72, 0x42, 0xB5, 0x42, 0xF7,
- 0x43, 0x3A, 0x43, 0x7D, 0x43, 0xC0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8A,
- 0x44, 0xCE, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9A, 0x45, 0xDE, 0x46, 0x22,
- 0x46, 0x67, 0x46, 0xAB, 0x46, 0xF0, 0x47, 0x35, 0x47, 0x7B, 0x47, 0xC0,
- 0x48, 0x05, 0x48, 0x4B, 0x48, 0x91, 0x48, 0xD7, 0x49, 0x1D, 0x49, 0x63,
- 0x49, 0xA9, 0x49, 0xF0, 0x4A, 0x37, 0x4A, 0x7D, 0x4A, 0xC4, 0x4B, 0x0C,
- 0x4B, 0x53, 0x4B, 0x9A, 0x4B, 0xE2, 0x4C, 0x2A, 0x4C, 0x72, 0x4C, 0xBA,
- 0x4D, 0x02, 0x4D, 0x4A, 0x4D, 0x93, 0x4D, 0xDC, 0x4E, 0x25, 0x4E, 0x6E,
- 0x4E, 0xB7, 0x4F, 0x00, 0x4F, 0x49, 0x4F, 0x93, 0x4F, 0xDD, 0x50, 0x27,
- 0x50, 0x71, 0x50, 0xBB, 0x51, 0x06, 0x51, 0x50, 0x51, 0x9B, 0x51, 0xE6,
- 0x52, 0x31, 0x52, 0x7C, 0x52, 0xC7, 0x53, 0x13, 0x53, 0x5F, 0x53, 0xAA,
- 0x53, 0xF6, 0x54, 0x42, 0x54, 0x8F, 0x54, 0xDB, 0x55, 0x28, 0x55, 0x75,
- 0x55, 0xC2, 0x56, 0x0F, 0x56, 0x5C, 0x56, 0xA9, 0x56, 0xF7, 0x57, 0x44,
- 0x57, 0x92, 0x57, 0xE0, 0x58, 0x2F, 0x58, 0x7D, 0x58, 0xCB, 0x59, 0x1A,
- 0x59, 0x69, 0x59, 0xB8, 0x5A, 0x07, 0x5A, 0x56, 0x5A, 0xA6, 0x5A, 0xF5,
- 0x5B, 0x45, 0x5B, 0x95, 0x5B, 0xE5, 0x5C, 0x35, 0x5C, 0x86, 0x5C, 0xD6,
- 0x5D, 0x27, 0x5D, 0x78, 0x5D, 0xC9, 0x5E, 0x1A, 0x5E, 0x6C, 0x5E, 0xBD,
- 0x5F, 0x0F, 0x5F, 0x61, 0x5F, 0xB3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xAA,
- 0x60, 0xFC, 0x61, 0x4F, 0x61, 0xA2, 0x61, 0xF5, 0x62, 0x49, 0x62, 0x9C,
- 0x62, 0xF0, 0x63, 0x43, 0x63, 0x97, 0x63, 0xEB, 0x64, 0x40, 0x64, 0x94,
- 0x64, 0xE9, 0x65, 0x3D, 0x65, 0x92, 0x65, 0xE7, 0x66, 0x3D, 0x66, 0x92,
- 0x66, 0xE8, 0x67, 0x3D, 0x67, 0x93, 0x67, 0xE9, 0x68, 0x3F, 0x68, 0x96,
- 0x68, 0xEC, 0x69, 0x43, 0x69, 0x9A, 0x69, 0xF1, 0x6A, 0x48, 0x6A, 0x9F,
- 0x6A, 0xF7, 0x6B, 0x4F, 0x6B, 0xA7, 0x6B, 0xFF, 0x6C, 0x57, 0x6C, 0xAF,
- 0x6D, 0x08, 0x6D, 0x60, 0x6D, 0xB9, 0x6E, 0x12, 0x6E, 0x6B, 0x6E, 0xC4,
- 0x6F, 0x1E, 0x6F, 0x78, 0x6F, 0xD1, 0x70, 0x2B, 0x70, 0x86, 0x70, 0xE0,
- 0x71, 0x3A, 0x71, 0x95, 0x71, 0xF0, 0x72, 0x4B, 0x72, 0xA6, 0x73, 0x01,
- 0x73, 0x5D, 0x73, 0xB8, 0x74, 0x14, 0x74, 0x70, 0x74, 0xCC, 0x75, 0x28,
- 0x75, 0x85, 0x75, 0xE1, 0x76, 0x3E, 0x76, 0x9B, 0x76, 0xF8, 0x77, 0x56,
- 0x77, 0xB3, 0x78, 0x11, 0x78, 0x6E, 0x78, 0xCC, 0x79, 0x2A, 0x79, 0x89,
- 0x79, 0xE7, 0x7A, 0x46, 0x7A, 0xA5, 0x7B, 0x04, 0x7B, 0x63, 0x7B, 0xC2,
- 0x7C, 0x21, 0x7C, 0x81, 0x7C, 0xE1, 0x7D, 0x41, 0x7D, 0xA1, 0x7E, 0x01,
- 0x7E, 0x62, 0x7E, 0xC2, 0x7F, 0x23, 0x7F, 0x84, 0x7F, 0xE5, 0x80, 0x47,
- 0x80, 0xA8, 0x81, 0x0A, 0x81, 0x6B, 0x81, 0xCD, 0x82, 0x30, 0x82, 0x92,
- 0x82, 0xF4, 0x83, 0x57, 0x83, 0xBA, 0x84, 0x1D, 0x84, 0x80, 0x84, 0xE3,
- 0x85, 0x47, 0x85, 0xAB, 0x86, 0x0E, 0x86, 0x72, 0x86, 0xD7, 0x87, 0x3B,
- 0x87, 0x9F, 0x88, 0x04, 0x88, 0x69, 0x88, 0xCE, 0x89, 0x33, 0x89, 0x99,
- 0x89, 0xFE, 0x8A, 0x64, 0x8A, 0xCA, 0x8B, 0x30, 0x8B, 0x96, 0x8B, 0xFC,
- 0x8C, 0x63, 0x8C, 0xCA, 0x8D, 0x31, 0x8D, 0x98, 0x8D, 0xFF, 0x8E, 0x66,
- 0x8E, 0xCE, 0x8F, 0x36, 0x8F, 0x9E, 0x90, 0x06, 0x90, 0x6E, 0x90, 0xD6,
- 0x91, 0x3F, 0x91, 0xA8, 0x92, 0x11, 0x92, 0x7A, 0x92, 0xE3, 0x93, 0x4D,
- 0x93, 0xB6, 0x94, 0x20, 0x94, 0x8A, 0x94, 0xF4, 0x95, 0x5F, 0x95, 0xC9,
- 0x96, 0x34, 0x96, 0x9F, 0x97, 0x0A, 0x97, 0x75, 0x97, 0xE0, 0x98, 0x4C,
- 0x98, 0xB8, 0x99, 0x24, 0x99, 0x90, 0x99, 0xFC, 0x9A, 0x68, 0x9A, 0xD5,
- 0x9B, 0x42, 0x9B, 0xAF, 0x9C, 0x1C, 0x9C, 0x89, 0x9C, 0xF7, 0x9D, 0x64,
- 0x9D, 0xD2, 0x9E, 0x40, 0x9E, 0xAE, 0x9F, 0x1D, 0x9F, 0x8B, 0x9F, 0xFA,
- 0xA0, 0x69, 0xA0, 0xD8, 0xA1, 0x47, 0xA1, 0xB6, 0xA2, 0x26, 0xA2, 0x96,
- 0xA3, 0x06, 0xA3, 0x76, 0xA3, 0xE6, 0xA4, 0x56, 0xA4, 0xC7, 0xA5, 0x38,
- 0xA5, 0xA9, 0xA6, 0x1A, 0xA6, 0x8B, 0xA6, 0xFD, 0xA7, 0x6E, 0xA7, 0xE0,
- 0xA8, 0x52, 0xA8, 0xC4, 0xA9, 0x37, 0xA9, 0xA9, 0xAA, 0x1C, 0xAA, 0x8F,
- 0xAB, 0x02, 0xAB, 0x75, 0xAB, 0xE9, 0xAC, 0x5C, 0xAC, 0xD0, 0xAD, 0x44,
- 0xAD, 0xB8, 0xAE, 0x2D, 0xAE, 0xA1, 0xAF, 0x16, 0xAF, 0x8B, 0xB0, 0x00,
- 0xB0, 0x75, 0xB0, 0xEA, 0xB1, 0x60, 0xB1, 0xD6, 0xB2, 0x4B, 0xB2, 0xC2,
- 0xB3, 0x38, 0xB3, 0xAE, 0xB4, 0x25, 0xB4, 0x9C, 0xB5, 0x13, 0xB5, 0x8A,
- 0xB6, 0x01, 0xB6, 0x79, 0xB6, 0xF0, 0xB7, 0x68, 0xB7, 0xE0, 0xB8, 0x59,
- 0xB8, 0xD1, 0xB9, 0x4A, 0xB9, 0xC2, 0xBA, 0x3B, 0xBA, 0xB5, 0xBB, 0x2E,
- 0xBB, 0xA7, 0xBC, 0x21, 0xBC, 0x9B, 0xBD, 0x15, 0xBD, 0x8F, 0xBE, 0x0A,
- 0xBE, 0x84, 0xBE, 0xFF, 0xBF, 0x7A, 0xBF, 0xF5, 0xC0, 0x70, 0xC0, 0xEC,
- 0xC1, 0x67, 0xC1, 0xE3, 0xC2, 0x5F, 0xC2, 0xDB, 0xC3, 0x58, 0xC3, 0xD4,
- 0xC4, 0x51, 0xC4, 0xCE, 0xC5, 0x4B, 0xC5, 0xC8, 0xC6, 0x46, 0xC6, 0xC3,
- 0xC7, 0x41, 0xC7, 0xBF, 0xC8, 0x3D, 0xC8, 0xBC, 0xC9, 0x3A, 0xC9, 0xB9,
- 0xCA, 0x38, 0xCA, 0xB7, 0xCB, 0x36, 0xCB, 0xB6, 0xCC, 0x35, 0xCC, 0xB5,
- 0xCD, 0x35, 0xCD, 0xB5, 0xCE, 0x36, 0xCE, 0xB6, 0xCF, 0x37, 0xCF, 0xB8,
- 0xD0, 0x39, 0xD0, 0xBA, 0xD1, 0x3C, 0xD1, 0xBE, 0xD2, 0x3F, 0xD2, 0xC1,
- 0xD3, 0x44, 0xD3, 0xC6, 0xD4, 0x49, 0xD4, 0xCB, 0xD5, 0x4E, 0xD5, 0xD1,
- 0xD6, 0x55, 0xD6, 0xD8, 0xD7, 0x5C, 0xD7, 0xE0, 0xD8, 0x64, 0xD8, 0xE8,
- 0xD9, 0x6C, 0xD9, 0xF1, 0xDA, 0x76, 0xDA, 0xFB, 0xDB, 0x80, 0xDC, 0x05,
- 0xDC, 0x8A, 0xDD, 0x10, 0xDD, 0x96, 0xDE, 0x1C, 0xDE, 0xA2, 0xDF, 0x29,
- 0xDF, 0xAF, 0xE0, 0x36, 0xE0, 0xBD, 0xE1, 0x44, 0xE1, 0xCC, 0xE2, 0x53,
- 0xE2, 0xDB, 0xE3, 0x63, 0xE3, 0xEB, 0xE4, 0x73, 0xE4, 0xFC, 0xE5, 0x84,
- 0xE6, 0x0D, 0xE6, 0x96, 0xE7, 0x1F, 0xE7, 0xA9, 0xE8, 0x32, 0xE8, 0xBC,
- 0xE9, 0x46, 0xE9, 0xD0, 0xEA, 0x5B, 0xEA, 0xE5, 0xEB, 0x70, 0xEB, 0xFB,
- 0xEC, 0x86, 0xED, 0x11, 0xED, 0x9C, 0xEE, 0x28, 0xEE, 0xB4, 0xEF, 0x40,
- 0xEF, 0xCC, 0xF0, 0x58, 0xF0, 0xE5, 0xF1, 0x72, 0xF1, 0xFF, 0xF2, 0x8C,
- 0xF3, 0x19, 0xF3, 0xA7, 0xF4, 0x34, 0xF4, 0xC2, 0xF5, 0x50, 0xF5, 0xDE,
- 0xF6, 0x6D, 0xF6, 0xFB, 0xF7, 0x8A, 0xF8, 0x19, 0xF8, 0xA8, 0xF9, 0x38,
- 0xF9, 0xC7, 0xFA, 0x57, 0xFA, 0xE7, 0xFB, 0x77, 0xFC, 0x07, 0xFC, 0x98,
- 0xFD, 0x29, 0xFD, 0xBA, 0xFE, 0x4B, 0xFE, 0xDC, 0xFF, 0x6D, 0xFF, 0xFF
- };
-
- size = sizeof (ksRGBProfileData);
- data = ksRGBProfileData;
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-const dng_color_space & dng_space_sRGB::Get ()
- {
-
- static dng_space_sRGB static_space;
-
- return static_space;
-
- }
-
-/*****************************************************************************/
-
-dng_space_AdobeRGB::dng_space_AdobeRGB ()
- {
-
- SetMatrixToPCS (dng_matrix_3by3 (0.6097, 0.2053, 0.1492,
- 0.3111, 0.6257, 0.0632,
- 0.0195, 0.0609, 0.7446));
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_space_AdobeRGB::GammaFunction () const
- {
-
- return dng_function_GammaEncode_2_2::Get ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_space_AdobeRGB::ICCProfile (uint32 &size,
- const uint8 *&data) const
-
- {
-
- static const uint8 kAdobeRGBProfileData [] =
- {
- 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00, 0x00,
- 0x6D, 0x6E, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5A, 0x20,
- 0x07, 0xCF, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4C, 0x00, 0x00, 0x00, 0x00,
- 0x6E, 0x6F, 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x41, 0x44, 0x42, 0x45,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
- 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x32,
- 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x00, 0x6B,
- 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9C, 0x00, 0x00, 0x00, 0x14,
- 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x14,
- 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xC4, 0x00, 0x00, 0x00, 0x0E,
- 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xD4, 0x00, 0x00, 0x00, 0x0E,
- 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xE4, 0x00, 0x00, 0x00, 0x0E,
- 0x72, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x14,
- 0x67, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14,
- 0x62, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x00, 0x14,
- 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
- 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x41,
- 0x64, 0x6F, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
- 0x20, 0x49, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x65,
- 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x11, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x52, 0x47,
- 0x42, 0x20, 0x28, 0x31, 0x39, 0x39, 0x38, 0x29, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xF3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xCC,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00,
- 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x02, 0x33, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x18, 0x00, 0x00, 0x4F, 0xA5,
- 0x00, 0x00, 0x04, 0xFC, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x34, 0x8D, 0x00, 0x00, 0xA0, 0x2C, 0x00, 0x00, 0x0F, 0x95,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x31,
- 0x00, 0x00, 0x10, 0x2F, 0x00, 0x00, 0xBE, 0x9C
- };
-
- size = sizeof (kAdobeRGBProfileData);
- data = kAdobeRGBProfileData;
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-const dng_color_space & dng_space_AdobeRGB::Get ()
- {
-
- static dng_space_AdobeRGB static_space;
-
- return static_space;
-
- }
-
-/*****************************************************************************/
-
-dng_space_ColorMatch::dng_space_ColorMatch ()
- {
-
- SetMatrixToPCS (dng_matrix_3by3 (0.5094, 0.3208, 0.1339,
- 0.2749, 0.6581, 0.0670,
- 0.0243, 0.1087, 0.6919));
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_space_ColorMatch::GammaFunction () const
- {
-
- return dng_function_GammaEncode_1_8::Get ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_space_ColorMatch::ICCProfile (uint32 &size,
- const uint8 *&data) const
-
- {
-
- static const uint8 kColorMatchProfileData [] =
- {
- 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00, 0x00,
- 0x6D, 0x6E, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5A, 0x20,
- 0x07, 0xCF, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4C, 0x00, 0x00, 0x00, 0x00,
- 0x6E, 0x6F, 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x41, 0x44, 0x42, 0x45,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
- 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x32,
- 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x00, 0x69,
- 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9C, 0x00, 0x00, 0x00, 0x14,
- 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x14,
- 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xC4, 0x00, 0x00, 0x00, 0x0E,
- 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xD4, 0x00, 0x00, 0x00, 0x0E,
- 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xE4, 0x00, 0x00, 0x00, 0x0E,
- 0x72, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x14,
- 0x67, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14,
- 0x62, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x00, 0x14,
- 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
- 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x41,
- 0x64, 0x6F, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
- 0x20, 0x49, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x65,
- 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0F, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x4D, 0x61, 0x74,
- 0x63, 0x68, 0x20, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xF6, 0xDC, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x3A,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xCD, 0x00, 0x00,
- 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x01, 0xCD, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x01, 0xCD, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x6B, 0x00, 0x00, 0x46, 0x63,
- 0x00, 0x00, 0x06, 0x36, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x52, 0x23, 0x00, 0x00, 0xA8, 0x79, 0x00, 0x00, 0x1B, 0xD7,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x48,
- 0x00, 0x00, 0x11, 0x25, 0x00, 0x00, 0xB1, 0x20
- };
-
- size = sizeof (kColorMatchProfileData);
- data = kColorMatchProfileData;
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-const dng_color_space & dng_space_ColorMatch::Get ()
- {
-
- static dng_space_ColorMatch static_space;
-
- return static_space;
-
- }
-
-/*****************************************************************************/
-
-dng_space_ProPhoto::dng_space_ProPhoto ()
- {
-
- SetMatrixToPCS (dng_matrix_3by3 (0.7977, 0.1352, 0.0313,
- 0.2880, 0.7119, 0.0001,
- 0.0000, 0.0000, 0.8249));
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_space_ProPhoto::GammaFunction () const
- {
-
- return dng_function_GammaEncode_1_8::Get ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_space_ProPhoto::ICCProfile (uint32 &size,
- const uint8 *&data) const
-
- {
-
- static const uint8 kProPhotoProfileData [] =
- {
- 0x00, 0x00, 0x03, 0xAC, 0x4B, 0x43, 0x4D, 0x53, 0x02, 0x10, 0x00, 0x00,
- 0x6D, 0x6E, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5A, 0x20,
- 0x07, 0xCE, 0x00, 0x0C, 0x00, 0x01, 0x00, 0x12, 0x00, 0x3A, 0x00, 0x15,
- 0x61, 0x63, 0x73, 0x70, 0x4D, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
- 0x4B, 0x4F, 0x44, 0x41, 0x52, 0x4F, 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2B, 0x4B, 0x4F, 0x44, 0x41,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
- 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x48,
- 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x5C, 0x00, 0x00, 0x00, 0x83,
- 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x14,
- 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x0E,
- 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x0E,
- 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x0E,
- 0x72, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14,
- 0x67, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x14,
- 0x62, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x00, 0x14,
- 0x64, 0x6D, 0x6E, 0x64, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x6E,
- 0x64, 0x6D, 0x64, 0x64, 0x00, 0x00, 0x02, 0xB0, 0x00, 0x00, 0x00, 0xD1,
- 0x6D, 0x6D, 0x6F, 0x64, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x00, 0x28,
- 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
- 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x45, 0x61,
- 0x73, 0x74, 0x6D, 0x61, 0x6E, 0x20, 0x4B, 0x6F, 0x64, 0x61, 0x6B, 0x20,
- 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x6E, 0x79, 0x2C, 0x20, 0x31, 0x39, 0x39,
- 0x39, 0x2C, 0x20, 0x61, 0x6C, 0x6C, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74,
- 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2E, 0x00,
- 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D,
- 0x50, 0x72, 0x6F, 0x50, 0x68, 0x6F, 0x74, 0x6F, 0x20, 0x52, 0x47, 0x42,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xFE, 0xFF, 0x00,
- 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x50, 0x00, 0x68, 0x00, 0x6F, 0x00,
- 0x74, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x52, 0x00, 0x47, 0x00, 0x42, 0x00,
- 0x00, 0x00, 0x00, 0x0D, 0x50, 0x72, 0x6F, 0x50, 0x68, 0x6F, 0x74, 0x6F,
- 0x20, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2C, 0x63, 0x75, 0x72, 0x76,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xCD, 0x00, 0x00,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x34,
- 0x00, 0x00, 0x49, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x9C, 0x00, 0x00, 0xB6, 0x3E,
- 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xD3, 0x2D,
- 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
- 0x4B, 0x4F, 0x44, 0x41, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x07, 0xFE, 0xFF, 0x00, 0x4B, 0x00, 0x4F, 0x00, 0x44, 0x00, 0x41,
- 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x06, 0x4B, 0x4F, 0x44, 0x41, 0x4B,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x27, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63,
- 0x65, 0x20, 0x4F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x4D, 0x65, 0x64,
- 0x69, 0x75, 0x6D, 0x20, 0x4D, 0x65, 0x74, 0x72, 0x69, 0x63, 0x28, 0x52,
- 0x4F, 0x4D, 0x4D, 0x29, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x28, 0xFE, 0xFF, 0x00, 0x52, 0x00, 0x65, 0x00, 0x66, 0x00,
- 0x65, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x65, 0x00,
- 0x20, 0x00, 0x4F, 0x00, 0x75, 0x00, 0x74, 0x00, 0x70, 0x00, 0x75, 0x00,
- 0x74, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00,
- 0x75, 0x00, 0x6D, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x65, 0x00, 0x74, 0x00,
- 0x72, 0x00, 0x69, 0x00, 0x63, 0x00, 0x28, 0x00, 0x52, 0x00, 0x4F, 0x00,
- 0x4D, 0x00, 0x4D, 0x00, 0x29, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00,
- 0x00, 0x27, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63, 0x65, 0x20,
- 0x4F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x4D, 0x65, 0x64, 0x69, 0x75,
- 0x6D, 0x20, 0x4D, 0x65, 0x74, 0x72, 0x69, 0x63, 0x28, 0x52, 0x4F, 0x4D,
- 0x4D, 0x29, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x6D, 0x6D, 0x6F, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10,
- 0x00, 0x00, 0x9D, 0x03, 0x01, 0x01, 0x01, 0x01, 0xB0, 0xCF, 0x3B, 0x80,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
-
- size = sizeof (kProPhotoProfileData);
- data = kProPhotoProfileData;
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-const dng_color_space & dng_space_ProPhoto::Get ()
- {
-
- static dng_space_ProPhoto static_space;
-
- return static_space;
-
- }
-
-/*****************************************************************************/
-
-dng_space_GrayGamma18::dng_space_GrayGamma18 ()
- {
-
- SetMonochrome ();
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_space_GrayGamma18::GammaFunction () const
- {
-
- return dng_function_GammaEncode_1_8::Get ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_space_GrayGamma18::ICCProfile (uint32 &size,
- const uint8 *&data) const
-
- {
-
- static const uint8 kGamma18ProfileData [] =
- {
- 0x00, 0x00, 0x01, 0x98, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00, 0x00,
- 0x6D, 0x6E, 0x74, 0x72, 0x47, 0x52, 0x41, 0x59, 0x58, 0x59, 0x5A, 0x20,
- 0x07, 0xCF, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4C, 0x00, 0x00, 0x00, 0x00,
- 0x6E, 0x6F, 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x41, 0x44, 0x42, 0x45,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
- 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x32,
- 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x69,
- 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x00, 0x14,
- 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x01, 0x74, 0x00, 0x00, 0x00, 0x14,
- 0x6B, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x0E,
- 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
- 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x41,
- 0x64, 0x6F, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
- 0x20, 0x49, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x65,
- 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0F, 0x47, 0x72, 0x61, 0x79, 0x20, 0x47, 0x61, 0x6D,
- 0x6D, 0x61, 0x20, 0x31, 0x2E, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xF3, 0x54, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xCF,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xCD, 0x00, 0x00
- };
-
- size = sizeof (kGamma18ProfileData);
- data = kGamma18ProfileData;
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-const dng_color_space & dng_space_GrayGamma18::Get ()
- {
-
- static dng_space_GrayGamma18 static_space;
-
- return static_space;
-
- }
-
-/*****************************************************************************/
-
-dng_space_GrayGamma22::dng_space_GrayGamma22 ()
- {
-
- SetMonochrome ();
-
- }
-
-/*****************************************************************************/
-
-const dng_1d_function & dng_space_GrayGamma22::GammaFunction () const
- {
-
- return dng_function_GammaEncode_2_2::Get ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_space_GrayGamma22::ICCProfile (uint32 &size,
- const uint8 *&data) const
-
- {
-
- static const uint8 kGamma22ProfileData [] =
- {
- 0x00, 0x00, 0x01, 0x98, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00, 0x00,
- 0x6D, 0x6E, 0x74, 0x72, 0x47, 0x52, 0x41, 0x59, 0x58, 0x59, 0x5A, 0x20,
- 0x07, 0xCF, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4C, 0x00, 0x00, 0x00, 0x00,
- 0x6E, 0x6F, 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x41, 0x44, 0x42, 0x45,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
- 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x32,
- 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x69,
- 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x00, 0x14,
- 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x01, 0x74, 0x00, 0x00, 0x00, 0x14,
- 0x6B, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x0E,
- 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
- 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x41,
- 0x64, 0x6F, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
- 0x20, 0x49, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x65,
- 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0F, 0x47, 0x72, 0x61, 0x79, 0x20, 0x47, 0x61, 0x6D,
- 0x6D, 0x61, 0x20, 0x32, 0x2E, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xF3, 0x54, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xCF,
- 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00
- };
-
- size = sizeof (kGamma22ProfileData);
- data = kGamma22ProfileData;
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-const dng_color_space & dng_space_GrayGamma22::Get ()
- {
-
- static dng_space_GrayGamma22 static_space;
-
- return static_space;
-
- }
-
-/*****************************************************************************/
-
-dng_space_fakeRGB::dng_space_fakeRGB ()
- {
-
- SetMatrixToPCS (dng_matrix_3by3 (0.6097, 0.2053, 0.1492,
- 0.3111, 0.6257, 0.0632,
- 0.0195, 0.0609, 0.7446));
-
- }
-
-/*****************************************************************************/
-
-const dng_color_space & dng_space_fakeRGB::Get ()
- {
-
- static dng_space_fakeRGB static_space;
-
- return static_space;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_color_space.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+#include "dng_color_space.h"
+
+#include "dng_1d_table.h"
+#include "dng_exceptions.h"
+#include "dng_flags.h"
+#include "dng_matrix.h"
+#include "dng_spline.h"
+#include "dng_utils.h"
+#include "dng_xy_coord.h"
+
+/*****************************************************************************/
+
+real64 dng_function_GammaEncode_sRGB::Evaluate (real64 x) const
+ {
+
+ if (x <= 0.0031308)
+ return x * 12.92;
+
+ else
+ return 1.055 * pow (x, 1.0 / 2.4) - 0.055;
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_function_GammaEncode_sRGB::EvaluateInverse (real64 y) const
+ {
+
+ if (y <= 0.0031308 * 12.92)
+ return y * (1.0 / 12.92);
+
+ else
+ return pow ((y + 0.055) * (1.0 / 1.055), 2.4);
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_function_GammaEncode_sRGB::Get ()
+ {
+
+ static dng_function_GammaEncode_sRGB static_function;
+
+ return static_function;
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_function_GammaEncode_1_8::Evaluate (real64 x) const
+ {
+
+ const real64 gamma = 1.0 / 1.8;
+
+ const real64 slope0 = 32.0;
+
+ const real64 x1 = 8.2118790552e-4; // pow (slope0, 1.0 / (gamma - 1.0)) * 2.0
+
+ const real64 y1 = 0.019310851; // pow (x1, gamma)
+
+ const real64 slope1 = 13.064306598; // gamma * pow (x1, gamma - 1.0)
+
+ if (x <= x1)
+ return EvaluateSplineSegment (x,
+ 0.0,
+ 0.0,
+ slope0,
+ x1,
+ y1,
+ slope1);
+
+ else
+ return pow (x, gamma);
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_function_GammaEncode_1_8::EvaluateInverse (real64 y) const
+ {
+
+ if (y > 0.0 && y < 0.019310851)
+ {
+
+ return dng_1d_function::EvaluateInverse (y);
+
+ }
+
+ return pow (y, 1.8);
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_function_GammaEncode_1_8::Get ()
+ {
+
+ static dng_function_GammaEncode_1_8 static_function;
+
+ return static_function;
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_function_GammaEncode_2_2::Evaluate (real64 x) const
+ {
+
+ const real64 gamma = 1.0 / 2.2;
+
+ const real64 slope0 = 32.0;
+
+ const real64 x1 = 0.0034800731; // pow (slope0, 1.0 / (gamma - 1.0)) * 2.0
+
+ const real64 y1 = 0.0763027458; // pow (x1, gamma)
+
+ const real64 slope1 = 9.9661890075; // gamma * pow (x1, gamma - 1.0)
+
+ if (x <= x1)
+ return EvaluateSplineSegment (x,
+ 0.0,
+ 0.0,
+ slope0,
+ x1,
+ y1,
+ slope1);
+
+ else
+ return pow (x, gamma);
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_function_GammaEncode_2_2::EvaluateInverse (real64 y) const
+ {
+
+ if (y > 0.0 && y < 0.0763027458)
+ {
+
+ return dng_1d_function::EvaluateInverse (y);
+
+ }
+
+ return pow (y, 2.2);
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_function_GammaEncode_2_2::Get ()
+ {
+
+ static dng_function_GammaEncode_2_2 static_function;
+
+ return static_function;
+
+ }
+
+/*****************************************************************************/
+
+dng_color_space::dng_color_space ()
+
+ : fMatrixToPCS ()
+ , fMatrixFromPCS ()
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_color_space::~dng_color_space ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_color_space::SetMonochrome ()
+ {
+
+ fMatrixToPCS = PCStoXYZ ().AsColumn ();
+
+ dng_matrix m (1, 3);
+
+ m [0] [0] = 0.0;
+ m [0] [1] = 1.0;
+ m [0] [2] = 0.0;
+
+ fMatrixFromPCS = m;
+
+ }
+
+/*****************************************************************************/
+
+void dng_color_space::SetMatrixToPCS (const dng_matrix_3by3 &M)
+ {
+
+ // The matrix values are often rounded, so adjust to
+ // get them to convert device white exactly to the PCS.
+
+ dng_vector_3 W1 = M * dng_vector_3 (1.0, 1.0, 1.0);
+ dng_vector_3 W2 = PCStoXYZ ();
+
+ real64 s0 = W2 [0] / W1 [0];
+ real64 s1 = W2 [1] / W1 [1];
+ real64 s2 = W2 [2] / W1 [2];
+
+ dng_matrix_3by3 S (s0, 0, 0,
+ 0, s1, 0,
+ 0, 0, s2);
+
+ fMatrixToPCS = S * M;
+
+ // Find reverse matrix.
+
+ fMatrixFromPCS = Invert (fMatrixToPCS);
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_color_space::GammaFunction () const
+ {
+
+ return dng_1d_identity::Get ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_color_space::ICCProfile (uint32 &size,
+ const uint8 *&data) const
+ {
+
+ size = 0;
+ data = NULL;
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+dng_space_sRGB::dng_space_sRGB ()
+ {
+
+ SetMatrixToPCS (dng_matrix_3by3 (0.4361, 0.3851, 0.1431,
+ 0.2225, 0.7169, 0.0606,
+ 0.0139, 0.0971, 0.7141));
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_space_sRGB::GammaFunction () const
+ {
+
+ return dng_function_GammaEncode_sRGB::Get ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_space_sRGB::ICCProfile (uint32 &size,
+ const uint8 *&data) const
+
+ {
+
+ static const uint8 ksRGBProfileData [] =
+ {
+ 0x00, 0x00, 0x0C, 0x48, 0x4C, 0x69, 0x6E, 0x6F, 0x02, 0x10, 0x00, 0x00,
+ 0x6D, 0x6E, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5A, 0x20,
+ 0x07, 0xCE, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00, 0x31, 0x00, 0x00,
+ 0x61, 0x63, 0x73, 0x70, 0x4D, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
+ 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x48, 0x50, 0x20, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
+ 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x50, 0x00, 0x00, 0x00, 0x33,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x84, 0x00, 0x00, 0x00, 0x6C,
+ 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14,
+ 0x72, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x14,
+ 0x67, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x14,
+ 0x64, 0x6D, 0x6E, 0x64, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x00, 0x70,
+ 0x64, 0x6D, 0x64, 0x64, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x88,
+ 0x76, 0x75, 0x65, 0x64, 0x00, 0x00, 0x03, 0x4C, 0x00, 0x00, 0x00, 0x86,
+ 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x03, 0xD4, 0x00, 0x00, 0x00, 0x24,
+ 0x6C, 0x75, 0x6D, 0x69, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x14,
+ 0x6D, 0x65, 0x61, 0x73, 0x00, 0x00, 0x04, 0x0C, 0x00, 0x00, 0x00, 0x24,
+ 0x74, 0x65, 0x63, 0x68, 0x00, 0x00, 0x04, 0x30, 0x00, 0x00, 0x00, 0x0C,
+ 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3C, 0x00, 0x00, 0x08, 0x0C,
+ 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3C, 0x00, 0x00, 0x08, 0x0C,
+ 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x04, 0x3C, 0x00, 0x00, 0x08, 0x0C,
+ 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39,
+ 0x39, 0x38, 0x20, 0x48, 0x65, 0x77, 0x6C, 0x65, 0x74, 0x74, 0x2D, 0x50,
+ 0x61, 0x63, 0x6B, 0x61, 0x72, 0x64, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x61,
+ 0x6E, 0x79, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47, 0x42, 0x20, 0x49, 0x45, 0x43,
+ 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32, 0x2E, 0x31, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x73, 0x52, 0x47,
+ 0x42, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32,
+ 0x2E, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xCC,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F, 0xA2, 0x00, 0x00, 0x38, 0xF5,
+ 0x00, 0x00, 0x03, 0x90, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x62, 0x99, 0x00, 0x00, 0xB7, 0x85, 0x00, 0x00, 0x18, 0xDA,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xA0,
+ 0x00, 0x00, 0x0F, 0x84, 0x00, 0x00, 0xB6, 0xCF, 0x64, 0x65, 0x73, 0x63,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20,
+ 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x69,
+ 0x65, 0x63, 0x2E, 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x16, 0x49, 0x45, 0x43, 0x20, 0x68, 0x74, 0x74,
+ 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x69, 0x65, 0x63, 0x2E,
+ 0x63, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E,
+ 0x49, 0x45, 0x43, 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32, 0x2E,
+ 0x31, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x52, 0x47,
+ 0x42, 0x20, 0x63, 0x6F, 0x6C, 0x6F, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61,
+ 0x63, 0x65, 0x20, 0x2D, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x49, 0x45, 0x43,
+ 0x20, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32, 0x2E, 0x31, 0x20, 0x44,
+ 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x20, 0x52, 0x47, 0x42, 0x20, 0x63,
+ 0x6F, 0x6C, 0x6F, 0x75, 0x72, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20,
+ 0x2D, 0x20, 0x73, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x2C, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63,
+ 0x65, 0x20, 0x56, 0x69, 0x65, 0x77, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x6F,
+ 0x6E, 0x64, 0x69, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x49,
+ 0x45, 0x43, 0x36, 0x31, 0x39, 0x36, 0x36, 0x2D, 0x32, 0x2E, 0x31, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x52,
+ 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63, 0x65, 0x20, 0x56, 0x69, 0x65,
+ 0x77, 0x69, 0x6E, 0x67, 0x20, 0x43, 0x6F, 0x6E, 0x64, 0x69, 0x74, 0x69,
+ 0x6F, 0x6E, 0x20, 0x69, 0x6E, 0x20, 0x49, 0x45, 0x43, 0x36, 0x31, 0x39,
+ 0x36, 0x36, 0x2D, 0x32, 0x2E, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x65, 0x77,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xA4, 0xFE, 0x00, 0x14, 0x5F, 0x2E,
+ 0x00, 0x10, 0xCF, 0x14, 0x00, 0x03, 0xED, 0xCC, 0x00, 0x04, 0x13, 0x0B,
+ 0x00, 0x03, 0x5C, 0x9E, 0x00, 0x00, 0x00, 0x01, 0x58, 0x59, 0x5A, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x09, 0x56, 0x00, 0x50, 0x00, 0x00,
+ 0x00, 0x57, 0x1F, 0xE7, 0x6D, 0x65, 0x61, 0x73, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x8F,
+ 0x00, 0x00, 0x00, 0x02, 0x73, 0x69, 0x67, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x43, 0x52, 0x54, 0x20, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F,
+ 0x00, 0x14, 0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28, 0x00, 0x2D,
+ 0x00, 0x32, 0x00, 0x37, 0x00, 0x3B, 0x00, 0x40, 0x00, 0x45, 0x00, 0x4A,
+ 0x00, 0x4F, 0x00, 0x54, 0x00, 0x59, 0x00, 0x5E, 0x00, 0x63, 0x00, 0x68,
+ 0x00, 0x6D, 0x00, 0x72, 0x00, 0x77, 0x00, 0x7C, 0x00, 0x81, 0x00, 0x86,
+ 0x00, 0x8B, 0x00, 0x90, 0x00, 0x95, 0x00, 0x9A, 0x00, 0x9F, 0x00, 0xA4,
+ 0x00, 0xA9, 0x00, 0xAE, 0x00, 0xB2, 0x00, 0xB7, 0x00, 0xBC, 0x00, 0xC1,
+ 0x00, 0xC6, 0x00, 0xCB, 0x00, 0xD0, 0x00, 0xD5, 0x00, 0xDB, 0x00, 0xE0,
+ 0x00, 0xE5, 0x00, 0xEB, 0x00, 0xF0, 0x00, 0xF6, 0x00, 0xFB, 0x01, 0x01,
+ 0x01, 0x07, 0x01, 0x0D, 0x01, 0x13, 0x01, 0x19, 0x01, 0x1F, 0x01, 0x25,
+ 0x01, 0x2B, 0x01, 0x32, 0x01, 0x38, 0x01, 0x3E, 0x01, 0x45, 0x01, 0x4C,
+ 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 0x67, 0x01, 0x6E, 0x01, 0x75,
+ 0x01, 0x7C, 0x01, 0x83, 0x01, 0x8B, 0x01, 0x92, 0x01, 0x9A, 0x01, 0xA1,
+ 0x01, 0xA9, 0x01, 0xB1, 0x01, 0xB9, 0x01, 0xC1, 0x01, 0xC9, 0x01, 0xD1,
+ 0x01, 0xD9, 0x01, 0xE1, 0x01, 0xE9, 0x01, 0xF2, 0x01, 0xFA, 0x02, 0x03,
+ 0x02, 0x0C, 0x02, 0x14, 0x02, 0x1D, 0x02, 0x26, 0x02, 0x2F, 0x02, 0x38,
+ 0x02, 0x41, 0x02, 0x4B, 0x02, 0x54, 0x02, 0x5D, 0x02, 0x67, 0x02, 0x71,
+ 0x02, 0x7A, 0x02, 0x84, 0x02, 0x8E, 0x02, 0x98, 0x02, 0xA2, 0x02, 0xAC,
+ 0x02, 0xB6, 0x02, 0xC1, 0x02, 0xCB, 0x02, 0xD5, 0x02, 0xE0, 0x02, 0xEB,
+ 0x02, 0xF5, 0x03, 0x00, 0x03, 0x0B, 0x03, 0x16, 0x03, 0x21, 0x03, 0x2D,
+ 0x03, 0x38, 0x03, 0x43, 0x03, 0x4F, 0x03, 0x5A, 0x03, 0x66, 0x03, 0x72,
+ 0x03, 0x7E, 0x03, 0x8A, 0x03, 0x96, 0x03, 0xA2, 0x03, 0xAE, 0x03, 0xBA,
+ 0x03, 0xC7, 0x03, 0xD3, 0x03, 0xE0, 0x03, 0xEC, 0x03, 0xF9, 0x04, 0x06,
+ 0x04, 0x13, 0x04, 0x20, 0x04, 0x2D, 0x04, 0x3B, 0x04, 0x48, 0x04, 0x55,
+ 0x04, 0x63, 0x04, 0x71, 0x04, 0x7E, 0x04, 0x8C, 0x04, 0x9A, 0x04, 0xA8,
+ 0x04, 0xB6, 0x04, 0xC4, 0x04, 0xD3, 0x04, 0xE1, 0x04, 0xF0, 0x04, 0xFE,
+ 0x05, 0x0D, 0x05, 0x1C, 0x05, 0x2B, 0x05, 0x3A, 0x05, 0x49, 0x05, 0x58,
+ 0x05, 0x67, 0x05, 0x77, 0x05, 0x86, 0x05, 0x96, 0x05, 0xA6, 0x05, 0xB5,
+ 0x05, 0xC5, 0x05, 0xD5, 0x05, 0xE5, 0x05, 0xF6, 0x06, 0x06, 0x06, 0x16,
+ 0x06, 0x27, 0x06, 0x37, 0x06, 0x48, 0x06, 0x59, 0x06, 0x6A, 0x06, 0x7B,
+ 0x06, 0x8C, 0x06, 0x9D, 0x06, 0xAF, 0x06, 0xC0, 0x06, 0xD1, 0x06, 0xE3,
+ 0x06, 0xF5, 0x07, 0x07, 0x07, 0x19, 0x07, 0x2B, 0x07, 0x3D, 0x07, 0x4F,
+ 0x07, 0x61, 0x07, 0x74, 0x07, 0x86, 0x07, 0x99, 0x07, 0xAC, 0x07, 0xBF,
+ 0x07, 0xD2, 0x07, 0xE5, 0x07, 0xF8, 0x08, 0x0B, 0x08, 0x1F, 0x08, 0x32,
+ 0x08, 0x46, 0x08, 0x5A, 0x08, 0x6E, 0x08, 0x82, 0x08, 0x96, 0x08, 0xAA,
+ 0x08, 0xBE, 0x08, 0xD2, 0x08, 0xE7, 0x08, 0xFB, 0x09, 0x10, 0x09, 0x25,
+ 0x09, 0x3A, 0x09, 0x4F, 0x09, 0x64, 0x09, 0x79, 0x09, 0x8F, 0x09, 0xA4,
+ 0x09, 0xBA, 0x09, 0xCF, 0x09, 0xE5, 0x09, 0xFB, 0x0A, 0x11, 0x0A, 0x27,
+ 0x0A, 0x3D, 0x0A, 0x54, 0x0A, 0x6A, 0x0A, 0x81, 0x0A, 0x98, 0x0A, 0xAE,
+ 0x0A, 0xC5, 0x0A, 0xDC, 0x0A, 0xF3, 0x0B, 0x0B, 0x0B, 0x22, 0x0B, 0x39,
+ 0x0B, 0x51, 0x0B, 0x69, 0x0B, 0x80, 0x0B, 0x98, 0x0B, 0xB0, 0x0B, 0xC8,
+ 0x0B, 0xE1, 0x0B, 0xF9, 0x0C, 0x12, 0x0C, 0x2A, 0x0C, 0x43, 0x0C, 0x5C,
+ 0x0C, 0x75, 0x0C, 0x8E, 0x0C, 0xA7, 0x0C, 0xC0, 0x0C, 0xD9, 0x0C, 0xF3,
+ 0x0D, 0x0D, 0x0D, 0x26, 0x0D, 0x40, 0x0D, 0x5A, 0x0D, 0x74, 0x0D, 0x8E,
+ 0x0D, 0xA9, 0x0D, 0xC3, 0x0D, 0xDE, 0x0D, 0xF8, 0x0E, 0x13, 0x0E, 0x2E,
+ 0x0E, 0x49, 0x0E, 0x64, 0x0E, 0x7F, 0x0E, 0x9B, 0x0E, 0xB6, 0x0E, 0xD2,
+ 0x0E, 0xEE, 0x0F, 0x09, 0x0F, 0x25, 0x0F, 0x41, 0x0F, 0x5E, 0x0F, 0x7A,
+ 0x0F, 0x96, 0x0F, 0xB3, 0x0F, 0xCF, 0x0F, 0xEC, 0x10, 0x09, 0x10, 0x26,
+ 0x10, 0x43, 0x10, 0x61, 0x10, 0x7E, 0x10, 0x9B, 0x10, 0xB9, 0x10, 0xD7,
+ 0x10, 0xF5, 0x11, 0x13, 0x11, 0x31, 0x11, 0x4F, 0x11, 0x6D, 0x11, 0x8C,
+ 0x11, 0xAA, 0x11, 0xC9, 0x11, 0xE8, 0x12, 0x07, 0x12, 0x26, 0x12, 0x45,
+ 0x12, 0x64, 0x12, 0x84, 0x12, 0xA3, 0x12, 0xC3, 0x12, 0xE3, 0x13, 0x03,
+ 0x13, 0x23, 0x13, 0x43, 0x13, 0x63, 0x13, 0x83, 0x13, 0xA4, 0x13, 0xC5,
+ 0x13, 0xE5, 0x14, 0x06, 0x14, 0x27, 0x14, 0x49, 0x14, 0x6A, 0x14, 0x8B,
+ 0x14, 0xAD, 0x14, 0xCE, 0x14, 0xF0, 0x15, 0x12, 0x15, 0x34, 0x15, 0x56,
+ 0x15, 0x78, 0x15, 0x9B, 0x15, 0xBD, 0x15, 0xE0, 0x16, 0x03, 0x16, 0x26,
+ 0x16, 0x49, 0x16, 0x6C, 0x16, 0x8F, 0x16, 0xB2, 0x16, 0xD6, 0x16, 0xFA,
+ 0x17, 0x1D, 0x17, 0x41, 0x17, 0x65, 0x17, 0x89, 0x17, 0xAE, 0x17, 0xD2,
+ 0x17, 0xF7, 0x18, 0x1B, 0x18, 0x40, 0x18, 0x65, 0x18, 0x8A, 0x18, 0xAF,
+ 0x18, 0xD5, 0x18, 0xFA, 0x19, 0x20, 0x19, 0x45, 0x19, 0x6B, 0x19, 0x91,
+ 0x19, 0xB7, 0x19, 0xDD, 0x1A, 0x04, 0x1A, 0x2A, 0x1A, 0x51, 0x1A, 0x77,
+ 0x1A, 0x9E, 0x1A, 0xC5, 0x1A, 0xEC, 0x1B, 0x14, 0x1B, 0x3B, 0x1B, 0x63,
+ 0x1B, 0x8A, 0x1B, 0xB2, 0x1B, 0xDA, 0x1C, 0x02, 0x1C, 0x2A, 0x1C, 0x52,
+ 0x1C, 0x7B, 0x1C, 0xA3, 0x1C, 0xCC, 0x1C, 0xF5, 0x1D, 0x1E, 0x1D, 0x47,
+ 0x1D, 0x70, 0x1D, 0x99, 0x1D, 0xC3, 0x1D, 0xEC, 0x1E, 0x16, 0x1E, 0x40,
+ 0x1E, 0x6A, 0x1E, 0x94, 0x1E, 0xBE, 0x1E, 0xE9, 0x1F, 0x13, 0x1F, 0x3E,
+ 0x1F, 0x69, 0x1F, 0x94, 0x1F, 0xBF, 0x1F, 0xEA, 0x20, 0x15, 0x20, 0x41,
+ 0x20, 0x6C, 0x20, 0x98, 0x20, 0xC4, 0x20, 0xF0, 0x21, 0x1C, 0x21, 0x48,
+ 0x21, 0x75, 0x21, 0xA1, 0x21, 0xCE, 0x21, 0xFB, 0x22, 0x27, 0x22, 0x55,
+ 0x22, 0x82, 0x22, 0xAF, 0x22, 0xDD, 0x23, 0x0A, 0x23, 0x38, 0x23, 0x66,
+ 0x23, 0x94, 0x23, 0xC2, 0x23, 0xF0, 0x24, 0x1F, 0x24, 0x4D, 0x24, 0x7C,
+ 0x24, 0xAB, 0x24, 0xDA, 0x25, 0x09, 0x25, 0x38, 0x25, 0x68, 0x25, 0x97,
+ 0x25, 0xC7, 0x25, 0xF7, 0x26, 0x27, 0x26, 0x57, 0x26, 0x87, 0x26, 0xB7,
+ 0x26, 0xE8, 0x27, 0x18, 0x27, 0x49, 0x27, 0x7A, 0x27, 0xAB, 0x27, 0xDC,
+ 0x28, 0x0D, 0x28, 0x3F, 0x28, 0x71, 0x28, 0xA2, 0x28, 0xD4, 0x29, 0x06,
+ 0x29, 0x38, 0x29, 0x6B, 0x29, 0x9D, 0x29, 0xD0, 0x2A, 0x02, 0x2A, 0x35,
+ 0x2A, 0x68, 0x2A, 0x9B, 0x2A, 0xCF, 0x2B, 0x02, 0x2B, 0x36, 0x2B, 0x69,
+ 0x2B, 0x9D, 0x2B, 0xD1, 0x2C, 0x05, 0x2C, 0x39, 0x2C, 0x6E, 0x2C, 0xA2,
+ 0x2C, 0xD7, 0x2D, 0x0C, 0x2D, 0x41, 0x2D, 0x76, 0x2D, 0xAB, 0x2D, 0xE1,
+ 0x2E, 0x16, 0x2E, 0x4C, 0x2E, 0x82, 0x2E, 0xB7, 0x2E, 0xEE, 0x2F, 0x24,
+ 0x2F, 0x5A, 0x2F, 0x91, 0x2F, 0xC7, 0x2F, 0xFE, 0x30, 0x35, 0x30, 0x6C,
+ 0x30, 0xA4, 0x30, 0xDB, 0x31, 0x12, 0x31, 0x4A, 0x31, 0x82, 0x31, 0xBA,
+ 0x31, 0xF2, 0x32, 0x2A, 0x32, 0x63, 0x32, 0x9B, 0x32, 0xD4, 0x33, 0x0D,
+ 0x33, 0x46, 0x33, 0x7F, 0x33, 0xB8, 0x33, 0xF1, 0x34, 0x2B, 0x34, 0x65,
+ 0x34, 0x9E, 0x34, 0xD8, 0x35, 0x13, 0x35, 0x4D, 0x35, 0x87, 0x35, 0xC2,
+ 0x35, 0xFD, 0x36, 0x37, 0x36, 0x72, 0x36, 0xAE, 0x36, 0xE9, 0x37, 0x24,
+ 0x37, 0x60, 0x37, 0x9C, 0x37, 0xD7, 0x38, 0x14, 0x38, 0x50, 0x38, 0x8C,
+ 0x38, 0xC8, 0x39, 0x05, 0x39, 0x42, 0x39, 0x7F, 0x39, 0xBC, 0x39, 0xF9,
+ 0x3A, 0x36, 0x3A, 0x74, 0x3A, 0xB2, 0x3A, 0xEF, 0x3B, 0x2D, 0x3B, 0x6B,
+ 0x3B, 0xAA, 0x3B, 0xE8, 0x3C, 0x27, 0x3C, 0x65, 0x3C, 0xA4, 0x3C, 0xE3,
+ 0x3D, 0x22, 0x3D, 0x61, 0x3D, 0xA1, 0x3D, 0xE0, 0x3E, 0x20, 0x3E, 0x60,
+ 0x3E, 0xA0, 0x3E, 0xE0, 0x3F, 0x21, 0x3F, 0x61, 0x3F, 0xA2, 0x3F, 0xE2,
+ 0x40, 0x23, 0x40, 0x64, 0x40, 0xA6, 0x40, 0xE7, 0x41, 0x29, 0x41, 0x6A,
+ 0x41, 0xAC, 0x41, 0xEE, 0x42, 0x30, 0x42, 0x72, 0x42, 0xB5, 0x42, 0xF7,
+ 0x43, 0x3A, 0x43, 0x7D, 0x43, 0xC0, 0x44, 0x03, 0x44, 0x47, 0x44, 0x8A,
+ 0x44, 0xCE, 0x45, 0x12, 0x45, 0x55, 0x45, 0x9A, 0x45, 0xDE, 0x46, 0x22,
+ 0x46, 0x67, 0x46, 0xAB, 0x46, 0xF0, 0x47, 0x35, 0x47, 0x7B, 0x47, 0xC0,
+ 0x48, 0x05, 0x48, 0x4B, 0x48, 0x91, 0x48, 0xD7, 0x49, 0x1D, 0x49, 0x63,
+ 0x49, 0xA9, 0x49, 0xF0, 0x4A, 0x37, 0x4A, 0x7D, 0x4A, 0xC4, 0x4B, 0x0C,
+ 0x4B, 0x53, 0x4B, 0x9A, 0x4B, 0xE2, 0x4C, 0x2A, 0x4C, 0x72, 0x4C, 0xBA,
+ 0x4D, 0x02, 0x4D, 0x4A, 0x4D, 0x93, 0x4D, 0xDC, 0x4E, 0x25, 0x4E, 0x6E,
+ 0x4E, 0xB7, 0x4F, 0x00, 0x4F, 0x49, 0x4F, 0x93, 0x4F, 0xDD, 0x50, 0x27,
+ 0x50, 0x71, 0x50, 0xBB, 0x51, 0x06, 0x51, 0x50, 0x51, 0x9B, 0x51, 0xE6,
+ 0x52, 0x31, 0x52, 0x7C, 0x52, 0xC7, 0x53, 0x13, 0x53, 0x5F, 0x53, 0xAA,
+ 0x53, 0xF6, 0x54, 0x42, 0x54, 0x8F, 0x54, 0xDB, 0x55, 0x28, 0x55, 0x75,
+ 0x55, 0xC2, 0x56, 0x0F, 0x56, 0x5C, 0x56, 0xA9, 0x56, 0xF7, 0x57, 0x44,
+ 0x57, 0x92, 0x57, 0xE0, 0x58, 0x2F, 0x58, 0x7D, 0x58, 0xCB, 0x59, 0x1A,
+ 0x59, 0x69, 0x59, 0xB8, 0x5A, 0x07, 0x5A, 0x56, 0x5A, 0xA6, 0x5A, 0xF5,
+ 0x5B, 0x45, 0x5B, 0x95, 0x5B, 0xE5, 0x5C, 0x35, 0x5C, 0x86, 0x5C, 0xD6,
+ 0x5D, 0x27, 0x5D, 0x78, 0x5D, 0xC9, 0x5E, 0x1A, 0x5E, 0x6C, 0x5E, 0xBD,
+ 0x5F, 0x0F, 0x5F, 0x61, 0x5F, 0xB3, 0x60, 0x05, 0x60, 0x57, 0x60, 0xAA,
+ 0x60, 0xFC, 0x61, 0x4F, 0x61, 0xA2, 0x61, 0xF5, 0x62, 0x49, 0x62, 0x9C,
+ 0x62, 0xF0, 0x63, 0x43, 0x63, 0x97, 0x63, 0xEB, 0x64, 0x40, 0x64, 0x94,
+ 0x64, 0xE9, 0x65, 0x3D, 0x65, 0x92, 0x65, 0xE7, 0x66, 0x3D, 0x66, 0x92,
+ 0x66, 0xE8, 0x67, 0x3D, 0x67, 0x93, 0x67, 0xE9, 0x68, 0x3F, 0x68, 0x96,
+ 0x68, 0xEC, 0x69, 0x43, 0x69, 0x9A, 0x69, 0xF1, 0x6A, 0x48, 0x6A, 0x9F,
+ 0x6A, 0xF7, 0x6B, 0x4F, 0x6B, 0xA7, 0x6B, 0xFF, 0x6C, 0x57, 0x6C, 0xAF,
+ 0x6D, 0x08, 0x6D, 0x60, 0x6D, 0xB9, 0x6E, 0x12, 0x6E, 0x6B, 0x6E, 0xC4,
+ 0x6F, 0x1E, 0x6F, 0x78, 0x6F, 0xD1, 0x70, 0x2B, 0x70, 0x86, 0x70, 0xE0,
+ 0x71, 0x3A, 0x71, 0x95, 0x71, 0xF0, 0x72, 0x4B, 0x72, 0xA6, 0x73, 0x01,
+ 0x73, 0x5D, 0x73, 0xB8, 0x74, 0x14, 0x74, 0x70, 0x74, 0xCC, 0x75, 0x28,
+ 0x75, 0x85, 0x75, 0xE1, 0x76, 0x3E, 0x76, 0x9B, 0x76, 0xF8, 0x77, 0x56,
+ 0x77, 0xB3, 0x78, 0x11, 0x78, 0x6E, 0x78, 0xCC, 0x79, 0x2A, 0x79, 0x89,
+ 0x79, 0xE7, 0x7A, 0x46, 0x7A, 0xA5, 0x7B, 0x04, 0x7B, 0x63, 0x7B, 0xC2,
+ 0x7C, 0x21, 0x7C, 0x81, 0x7C, 0xE1, 0x7D, 0x41, 0x7D, 0xA1, 0x7E, 0x01,
+ 0x7E, 0x62, 0x7E, 0xC2, 0x7F, 0x23, 0x7F, 0x84, 0x7F, 0xE5, 0x80, 0x47,
+ 0x80, 0xA8, 0x81, 0x0A, 0x81, 0x6B, 0x81, 0xCD, 0x82, 0x30, 0x82, 0x92,
+ 0x82, 0xF4, 0x83, 0x57, 0x83, 0xBA, 0x84, 0x1D, 0x84, 0x80, 0x84, 0xE3,
+ 0x85, 0x47, 0x85, 0xAB, 0x86, 0x0E, 0x86, 0x72, 0x86, 0xD7, 0x87, 0x3B,
+ 0x87, 0x9F, 0x88, 0x04, 0x88, 0x69, 0x88, 0xCE, 0x89, 0x33, 0x89, 0x99,
+ 0x89, 0xFE, 0x8A, 0x64, 0x8A, 0xCA, 0x8B, 0x30, 0x8B, 0x96, 0x8B, 0xFC,
+ 0x8C, 0x63, 0x8C, 0xCA, 0x8D, 0x31, 0x8D, 0x98, 0x8D, 0xFF, 0x8E, 0x66,
+ 0x8E, 0xCE, 0x8F, 0x36, 0x8F, 0x9E, 0x90, 0x06, 0x90, 0x6E, 0x90, 0xD6,
+ 0x91, 0x3F, 0x91, 0xA8, 0x92, 0x11, 0x92, 0x7A, 0x92, 0xE3, 0x93, 0x4D,
+ 0x93, 0xB6, 0x94, 0x20, 0x94, 0x8A, 0x94, 0xF4, 0x95, 0x5F, 0x95, 0xC9,
+ 0x96, 0x34, 0x96, 0x9F, 0x97, 0x0A, 0x97, 0x75, 0x97, 0xE0, 0x98, 0x4C,
+ 0x98, 0xB8, 0x99, 0x24, 0x99, 0x90, 0x99, 0xFC, 0x9A, 0x68, 0x9A, 0xD5,
+ 0x9B, 0x42, 0x9B, 0xAF, 0x9C, 0x1C, 0x9C, 0x89, 0x9C, 0xF7, 0x9D, 0x64,
+ 0x9D, 0xD2, 0x9E, 0x40, 0x9E, 0xAE, 0x9F, 0x1D, 0x9F, 0x8B, 0x9F, 0xFA,
+ 0xA0, 0x69, 0xA0, 0xD8, 0xA1, 0x47, 0xA1, 0xB6, 0xA2, 0x26, 0xA2, 0x96,
+ 0xA3, 0x06, 0xA3, 0x76, 0xA3, 0xE6, 0xA4, 0x56, 0xA4, 0xC7, 0xA5, 0x38,
+ 0xA5, 0xA9, 0xA6, 0x1A, 0xA6, 0x8B, 0xA6, 0xFD, 0xA7, 0x6E, 0xA7, 0xE0,
+ 0xA8, 0x52, 0xA8, 0xC4, 0xA9, 0x37, 0xA9, 0xA9, 0xAA, 0x1C, 0xAA, 0x8F,
+ 0xAB, 0x02, 0xAB, 0x75, 0xAB, 0xE9, 0xAC, 0x5C, 0xAC, 0xD0, 0xAD, 0x44,
+ 0xAD, 0xB8, 0xAE, 0x2D, 0xAE, 0xA1, 0xAF, 0x16, 0xAF, 0x8B, 0xB0, 0x00,
+ 0xB0, 0x75, 0xB0, 0xEA, 0xB1, 0x60, 0xB1, 0xD6, 0xB2, 0x4B, 0xB2, 0xC2,
+ 0xB3, 0x38, 0xB3, 0xAE, 0xB4, 0x25, 0xB4, 0x9C, 0xB5, 0x13, 0xB5, 0x8A,
+ 0xB6, 0x01, 0xB6, 0x79, 0xB6, 0xF0, 0xB7, 0x68, 0xB7, 0xE0, 0xB8, 0x59,
+ 0xB8, 0xD1, 0xB9, 0x4A, 0xB9, 0xC2, 0xBA, 0x3B, 0xBA, 0xB5, 0xBB, 0x2E,
+ 0xBB, 0xA7, 0xBC, 0x21, 0xBC, 0x9B, 0xBD, 0x15, 0xBD, 0x8F, 0xBE, 0x0A,
+ 0xBE, 0x84, 0xBE, 0xFF, 0xBF, 0x7A, 0xBF, 0xF5, 0xC0, 0x70, 0xC0, 0xEC,
+ 0xC1, 0x67, 0xC1, 0xE3, 0xC2, 0x5F, 0xC2, 0xDB, 0xC3, 0x58, 0xC3, 0xD4,
+ 0xC4, 0x51, 0xC4, 0xCE, 0xC5, 0x4B, 0xC5, 0xC8, 0xC6, 0x46, 0xC6, 0xC3,
+ 0xC7, 0x41, 0xC7, 0xBF, 0xC8, 0x3D, 0xC8, 0xBC, 0xC9, 0x3A, 0xC9, 0xB9,
+ 0xCA, 0x38, 0xCA, 0xB7, 0xCB, 0x36, 0xCB, 0xB6, 0xCC, 0x35, 0xCC, 0xB5,
+ 0xCD, 0x35, 0xCD, 0xB5, 0xCE, 0x36, 0xCE, 0xB6, 0xCF, 0x37, 0xCF, 0xB8,
+ 0xD0, 0x39, 0xD0, 0xBA, 0xD1, 0x3C, 0xD1, 0xBE, 0xD2, 0x3F, 0xD2, 0xC1,
+ 0xD3, 0x44, 0xD3, 0xC6, 0xD4, 0x49, 0xD4, 0xCB, 0xD5, 0x4E, 0xD5, 0xD1,
+ 0xD6, 0x55, 0xD6, 0xD8, 0xD7, 0x5C, 0xD7, 0xE0, 0xD8, 0x64, 0xD8, 0xE8,
+ 0xD9, 0x6C, 0xD9, 0xF1, 0xDA, 0x76, 0xDA, 0xFB, 0xDB, 0x80, 0xDC, 0x05,
+ 0xDC, 0x8A, 0xDD, 0x10, 0xDD, 0x96, 0xDE, 0x1C, 0xDE, 0xA2, 0xDF, 0x29,
+ 0xDF, 0xAF, 0xE0, 0x36, 0xE0, 0xBD, 0xE1, 0x44, 0xE1, 0xCC, 0xE2, 0x53,
+ 0xE2, 0xDB, 0xE3, 0x63, 0xE3, 0xEB, 0xE4, 0x73, 0xE4, 0xFC, 0xE5, 0x84,
+ 0xE6, 0x0D, 0xE6, 0x96, 0xE7, 0x1F, 0xE7, 0xA9, 0xE8, 0x32, 0xE8, 0xBC,
+ 0xE9, 0x46, 0xE9, 0xD0, 0xEA, 0x5B, 0xEA, 0xE5, 0xEB, 0x70, 0xEB, 0xFB,
+ 0xEC, 0x86, 0xED, 0x11, 0xED, 0x9C, 0xEE, 0x28, 0xEE, 0xB4, 0xEF, 0x40,
+ 0xEF, 0xCC, 0xF0, 0x58, 0xF0, 0xE5, 0xF1, 0x72, 0xF1, 0xFF, 0xF2, 0x8C,
+ 0xF3, 0x19, 0xF3, 0xA7, 0xF4, 0x34, 0xF4, 0xC2, 0xF5, 0x50, 0xF5, 0xDE,
+ 0xF6, 0x6D, 0xF6, 0xFB, 0xF7, 0x8A, 0xF8, 0x19, 0xF8, 0xA8, 0xF9, 0x38,
+ 0xF9, 0xC7, 0xFA, 0x57, 0xFA, 0xE7, 0xFB, 0x77, 0xFC, 0x07, 0xFC, 0x98,
+ 0xFD, 0x29, 0xFD, 0xBA, 0xFE, 0x4B, 0xFE, 0xDC, 0xFF, 0x6D, 0xFF, 0xFF
+ };
+
+ size = sizeof (ksRGBProfileData);
+ data = ksRGBProfileData;
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+const dng_color_space & dng_space_sRGB::Get ()
+ {
+
+ static dng_space_sRGB static_space;
+
+ return static_space;
+
+ }
+
+/*****************************************************************************/
+
+dng_space_AdobeRGB::dng_space_AdobeRGB ()
+ {
+
+ SetMatrixToPCS (dng_matrix_3by3 (0.6097, 0.2053, 0.1492,
+ 0.3111, 0.6257, 0.0632,
+ 0.0195, 0.0609, 0.7446));
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_space_AdobeRGB::GammaFunction () const
+ {
+
+ return dng_function_GammaEncode_2_2::Get ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_space_AdobeRGB::ICCProfile (uint32 &size,
+ const uint8 *&data) const
+
+ {
+
+ static const uint8 kAdobeRGBProfileData [] =
+ {
+ 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00, 0x00,
+ 0x6D, 0x6E, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5A, 0x20,
+ 0x07, 0xCF, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4C, 0x00, 0x00, 0x00, 0x00,
+ 0x6E, 0x6F, 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x41, 0x44, 0x42, 0x45,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
+ 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x32,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x00, 0x6B,
+ 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9C, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x14,
+ 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xC4, 0x00, 0x00, 0x00, 0x0E,
+ 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xD4, 0x00, 0x00, 0x00, 0x0E,
+ 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xE4, 0x00, 0x00, 0x00, 0x0E,
+ 0x72, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x14,
+ 0x67, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x00, 0x14,
+ 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x41,
+ 0x64, 0x6F, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
+ 0x20, 0x49, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x65,
+ 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x11, 0x41, 0x64, 0x6F, 0x62, 0x65, 0x20, 0x52, 0x47,
+ 0x42, 0x20, 0x28, 0x31, 0x39, 0x39, 0x38, 0x29, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF3, 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xCC,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00,
+ 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x02, 0x33, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x18, 0x00, 0x00, 0x4F, 0xA5,
+ 0x00, 0x00, 0x04, 0xFC, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x34, 0x8D, 0x00, 0x00, 0xA0, 0x2C, 0x00, 0x00, 0x0F, 0x95,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x31,
+ 0x00, 0x00, 0x10, 0x2F, 0x00, 0x00, 0xBE, 0x9C
+ };
+
+ size = sizeof (kAdobeRGBProfileData);
+ data = kAdobeRGBProfileData;
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+const dng_color_space & dng_space_AdobeRGB::Get ()
+ {
+
+ static dng_space_AdobeRGB static_space;
+
+ return static_space;
+
+ }
+
+/*****************************************************************************/
+
+dng_space_ColorMatch::dng_space_ColorMatch ()
+ {
+
+ SetMatrixToPCS (dng_matrix_3by3 (0.5094, 0.3208, 0.1339,
+ 0.2749, 0.6581, 0.0670,
+ 0.0243, 0.1087, 0.6919));
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_space_ColorMatch::GammaFunction () const
+ {
+
+ return dng_function_GammaEncode_1_8::Get ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_space_ColorMatch::ICCProfile (uint32 &size,
+ const uint8 *&data) const
+
+ {
+
+ static const uint8 kColorMatchProfileData [] =
+ {
+ 0x00, 0x00, 0x02, 0x30, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00, 0x00,
+ 0x6D, 0x6E, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5A, 0x20,
+ 0x07, 0xCF, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4C, 0x00, 0x00, 0x00, 0x00,
+ 0x6E, 0x6F, 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x41, 0x44, 0x42, 0x45,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A,
+ 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x32,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x30, 0x00, 0x00, 0x00, 0x69,
+ 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x9C, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x14,
+ 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xC4, 0x00, 0x00, 0x00, 0x0E,
+ 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xD4, 0x00, 0x00, 0x00, 0x0E,
+ 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xE4, 0x00, 0x00, 0x00, 0x0E,
+ 0x72, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x14,
+ 0x67, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x1C, 0x00, 0x00, 0x00, 0x14,
+ 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x41,
+ 0x64, 0x6F, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
+ 0x20, 0x49, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x65,
+ 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0F, 0x43, 0x6F, 0x6C, 0x6F, 0x72, 0x4D, 0x61, 0x74,
+ 0x63, 0x68, 0x20, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF6, 0xDC, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x3A,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xCD, 0x00, 0x00,
+ 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x01, 0xCD, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0xCD, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x6B, 0x00, 0x00, 0x46, 0x63,
+ 0x00, 0x00, 0x06, 0x36, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x52, 0x23, 0x00, 0x00, 0xA8, 0x79, 0x00, 0x00, 0x1B, 0xD7,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x48,
+ 0x00, 0x00, 0x11, 0x25, 0x00, 0x00, 0xB1, 0x20
+ };
+
+ size = sizeof (kColorMatchProfileData);
+ data = kColorMatchProfileData;
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+const dng_color_space & dng_space_ColorMatch::Get ()
+ {
+
+ static dng_space_ColorMatch static_space;
+
+ return static_space;
+
+ }
+
+/*****************************************************************************/
+
+dng_space_ProPhoto::dng_space_ProPhoto ()
+ {
+
+ SetMatrixToPCS (dng_matrix_3by3 (0.7977, 0.1352, 0.0313,
+ 0.2880, 0.7119, 0.0001,
+ 0.0000, 0.0000, 0.8249));
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_space_ProPhoto::GammaFunction () const
+ {
+
+ return dng_function_GammaEncode_1_8::Get ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_space_ProPhoto::ICCProfile (uint32 &size,
+ const uint8 *&data) const
+
+ {
+
+ static const uint8 kProPhotoProfileData [] =
+ {
+ 0x00, 0x00, 0x03, 0xAC, 0x4B, 0x43, 0x4D, 0x53, 0x02, 0x10, 0x00, 0x00,
+ 0x6D, 0x6E, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59, 0x5A, 0x20,
+ 0x07, 0xCE, 0x00, 0x0C, 0x00, 0x01, 0x00, 0x12, 0x00, 0x3A, 0x00, 0x15,
+ 0x61, 0x63, 0x73, 0x70, 0x4D, 0x53, 0x46, 0x54, 0x00, 0x00, 0x00, 0x00,
+ 0x4B, 0x4F, 0x44, 0x41, 0x52, 0x4F, 0x4D, 0x4D, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2B, 0x4B, 0x4F, 0x44, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C,
+ 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x01, 0x14, 0x00, 0x00, 0x00, 0x48,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x01, 0x5C, 0x00, 0x00, 0x00, 0x83,
+ 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x00, 0x14,
+ 0x72, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x0E,
+ 0x67, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x0E,
+ 0x62, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0xF4, 0x00, 0x00, 0x00, 0x0E,
+ 0x72, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x14,
+ 0x67, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x58, 0x59, 0x5A, 0x00, 0x00, 0x02, 0x2C, 0x00, 0x00, 0x00, 0x14,
+ 0x64, 0x6D, 0x6E, 0x64, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x6E,
+ 0x64, 0x6D, 0x64, 0x64, 0x00, 0x00, 0x02, 0xB0, 0x00, 0x00, 0x00, 0xD1,
+ 0x6D, 0x6D, 0x6F, 0x64, 0x00, 0x00, 0x03, 0x84, 0x00, 0x00, 0x00, 0x28,
+ 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x45, 0x61,
+ 0x73, 0x74, 0x6D, 0x61, 0x6E, 0x20, 0x4B, 0x6F, 0x64, 0x61, 0x6B, 0x20,
+ 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x6E, 0x79, 0x2C, 0x20, 0x31, 0x39, 0x39,
+ 0x39, 0x2C, 0x20, 0x61, 0x6C, 0x6C, 0x20, 0x72, 0x69, 0x67, 0x68, 0x74,
+ 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2E, 0x00,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D,
+ 0x50, 0x72, 0x6F, 0x50, 0x68, 0x6F, 0x74, 0x6F, 0x20, 0x52, 0x47, 0x42,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xFE, 0xFF, 0x00,
+ 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x50, 0x00, 0x68, 0x00, 0x6F, 0x00,
+ 0x74, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x52, 0x00, 0x47, 0x00, 0x42, 0x00,
+ 0x00, 0x00, 0x00, 0x0D, 0x50, 0x72, 0x6F, 0x50, 0x68, 0x6F, 0x74, 0x6F,
+ 0x20, 0x52, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2C, 0x63, 0x75, 0x72, 0x76,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xCD, 0x00, 0x00,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x34,
+ 0x00, 0x00, 0x49, 0xBD, 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x9C, 0x00, 0x00, 0xB6, 0x3E,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xD3, 0x2D,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
+ 0x4B, 0x4F, 0x44, 0x41, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x07, 0xFE, 0xFF, 0x00, 0x4B, 0x00, 0x4F, 0x00, 0x44, 0x00, 0x41,
+ 0x00, 0x4B, 0x00, 0x00, 0x00, 0x00, 0x06, 0x4B, 0x4F, 0x44, 0x41, 0x4B,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x27, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63,
+ 0x65, 0x20, 0x4F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x4D, 0x65, 0x64,
+ 0x69, 0x75, 0x6D, 0x20, 0x4D, 0x65, 0x74, 0x72, 0x69, 0x63, 0x28, 0x52,
+ 0x4F, 0x4D, 0x4D, 0x29, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x28, 0xFE, 0xFF, 0x00, 0x52, 0x00, 0x65, 0x00, 0x66, 0x00,
+ 0x65, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x65, 0x00,
+ 0x20, 0x00, 0x4F, 0x00, 0x75, 0x00, 0x74, 0x00, 0x70, 0x00, 0x75, 0x00,
+ 0x74, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00,
+ 0x75, 0x00, 0x6D, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x65, 0x00, 0x74, 0x00,
+ 0x72, 0x00, 0x69, 0x00, 0x63, 0x00, 0x28, 0x00, 0x52, 0x00, 0x4F, 0x00,
+ 0x4D, 0x00, 0x4D, 0x00, 0x29, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x27, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6E, 0x63, 0x65, 0x20,
+ 0x4F, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x4D, 0x65, 0x64, 0x69, 0x75,
+ 0x6D, 0x20, 0x4D, 0x65, 0x74, 0x72, 0x69, 0x63, 0x28, 0x52, 0x4F, 0x4D,
+ 0x4D, 0x29, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x6D, 0x6D, 0x6F, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10,
+ 0x00, 0x00, 0x9D, 0x03, 0x01, 0x01, 0x01, 0x01, 0xB0, 0xCF, 0x3B, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
+ size = sizeof (kProPhotoProfileData);
+ data = kProPhotoProfileData;
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+const dng_color_space & dng_space_ProPhoto::Get ()
+ {
+
+ static dng_space_ProPhoto static_space;
+
+ return static_space;
+
+ }
+
+/*****************************************************************************/
+
+dng_space_GrayGamma18::dng_space_GrayGamma18 ()
+ {
+
+ SetMonochrome ();
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_space_GrayGamma18::GammaFunction () const
+ {
+
+ return dng_function_GammaEncode_1_8::Get ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_space_GrayGamma18::ICCProfile (uint32 &size,
+ const uint8 *&data) const
+
+ {
+
+ static const uint8 kGamma18ProfileData [] =
+ {
+ 0x00, 0x00, 0x01, 0x98, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00, 0x00,
+ 0x6D, 0x6E, 0x74, 0x72, 0x47, 0x52, 0x41, 0x59, 0x58, 0x59, 0x5A, 0x20,
+ 0x07, 0xCF, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4C, 0x00, 0x00, 0x00, 0x00,
+ 0x6E, 0x6F, 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x41, 0x44, 0x42, 0x45,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x32,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x69,
+ 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x01, 0x74, 0x00, 0x00, 0x00, 0x14,
+ 0x6B, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x0E,
+ 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x41,
+ 0x64, 0x6F, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
+ 0x20, 0x49, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x65,
+ 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0F, 0x47, 0x72, 0x61, 0x79, 0x20, 0x47, 0x61, 0x6D,
+ 0x6D, 0x61, 0x20, 0x31, 0x2E, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF3, 0x54, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xCF,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xCD, 0x00, 0x00
+ };
+
+ size = sizeof (kGamma18ProfileData);
+ data = kGamma18ProfileData;
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+const dng_color_space & dng_space_GrayGamma18::Get ()
+ {
+
+ static dng_space_GrayGamma18 static_space;
+
+ return static_space;
+
+ }
+
+/*****************************************************************************/
+
+dng_space_GrayGamma22::dng_space_GrayGamma22 ()
+ {
+
+ SetMonochrome ();
+
+ }
+
+/*****************************************************************************/
+
+const dng_1d_function & dng_space_GrayGamma22::GammaFunction () const
+ {
+
+ return dng_function_GammaEncode_2_2::Get ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_space_GrayGamma22::ICCProfile (uint32 &size,
+ const uint8 *&data) const
+
+ {
+
+ static const uint8 kGamma22ProfileData [] =
+ {
+ 0x00, 0x00, 0x01, 0x98, 0x41, 0x44, 0x42, 0x45, 0x02, 0x10, 0x00, 0x00,
+ 0x6D, 0x6E, 0x74, 0x72, 0x47, 0x52, 0x41, 0x59, 0x58, 0x59, 0x5A, 0x20,
+ 0x07, 0xCF, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x61, 0x63, 0x73, 0x70, 0x41, 0x50, 0x50, 0x4C, 0x00, 0x00, 0x00, 0x00,
+ 0x6E, 0x6F, 0x6E, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF6, 0xD6,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xD3, 0x2D, 0x41, 0x44, 0x42, 0x45,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
+ 0x63, 0x70, 0x72, 0x74, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x32,
+ 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x69,
+ 0x77, 0x74, 0x70, 0x74, 0x00, 0x00, 0x01, 0x60, 0x00, 0x00, 0x00, 0x14,
+ 0x62, 0x6B, 0x70, 0x74, 0x00, 0x00, 0x01, 0x74, 0x00, 0x00, 0x00, 0x14,
+ 0x6B, 0x54, 0x52, 0x43, 0x00, 0x00, 0x01, 0x88, 0x00, 0x00, 0x00, 0x0E,
+ 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6F, 0x70, 0x79,
+ 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x39, 0x39, 0x39, 0x20, 0x41,
+ 0x64, 0x6F, 0x62, 0x65, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x73,
+ 0x20, 0x49, 0x6E, 0x63, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x65,
+ 0x64, 0x00, 0x00, 0x00, 0x64, 0x65, 0x73, 0x63, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0F, 0x47, 0x72, 0x61, 0x79, 0x20, 0x47, 0x61, 0x6D,
+ 0x6D, 0x61, 0x20, 0x32, 0x2E, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xF3, 0x54, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x16, 0xCF,
+ 0x58, 0x59, 0x5A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x75, 0x72, 0x76,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x33, 0x00, 0x00
+ };
+
+ size = sizeof (kGamma22ProfileData);
+ data = kGamma22ProfileData;
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+const dng_color_space & dng_space_GrayGamma22::Get ()
+ {
+
+ static dng_space_GrayGamma22 static_space;
+
+ return static_space;
+
+ }
+
+/*****************************************************************************/
+
+dng_space_fakeRGB::dng_space_fakeRGB ()
+ {
+
+ SetMatrixToPCS (dng_matrix_3by3 (0.6097, 0.2053, 0.1492,
+ 0.3111, 0.6257, 0.0632,
+ 0.0195, 0.0609, 0.7446));
+
+ }
+
+/*****************************************************************************/
+
+const dng_color_space & dng_space_fakeRGB::Get ()
+ {
+
+ static dng_space_fakeRGB static_space;
+
+ return static_space;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_color_space.h b/source/dng_color_space.h
index 00d0d14..ce0d2b0 100644
--- a/source/dng_color_space.h
+++ b/source/dng_color_space.h
@@ -1,351 +1,351 @@
-/*****************************************************************************/
-// Copyright 2006 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_color_space.h#2 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Standard gamma functions and color spaces used within the DNG SDK.
- */
-
-#ifndef __dng_color_space__
-#define __dng_color_space__
-
-/*****************************************************************************/
-
-#include "dng_1d_function.h"
-#include "dng_classes.h"
-#include "dng_matrix.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief A dng_1d_function for gamma encoding in sRGB color space
-
-class dng_function_GammaEncode_sRGB: public dng_1d_function
- {
-
- public:
-
- virtual real64 Evaluate (real64 x) const;
-
- virtual real64 EvaluateInverse (real64 y) const;
-
- static const dng_1d_function & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief A dng_1d_function for gamma encoding with 1.8 gamma.
-
-class dng_function_GammaEncode_1_8: public dng_1d_function
- {
-
- public:
-
- virtual real64 Evaluate (real64 x) const;
-
- virtual real64 EvaluateInverse (real64 y) const;
-
- static const dng_1d_function & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief A dng_1d_function for gamma encoding with 2.2 gamma.
-
-class dng_function_GammaEncode_2_2: public dng_1d_function
- {
-
- public:
-
- virtual real64 Evaluate (real64 x) const;
-
- virtual real64 EvaluateInverse (real64 y) const;
-
- static const dng_1d_function & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief An abstract color space
-
-class dng_color_space
- {
-
- protected:
-
- dng_matrix fMatrixToPCS;
-
- dng_matrix fMatrixFromPCS;
-
- public:
-
- virtual ~dng_color_space ();
-
- /// Return a matrix which transforms source data in this color space into the
- /// Profile Connection Space.
-
- const dng_matrix & MatrixToPCS () const
- {
- return fMatrixToPCS;
- }
-
- /// Return a matrix which transforms Profile Connection Space data into this
- /// color space.
-
- const dng_matrix & MatrixFromPCS () const
- {
- return fMatrixFromPCS;
- }
-
- /// Predicate which is true if this color space is monochrome (has only a
- /// single column).
-
- bool IsMonochrome () const
- {
- return fMatrixToPCS.Cols () == 1;
- }
-
- /// Getter for the gamma function for this color space.
-
- virtual const dng_1d_function & GammaFunction () const;
-
- /// Returns true if this color space is linear. (I.e. has gamma 1.0.)
-
- bool IsLinear () const
- {
- return GammaFunction ().IsIdentity ();
- }
-
- /// Map an input value through this color space's encoding gamma.
-
- real64 GammaEncode (real64 x) const
- {
- return GammaFunction ().Evaluate (x);
- }
-
- /// Map an input value through this color space's decoding gamma (inverse of
- /// the encoding gamma).
-
- real64 GammaDecode (real64 y) const
- {
- return GammaFunction ().EvaluateInverse (y);
- }
-
- /// Getter for ICC profile, if this color space has one.
- /// \param size Out parameter which receives size on return.
- /// \param data Receives bytes of profile.
- /// \retval Returns true if this color space has an ICC profile, false otherwise.
-
- virtual bool ICCProfile (uint32 &size,
- const uint8 *&data) const;
-
- protected:
-
- dng_color_space ();
-
- void SetMonochrome ();
-
- void SetMatrixToPCS (const dng_matrix_3by3 &M);
-
- };
-
-/*****************************************************************************/
-
-/// Singleton class for sRGB color space.
-
-class dng_space_sRGB: public dng_color_space
- {
-
- protected:
-
- dng_space_sRGB ();
-
- public:
-
- /// Returns dng_function_GammaEncode_sRGB
-
- virtual const dng_1d_function & GammaFunction () const;
-
- /// Returns sRGB IEC61966-2.1 ICC profile
-
- virtual bool ICCProfile (uint32 &size,
- const uint8 *&data) const;
-
- /// Static method for getting single global instance of this color space.
-
- static const dng_color_space & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief Singleton class for AdobeRGB color space.
-
-class dng_space_AdobeRGB: public dng_color_space
- {
-
- protected:
-
- dng_space_AdobeRGB ();
-
- public:
-
- /// Returns dng_function_GammaEncode_1_8
-
- virtual const dng_1d_function & GammaFunction () const;
-
- /// Returns AdobeRGB (1998) ICC profile
-
- virtual bool ICCProfile (uint32 &size,
- const uint8 *&data) const;
-
- /// Static method for getting single global instance of this color space.
-
- static const dng_color_space & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief Singleton class for ColorMatch color space.
-
-class dng_space_ColorMatch: public dng_color_space
- {
-
- protected:
-
- dng_space_ColorMatch ();
-
- public:
-
- /// Returns dng_function_GammaEncode_1_8
-
- virtual const dng_1d_function & GammaFunction () const;
-
- /// Returns ColorMatch RGB ICC profile
-
- virtual bool ICCProfile (uint32 &size,
- const uint8 *&data) const;
-
- /// Static method for getting single global instance of this color space.
-
- static const dng_color_space & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief Singleton class for ProPhoto RGB color space.
-
-class dng_space_ProPhoto: public dng_color_space
- {
-
- protected:
-
- dng_space_ProPhoto ();
-
- public:
-
- /// Returns dng_function_GammaEncode_1_8
-
- virtual const dng_1d_function & GammaFunction () const;
-
- /// Returns ProPhoto RGB ICC profile
-
- virtual bool ICCProfile (uint32 &size,
- const uint8 *&data) const;
-
- /// Static method for getting single global instance of this color space.
-
- static const dng_color_space & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief Singleton class for gamma 1.8 grayscale color space.
-
-class dng_space_GrayGamma18: public dng_color_space
- {
-
- protected:
-
- dng_space_GrayGamma18 ();
-
- public:
-
- /// Returns dng_function_GammaEncode_1_8
-
- virtual const dng_1d_function & GammaFunction () const;
-
- /// Returns simple grayscale gamma 1.8 ICC profile
-
- virtual bool ICCProfile (uint32 &size,
- const uint8 *&data) const;
-
- /// Static method for getting single global instance of this color space.
-
- static const dng_color_space & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief Singleton class for gamma 2.2 grayscale color space.
-
-class dng_space_GrayGamma22: public dng_color_space
- {
-
- protected:
-
- dng_space_GrayGamma22 ();
-
- public:
-
- /// Returns dng_function_GammaEncode_2_2
-
- virtual const dng_1d_function & GammaFunction () const;
-
- /// Returns simple grayscale gamma 2.2 ICC profile
-
- virtual bool ICCProfile (uint32 &size,
- const uint8 *&data) const;
-
- /// Static method for getting single global instance of this color space.
-
- static const dng_color_space & Get ();
-
- };
-
-/*****************************************************************************/
-
-class dng_space_fakeRGB: public dng_color_space
- {
-
- protected:
-
- dng_space_fakeRGB ();
-
- public:
-
- static const dng_color_space & Get ();
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_color_space.h#2 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Standard gamma functions and color spaces used within the DNG SDK.
+ */
+
+#ifndef __dng_color_space__
+#define __dng_color_space__
+
+/*****************************************************************************/
+
+#include "dng_1d_function.h"
+#include "dng_classes.h"
+#include "dng_matrix.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief A dng_1d_function for gamma encoding in sRGB color space
+
+class dng_function_GammaEncode_sRGB: public dng_1d_function
+ {
+
+ public:
+
+ virtual real64 Evaluate (real64 x) const;
+
+ virtual real64 EvaluateInverse (real64 y) const;
+
+ static const dng_1d_function & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief A dng_1d_function for gamma encoding with 1.8 gamma.
+
+class dng_function_GammaEncode_1_8: public dng_1d_function
+ {
+
+ public:
+
+ virtual real64 Evaluate (real64 x) const;
+
+ virtual real64 EvaluateInverse (real64 y) const;
+
+ static const dng_1d_function & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief A dng_1d_function for gamma encoding with 2.2 gamma.
+
+class dng_function_GammaEncode_2_2: public dng_1d_function
+ {
+
+ public:
+
+ virtual real64 Evaluate (real64 x) const;
+
+ virtual real64 EvaluateInverse (real64 y) const;
+
+ static const dng_1d_function & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief An abstract color space
+
+class dng_color_space
+ {
+
+ protected:
+
+ dng_matrix fMatrixToPCS;
+
+ dng_matrix fMatrixFromPCS;
+
+ public:
+
+ virtual ~dng_color_space ();
+
+ /// Return a matrix which transforms source data in this color space into the
+ /// Profile Connection Space.
+
+ const dng_matrix & MatrixToPCS () const
+ {
+ return fMatrixToPCS;
+ }
+
+ /// Return a matrix which transforms Profile Connection Space data into this
+ /// color space.
+
+ const dng_matrix & MatrixFromPCS () const
+ {
+ return fMatrixFromPCS;
+ }
+
+ /// Predicate which is true if this color space is monochrome (has only a
+ /// single column).
+
+ bool IsMonochrome () const
+ {
+ return fMatrixToPCS.Cols () == 1;
+ }
+
+ /// Getter for the gamma function for this color space.
+
+ virtual const dng_1d_function & GammaFunction () const;
+
+ /// Returns true if this color space is linear. (I.e. has gamma 1.0.)
+
+ bool IsLinear () const
+ {
+ return GammaFunction ().IsIdentity ();
+ }
+
+ /// Map an input value through this color space's encoding gamma.
+
+ real64 GammaEncode (real64 x) const
+ {
+ return GammaFunction ().Evaluate (x);
+ }
+
+ /// Map an input value through this color space's decoding gamma (inverse of
+ /// the encoding gamma).
+
+ real64 GammaDecode (real64 y) const
+ {
+ return GammaFunction ().EvaluateInverse (y);
+ }
+
+ /// Getter for ICC profile, if this color space has one.
+ /// \param size Out parameter which receives size on return.
+ /// \param data Receives bytes of profile.
+ /// \retval Returns true if this color space has an ICC profile, false otherwise.
+
+ virtual bool ICCProfile (uint32 &size,
+ const uint8 *&data) const;
+
+ protected:
+
+ dng_color_space ();
+
+ void SetMonochrome ();
+
+ void SetMatrixToPCS (const dng_matrix_3by3 &M);
+
+ };
+
+/*****************************************************************************/
+
+/// Singleton class for sRGB color space.
+
+class dng_space_sRGB: public dng_color_space
+ {
+
+ protected:
+
+ dng_space_sRGB ();
+
+ public:
+
+ /// Returns dng_function_GammaEncode_sRGB
+
+ virtual const dng_1d_function & GammaFunction () const;
+
+ /// Returns sRGB IEC61966-2.1 ICC profile
+
+ virtual bool ICCProfile (uint32 &size,
+ const uint8 *&data) const;
+
+ /// Static method for getting single global instance of this color space.
+
+ static const dng_color_space & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Singleton class for AdobeRGB color space.
+
+class dng_space_AdobeRGB: public dng_color_space
+ {
+
+ protected:
+
+ dng_space_AdobeRGB ();
+
+ public:
+
+ /// Returns dng_function_GammaEncode_1_8
+
+ virtual const dng_1d_function & GammaFunction () const;
+
+ /// Returns AdobeRGB (1998) ICC profile
+
+ virtual bool ICCProfile (uint32 &size,
+ const uint8 *&data) const;
+
+ /// Static method for getting single global instance of this color space.
+
+ static const dng_color_space & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Singleton class for ColorMatch color space.
+
+class dng_space_ColorMatch: public dng_color_space
+ {
+
+ protected:
+
+ dng_space_ColorMatch ();
+
+ public:
+
+ /// Returns dng_function_GammaEncode_1_8
+
+ virtual const dng_1d_function & GammaFunction () const;
+
+ /// Returns ColorMatch RGB ICC profile
+
+ virtual bool ICCProfile (uint32 &size,
+ const uint8 *&data) const;
+
+ /// Static method for getting single global instance of this color space.
+
+ static const dng_color_space & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Singleton class for ProPhoto RGB color space.
+
+class dng_space_ProPhoto: public dng_color_space
+ {
+
+ protected:
+
+ dng_space_ProPhoto ();
+
+ public:
+
+ /// Returns dng_function_GammaEncode_1_8
+
+ virtual const dng_1d_function & GammaFunction () const;
+
+ /// Returns ProPhoto RGB ICC profile
+
+ virtual bool ICCProfile (uint32 &size,
+ const uint8 *&data) const;
+
+ /// Static method for getting single global instance of this color space.
+
+ static const dng_color_space & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Singleton class for gamma 1.8 grayscale color space.
+
+class dng_space_GrayGamma18: public dng_color_space
+ {
+
+ protected:
+
+ dng_space_GrayGamma18 ();
+
+ public:
+
+ /// Returns dng_function_GammaEncode_1_8
+
+ virtual const dng_1d_function & GammaFunction () const;
+
+ /// Returns simple grayscale gamma 1.8 ICC profile
+
+ virtual bool ICCProfile (uint32 &size,
+ const uint8 *&data) const;
+
+ /// Static method for getting single global instance of this color space.
+
+ static const dng_color_space & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Singleton class for gamma 2.2 grayscale color space.
+
+class dng_space_GrayGamma22: public dng_color_space
+ {
+
+ protected:
+
+ dng_space_GrayGamma22 ();
+
+ public:
+
+ /// Returns dng_function_GammaEncode_2_2
+
+ virtual const dng_1d_function & GammaFunction () const;
+
+ /// Returns simple grayscale gamma 2.2 ICC profile
+
+ virtual bool ICCProfile (uint32 &size,
+ const uint8 *&data) const;
+
+ /// Static method for getting single global instance of this color space.
+
+ static const dng_color_space & Get ();
+
+ };
+
+/*****************************************************************************/
+
+class dng_space_fakeRGB: public dng_color_space
+ {
+
+ protected:
+
+ dng_space_fakeRGB ();
+
+ public:
+
+ static const dng_color_space & Get ();
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_color_spec.cpp b/source/dng_color_spec.cpp
index 807ee4d..b376410 100644
--- a/source/dng_color_spec.cpp
+++ b/source/dng_color_spec.cpp
@@ -1,567 +1,567 @@
-/*****************************************************************************/
-// Copyright 2006-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_color_spec.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-#include "dng_color_spec.h"
-
-#include "dng_assertions.h"
-#include "dng_camera_profile.h"
-#include "dng_exceptions.h"
-#include "dng_matrix.h"
-#include "dng_negative.h"
-#include "dng_temperature.h"
-#include "dng_utils.h"
-#include "dng_xy_coord.h"
-
-/*****************************************************************************/
-
-dng_matrix_3by3 MapWhiteMatrix (const dng_xy_coord &white1,
- const dng_xy_coord &white2)
- {
-
- // Use the linearized Bradford adaptation matrix.
-
- dng_matrix_3by3 Mb ( 0.8951, 0.2664, -0.1614,
- -0.7502, 1.7135, 0.0367,
- 0.0389, -0.0685, 1.0296);
-
- dng_vector_3 w1 = Mb * XYtoXYZ (white1);
- dng_vector_3 w2 = Mb * XYtoXYZ (white2);
-
- // Negative white coordinates are kind of meaningless.
-
- w1 [0] = Max_real64 (w1 [0], 0.0);
- w1 [1] = Max_real64 (w1 [1], 0.0);
- w1 [2] = Max_real64 (w1 [2], 0.0);
-
- w2 [0] = Max_real64 (w2 [0], 0.0);
- w2 [1] = Max_real64 (w2 [1], 0.0);
- w2 [2] = Max_real64 (w2 [2], 0.0);
-
- // Limit scaling to something reasonable.
-
- dng_matrix_3by3 A;
-
- A [0] [0] = Pin_real64 (0.1, w1 [0] > 0.0 ? w2 [0] / w1 [0] : 10.0, 10.0);
- A [1] [1] = Pin_real64 (0.1, w1 [1] > 0.0 ? w2 [1] / w1 [1] : 10.0, 10.0);
- A [2] [2] = Pin_real64 (0.1, w1 [2] > 0.0 ? w2 [2] / w1 [2] : 10.0, 10.0);
-
- dng_matrix_3by3 B = Invert (Mb) * A * Mb;
-
- return B;
-
- }
-
-/******************************************************************************/
-
-dng_color_spec::dng_color_spec (const dng_negative &negative,
- const dng_camera_profile *profile)
-
- : fChannels (negative.ColorChannels ())
-
- , fTemperature1 (0.0)
- , fTemperature2 (0.0)
-
- , fColorMatrix1 ()
- , fColorMatrix2 ()
-
- , fForwardMatrix1 ()
- , fForwardMatrix2 ()
-
- , fReductionMatrix1 ()
- , fReductionMatrix2 ()
-
- , fCameraCalibration1 ()
- , fCameraCalibration2 ()
-
- , fAnalogBalance ()
-
- , fWhiteXY ()
-
- , fCameraWhite ()
- , fCameraToPCS ()
-
- , fPCStoCamera ()
-
- {
-
- if (fChannels > 1)
- {
-
- if (!profile || !profile->IsValid (fChannels))
- {
- ThrowBadFormat ();
- }
-
- if (profile->WasStubbed ())
- {
- ThrowProgramError ("Using stubbed profile");
- }
-
- fTemperature1 = profile->CalibrationTemperature1 ();
- fTemperature2 = profile->CalibrationTemperature2 ();
-
- fColorMatrix1 = profile->ColorMatrix1 ();
- fColorMatrix2 = profile->ColorMatrix2 ();
-
- fForwardMatrix1 = profile->ForwardMatrix1 ();
- fForwardMatrix2 = profile->ForwardMatrix2 ();
-
- fReductionMatrix1 = profile->ReductionMatrix1 ();
- fReductionMatrix2 = profile->ReductionMatrix2 ();
-
- fCameraCalibration1.SetIdentity (fChannels);
- fCameraCalibration2.SetIdentity (fChannels);
-
- if (negative. CameraCalibrationSignature () ==
- profile->ProfileCalibrationSignature ())
- {
-
- if (negative.CameraCalibration1 ().Rows () == fChannels &&
- negative.CameraCalibration1 ().Cols () == fChannels)
- {
-
- fCameraCalibration1 = negative.CameraCalibration1 ();
-
- }
-
- if (negative.CameraCalibration2 ().Rows () == fChannels &&
- negative.CameraCalibration2 ().Cols () == fChannels)
- {
-
- fCameraCalibration2 = negative.CameraCalibration2 ();
-
- }
-
- }
-
- fAnalogBalance = dng_matrix (fChannels, fChannels);
-
- for (uint32 j = 0; j < fChannels; j++)
- {
-
- fAnalogBalance [j] [j] = negative.AnalogBalance (j);
-
- }
-
- dng_camera_profile::NormalizeForwardMatrix (fForwardMatrix1);
-
- fColorMatrix1 = fAnalogBalance * fCameraCalibration1 * fColorMatrix1;
-
- if (!profile->HasColorMatrix2 () ||
- fTemperature1 <= 0.0 ||
- fTemperature2 <= 0.0 ||
- fTemperature1 == fTemperature2)
- {
-
- fTemperature1 = 5000.0;
- fTemperature2 = 5000.0;
-
- fColorMatrix2 = fColorMatrix1;
- fForwardMatrix2 = fForwardMatrix1;
- fReductionMatrix2 = fReductionMatrix1;
- fCameraCalibration2 = fCameraCalibration1;
-
- }
-
- else
- {
-
- dng_camera_profile::NormalizeForwardMatrix (fForwardMatrix2);
-
- fColorMatrix2 = fAnalogBalance * fCameraCalibration2 * fColorMatrix2;
-
- // Swap values if temperatures are out of order.
-
- if (fTemperature1 > fTemperature2)
- {
-
- real64 temp = fTemperature1;
- fTemperature1 = fTemperature2;
- fTemperature2 = temp;
-
- dng_matrix T = fColorMatrix1;
- fColorMatrix1 = fColorMatrix2;
- fColorMatrix2 = T;
-
- T = fForwardMatrix1;
- fForwardMatrix1 = fForwardMatrix2;
- fForwardMatrix2 = T;
-
- T = fReductionMatrix1;
- fReductionMatrix1 = fReductionMatrix2;
- fReductionMatrix2 = T;
-
- T = fCameraCalibration1;
- fCameraCalibration1 = fCameraCalibration2;
- fCameraCalibration2 = T;
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_matrix dng_color_spec::FindXYZtoCamera (const dng_xy_coord &white,
- dng_matrix *forwardMatrix,
- dng_matrix *reductionMatrix,
- dng_matrix *cameraCalibration)
- {
-
- // Convert to temperature/offset space.
-
- dng_temperature td (white);
-
- // Find fraction to weight the first calibration.
-
- real64 g;
-
- if (td.Temperature () <= fTemperature1)
- g = 1.0;
-
- else if (td.Temperature () >= fTemperature2)
- g = 0.0;
-
- else
- {
-
- real64 invT = 1.0 / td.Temperature ();
-
- g = (invT - (1.0 / fTemperature2)) /
- ((1.0 / fTemperature1) - (1.0 / fTemperature2));
-
- }
-
- // Interpolate the color matrix.
-
- dng_matrix colorMatrix;
-
- if (g >= 1.0)
- colorMatrix = fColorMatrix1;
-
- else if (g <= 0.0)
- colorMatrix = fColorMatrix2;
-
- else
- colorMatrix = (g ) * fColorMatrix1 +
- (1.0 - g) * fColorMatrix2;
-
- // Interpolate forward matrix, if any.
-
- if (forwardMatrix)
- {
-
- bool has1 = fForwardMatrix1.NotEmpty ();
- bool has2 = fForwardMatrix2.NotEmpty ();
-
- if (has1 && has2)
- {
-
- if (g >= 1.0)
- *forwardMatrix = fForwardMatrix1;
-
- else if (g <= 0.0)
- *forwardMatrix = fForwardMatrix2;
-
- else
- *forwardMatrix = (g ) * fForwardMatrix1 +
- (1.0 - g) * fForwardMatrix2;
-
- }
-
- else if (has1)
- {
-
- *forwardMatrix = fForwardMatrix1;
-
- }
-
- else if (has2)
- {
-
- *forwardMatrix = fForwardMatrix2;
-
- }
-
- else
- {
-
- forwardMatrix->Clear ();
-
- }
-
- }
-
- // Interpolate reduction matrix, if any.
-
- if (reductionMatrix)
- {
-
- bool has1 = fReductionMatrix1.NotEmpty ();
- bool has2 = fReductionMatrix2.NotEmpty ();
-
- if (has1 && has2)
- {
-
- if (g >= 1.0)
- *reductionMatrix = fReductionMatrix1;
-
- else if (g <= 0.0)
- *reductionMatrix = fReductionMatrix2;
-
- else
- *reductionMatrix = (g ) * fReductionMatrix1 +
- (1.0 - g) * fReductionMatrix2;
-
- }
-
- else if (has1)
- {
-
- *reductionMatrix = fReductionMatrix1;
-
- }
-
- else if (has2)
- {
-
- *reductionMatrix = fReductionMatrix2;
-
- }
-
- else
- {
-
- reductionMatrix->Clear ();
-
- }
-
- }
-
- // Interpolate camera calibration matrix.
-
- if (cameraCalibration)
- {
-
- if (g >= 1.0)
- *cameraCalibration = fCameraCalibration1;
-
- else if (g <= 0.0)
- *cameraCalibration = fCameraCalibration2;
-
- else
- *cameraCalibration = (g ) * fCameraCalibration1 +
- (1.0 - g) * fCameraCalibration2;
-
- }
-
- // Return the interpolated color matrix.
-
- return colorMatrix;
-
- }
-
-/*****************************************************************************/
-
-void dng_color_spec::SetWhiteXY (const dng_xy_coord &white)
- {
-
- fWhiteXY = white;
-
- // Deal with monochrome cameras.
-
- if (fChannels == 1)
- {
-
- fCameraWhite.SetIdentity (1);
-
- fCameraToPCS = PCStoXYZ ().AsColumn ();
-
- return;
-
- }
-
- // Interpolate an matric values for this white point.
-
- dng_matrix colorMatrix;
- dng_matrix forwardMatrix;
- dng_matrix reductionMatrix;
- dng_matrix cameraCalibration;
-
- colorMatrix = FindXYZtoCamera (fWhiteXY,
- &forwardMatrix,
- &reductionMatrix,
- &cameraCalibration);
-
- // Find the camera white values.
-
- fCameraWhite = colorMatrix * XYtoXYZ (fWhiteXY);
- real64 cameraWhiteMaxEntry = MaxEntry (fCameraWhite);
- if (cameraWhiteMaxEntry == 0)
- {
- ThrowBadFormat ();
- }
- real64 whiteScale = 1.0 / cameraWhiteMaxEntry;
-
- for (uint32 j = 0; j < fChannels; j++)
- {
-
- // We don't support non-positive values for camera neutral values.
-
- fCameraWhite [j] = Pin_real64 (0.001,
- whiteScale * fCameraWhite [j],
- 1.0);
-
- }
-
- // Find PCS to Camera transform. Scale matrix so PCS white can just be
- // reached when the first camera channel saturates
-
- fPCStoCamera = colorMatrix * MapWhiteMatrix (PCStoXY (), fWhiteXY);
-
- real64 scale = MaxEntry (fPCStoCamera * PCStoXYZ ());
-
- if (scale == 0)
- {
- ThrowBadFormat ();
- }
- fPCStoCamera = (1.0 / scale) * fPCStoCamera;
-
- // If we have a forward matrix, then just use that.
-
- if (forwardMatrix.NotEmpty ())
- {
-
- dng_matrix individualToReference = Invert (fAnalogBalance * cameraCalibration);
-
- dng_vector refCameraWhite = individualToReference * fCameraWhite;
-
- fCameraToPCS = forwardMatrix *
- Invert (refCameraWhite.AsDiagonal ()) *
- individualToReference;
-
- }
-
- // Else we need to use the adapt in XYZ method.
-
- else
- {
-
- // Invert this PCS to camera matrix. Note that if there are more than three
- // camera channels, this inversion is non-unique.
-
- fCameraToPCS = Invert (fPCStoCamera, reductionMatrix);
-
- }
-
- }
-
-/*****************************************************************************/
-
-const dng_xy_coord & dng_color_spec::WhiteXY () const
- {
-
- DNG_ASSERT (fWhiteXY.IsValid (), "Using invalid WhiteXY");
-
- return fWhiteXY;
-
- }
-
-/*****************************************************************************/
-
-const dng_vector & dng_color_spec::CameraWhite () const
- {
-
- DNG_ASSERT (fCameraWhite.NotEmpty (), "Using invalid CameraWhite");
-
- return fCameraWhite;
-
- }
-
-/*****************************************************************************/
-
-const dng_matrix & dng_color_spec::CameraToPCS () const
- {
-
- DNG_ASSERT (fCameraToPCS.NotEmpty (), "Using invalid CameraToPCS");
-
- return fCameraToPCS;
-
- }
-
-/*****************************************************************************/
-
-const dng_matrix & dng_color_spec::PCStoCamera () const
- {
-
- DNG_ASSERT (fPCStoCamera.NotEmpty (), "Using invalid PCStoCamera");
-
- return fPCStoCamera;
-
- }
-
-/*****************************************************************************/
-
-dng_xy_coord dng_color_spec::NeutralToXY (const dng_vector &neutral)
- {
-
- const uint32 kMaxPasses = 30;
-
- if (fChannels == 1)
- {
-
- return PCStoXY ();
-
- }
-
- dng_xy_coord last = D50_xy_coord ();
-
- for (uint32 pass = 0; pass < kMaxPasses; pass++)
- {
-
- dng_matrix xyzToCamera = FindXYZtoCamera (last);
-
- dng_xy_coord next = XYZtoXY (Invert (xyzToCamera) * neutral);
-
- if (Abs_real64 (next.x - last.x) +
- Abs_real64 (next.y - last.y) < 0.0000001)
- {
-
- return next;
-
- }
-
- // If we reach the limit without converging, we are most likely
- // in a two value oscillation. So take the average of the last
- // two estimates and give up.
-
- if (pass == kMaxPasses - 1)
- {
-
- next.x = (last.x + next.x) * 0.5;
- next.y = (last.y + next.y) * 0.5;
-
- }
-
- last = next;
-
- }
-
- return last;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_color_spec.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+#include "dng_color_spec.h"
+
+#include "dng_assertions.h"
+#include "dng_camera_profile.h"
+#include "dng_exceptions.h"
+#include "dng_matrix.h"
+#include "dng_negative.h"
+#include "dng_temperature.h"
+#include "dng_utils.h"
+#include "dng_xy_coord.h"
+
+/*****************************************************************************/
+
+dng_matrix_3by3 MapWhiteMatrix (const dng_xy_coord &white1,
+ const dng_xy_coord &white2)
+ {
+
+ // Use the linearized Bradford adaptation matrix.
+
+ dng_matrix_3by3 Mb ( 0.8951, 0.2664, -0.1614,
+ -0.7502, 1.7135, 0.0367,
+ 0.0389, -0.0685, 1.0296);
+
+ dng_vector_3 w1 = Mb * XYtoXYZ (white1);
+ dng_vector_3 w2 = Mb * XYtoXYZ (white2);
+
+ // Negative white coordinates are kind of meaningless.
+
+ w1 [0] = Max_real64 (w1 [0], 0.0);
+ w1 [1] = Max_real64 (w1 [1], 0.0);
+ w1 [2] = Max_real64 (w1 [2], 0.0);
+
+ w2 [0] = Max_real64 (w2 [0], 0.0);
+ w2 [1] = Max_real64 (w2 [1], 0.0);
+ w2 [2] = Max_real64 (w2 [2], 0.0);
+
+ // Limit scaling to something reasonable.
+
+ dng_matrix_3by3 A;
+
+ A [0] [0] = Pin_real64 (0.1, w1 [0] > 0.0 ? w2 [0] / w1 [0] : 10.0, 10.0);
+ A [1] [1] = Pin_real64 (0.1, w1 [1] > 0.0 ? w2 [1] / w1 [1] : 10.0, 10.0);
+ A [2] [2] = Pin_real64 (0.1, w1 [2] > 0.0 ? w2 [2] / w1 [2] : 10.0, 10.0);
+
+ dng_matrix_3by3 B = Invert (Mb) * A * Mb;
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+dng_color_spec::dng_color_spec (const dng_negative &negative,
+ const dng_camera_profile *profile)
+
+ : fChannels (negative.ColorChannels ())
+
+ , fTemperature1 (0.0)
+ , fTemperature2 (0.0)
+
+ , fColorMatrix1 ()
+ , fColorMatrix2 ()
+
+ , fForwardMatrix1 ()
+ , fForwardMatrix2 ()
+
+ , fReductionMatrix1 ()
+ , fReductionMatrix2 ()
+
+ , fCameraCalibration1 ()
+ , fCameraCalibration2 ()
+
+ , fAnalogBalance ()
+
+ , fWhiteXY ()
+
+ , fCameraWhite ()
+ , fCameraToPCS ()
+
+ , fPCStoCamera ()
+
+ {
+
+ if (fChannels > 1)
+ {
+
+ if (!profile || !profile->IsValid (fChannels))
+ {
+ ThrowBadFormat ();
+ }
+
+ if (profile->WasStubbed ())
+ {
+ ThrowProgramError ("Using stubbed profile");
+ }
+
+ fTemperature1 = profile->CalibrationTemperature1 ();
+ fTemperature2 = profile->CalibrationTemperature2 ();
+
+ fColorMatrix1 = profile->ColorMatrix1 ();
+ fColorMatrix2 = profile->ColorMatrix2 ();
+
+ fForwardMatrix1 = profile->ForwardMatrix1 ();
+ fForwardMatrix2 = profile->ForwardMatrix2 ();
+
+ fReductionMatrix1 = profile->ReductionMatrix1 ();
+ fReductionMatrix2 = profile->ReductionMatrix2 ();
+
+ fCameraCalibration1.SetIdentity (fChannels);
+ fCameraCalibration2.SetIdentity (fChannels);
+
+ if (negative. CameraCalibrationSignature () ==
+ profile->ProfileCalibrationSignature ())
+ {
+
+ if (negative.CameraCalibration1 ().Rows () == fChannels &&
+ negative.CameraCalibration1 ().Cols () == fChannels)
+ {
+
+ fCameraCalibration1 = negative.CameraCalibration1 ();
+
+ }
+
+ if (negative.CameraCalibration2 ().Rows () == fChannels &&
+ negative.CameraCalibration2 ().Cols () == fChannels)
+ {
+
+ fCameraCalibration2 = negative.CameraCalibration2 ();
+
+ }
+
+ }
+
+ fAnalogBalance = dng_matrix (fChannels, fChannels);
+
+ for (uint32 j = 0; j < fChannels; j++)
+ {
+
+ fAnalogBalance [j] [j] = negative.AnalogBalance (j);
+
+ }
+
+ dng_camera_profile::NormalizeForwardMatrix (fForwardMatrix1);
+
+ fColorMatrix1 = fAnalogBalance * fCameraCalibration1 * fColorMatrix1;
+
+ if (!profile->HasColorMatrix2 () ||
+ fTemperature1 <= 0.0 ||
+ fTemperature2 <= 0.0 ||
+ fTemperature1 == fTemperature2)
+ {
+
+ fTemperature1 = 5000.0;
+ fTemperature2 = 5000.0;
+
+ fColorMatrix2 = fColorMatrix1;
+ fForwardMatrix2 = fForwardMatrix1;
+ fReductionMatrix2 = fReductionMatrix1;
+ fCameraCalibration2 = fCameraCalibration1;
+
+ }
+
+ else
+ {
+
+ dng_camera_profile::NormalizeForwardMatrix (fForwardMatrix2);
+
+ fColorMatrix2 = fAnalogBalance * fCameraCalibration2 * fColorMatrix2;
+
+ // Swap values if temperatures are out of order.
+
+ if (fTemperature1 > fTemperature2)
+ {
+
+ real64 temp = fTemperature1;
+ fTemperature1 = fTemperature2;
+ fTemperature2 = temp;
+
+ dng_matrix T = fColorMatrix1;
+ fColorMatrix1 = fColorMatrix2;
+ fColorMatrix2 = T;
+
+ T = fForwardMatrix1;
+ fForwardMatrix1 = fForwardMatrix2;
+ fForwardMatrix2 = T;
+
+ T = fReductionMatrix1;
+ fReductionMatrix1 = fReductionMatrix2;
+ fReductionMatrix2 = T;
+
+ T = fCameraCalibration1;
+ fCameraCalibration1 = fCameraCalibration2;
+ fCameraCalibration2 = T;
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix dng_color_spec::FindXYZtoCamera (const dng_xy_coord &white,
+ dng_matrix *forwardMatrix,
+ dng_matrix *reductionMatrix,
+ dng_matrix *cameraCalibration)
+ {
+
+ // Convert to temperature/offset space.
+
+ dng_temperature td (white);
+
+ // Find fraction to weight the first calibration.
+
+ real64 g;
+
+ if (td.Temperature () <= fTemperature1)
+ g = 1.0;
+
+ else if (td.Temperature () >= fTemperature2)
+ g = 0.0;
+
+ else
+ {
+
+ real64 invT = 1.0 / td.Temperature ();
+
+ g = (invT - (1.0 / fTemperature2)) /
+ ((1.0 / fTemperature1) - (1.0 / fTemperature2));
+
+ }
+
+ // Interpolate the color matrix.
+
+ dng_matrix colorMatrix;
+
+ if (g >= 1.0)
+ colorMatrix = fColorMatrix1;
+
+ else if (g <= 0.0)
+ colorMatrix = fColorMatrix2;
+
+ else
+ colorMatrix = (g ) * fColorMatrix1 +
+ (1.0 - g) * fColorMatrix2;
+
+ // Interpolate forward matrix, if any.
+
+ if (forwardMatrix)
+ {
+
+ bool has1 = fForwardMatrix1.NotEmpty ();
+ bool has2 = fForwardMatrix2.NotEmpty ();
+
+ if (has1 && has2)
+ {
+
+ if (g >= 1.0)
+ *forwardMatrix = fForwardMatrix1;
+
+ else if (g <= 0.0)
+ *forwardMatrix = fForwardMatrix2;
+
+ else
+ *forwardMatrix = (g ) * fForwardMatrix1 +
+ (1.0 - g) * fForwardMatrix2;
+
+ }
+
+ else if (has1)
+ {
+
+ *forwardMatrix = fForwardMatrix1;
+
+ }
+
+ else if (has2)
+ {
+
+ *forwardMatrix = fForwardMatrix2;
+
+ }
+
+ else
+ {
+
+ forwardMatrix->Clear ();
+
+ }
+
+ }
+
+ // Interpolate reduction matrix, if any.
+
+ if (reductionMatrix)
+ {
+
+ bool has1 = fReductionMatrix1.NotEmpty ();
+ bool has2 = fReductionMatrix2.NotEmpty ();
+
+ if (has1 && has2)
+ {
+
+ if (g >= 1.0)
+ *reductionMatrix = fReductionMatrix1;
+
+ else if (g <= 0.0)
+ *reductionMatrix = fReductionMatrix2;
+
+ else
+ *reductionMatrix = (g ) * fReductionMatrix1 +
+ (1.0 - g) * fReductionMatrix2;
+
+ }
+
+ else if (has1)
+ {
+
+ *reductionMatrix = fReductionMatrix1;
+
+ }
+
+ else if (has2)
+ {
+
+ *reductionMatrix = fReductionMatrix2;
+
+ }
+
+ else
+ {
+
+ reductionMatrix->Clear ();
+
+ }
+
+ }
+
+ // Interpolate camera calibration matrix.
+
+ if (cameraCalibration)
+ {
+
+ if (g >= 1.0)
+ *cameraCalibration = fCameraCalibration1;
+
+ else if (g <= 0.0)
+ *cameraCalibration = fCameraCalibration2;
+
+ else
+ *cameraCalibration = (g ) * fCameraCalibration1 +
+ (1.0 - g) * fCameraCalibration2;
+
+ }
+
+ // Return the interpolated color matrix.
+
+ return colorMatrix;
+
+ }
+
+/*****************************************************************************/
+
+void dng_color_spec::SetWhiteXY (const dng_xy_coord &white)
+ {
+
+ fWhiteXY = white;
+
+ // Deal with monochrome cameras.
+
+ if (fChannels == 1)
+ {
+
+ fCameraWhite.SetIdentity (1);
+
+ fCameraToPCS = PCStoXYZ ().AsColumn ();
+
+ return;
+
+ }
+
+ // Interpolate an matric values for this white point.
+
+ dng_matrix colorMatrix;
+ dng_matrix forwardMatrix;
+ dng_matrix reductionMatrix;
+ dng_matrix cameraCalibration;
+
+ colorMatrix = FindXYZtoCamera (fWhiteXY,
+ &forwardMatrix,
+ &reductionMatrix,
+ &cameraCalibration);
+
+ // Find the camera white values.
+
+ fCameraWhite = colorMatrix * XYtoXYZ (fWhiteXY);
+ real64 cameraWhiteMaxEntry = MaxEntry (fCameraWhite);
+ if (cameraWhiteMaxEntry == 0)
+ {
+ ThrowBadFormat ();
+ }
+ real64 whiteScale = 1.0 / cameraWhiteMaxEntry;
+
+ for (uint32 j = 0; j < fChannels; j++)
+ {
+
+ // We don't support non-positive values for camera neutral values.
+
+ fCameraWhite [j] = Pin_real64 (0.001,
+ whiteScale * fCameraWhite [j],
+ 1.0);
+
+ }
+
+ // Find PCS to Camera transform. Scale matrix so PCS white can just be
+ // reached when the first camera channel saturates
+
+ fPCStoCamera = colorMatrix * MapWhiteMatrix (PCStoXY (), fWhiteXY);
+
+ real64 scale = MaxEntry (fPCStoCamera * PCStoXYZ ());
+
+ if (scale == 0)
+ {
+ ThrowBadFormat ();
+ }
+ fPCStoCamera = (1.0 / scale) * fPCStoCamera;
+
+ // If we have a forward matrix, then just use that.
+
+ if (forwardMatrix.NotEmpty ())
+ {
+
+ dng_matrix individualToReference = Invert (fAnalogBalance * cameraCalibration);
+
+ dng_vector refCameraWhite = individualToReference * fCameraWhite;
+
+ fCameraToPCS = forwardMatrix *
+ Invert (refCameraWhite.AsDiagonal ()) *
+ individualToReference;
+
+ }
+
+ // Else we need to use the adapt in XYZ method.
+
+ else
+ {
+
+ // Invert this PCS to camera matrix. Note that if there are more than three
+ // camera channels, this inversion is non-unique.
+
+ fCameraToPCS = Invert (fPCStoCamera, reductionMatrix);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+const dng_xy_coord & dng_color_spec::WhiteXY () const
+ {
+
+ DNG_ASSERT (fWhiteXY.IsValid (), "Using invalid WhiteXY");
+
+ return fWhiteXY;
+
+ }
+
+/*****************************************************************************/
+
+const dng_vector & dng_color_spec::CameraWhite () const
+ {
+
+ DNG_ASSERT (fCameraWhite.NotEmpty (), "Using invalid CameraWhite");
+
+ return fCameraWhite;
+
+ }
+
+/*****************************************************************************/
+
+const dng_matrix & dng_color_spec::CameraToPCS () const
+ {
+
+ DNG_ASSERT (fCameraToPCS.NotEmpty (), "Using invalid CameraToPCS");
+
+ return fCameraToPCS;
+
+ }
+
+/*****************************************************************************/
+
+const dng_matrix & dng_color_spec::PCStoCamera () const
+ {
+
+ DNG_ASSERT (fPCStoCamera.NotEmpty (), "Using invalid PCStoCamera");
+
+ return fPCStoCamera;
+
+ }
+
+/*****************************************************************************/
+
+dng_xy_coord dng_color_spec::NeutralToXY (const dng_vector &neutral)
+ {
+
+ const uint32 kMaxPasses = 30;
+
+ if (fChannels == 1)
+ {
+
+ return PCStoXY ();
+
+ }
+
+ dng_xy_coord last = D50_xy_coord ();
+
+ for (uint32 pass = 0; pass < kMaxPasses; pass++)
+ {
+
+ dng_matrix xyzToCamera = FindXYZtoCamera (last);
+
+ dng_xy_coord next = XYZtoXY (Invert (xyzToCamera) * neutral);
+
+ if (Abs_real64 (next.x - last.x) +
+ Abs_real64 (next.y - last.y) < 0.0000001)
+ {
+
+ return next;
+
+ }
+
+ // If we reach the limit without converging, we are most likely
+ // in a two value oscillation. So take the average of the last
+ // two estimates and give up.
+
+ if (pass == kMaxPasses - 1)
+ {
+
+ next.x = (last.x + next.x) * 0.5;
+ next.y = (last.y + next.y) * 0.5;
+
+ }
+
+ last = next;
+
+ }
+
+ return last;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_color_spec.h b/source/dng_color_spec.h
index 0d06dde..c8fcbea 100644
--- a/source/dng_color_spec.h
+++ b/source/dng_color_spec.h
@@ -1,146 +1,146 @@
-/*****************************************************************************/
-// Copyright 2006-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_color_spec.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Class for holding a specific color transform.
-*/
-
-#ifndef __dng_color_spec__
-#define __dng_color_spec__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_matrix.h"
-#include "dng_types.h"
-#include "dng_xy_coord.h"
-
-/*****************************************************************************/
-
-/// \brief Compute a 3x3 matrix which maps colors from white point white1 to
-/// white point white2
-///
-/// Uses linearized Bradford adaptation matrix to compute a mapping from
-/// colors measured with one white point (white1) to another (white2).
-
-dng_matrix_3by3 MapWhiteMatrix (const dng_xy_coord &white1,
- const dng_xy_coord &white2);
-
-/*****************************************************************************/
-
-/// Color transform taking into account white point and camera calibration and
-/// individual calibration from DNG negative.
-
-class dng_color_spec
- {
-
- private:
-
- uint32 fChannels;
-
- real64 fTemperature1;
- real64 fTemperature2;
-
- dng_matrix fColorMatrix1;
- dng_matrix fColorMatrix2;
-
- dng_matrix fForwardMatrix1;
- dng_matrix fForwardMatrix2;
-
- dng_matrix fReductionMatrix1;
- dng_matrix fReductionMatrix2;
-
- dng_matrix fCameraCalibration1;
- dng_matrix fCameraCalibration2;
-
- dng_matrix fAnalogBalance;
-
- dng_xy_coord fWhiteXY;
-
- dng_vector fCameraWhite;
- dng_matrix fCameraToPCS;
-
- dng_matrix fPCStoCamera;
-
- public:
-
- /// Read calibration info from DNG negative and construct a
- /// dng_color_spec.
-
- dng_color_spec (const dng_negative &negative,
- const dng_camera_profile *profile);
-
- virtual ~dng_color_spec ()
- {
- }
-
- /// Number of channels used for this color transform. Three
- /// for most cameras.
-
- uint32 Channels () const
- {
- return fChannels;
- }
-
- /// Setter for white point. Value is as XY colorspace coordinate.
- /// \param white White point to set as an XY value.
-
- void SetWhiteXY (const dng_xy_coord &white);
-
- /// Getter for white point. Value is as XY colorspace coordinate.
- /// \retval XY value of white point.
-
- const dng_xy_coord & WhiteXY () const;
-
- /// Return white point in camera native color coordinates.
- /// \retval A dng_vector with components ranging from 0.0 to 1.0
- /// that is normalized such that one component is equal to 1.0 .
-
- const dng_vector & CameraWhite () const;
-
- /// Getter for camera to Profile Connection Space color transform.
- /// \retval A transform that takes into account all camera calibration
- /// transforms and white point.
-
- const dng_matrix & CameraToPCS () const;
-
- /// Getter for Profile Connection Space to camera color transform.
- /// \retval A transform that takes into account all camera calibration
- /// transforms and white point.
-
- const dng_matrix & PCStoCamera () const;
-
- /// Return the XY value to use for SetWhiteXY for a given camera color
- /// space coordinate as the white point.
- /// \param neutral A camera color space value to use for white point.
- /// Components range from 0.0 to 1.0 and should be normalized such that
- /// the largest value is 1.0 .
- /// \retval White point in XY space that makes neutral map to this
- /// XY value as closely as possible.
-
- dng_xy_coord NeutralToXY (const dng_vector &neutral);
-
- private:
-
- dng_matrix FindXYZtoCamera (const dng_xy_coord &white,
- dng_matrix *forwardMatrix = NULL,
- dng_matrix *reductionMatrix = NULL,
- dng_matrix *cameraCalibration = NULL);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_color_spec.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Class for holding a specific color transform.
+*/
+
+#ifndef __dng_color_spec__
+#define __dng_color_spec__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_matrix.h"
+#include "dng_types.h"
+#include "dng_xy_coord.h"
+
+/*****************************************************************************/
+
+/// \brief Compute a 3x3 matrix which maps colors from white point white1 to
+/// white point white2
+///
+/// Uses linearized Bradford adaptation matrix to compute a mapping from
+/// colors measured with one white point (white1) to another (white2).
+
+dng_matrix_3by3 MapWhiteMatrix (const dng_xy_coord &white1,
+ const dng_xy_coord &white2);
+
+/*****************************************************************************/
+
+/// Color transform taking into account white point and camera calibration and
+/// individual calibration from DNG negative.
+
+class dng_color_spec
+ {
+
+ private:
+
+ uint32 fChannels;
+
+ real64 fTemperature1;
+ real64 fTemperature2;
+
+ dng_matrix fColorMatrix1;
+ dng_matrix fColorMatrix2;
+
+ dng_matrix fForwardMatrix1;
+ dng_matrix fForwardMatrix2;
+
+ dng_matrix fReductionMatrix1;
+ dng_matrix fReductionMatrix2;
+
+ dng_matrix fCameraCalibration1;
+ dng_matrix fCameraCalibration2;
+
+ dng_matrix fAnalogBalance;
+
+ dng_xy_coord fWhiteXY;
+
+ dng_vector fCameraWhite;
+ dng_matrix fCameraToPCS;
+
+ dng_matrix fPCStoCamera;
+
+ public:
+
+ /// Read calibration info from DNG negative and construct a
+ /// dng_color_spec.
+
+ dng_color_spec (const dng_negative &negative,
+ const dng_camera_profile *profile);
+
+ virtual ~dng_color_spec ()
+ {
+ }
+
+ /// Number of channels used for this color transform. Three
+ /// for most cameras.
+
+ uint32 Channels () const
+ {
+ return fChannels;
+ }
+
+ /// Setter for white point. Value is as XY colorspace coordinate.
+ /// \param white White point to set as an XY value.
+
+ void SetWhiteXY (const dng_xy_coord &white);
+
+ /// Getter for white point. Value is as XY colorspace coordinate.
+ /// \retval XY value of white point.
+
+ const dng_xy_coord & WhiteXY () const;
+
+ /// Return white point in camera native color coordinates.
+ /// \retval A dng_vector with components ranging from 0.0 to 1.0
+ /// that is normalized such that one component is equal to 1.0 .
+
+ const dng_vector & CameraWhite () const;
+
+ /// Getter for camera to Profile Connection Space color transform.
+ /// \retval A transform that takes into account all camera calibration
+ /// transforms and white point.
+
+ const dng_matrix & CameraToPCS () const;
+
+ /// Getter for Profile Connection Space to camera color transform.
+ /// \retval A transform that takes into account all camera calibration
+ /// transforms and white point.
+
+ const dng_matrix & PCStoCamera () const;
+
+ /// Return the XY value to use for SetWhiteXY for a given camera color
+ /// space coordinate as the white point.
+ /// \param neutral A camera color space value to use for white point.
+ /// Components range from 0.0 to 1.0 and should be normalized such that
+ /// the largest value is 1.0 .
+ /// \retval White point in XY space that makes neutral map to this
+ /// XY value as closely as possible.
+
+ dng_xy_coord NeutralToXY (const dng_vector &neutral);
+
+ private:
+
+ dng_matrix FindXYZtoCamera (const dng_xy_coord &white,
+ dng_matrix *forwardMatrix = NULL,
+ dng_matrix *reductionMatrix = NULL,
+ dng_matrix *cameraCalibration = NULL);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_date_time.h b/source/dng_date_time.h
index 6f9f0ba..846c5c9 100644
--- a/source/dng_date_time.h
+++ b/source/dng_date_time.h
@@ -1,385 +1,385 @@
-/*****************************************************************************/
-// Copyright 2006-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_date_time.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Functions and classes for working with dates and times in DNG files.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_date_time__
-#define __dng_date_time__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_string.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief Class for holding a date/time and converting to and from relevant
-/// date/time formats
-
-class dng_date_time
- {
-
- public:
-
- uint32 fYear;
- uint32 fMonth;
- uint32 fDay;
- uint32 fHour;
- uint32 fMinute;
- uint32 fSecond;
-
- public:
-
- /// Construct an invalid date/time
-
- dng_date_time ();
-
- /// Construct a date/time with specific values.
- /// \param year Year to use as actual integer value, such as 2006.
- /// \param month Month to use from 1 - 12, where 1 is January.
- /// \param day Day of month to use from 1 -31, where 1 is the first.
- /// \param hour Hour of day to use from 0 - 23, where 0 is midnight.
- /// \param minute Minute of hour to use from 0 - 59.
- /// \param second Second of minute to use from 0 - 59.
-
- dng_date_time (uint32 year,
- uint32 month,
- uint32 day,
- uint32 hour,
- uint32 minute,
- uint32 second);
-
- /// Predicate to determine if a date is valid.
- /// \retval true if all fields are within range.
-
- bool IsValid () const;
-
- /// Predicate to determine if a date is invalid.
- /// \retval true if any field is out of range.
-
- bool NotValid () const
- {
- return !IsValid ();
- }
-
- /// Equal operator.
-
- bool operator== (const dng_date_time &dt) const
- {
- return fYear == dt.fYear &&
- fMonth == dt.fMonth &&
- fDay == dt.fDay &&
- fHour == dt.fHour &&
- fMinute == dt.fMinute &&
- fSecond == dt.fSecond;
- }
-
- // Not-equal operator.
-
- bool operator!= (const dng_date_time &dt) const
- {
- return !(*this == dt);
- }
-
- /// Set date to an invalid value.
-
- void Clear ();
-
- /// Parse an EXIF format date string.
- /// \param s Input date string to parse.
- /// \retval true if date was parsed successfully and date is valid.
-
- bool Parse (const char *s);
-
- };
-
-/*****************************************************************************/
-
-/// \brief Class for holding a time zone.
-
-class dng_time_zone
- {
-
- private:
-
- enum
- {
-
- kMaxOffsetHours = 15,
- kMinOffsetHours = -kMaxOffsetHours,
-
- kMaxOffsetMinutes = kMaxOffsetHours * 60,
- kMinOffsetMinutes = kMinOffsetHours * 60,
-
- kInvalidOffset = kMinOffsetMinutes - 1
-
- };
-
- // Offset from GMT in minutes. Positive numbers are
- // ahead of GMT, negative number are behind GMT.
-
- int32 fOffsetMinutes;
-
- public:
-
- dng_time_zone ()
- : fOffsetMinutes (kInvalidOffset)
- {
- }
-
- void Clear ()
- {
- fOffsetMinutes = kInvalidOffset;
- }
-
- void SetOffsetHours (int32 offset)
- {
- fOffsetMinutes = (int32) ((int64) offset * 60);
- }
-
- void SetOffsetMinutes (int32 offset)
- {
- fOffsetMinutes = offset;
- }
-
- void SetOffsetSeconds (int32 offset)
- {
- fOffsetMinutes = (offset > 0) ? ((offset + 30) / 60)
- : ((offset - 30) / 60);
- }
-
- bool IsValid () const
- {
- return fOffsetMinutes >= kMinOffsetMinutes &&
- fOffsetMinutes <= kMaxOffsetMinutes;
- }
-
- bool NotValid () const
- {
- return !IsValid ();
- }
-
- int32 OffsetMinutes () const
- {
- return fOffsetMinutes;
- }
-
- bool IsExactHourOffset () const
- {
- return IsValid () && ((fOffsetMinutes % 60) == 0);
- }
-
- int32 ExactHourOffset () const
- {
- return fOffsetMinutes / 60;
- }
-
- dng_string Encode_ISO_8601 () const;
-
- };
-
-/*****************************************************************************/
-
-/// \brief Class for holding complete data/time/zone information.
-
-class dng_date_time_info
- {
-
- private:
-
- // Is only the date valid and not the time?
-
- bool fDateOnly;
-
- // Date and time.
-
- dng_date_time fDateTime;
-
- // Subseconds string (stored in a separate tag in EXIF).
-
- dng_string fSubseconds;
-
- // Time zone, if known.
-
- dng_time_zone fTimeZone;
-
- public:
-
- dng_date_time_info ();
-
- bool IsValid () const;
-
- bool NotValid () const
- {
- return !IsValid ();
- }
-
- void Clear ()
- {
- *this = dng_date_time_info ();
- }
-
- const dng_date_time & DateTime () const
- {
- return fDateTime;
- }
-
- void SetDateTime (const dng_date_time &dt)
- {
- fDateOnly = false;
- fDateTime = dt;
- }
-
- const dng_string & Subseconds () const
- {
- return fSubseconds;
- }
-
- void SetSubseconds (const dng_string &s)
- {
- fSubseconds = s;
- }
-
- const dng_time_zone & TimeZone () const
- {
- return fTimeZone;
- }
-
- void SetZone (const dng_time_zone &zone)
- {
- fTimeZone = zone;
- }
-
- void Decode_ISO_8601 (const char *s);
-
- dng_string Encode_ISO_8601 () const;
-
- void Decode_IPTC_Date (const char *s);
-
- dng_string Encode_IPTC_Date () const;
-
- void Decode_IPTC_Time (const char *s);
-
- dng_string Encode_IPTC_Time () const;
-
- private:
-
- void SetDate (uint32 year,
- uint32 month,
- uint32 day);
-
- void SetTime (uint32 hour,
- uint32 minute,
- uint32 second);
-
- };
-
-/*****************************************************************************/
-
-/// Get the current date/time and timezone.
-/// \param info Receives current data/time/zone.
-
-void CurrentDateTimeAndZone (dng_date_time_info &info);
-
-/*****************************************************************************/
-
-/// Convert UNIX "seconds since Jan 1, 1970" time to a dng_date_time
-
-void DecodeUnixTime (uint32 unixTime, dng_date_time &dt);
-
-/*****************************************************************************/
-
-/// Return timezone of current location at a given date.
-/// \param dt Date at which to compute timezone difference. (For example, used
-/// to determine Daylight Savings, etc.)
-/// \retval Time zone for date/time dt.
-
-dng_time_zone LocalTimeZone (const dng_date_time &dt);
-
-/*****************************************************************************/
-
-/// Tag to encode date represenation format
-
-enum dng_date_time_format
- {
- dng_date_time_format_unknown = 0, /// Date format not known
- dng_date_time_format_exif = 1, /// EXIF date string
- dng_date_time_format_unix_little_endian = 2, /// 32-bit UNIX time as 4-byte little endian
- dng_date_time_format_unix_big_endian = 3 /// 32-bit UNIX time as 4-byte big endian
- };
-
-/*****************************************************************************/
-
-/// \brief Store file offset from which date was read.
-///
-/// Used internally by Adobe to update date in original file.
-/// \warning Use at your own risk.
-
-class dng_date_time_storage_info
- {
-
- private:
-
- uint64 fOffset;
-
- dng_date_time_format fFormat;
-
- public:
-
- /// The default constructor initializes to an invalid state.
-
- dng_date_time_storage_info ();
-
- /// Construct with file offset and date format.
-
- dng_date_time_storage_info (uint64 offset,
- dng_date_time_format format);
-
- /// Predicate to determine if an offset is valid.
- /// \retval true if offset is valid.
-
- bool IsValid () const;
-
- // The accessors throw if the data is not valid.
-
- /// Getter for offset in file.
- /// \exception dng_exception with fErrorCode equal to dng_error_unknown
- /// if offset is not valid.
-
- uint64 Offset () const;
-
- /// Get for format date was originally stored in file. Throws a
- /// dng_error_unknown exception if offset is invalid.
- /// \exception dng_exception with fErrorCode equal to dng_error_unknown
- /// if offset is not valid.
-
- dng_date_time_format Format () const;
-
- };
-
-/*****************************************************************************/
-
-// Kludge: Global boolean to turn on fake time zones in XMP for old software.
-
-extern bool gDNGUseFakeTimeZonesInXMP;
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_date_time.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Functions and classes for working with dates and times in DNG files.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_date_time__
+#define __dng_date_time__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_string.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief Class for holding a date/time and converting to and from relevant
+/// date/time formats
+
+class dng_date_time
+ {
+
+ public:
+
+ uint32 fYear;
+ uint32 fMonth;
+ uint32 fDay;
+ uint32 fHour;
+ uint32 fMinute;
+ uint32 fSecond;
+
+ public:
+
+ /// Construct an invalid date/time
+
+ dng_date_time ();
+
+ /// Construct a date/time with specific values.
+ /// \param year Year to use as actual integer value, such as 2006.
+ /// \param month Month to use from 1 - 12, where 1 is January.
+ /// \param day Day of month to use from 1 -31, where 1 is the first.
+ /// \param hour Hour of day to use from 0 - 23, where 0 is midnight.
+ /// \param minute Minute of hour to use from 0 - 59.
+ /// \param second Second of minute to use from 0 - 59.
+
+ dng_date_time (uint32 year,
+ uint32 month,
+ uint32 day,
+ uint32 hour,
+ uint32 minute,
+ uint32 second);
+
+ /// Predicate to determine if a date is valid.
+ /// \retval true if all fields are within range.
+
+ bool IsValid () const;
+
+ /// Predicate to determine if a date is invalid.
+ /// \retval true if any field is out of range.
+
+ bool NotValid () const
+ {
+ return !IsValid ();
+ }
+
+ /// Equal operator.
+
+ bool operator== (const dng_date_time &dt) const
+ {
+ return fYear == dt.fYear &&
+ fMonth == dt.fMonth &&
+ fDay == dt.fDay &&
+ fHour == dt.fHour &&
+ fMinute == dt.fMinute &&
+ fSecond == dt.fSecond;
+ }
+
+ // Not-equal operator.
+
+ bool operator!= (const dng_date_time &dt) const
+ {
+ return !(*this == dt);
+ }
+
+ /// Set date to an invalid value.
+
+ void Clear ();
+
+ /// Parse an EXIF format date string.
+ /// \param s Input date string to parse.
+ /// \retval true if date was parsed successfully and date is valid.
+
+ bool Parse (const char *s);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Class for holding a time zone.
+
+class dng_time_zone
+ {
+
+ private:
+
+ enum
+ {
+
+ kMaxOffsetHours = 15,
+ kMinOffsetHours = -kMaxOffsetHours,
+
+ kMaxOffsetMinutes = kMaxOffsetHours * 60,
+ kMinOffsetMinutes = kMinOffsetHours * 60,
+
+ kInvalidOffset = kMinOffsetMinutes - 1
+
+ };
+
+ // Offset from GMT in minutes. Positive numbers are
+ // ahead of GMT, negative number are behind GMT.
+
+ int32 fOffsetMinutes;
+
+ public:
+
+ dng_time_zone ()
+ : fOffsetMinutes (kInvalidOffset)
+ {
+ }
+
+ void Clear ()
+ {
+ fOffsetMinutes = kInvalidOffset;
+ }
+
+ void SetOffsetHours (int32 offset)
+ {
+ fOffsetMinutes = (int32) ((int64) offset * 60);
+ }
+
+ void SetOffsetMinutes (int32 offset)
+ {
+ fOffsetMinutes = offset;
+ }
+
+ void SetOffsetSeconds (int32 offset)
+ {
+ fOffsetMinutes = (offset > 0) ? ((offset + 30) / 60)
+ : ((offset - 30) / 60);
+ }
+
+ bool IsValid () const
+ {
+ return fOffsetMinutes >= kMinOffsetMinutes &&
+ fOffsetMinutes <= kMaxOffsetMinutes;
+ }
+
+ bool NotValid () const
+ {
+ return !IsValid ();
+ }
+
+ int32 OffsetMinutes () const
+ {
+ return fOffsetMinutes;
+ }
+
+ bool IsExactHourOffset () const
+ {
+ return IsValid () && ((fOffsetMinutes % 60) == 0);
+ }
+
+ int32 ExactHourOffset () const
+ {
+ return fOffsetMinutes / 60;
+ }
+
+ dng_string Encode_ISO_8601 () const;
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Class for holding complete data/time/zone information.
+
+class dng_date_time_info
+ {
+
+ private:
+
+ // Is only the date valid and not the time?
+
+ bool fDateOnly;
+
+ // Date and time.
+
+ dng_date_time fDateTime;
+
+ // Subseconds string (stored in a separate tag in EXIF).
+
+ dng_string fSubseconds;
+
+ // Time zone, if known.
+
+ dng_time_zone fTimeZone;
+
+ public:
+
+ dng_date_time_info ();
+
+ bool IsValid () const;
+
+ bool NotValid () const
+ {
+ return !IsValid ();
+ }
+
+ void Clear ()
+ {
+ *this = dng_date_time_info ();
+ }
+
+ const dng_date_time & DateTime () const
+ {
+ return fDateTime;
+ }
+
+ void SetDateTime (const dng_date_time &dt)
+ {
+ fDateOnly = false;
+ fDateTime = dt;
+ }
+
+ const dng_string & Subseconds () const
+ {
+ return fSubseconds;
+ }
+
+ void SetSubseconds (const dng_string &s)
+ {
+ fSubseconds = s;
+ }
+
+ const dng_time_zone & TimeZone () const
+ {
+ return fTimeZone;
+ }
+
+ void SetZone (const dng_time_zone &zone)
+ {
+ fTimeZone = zone;
+ }
+
+ void Decode_ISO_8601 (const char *s);
+
+ dng_string Encode_ISO_8601 () const;
+
+ void Decode_IPTC_Date (const char *s);
+
+ dng_string Encode_IPTC_Date () const;
+
+ void Decode_IPTC_Time (const char *s);
+
+ dng_string Encode_IPTC_Time () const;
+
+ private:
+
+ void SetDate (uint32 year,
+ uint32 month,
+ uint32 day);
+
+ void SetTime (uint32 hour,
+ uint32 minute,
+ uint32 second);
+
+ };
+
+/*****************************************************************************/
+
+/// Get the current date/time and timezone.
+/// \param info Receives current data/time/zone.
+
+void CurrentDateTimeAndZone (dng_date_time_info &info);
+
+/*****************************************************************************/
+
+/// Convert UNIX "seconds since Jan 1, 1970" time to a dng_date_time
+
+void DecodeUnixTime (uint32 unixTime, dng_date_time &dt);
+
+/*****************************************************************************/
+
+/// Return timezone of current location at a given date.
+/// \param dt Date at which to compute timezone difference. (For example, used
+/// to determine Daylight Savings, etc.)
+/// \retval Time zone for date/time dt.
+
+dng_time_zone LocalTimeZone (const dng_date_time &dt);
+
+/*****************************************************************************/
+
+/// Tag to encode date represenation format
+
+enum dng_date_time_format
+ {
+ dng_date_time_format_unknown = 0, /// Date format not known
+ dng_date_time_format_exif = 1, /// EXIF date string
+ dng_date_time_format_unix_little_endian = 2, /// 32-bit UNIX time as 4-byte little endian
+ dng_date_time_format_unix_big_endian = 3 /// 32-bit UNIX time as 4-byte big endian
+ };
+
+/*****************************************************************************/
+
+/// \brief Store file offset from which date was read.
+///
+/// Used internally by Adobe to update date in original file.
+/// \warning Use at your own risk.
+
+class dng_date_time_storage_info
+ {
+
+ private:
+
+ uint64 fOffset;
+
+ dng_date_time_format fFormat;
+
+ public:
+
+ /// The default constructor initializes to an invalid state.
+
+ dng_date_time_storage_info ();
+
+ /// Construct with file offset and date format.
+
+ dng_date_time_storage_info (uint64 offset,
+ dng_date_time_format format);
+
+ /// Predicate to determine if an offset is valid.
+ /// \retval true if offset is valid.
+
+ bool IsValid () const;
+
+ // The accessors throw if the data is not valid.
+
+ /// Getter for offset in file.
+ /// \exception dng_exception with fErrorCode equal to dng_error_unknown
+ /// if offset is not valid.
+
+ uint64 Offset () const;
+
+ /// Get for format date was originally stored in file. Throws a
+ /// dng_error_unknown exception if offset is invalid.
+ /// \exception dng_exception with fErrorCode equal to dng_error_unknown
+ /// if offset is not valid.
+
+ dng_date_time_format Format () const;
+
+ };
+
+/*****************************************************************************/
+
+// Kludge: Global boolean to turn on fake time zones in XMP for old software.
+
+extern bool gDNGUseFakeTimeZonesInXMP;
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_errors.h b/source/dng_errors.h
index 44feb5a..50fee1e 100644
--- a/source/dng_errors.h
+++ b/source/dng_errors.h
@@ -1,58 +1,58 @@
-/*****************************************************************************/
-// Copyright 2006-2009 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_errors.h#2 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Error code values.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_errors__
-#define __dng_errors__
-
-/*****************************************************************************/
-
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// Type for all errors used in DNG SDK. Generally held inside a dng_exception.
-
-typedef int32 dng_error_code;
-
-enum
- {
- dng_error_none = 0, //!< No error. Success.
- dng_error_unknown = 100000, //!< Logic or program error or other unclassifiable error.
- dng_error_not_yet_implemented, //!< Functionality requested is not yet implemented.
- dng_error_silent, //!< An error which should not be signalled to user.
- dng_error_user_canceled, //!< Processing stopped by user (or host application) request
- dng_error_host_insufficient, //!< Necessary host functionality is not present.
- dng_error_memory, //!< Out of memory.
- dng_error_bad_format, //!< File format is not valid.
- dng_error_matrix_math, //!< Matrix has wrong shape, is badly conditioned, or similar problem.
- dng_error_open_file, //!< Could not open file.
- dng_error_read_file, //!< Error reading file.
- dng_error_write_file, //!< Error writing file.
- dng_error_end_of_file, //!< Unexpected end of file.
- dng_error_file_is_damaged, //!< File is damaged in some way.
- dng_error_image_too_big_dng, //!< Image is too big to save as DNG.
- dng_error_image_too_big_tiff, //!< Image is too big to save as TIFF.
- dng_error_unsupported_dng //!< DNG version is unsupported.
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2009 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_errors.h#2 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Error code values.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_errors__
+#define __dng_errors__
+
+/*****************************************************************************/
+
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// Type for all errors used in DNG SDK. Generally held inside a dng_exception.
+
+typedef int32 dng_error_code;
+
+enum
+ {
+ dng_error_none = 0, //!< No error. Success.
+ dng_error_unknown = 100000, //!< Logic or program error or other unclassifiable error.
+ dng_error_not_yet_implemented, //!< Functionality requested is not yet implemented.
+ dng_error_silent, //!< An error which should not be signalled to user.
+ dng_error_user_canceled, //!< Processing stopped by user (or host application) request
+ dng_error_host_insufficient, //!< Necessary host functionality is not present.
+ dng_error_memory, //!< Out of memory.
+ dng_error_bad_format, //!< File format is not valid.
+ dng_error_matrix_math, //!< Matrix has wrong shape, is badly conditioned, or similar problem.
+ dng_error_open_file, //!< Could not open file.
+ dng_error_read_file, //!< Error reading file.
+ dng_error_write_file, //!< Error writing file.
+ dng_error_end_of_file, //!< Unexpected end of file.
+ dng_error_file_is_damaged, //!< File is damaged in some way.
+ dng_error_image_too_big_dng, //!< Image is too big to save as DNG.
+ dng_error_image_too_big_tiff, //!< Image is too big to save as TIFF.
+ dng_error_unsupported_dng //!< DNG version is unsupported.
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_exceptions.cpp b/source/dng_exceptions.cpp
index 6ca4ece..e1d8731 100644
--- a/source/dng_exceptions.cpp
+++ b/source/dng_exceptions.cpp
@@ -1,205 +1,205 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_exceptions.cpp#2 $ */
-/* $DateTime: 2012/06/06 12:08:58 $ */
-/* $Change: 833617 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_exceptions.h"
-
-#include "dng_flags.h"
-#include "dng_globals.h"
-
-/*****************************************************************************/
-
-#ifndef qDNGReportErrors
-// assuming this isn't enable on Win, because it's using printf, but an app can redirect that to console
-#define qDNGReportErrors ((qDNGDebug && qMacOS) || qDNGValidate)
-#endif
-
-/*****************************************************************************/
-
-void ReportWarning (const char *message,
- const char *sub_message)
- {
-
-
- #if qDNGReportErrors
-
- if (sub_message)
- fprintf (stderr, "*** Warning: %s (%s) ***\n", message, sub_message);
- else
- fprintf (stderr, "*** Warning: %s ***\n", message);
-
- #else
-
- (void) message;
- (void) sub_message;
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-void ReportError (const char *message,
- const char *sub_message)
- {
-
- #if qDNGReportErrors
-
- if (sub_message)
- fprintf (stderr, "*** Error: %s (%s) ***\n", message, sub_message);
- else
- fprintf (stderr, "*** Error: %s ***\n", message);
-
- #else
-
- (void) message;
- (void) sub_message;
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-void Throw_dng_error (dng_error_code err,
- const char *message,
- const char *sub_message,
- bool silent)
- {
-
- #if qDNGReportErrors
-
- {
-
- if (!message)
- {
-
- switch (err)
- {
-
- case dng_error_none:
- case dng_error_silent:
- case dng_error_user_canceled:
- {
- break;
- }
-
- case dng_error_not_yet_implemented:
- {
- message = "Not yet implemented";
- break;
- }
-
- case dng_error_host_insufficient:
- {
- message = "Host insufficient";
- break;
- }
-
- case dng_error_memory:
- {
- message = "Unable to allocate memory";
- break;
- }
-
- case dng_error_bad_format:
- {
- message = "File format is invalid";
- break;
- }
-
- case dng_error_matrix_math:
- {
- message = "Matrix math error";
- break;
- }
-
- case dng_error_open_file:
- {
- message = "Unable to open file";
- break;
- }
-
- case dng_error_read_file:
- {
- message = "File read error";
- break;
- }
-
- case dng_error_write_file:
- {
- message = "File write error";
- break;
- }
-
- case dng_error_end_of_file:
- {
- message = "Unexpected end-of-file";
- break;
- }
-
- case dng_error_file_is_damaged:
- {
- message = "File is damaged";
- break;
- }
-
- case dng_error_image_too_big_dng:
- {
- message = "Image is too big to save as DNG";
- break;
- }
-
- case dng_error_image_too_big_tiff:
- {
- message = "Image is too big to save as TIFF";
- break;
- }
-
- case dng_error_unsupported_dng:
- {
- message = "DNG version is unsupported";
- break;
- }
-
- default:
- {
- message = "Unknown error";
- break;
- }
-
- }
-
- }
-
- if (message && !silent)
- {
- ReportError (message, sub_message);
- }
-
- }
-
- #else
-
- (void) message;
- (void) sub_message;
- (void) silent;
-
- #endif
-
- throw dng_exception (err);
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_exceptions.cpp#2 $ */
+/* $DateTime: 2012/06/06 12:08:58 $ */
+/* $Change: 833617 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_exceptions.h"
+
+#include "dng_flags.h"
+#include "dng_globals.h"
+
+/*****************************************************************************/
+
+#ifndef qDNGReportErrors
+// assuming this isn't enable on Win, because it's using printf, but an app can redirect that to console
+#define qDNGReportErrors ((qDNGDebug && qMacOS) || qDNGValidate)
+#endif
+
+/*****************************************************************************/
+
+void ReportWarning (const char *message,
+ const char *sub_message)
+ {
+
+
+ #if qDNGReportErrors
+
+ if (sub_message)
+ fprintf (stderr, "*** Warning: %s (%s) ***\n", message, sub_message);
+ else
+ fprintf (stderr, "*** Warning: %s ***\n", message);
+
+ #else
+
+ (void) message;
+ (void) sub_message;
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+void ReportError (const char *message,
+ const char *sub_message)
+ {
+
+ #if qDNGReportErrors
+
+ if (sub_message)
+ fprintf (stderr, "*** Error: %s (%s) ***\n", message, sub_message);
+ else
+ fprintf (stderr, "*** Error: %s ***\n", message);
+
+ #else
+
+ (void) message;
+ (void) sub_message;
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+void Throw_dng_error (dng_error_code err,
+ const char *message,
+ const char *sub_message,
+ bool silent)
+ {
+
+ #if qDNGReportErrors
+
+ {
+
+ if (!message)
+ {
+
+ switch (err)
+ {
+
+ case dng_error_none:
+ case dng_error_silent:
+ case dng_error_user_canceled:
+ {
+ break;
+ }
+
+ case dng_error_not_yet_implemented:
+ {
+ message = "Not yet implemented";
+ break;
+ }
+
+ case dng_error_host_insufficient:
+ {
+ message = "Host insufficient";
+ break;
+ }
+
+ case dng_error_memory:
+ {
+ message = "Unable to allocate memory";
+ break;
+ }
+
+ case dng_error_bad_format:
+ {
+ message = "File format is invalid";
+ break;
+ }
+
+ case dng_error_matrix_math:
+ {
+ message = "Matrix math error";
+ break;
+ }
+
+ case dng_error_open_file:
+ {
+ message = "Unable to open file";
+ break;
+ }
+
+ case dng_error_read_file:
+ {
+ message = "File read error";
+ break;
+ }
+
+ case dng_error_write_file:
+ {
+ message = "File write error";
+ break;
+ }
+
+ case dng_error_end_of_file:
+ {
+ message = "Unexpected end-of-file";
+ break;
+ }
+
+ case dng_error_file_is_damaged:
+ {
+ message = "File is damaged";
+ break;
+ }
+
+ case dng_error_image_too_big_dng:
+ {
+ message = "Image is too big to save as DNG";
+ break;
+ }
+
+ case dng_error_image_too_big_tiff:
+ {
+ message = "Image is too big to save as TIFF";
+ break;
+ }
+
+ case dng_error_unsupported_dng:
+ {
+ message = "DNG version is unsupported";
+ break;
+ }
+
+ default:
+ {
+ message = "Unknown error";
+ break;
+ }
+
+ }
+
+ }
+
+ if (message && !silent)
+ {
+ ReportError (message, sub_message);
+ }
+
+ }
+
+ #else
+
+ (void) message;
+ (void) sub_message;
+ (void) silent;
+
+ #endif
+
+ throw dng_exception (err);
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_exceptions.h b/source/dng_exceptions.h
index 7bfb1cd..9551709 100644
--- a/source/dng_exceptions.h
+++ b/source/dng_exceptions.h
@@ -1,301 +1,301 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_exceptions.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * C++ exception support for DNG SDK.
-*/
-
-/*****************************************************************************/
-
-#ifndef __dng_exceptions__
-#define __dng_exceptions__
-
-/*****************************************************************************/
-
-#include "dng_errors.h"
-#include "dng_flags.h"
-
-/*****************************************************************************/
-
-/// Display a warning message. Note that this may just eat the message.
-
-void ReportWarning (const char *message,
- const char *sub_message = NULL);
-
-/*****************************************************************************/
-
-/// Display an error message. Note that this may just eat the message.
-
-void ReportError (const char *message,
- const char *sub_message = NULL);
-
-/*****************************************************************************/
-
-/// \brief All exceptions thrown by the DNG SDK use this exception class.
-
-class dng_exception
- {
-
- private:
-
- dng_error_code fErrorCode;
-
- public:
-
- /// Construct an exception representing the given error code.
- /// \param code Error code this exception is for.
-
- dng_exception (dng_error_code code)
-
- : fErrorCode (code)
-
- {
- }
-
- virtual ~dng_exception ()
- {
- }
-
- /// Getter for error code of this exception
- /// \retval The error code of this exception.
-
- dng_error_code ErrorCode () const
- {
- return fErrorCode;
- }
-
- };
-
-/******************************************************************************/
-
-/// \brief Throw an exception based on an arbitrary error code.
-
-void Throw_dng_error (dng_error_code err,
- const char * message = NULL,
- const char * sub_message = NULL,
- bool silent = false);
-
-/******************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code if
-/// error_code is not dng_error_none .
-
-inline void Fail_dng_error (dng_error_code err)
- {
-
- if (err != dng_error_none)
- {
-
- Throw_dng_error (err);
-
- }
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_unknown .
-
-inline void ThrowProgramError (const char * sub_message = NULL)
- {
-
- Throw_dng_error (dng_error_unknown, NULL, sub_message);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_not_yet_implemented .
-
-inline void ThrowNotYetImplemented (const char * sub_message = NULL)
- {
-
- Throw_dng_error (dng_error_not_yet_implemented, NULL, sub_message);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_silent .
-
-inline void ThrowSilentError ()
- {
-
- Throw_dng_error (dng_error_silent);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_user_canceled .
-
-inline void ThrowUserCanceled ()
- {
-
- Throw_dng_error (dng_error_user_canceled);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_host_insufficient .
-
-inline void ThrowHostInsufficient (const char * sub_message = NULL)
- {
-
- Throw_dng_error (dng_error_host_insufficient, NULL, sub_message);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_memory .
-
-inline void ThrowMemoryFull (const char * sub_message = NULL)
- {
-
- Throw_dng_error (dng_error_memory, NULL, sub_message);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_bad_format .
-
-inline void ThrowBadFormat (const char * sub_message = NULL)
- {
-
- Throw_dng_error (dng_error_bad_format, NULL, sub_message);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_matrix_math .
-
-inline void ThrowMatrixMath (const char * sub_message = NULL)
- {
-
- Throw_dng_error (dng_error_matrix_math, NULL, sub_message);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_open_file .
-
-inline void ThrowOpenFile (const char * sub_message = NULL, bool silent = false)
- {
-
- Throw_dng_error (dng_error_open_file, NULL, sub_message, silent);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_read_file .
-
-inline void ThrowReadFile (const char *sub_message = NULL)
- {
-
- Throw_dng_error (dng_error_read_file, NULL, sub_message);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_write_file .
-
-inline void ThrowWriteFile (const char *sub_message = NULL)
- {
-
- Throw_dng_error (dng_error_write_file, NULL, sub_message);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_end_of_file .
-
-inline void ThrowEndOfFile (const char *sub_message = NULL)
- {
-
- Throw_dng_error (dng_error_end_of_file, NULL, sub_message);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_file_is_damaged .
-
-inline void ThrowFileIsDamaged ()
- {
-
- Throw_dng_error (dng_error_file_is_damaged);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_image_too_big_dng .
-
-inline void ThrowImageTooBigDNG ()
- {
-
- Throw_dng_error (dng_error_image_too_big_dng);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_image_too_big_tiff .
-
-inline void ThrowImageTooBigTIFF ()
- {
-
- Throw_dng_error (dng_error_image_too_big_tiff);
-
- }
-
-/*****************************************************************************/
-
-/// \brief Convenience function to throw dng_exception with error code
-/// dng_error_unsupported_dng .
-
-inline void ThrowUnsupportedDNG ()
- {
-
- Throw_dng_error (dng_error_unsupported_dng);
-
- }
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_exceptions.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * C++ exception support for DNG SDK.
+*/
+
+/*****************************************************************************/
+
+#ifndef __dng_exceptions__
+#define __dng_exceptions__
+
+/*****************************************************************************/
+
+#include "dng_errors.h"
+#include "dng_flags.h"
+
+/*****************************************************************************/
+
+/// Display a warning message. Note that this may just eat the message.
+
+void ReportWarning (const char *message,
+ const char *sub_message = NULL);
+
+/*****************************************************************************/
+
+/// Display an error message. Note that this may just eat the message.
+
+void ReportError (const char *message,
+ const char *sub_message = NULL);
+
+/*****************************************************************************/
+
+/// \brief All exceptions thrown by the DNG SDK use this exception class.
+
+class dng_exception
+ {
+
+ private:
+
+ dng_error_code fErrorCode;
+
+ public:
+
+ /// Construct an exception representing the given error code.
+ /// \param code Error code this exception is for.
+
+ dng_exception (dng_error_code code)
+
+ : fErrorCode (code)
+
+ {
+ }
+
+ virtual ~dng_exception ()
+ {
+ }
+
+ /// Getter for error code of this exception
+ /// \retval The error code of this exception.
+
+ dng_error_code ErrorCode () const
+ {
+ return fErrorCode;
+ }
+
+ };
+
+/******************************************************************************/
+
+/// \brief Throw an exception based on an arbitrary error code.
+
+void Throw_dng_error (dng_error_code err,
+ const char * message = NULL,
+ const char * sub_message = NULL,
+ bool silent = false);
+
+/******************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code if
+/// error_code is not dng_error_none .
+
+inline void Fail_dng_error (dng_error_code err)
+ {
+
+ if (err != dng_error_none)
+ {
+
+ Throw_dng_error (err);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_unknown .
+
+inline void ThrowProgramError (const char * sub_message = NULL)
+ {
+
+ Throw_dng_error (dng_error_unknown, NULL, sub_message);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_not_yet_implemented .
+
+inline void ThrowNotYetImplemented (const char * sub_message = NULL)
+ {
+
+ Throw_dng_error (dng_error_not_yet_implemented, NULL, sub_message);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_silent .
+
+inline void ThrowSilentError ()
+ {
+
+ Throw_dng_error (dng_error_silent);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_user_canceled .
+
+inline void ThrowUserCanceled ()
+ {
+
+ Throw_dng_error (dng_error_user_canceled);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_host_insufficient .
+
+inline void ThrowHostInsufficient (const char * sub_message = NULL)
+ {
+
+ Throw_dng_error (dng_error_host_insufficient, NULL, sub_message);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_memory .
+
+inline void ThrowMemoryFull (const char * sub_message = NULL)
+ {
+
+ Throw_dng_error (dng_error_memory, NULL, sub_message);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_bad_format .
+
+inline void ThrowBadFormat (const char * sub_message = NULL)
+ {
+
+ Throw_dng_error (dng_error_bad_format, NULL, sub_message);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_matrix_math .
+
+inline void ThrowMatrixMath (const char * sub_message = NULL)
+ {
+
+ Throw_dng_error (dng_error_matrix_math, NULL, sub_message);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_open_file .
+
+inline void ThrowOpenFile (const char * sub_message = NULL, bool silent = false)
+ {
+
+ Throw_dng_error (dng_error_open_file, NULL, sub_message, silent);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_read_file .
+
+inline void ThrowReadFile (const char *sub_message = NULL)
+ {
+
+ Throw_dng_error (dng_error_read_file, NULL, sub_message);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_write_file .
+
+inline void ThrowWriteFile (const char *sub_message = NULL)
+ {
+
+ Throw_dng_error (dng_error_write_file, NULL, sub_message);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_end_of_file .
+
+inline void ThrowEndOfFile (const char *sub_message = NULL)
+ {
+
+ Throw_dng_error (dng_error_end_of_file, NULL, sub_message);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_file_is_damaged .
+
+inline void ThrowFileIsDamaged ()
+ {
+
+ Throw_dng_error (dng_error_file_is_damaged);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_image_too_big_dng .
+
+inline void ThrowImageTooBigDNG ()
+ {
+
+ Throw_dng_error (dng_error_image_too_big_dng);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_image_too_big_tiff .
+
+inline void ThrowImageTooBigTIFF ()
+ {
+
+ Throw_dng_error (dng_error_image_too_big_tiff);
+
+ }
+
+/*****************************************************************************/
+
+/// \brief Convenience function to throw dng_exception with error code
+/// dng_error_unsupported_dng .
+
+inline void ThrowUnsupportedDNG ()
+ {
+
+ Throw_dng_error (dng_error_unsupported_dng);
+
+ }
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_exif.cpp b/source/dng_exif.cpp
index 289c184..aedb706 100644
--- a/source/dng_exif.cpp
+++ b/source/dng_exif.cpp
@@ -1,4390 +1,4390 @@
-/*****************************************************************************/
-// Copyright 2006-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_exif.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_exif.h"
-
-#include "dng_tag_codes.h"
-#include "dng_tag_types.h"
-#include "dng_parse_utils.h"
-#include "dng_globals.h"
-#include "dng_exceptions.h"
-#include "dng_tag_values.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_exif::dng_exif ()
-
- : fImageDescription ()
- , fMake ()
- , fModel ()
- , fSoftware ()
- , fArtist ()
- , fCopyright ()
- , fCopyright2 ()
- , fUserComment ()
-
- , fDateTime ()
- , fDateTimeStorageInfo ()
-
- , fDateTimeOriginal ()
- , fDateTimeOriginalStorageInfo ()
-
- , fDateTimeDigitized ()
- , fDateTimeDigitizedStorageInfo ()
-
- , fTIFF_EP_StandardID (0)
- , fExifVersion (0)
- , fFlashPixVersion (0)
-
- , fExposureTime ()
- , fFNumber ()
- , fShutterSpeedValue ()
- , fApertureValue ()
- , fBrightnessValue ()
- , fExposureBiasValue ()
- , fMaxApertureValue ()
- , fFocalLength ()
- , fDigitalZoomRatio ()
- , fExposureIndex ()
- , fSubjectDistance ()
- , fGamma ()
-
- , fBatteryLevelR ()
- , fBatteryLevelA ()
-
- , fExposureProgram (0xFFFFFFFF)
- , fMeteringMode (0xFFFFFFFF)
- , fLightSource (0xFFFFFFFF)
- , fFlash (0xFFFFFFFF)
- , fFlashMask (0x0000FFFF)
- , fSensingMethod (0xFFFFFFFF)
- , fColorSpace (0xFFFFFFFF)
- , fFileSource (0xFFFFFFFF)
- , fSceneType (0xFFFFFFFF)
- , fCustomRendered (0xFFFFFFFF)
- , fExposureMode (0xFFFFFFFF)
- , fWhiteBalance (0xFFFFFFFF)
- , fSceneCaptureType (0xFFFFFFFF)
- , fGainControl (0xFFFFFFFF)
- , fContrast (0xFFFFFFFF)
- , fSaturation (0xFFFFFFFF)
- , fSharpness (0xFFFFFFFF)
- , fSubjectDistanceRange (0xFFFFFFFF)
- , fSelfTimerMode (0xFFFFFFFF)
- , fImageNumber (0xFFFFFFFF)
-
- , fFocalLengthIn35mmFilm (0)
-
- , fSensitivityType (0)
- , fStandardOutputSensitivity (0)
- , fRecommendedExposureIndex (0)
- , fISOSpeed (0)
- , fISOSpeedLatitudeyyy (0)
- , fISOSpeedLatitudezzz (0)
-
- , fSubjectAreaCount (0)
-
- , fComponentsConfiguration (0)
-
- , fCompresssedBitsPerPixel ()
-
- , fPixelXDimension (0)
- , fPixelYDimension (0)
-
- , fFocalPlaneXResolution ()
- , fFocalPlaneYResolution ()
-
- , fFocalPlaneResolutionUnit (0xFFFFFFFF)
-
- , fCFARepeatPatternRows (0)
- , fCFARepeatPatternCols (0)
-
- , fImageUniqueID ()
-
- , fGPSVersionID (0)
- , fGPSLatitudeRef ()
- , fGPSLongitudeRef ()
- , fGPSAltitudeRef (0xFFFFFFFF)
- , fGPSAltitude ()
- , fGPSSatellites ()
- , fGPSStatus ()
- , fGPSMeasureMode ()
- , fGPSDOP ()
- , fGPSSpeedRef ()
- , fGPSSpeed ()
- , fGPSTrackRef ()
- , fGPSTrack ()
- , fGPSImgDirectionRef ()
- , fGPSImgDirection ()
- , fGPSMapDatum ()
- , fGPSDestLatitudeRef ()
- , fGPSDestLongitudeRef ()
- , fGPSDestBearingRef ()
- , fGPSDestBearing ()
- , fGPSDestDistanceRef ()
- , fGPSDestDistance ()
- , fGPSProcessingMethod ()
- , fGPSAreaInformation ()
- , fGPSDateStamp ()
- , fGPSDifferential (0xFFFFFFFF)
- , fGPSHPositioningError ()
-
- , fInteroperabilityIndex ()
-
- , fInteroperabilityVersion (0)
-
- , fRelatedImageFileFormat ()
-
- , fRelatedImageWidth (0)
- , fRelatedImageLength (0)
-
- , fCameraSerialNumber ()
-
- , fLensID ()
- , fLensMake ()
- , fLensName ()
- , fLensSerialNumber ()
-
- , fLensNameWasReadFromExif (false)
-
- , fApproxFocusDistance ()
-
- , fFlashCompensation ()
-
- , fOwnerName ()
- , fFirmware ()
-
- {
-
- uint32 j;
- uint32 k;
-
- fISOSpeedRatings [0] = 0;
- fISOSpeedRatings [1] = 0;
- fISOSpeedRatings [2] = 0;
-
- for (j = 0; j < kMaxCFAPattern; j++)
- for (k = 0; k < kMaxCFAPattern; k++)
- {
- fCFAPattern [j] [k] = 255;
- }
-
- }
-
-/*****************************************************************************/
-
-dng_exif::~dng_exif ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_exif * dng_exif::Clone () const
- {
-
- dng_exif *result = new dng_exif (*this);
-
- if (!result)
- {
- ThrowMemoryFull ();
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-void dng_exif::SetEmpty ()
- {
-
- *this = dng_exif ();
-
- }
-
-/*****************************************************************************/
-
-void dng_exif::CopyGPSFrom (const dng_exif &exif)
- {
-
- fGPSVersionID = exif.fGPSVersionID;
- fGPSLatitudeRef = exif.fGPSLatitudeRef;
- fGPSLatitude [0] = exif.fGPSLatitude [0];
- fGPSLatitude [1] = exif.fGPSLatitude [1];
- fGPSLatitude [2] = exif.fGPSLatitude [2];
- fGPSLongitudeRef = exif.fGPSLongitudeRef;
- fGPSLongitude [0] = exif.fGPSLongitude [0];
- fGPSLongitude [1] = exif.fGPSLongitude [1];
- fGPSLongitude [2] = exif.fGPSLongitude [2];
- fGPSAltitudeRef = exif.fGPSAltitudeRef;
- fGPSAltitude = exif.fGPSAltitude;
- fGPSTimeStamp [0] = exif.fGPSTimeStamp [0];
- fGPSTimeStamp [1] = exif.fGPSTimeStamp [1];
- fGPSTimeStamp [2] = exif.fGPSTimeStamp [2];
- fGPSSatellites = exif.fGPSSatellites;
- fGPSStatus = exif.fGPSStatus;
- fGPSMeasureMode = exif.fGPSMeasureMode;
- fGPSDOP = exif.fGPSDOP;
- fGPSSpeedRef = exif.fGPSSpeedRef;
- fGPSSpeed = exif.fGPSSpeed;
- fGPSTrackRef = exif.fGPSTrackRef;
- fGPSTrack = exif.fGPSTrack;
- fGPSImgDirectionRef = exif.fGPSImgDirectionRef;
- fGPSImgDirection = exif.fGPSImgDirection;
- fGPSMapDatum = exif.fGPSMapDatum;
- fGPSDestLatitudeRef = exif.fGPSDestLatitudeRef;
- fGPSDestLatitude [0] = exif.fGPSDestLatitude [0];
- fGPSDestLatitude [1] = exif.fGPSDestLatitude [1];
- fGPSDestLatitude [2] = exif.fGPSDestLatitude [2];
- fGPSDestLongitudeRef = exif.fGPSDestLongitudeRef;
- fGPSDestLongitude [0] = exif.fGPSDestLongitude [0];
- fGPSDestLongitude [1] = exif.fGPSDestLongitude [1];
- fGPSDestLongitude [2] = exif.fGPSDestLongitude [2];
- fGPSDestBearingRef = exif.fGPSDestBearingRef;
- fGPSDestBearing = exif.fGPSDestBearing;
- fGPSDestDistanceRef = exif.fGPSDestDistanceRef;
- fGPSDestDistance = exif.fGPSDestDistance;
- fGPSProcessingMethod = exif.fGPSProcessingMethod;
- fGPSAreaInformation = exif.fGPSAreaInformation;
- fGPSDateStamp = exif.fGPSDateStamp;
- fGPSDifferential = exif.fGPSDifferential;
- fGPSHPositioningError = exif.fGPSHPositioningError;
-
- }
-
-/*****************************************************************************/
-
-// Fix up common errors and rounding issues with EXIF exposure times.
-
-real64 dng_exif::SnapExposureTime (real64 et)
- {
-
- // Protection against invalid values.
-
- if (et <= 0.0)
- return 0.0;
-
- // If near a standard shutter speed, snap to it.
-
- static const real64 kStandardSpeed [] =
- {
- 30.0,
- 25.0,
- 20.0,
- 15.0,
- 13.0,
- 10.0,
- 8.0,
- 6.0,
- 5.0,
- 4.0,
- 3.2,
- 3.0,
- 2.5,
- 2.0,
- 1.6,
- 1.5,
- 1.3,
- 1.0,
- 0.8,
- 0.7,
- 0.6,
- 0.5,
- 0.4,
- 0.3,
- 1.0 / 4.0,
- 1.0 / 5.0,
- 1.0 / 6.0,
- 1.0 / 8.0,
- 1.0 / 10.0,
- 1.0 / 13.0,
- 1.0 / 15.0,
- 1.0 / 20.0,
- 1.0 / 25.0,
- 1.0 / 30.0,
- 1.0 / 40.0,
- 1.0 / 45.0,
- 1.0 / 50.0,
- 1.0 / 60.0,
- 1.0 / 80.0,
- 1.0 / 90.0,
- 1.0 / 100.0,
- 1.0 / 125.0,
- 1.0 / 160.0,
- 1.0 / 180.0,
- 1.0 / 200.0,
- 1.0 / 250.0,
- 1.0 / 320.0,
- 1.0 / 350.0,
- 1.0 / 400.0,
- 1.0 / 500.0,
- 1.0 / 640.0,
- 1.0 / 750.0,
- 1.0 / 800.0,
- 1.0 / 1000.0,
- 1.0 / 1250.0,
- 1.0 / 1500.0,
- 1.0 / 1600.0,
- 1.0 / 2000.0,
- 1.0 / 2500.0,
- 1.0 / 3000.0,
- 1.0 / 3200.0,
- 1.0 / 4000.0,
- 1.0 / 5000.0,
- 1.0 / 6000.0,
- 1.0 / 6400.0,
- 1.0 / 8000.0,
- 1.0 / 10000.0,
- 1.0 / 12000.0,
- 1.0 / 12800.0,
- 1.0 / 16000.0
- };
-
- uint32 count = sizeof (kStandardSpeed ) /
- sizeof (kStandardSpeed [0]);
-
- for (uint32 fudge = 0; fudge <= 1; fudge++)
- {
-
- real64 testSpeed = et;
-
- if (fudge == 1)
- {
-
- // Often APEX values are rounded to a power of two,
- // which results in non-standard shutter speeds.
-
- if (et >= 0.1)
- {
-
- // No fudging slower than 1/10 second
-
- break;
-
- }
-
- else if (et >= 0.01)
- {
-
- // Between 1/10 and 1/100 the commonly misrounded
- // speeds are 1/15, 1/30, 1/60, which are often encoded as
- // 1/16, 1/32, 1/64. Try fudging and see if we get
- // near a standard speed.
-
- testSpeed *= 16.0 / 15.0;
-
- }
-
- else
- {
-
- // Faster than 1/100, the commonly misrounded
- // speeds are 1/125, 1/250, 1/500, etc., which
- // are often encoded as 1/128, 1/256, 1/512.
-
- testSpeed *= 128.0 / 125.0;
-
- }
-
- }
-
- for (uint32 index = 0; index < count; index++)
- {
-
- if (testSpeed >= kStandardSpeed [index] * 0.98 &&
- testSpeed <= kStandardSpeed [index] * 1.02)
- {
-
- return kStandardSpeed [index];
-
- }
-
- }
-
- }
-
- // We are not near any standard speeds. Round the non-standard value to something
- // that looks reasonable.
-
- if (et >= 10.0)
- {
-
- // Round to nearest second.
-
- et = floor (et + 0.5);
-
- }
-
- else if (et >= 0.5)
- {
-
- // Round to nearest 1/10 second
-
- et = floor (et * 10.0 + 0.5) * 0.1;
-
- }
-
- else if (et >= 1.0 / 20.0)
- {
-
- // Round to an exact inverse.
-
- et = 1.0 / floor (1.0 / et + 0.5);
-
- }
-
- else if (et >= 1.0 / 130.0)
- {
-
- // Round inverse to multiple of 5
-
- et = 0.2 / floor (0.2 / et + 0.5);
-
- }
-
- else if (et >= 1.0 / 750.0)
- {
-
- // Round inverse to multiple of 10
-
- et = 0.1 / floor (0.1 / et + 0.5);
-
- }
-
- else if (et >= 1.0 / 1300.0)
- {
-
- // Round inverse to multiple of 50
-
- et = 0.02 / floor (0.02 / et + 0.5);
-
- }
-
- else if (et >= 1.0 / 15000.0)
- {
-
- // Round inverse to multiple of 100
-
- et = 0.01 / floor (0.01 / et + 0.5);
-
- }
-
- else
- {
-
- // Round inverse to multiple of 1000
-
- et = 0.001 / floor (0.001 / et + 0.5);
-
- }
-
- return et;
-
- }
-
-/*****************************************************************************/
-
-void dng_exif::SetExposureTime (real64 et, bool snap)
- {
-
- fExposureTime.Clear ();
-
- fShutterSpeedValue.Clear ();
-
- if (snap)
- {
-
- et = SnapExposureTime (et);
-
- }
-
- if (et >= 1.0 / 32768.0 && et <= 32768.0)
- {
-
- if (et >= 100.0)
- {
-
- fExposureTime.Set_real64 (et, 1);
-
- }
-
- else if (et >= 1.0)
- {
-
- fExposureTime.Set_real64 (et, 10);
-
- fExposureTime.ReduceByFactor (10);
-
- }
-
- else if (et <= 0.1)
- {
-
- fExposureTime = dng_urational (1, Round_uint32 (1.0 / et));
-
- }
-
- else
- {
-
- fExposureTime.Set_real64 (et, 100);
-
- fExposureTime.ReduceByFactor (10);
-
- for (uint32 f = 2; f <= 9; f++)
- {
-
- real64 z = 1.0 / (real64) f / et;
-
- if (z >= 0.99 && z <= 1.01)
- {
-
- fExposureTime = dng_urational (1, f);
-
- break;
-
- }
-
- }
-
- }
-
- // Now mirror this value to the ShutterSpeedValue field.
-
- et = fExposureTime.As_real64 ();
-
- fShutterSpeedValue.Set_real64 (-log (et) / log (2.0), 1000000);
-
- fShutterSpeedValue.ReduceByFactor (10);
- fShutterSpeedValue.ReduceByFactor (10);
- fShutterSpeedValue.ReduceByFactor (10);
- fShutterSpeedValue.ReduceByFactor (10);
- fShutterSpeedValue.ReduceByFactor (10);
- fShutterSpeedValue.ReduceByFactor (10);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_exif::SetShutterSpeedValue (real64 ss)
- {
-
- if (fExposureTime.NotValid ())
- {
-
- real64 et = pow (2.0, -ss);
-
- SetExposureTime (et, true);
-
- }
-
- }
-
-/******************************************************************************/
-
-dng_urational dng_exif::EncodeFNumber (real64 fs)
- {
-
- dng_urational y;
-
- if (fs > 10.0)
- {
-
- y.Set_real64 (fs, 1);
-
- }
-
- else if (fs < 1.0)
- {
-
- y.Set_real64 (fs, 100);
-
- y.ReduceByFactor (10);
- y.ReduceByFactor (10);
-
- }
-
- else
- {
-
- y.Set_real64 (fs, 10);
-
- y.ReduceByFactor (10);
-
- }
-
- return y;
-
- }
-
-/*****************************************************************************/
-
-void dng_exif::SetFNumber (real64 fs)
- {
-
- fFNumber.Clear ();
-
- fApertureValue.Clear ();
-
- // Allow f-number values less than 1.0 (e.g., f/0.95), even though they would
- // correspond to negative APEX values, which the EXIF specification does not
- // support (ApertureValue is a rational, not srational). The ApertureValue tag
- // will be omitted in the case where fs < 1.0.
-
- if (fs > 0.0 && fs <= 32768.0)
- {
-
- fFNumber = EncodeFNumber (fs);
-
- // Now mirror this value to the ApertureValue field.
-
- real64 av = FNumberToApertureValue (fFNumber);
-
- if (av >= 0.0 && av <= 99.99)
- {
-
- fApertureValue.Set_real64 (av, 1000000);
-
- fApertureValue.ReduceByFactor (10);
- fApertureValue.ReduceByFactor (10);
- fApertureValue.ReduceByFactor (10);
- fApertureValue.ReduceByFactor (10);
- fApertureValue.ReduceByFactor (10);
- fApertureValue.ReduceByFactor (10);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_exif::SetApertureValue (real64 av)
- {
-
- if (fFNumber.NotValid ())
- {
-
- SetFNumber (ApertureValueToFNumber (av));
-
- }
-
- }
-
-/*****************************************************************************/
-
-real64 dng_exif::ApertureValueToFNumber (real64 av)
- {
-
- return pow (2.0, 0.5 * av);
-
- }
-
-/*****************************************************************************/
-
-real64 dng_exif::ApertureValueToFNumber (const dng_urational &av)
- {
-
- return ApertureValueToFNumber (av.As_real64 ());
-
- }
-
-/*****************************************************************************/
-
-real64 dng_exif::FNumberToApertureValue (real64 fNumber)
- {
-
- return 2.0 * log (fNumber) / log (2.0);
-
- }
-
-/*****************************************************************************/
-
-real64 dng_exif::FNumberToApertureValue (const dng_urational &fNumber)
- {
-
- return FNumberToApertureValue (fNumber.As_real64 ());
-
- }
-
-/*****************************************************************************/
-
-void dng_exif::UpdateDateTime (const dng_date_time_info &dt)
- {
-
- fDateTime = dt;
-
- }
-
-/*****************************************************************************/
-
-bool dng_exif::AtLeastVersion0230 () const
- {
-
- uint32 b0 = (fExifVersion >> 24) & 0xff;
- uint32 b1 = (fExifVersion >> 16) & 0xff;
- uint32 b2 = (fExifVersion >> 8) & 0xff;
-
- return (b0 > 0) || (b1 >= 2 && b2 >= 3);
-
- }
-
-/*****************************************************************************/
-
-bool dng_exif::ParseTag (dng_stream &stream,
- dng_shared &shared,
- uint32 parentCode,
- bool isMainIFD,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset)
- {
-
- if (parentCode == 0)
- {
-
- if (Parse_ifd0 (stream,
- shared,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- tagOffset))
- {
-
- return true;
-
- }
-
- }
-
- if (parentCode == 0 || isMainIFD)
- {
-
- if (Parse_ifd0_main (stream,
- shared,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- tagOffset))
- {
-
- return true;
-
- }
-
- }
-
- if (parentCode == 0 ||
- parentCode == tcExifIFD)
- {
-
- if (Parse_ifd0_exif (stream,
- shared,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- tagOffset))
- {
-
- return true;
-
- }
-
- }
-
- if (parentCode == tcGPSInfo)
- {
-
- if (Parse_gps (stream,
- shared,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- tagOffset))
- {
-
- return true;
-
- }
-
- }
-
- if (parentCode == tcInteroperabilityIFD)
- {
-
- if (Parse_interoperability (stream,
- shared,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- tagOffset))
- {
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-// Parses tags that should only appear in IFD 0.
-
-bool dng_exif::Parse_ifd0 (dng_stream &stream,
- dng_shared & /* shared */,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 /* tagOffset */)
- {
-
- switch (tagCode)
- {
-
- case tcImageDescription:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fImageDescription);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ImageDescription: ");
-
- DumpString (fImageDescription);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcMake:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fMake);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Make: ");
-
- DumpString (fMake);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcModel:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fModel);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Model: ");
-
- DumpString (fModel);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSoftware:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fSoftware);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Software: ");
-
- DumpString (fSoftware);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcDateTime:
- {
-
- uint64 tagPosition = stream.PositionInOriginalFile ();
-
- dng_date_time dt;
-
- if (!ParseDateTimeTag (stream,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- dt))
- {
- return false;
- }
-
- fDateTime.SetDateTime (dt);
-
- fDateTimeStorageInfo = dng_date_time_storage_info (tagPosition,
- dng_date_time_format_exif);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("DateTime: ");
-
- DumpDateTime (fDateTime.DateTime ());
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcArtist:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fArtist);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Artist: ");
-
- DumpString (fArtist);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCopyright:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseDualStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fCopyright,
- fCopyright2);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Copyright: ");
-
- DumpString (fCopyright);
-
- if (fCopyright2.Get () [0] != 0)
- {
-
- printf (" ");
-
- DumpString (fCopyright2);
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcTIFF_EP_StandardID:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttByte);
-
- CheckTagCount (parentCode, tagCode, tagCount, 4);
-
- uint32 b0 = stream.Get_uint8 ();
- uint32 b1 = stream.Get_uint8 ();
- uint32 b2 = stream.Get_uint8 ();
- uint32 b3 = stream.Get_uint8 ();
-
- fTIFF_EP_StandardID = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("TIFF/EPStandardID: %u.%u.%u.%u\n",
- (unsigned) b0,
- (unsigned) b1,
- (unsigned) b2,
- (unsigned) b3);
- }
-
- #endif
-
- break;
-
- }
-
- case tcCameraSerialNumber:
- case tcKodakCameraSerialNumber: // Kodak uses a very similar tag.
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fCameraSerialNumber);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: ", LookupTagCode (parentCode, tagCode));
-
- DumpString (fCameraSerialNumber);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcLensInfo:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
- return false;
-
- fLensInfo [0] = stream.TagValue_urational (tagType);
- fLensInfo [1] = stream.TagValue_urational (tagType);
- fLensInfo [2] = stream.TagValue_urational (tagType);
- fLensInfo [3] = stream.TagValue_urational (tagType);
-
- // Some third party software wrote zero rather and undefined values
- // for unknown entries. Work around this bug.
-
- for (uint32 j = 0; j < 4; j++)
- {
-
- if (fLensInfo [j].IsValid () && fLensInfo [j].As_real64 () <= 0.0)
- {
-
- fLensInfo [j] = dng_urational (0, 0);
-
- #if qDNGValidate
-
- ReportWarning ("Zero entry in LensInfo tag--should be undefined");
-
- #endif
-
- }
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("LensInfo: ");
-
- real64 minFL = fLensInfo [0].As_real64 ();
- real64 maxFL = fLensInfo [1].As_real64 ();
-
- if (minFL == maxFL)
- printf ("%0.1f mm", minFL);
- else
- printf ("%0.1f-%0.1f mm", minFL, maxFL);
-
- if (fLensInfo [2].d)
- {
-
- real64 minFS = fLensInfo [2].As_real64 ();
- real64 maxFS = fLensInfo [3].As_real64 ();
-
- if (minFS == maxFS)
- printf (" f/%0.1f", minFS);
- else
- printf (" f/%0.1f-%0.1f", minFS, maxFS);
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- default:
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-// Parses tags that should only appear in IFD 0 or the main image IFD.
-
-bool dng_exif::Parse_ifd0_main (dng_stream &stream,
- dng_shared & /* shared */,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 /* tagOffset */)
- {
-
- switch (tagCode)
- {
-
- case tcFocalPlaneXResolution:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFocalPlaneXResolution = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FocalPlaneXResolution: %0.4f\n",
- fFocalPlaneXResolution.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFocalPlaneYResolution:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFocalPlaneYResolution = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FocalPlaneYResolution: %0.4f\n",
- fFocalPlaneYResolution.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFocalPlaneResolutionUnit:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFocalPlaneResolutionUnit = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FocalPlaneResolutionUnit: %s\n",
- LookupResolutionUnit (fFocalPlaneResolutionUnit));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSensingMethod:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSensingMethod = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SensingMethod: %s\n",
- LookupSensingMethod (fSensingMethod));
-
- }
-
- #endif
-
- break;
-
- }
-
- default:
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-// Parses tags that should only appear in IFD 0 or EXIF IFD.
-
-bool dng_exif::Parse_ifd0_exif (dng_stream &stream,
- dng_shared & /* shared */,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 /* tagOffset */)
- {
-
- switch (tagCode)
- {
-
- case tcBatteryLevel:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational, ttAscii);
-
- if (tagType == ttAscii)
- {
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fBatteryLevelA);
-
- }
-
- else
- {
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fBatteryLevelR = stream.TagValue_urational (tagType);
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("BatteryLevel: ");
-
- if (tagType == ttAscii)
- {
-
- DumpString (fBatteryLevelA);
-
- }
-
- else
- {
-
- printf ("%0.2f", fBatteryLevelR.As_real64 ());
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcExposureTime:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- dng_urational et = stream.TagValue_urational (tagType);
-
- SetExposureTime (et.As_real64 (), true);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ExposureTime: ");
-
- DumpExposureTime (et.As_real64 ());
-
- printf ("\n");
-
- }
-
- if (et.As_real64 () <= 0.0)
- {
-
- ReportWarning ("The ExposureTime is <= 0");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFNumber:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- dng_urational fs = stream.TagValue_urational (tagType);
-
- // Sometimes "unknown" is recorded as zero.
-
- if (fs.As_real64 () <= 0.0)
- {
- fs.Clear ();
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FNumber: f/%0.2f\n",
- fs.As_real64 ());
-
- }
-
- #endif
-
- SetFNumber (fs.As_real64 ());
-
- break;
-
- }
-
- case tcExposureProgram:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fExposureProgram = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ExposureProgram: %s\n",
- LookupExposureProgram (fExposureProgram));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcISOSpeedRatings:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1, 3);
-
- for (uint32 j = 0; j < tagCount && j < 3; j++)
- {
-
- fISOSpeedRatings [j] = stream.TagValue_uint32 (tagType);
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ISOSpeedRatings:");
-
- for (uint32 j = 0; j < tagCount && j < 3; j++)
- {
-
- printf (" %u", (unsigned) fISOSpeedRatings [j]);
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSensitivityType:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSensitivityType = (uint32) stream.Get_uint16 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SensitivityType: %s\n",
- LookupSensitivityType (fSensitivityType));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcStandardOutputSensitivity:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fStandardOutputSensitivity = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("StandardOutputSensitivity: %u\n",
- (unsigned) fStandardOutputSensitivity);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcRecommendedExposureIndex:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fRecommendedExposureIndex = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("RecommendedExposureIndex: %u\n",
- (unsigned) fRecommendedExposureIndex);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcISOSpeed:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fISOSpeed = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ISOSpeed: %u\n",
- (unsigned) fISOSpeed);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcISOSpeedLatitudeyyy:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fISOSpeedLatitudeyyy = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ISOSpeedLatitudeyyy: %u\n",
- (unsigned) fISOSpeedLatitudeyyy);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcISOSpeedLatitudezzz:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fISOSpeedLatitudezzz = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ISOSpeedLatitudezzz: %u\n",
- (unsigned) fISOSpeedLatitudezzz);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcTimeZoneOffset:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttSShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1, 2);
-
- dng_time_zone zoneOriginal;
-
- zoneOriginal.SetOffsetHours (stream.TagValue_int32 (tagType));
-
- fDateTimeOriginal.SetZone (zoneOriginal);
-
- #if 0 // MWG: Not filling in time zones unless we are sure.
-
- // Note that there is no "TimeZoneOffsetDigitized" field, so
- // we assume the same tone zone as the original.
-
- fDateTimeDigitized.SetZone (zoneOriginal);
-
- #endif
-
- dng_time_zone zoneCurrent;
-
- if (tagCount >= 2)
- {
-
- zoneCurrent.SetOffsetHours (stream.TagValue_int32 (tagType));
-
- fDateTime.SetZone (zoneCurrent);
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("TimeZoneOffset: DateTimeOriginal = %d",
- (int) zoneOriginal.ExactHourOffset ());
-
- if (tagCount >= 2)
- {
-
- printf (", DateTime = %d",
- (int) zoneCurrent.ExactHourOffset ());
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSelfTimerMode:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSelfTimerMode = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SelfTimerMode: ");
-
- if (fSelfTimerMode)
- {
-
- printf ("%u sec", (unsigned) fSelfTimerMode);
-
- }
-
- else
- {
-
- printf ("Off");
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcExifVersion:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- CheckTagCount (parentCode, tagCode, tagCount, 4);
-
- uint32 b0 = stream.Get_uint8 ();
- uint32 b1 = stream.Get_uint8 ();
- uint32 b2 = stream.Get_uint8 ();
- uint32 b3 = stream.Get_uint8 ();
-
- fExifVersion = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- real64 x = (b0 - '0') * 10.00 +
- (b1 - '0') * 1.00 +
- (b2 - '0') * 0.10 +
- (b3 - '0') * 0.01;
-
- printf ("ExifVersion: %0.2f\n", x);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcDateTimeOriginal:
- {
-
- uint64 tagPosition = stream.PositionInOriginalFile ();
-
- dng_date_time dt;
-
- if (!ParseDateTimeTag (stream,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- dt))
- {
- return false;
- }
-
- fDateTimeOriginal.SetDateTime (dt);
-
- fDateTimeOriginalStorageInfo = dng_date_time_storage_info (tagPosition,
- dng_date_time_format_exif);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("DateTimeOriginal: ");
-
- DumpDateTime (fDateTimeOriginal.DateTime ());
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcDateTimeDigitized:
- {
-
- uint64 tagPosition = stream.PositionInOriginalFile ();
-
- dng_date_time dt;
-
- if (!ParseDateTimeTag (stream,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- dt))
- {
- return false;
- }
-
- fDateTimeDigitized.SetDateTime (dt);
-
- fDateTimeDigitizedStorageInfo = dng_date_time_storage_info (tagPosition,
- dng_date_time_format_exif);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("DateTimeDigitized: ");
-
- DumpDateTime (fDateTimeDigitized.DateTime ());
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcComponentsConfiguration:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- CheckTagCount (parentCode, tagCode, tagCount, 4);
-
- uint32 b0 = stream.Get_uint8 ();
- uint32 b1 = stream.Get_uint8 ();
- uint32 b2 = stream.Get_uint8 ();
- uint32 b3 = stream.Get_uint8 ();
-
- fComponentsConfiguration = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ComponentsConfiguration: %s %s %s %s\n",
- LookupComponent (b0),
- LookupComponent (b1),
- LookupComponent (b2),
- LookupComponent (b3));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCompressedBitsPerPixel:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fCompresssedBitsPerPixel = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("CompressedBitsPerPixel: %0.2f\n",
- fCompresssedBitsPerPixel.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcShutterSpeedValue:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttSRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- dng_srational ss = stream.TagValue_srational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ShutterSpeedValue: ");
-
- real64 x = pow (2.0, -ss.As_real64 ());
-
- DumpExposureTime (x);
-
- printf ("\n");
-
- }
-
- // The ExposureTime and ShutterSpeedValue tags should be consistent.
-
- if (fExposureTime.IsValid ())
- {
-
- real64 et = fExposureTime.As_real64 ();
-
- real64 tv1 = -1.0 * log (et) / log (2.0);
-
- real64 tv2 = ss.As_real64 ();
-
- // Make sure they are within 0.25 APEX values.
-
- if (Abs_real64 (tv1 - tv2) > 0.25)
- {
-
- ReportWarning ("The ExposureTime and ShutterSpeedValue tags have conflicting values");
-
- }
-
- }
-
- #endif
-
- SetShutterSpeedValue (ss.As_real64 ());
-
- break;
-
- }
-
- case tcApertureValue:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- dng_urational av = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- real64 x = pow (2.0, 0.5 * av.As_real64 ());
-
- printf ("ApertureValue: f/%0.2f\n", x);
-
- }
-
- // The FNumber and ApertureValue tags should be consistent.
-
- if (fFNumber.IsValid () && av.IsValid ())
- {
-
- real64 fs = fFNumber.As_real64 ();
-
- real64 av1 = FNumberToApertureValue (fs);
-
- real64 av2 = av.As_real64 ();
-
- if (Abs_real64 (av1 - av2) > 0.25)
- {
-
- ReportWarning ("The FNumber and ApertureValue tags have conflicting values");
-
- }
-
- }
-
- #endif
-
- SetApertureValue (av.As_real64 ());
-
- break;
-
- }
-
- case tcBrightnessValue:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttSRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fBrightnessValue = stream.TagValue_srational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("BrightnessValue: %0.2f\n",
- fBrightnessValue.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcExposureBiasValue:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttSRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fExposureBiasValue = stream.TagValue_srational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ExposureBiasValue: %0.2f\n",
- fExposureBiasValue.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcMaxApertureValue:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fMaxApertureValue = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- real64 x = pow (2.0, 0.5 * fMaxApertureValue.As_real64 ());
-
- printf ("MaxApertureValue: f/%0.1f\n", x);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSubjectDistance:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSubjectDistance = stream.TagValue_urational (tagType);
-
- fApproxFocusDistance = fSubjectDistance;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SubjectDistance: %u/%u\n",
- (unsigned) fSubjectDistance.n,
- (unsigned) fSubjectDistance.d);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcMeteringMode:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fMeteringMode = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("MeteringMode: %s\n",
- LookupMeteringMode (fMeteringMode));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcLightSource:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fLightSource = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("LightSource: %s\n",
- LookupLightSource (fLightSource));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFlash:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFlash = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Flash: %u\n", (unsigned) fFlash);
-
- if ((fFlash >> 5) & 1)
- {
- printf (" No flash function\n");
- }
-
- else
- {
-
- if (fFlash & 0x1)
- {
-
- printf (" Flash fired\n");
-
- switch ((fFlash >> 1) & 0x3)
- {
-
- case 2:
- printf (" Strobe return light not detected\n");
- break;
-
- case 3:
- printf (" Strobe return light detected\n");
- break;
-
- }
-
- }
-
- else
- {
- printf (" Flash did not fire\n");
- }
-
- switch ((fFlash >> 3) & 0x3)
- {
-
- case 1:
- printf (" Compulsory flash firing\n");
- break;
-
- case 2:
- printf (" Compulsory flash suppression\n");
- break;
-
- case 3:
- printf (" Auto mode\n");
- break;
-
- }
-
- if ((fFlash >> 6) & 1)
- {
- printf (" Red-eye reduction supported\n");
- }
-
- }
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFocalLength:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFocalLength = stream.TagValue_urational (tagType);
-
- // Sometimes "unknown" is recorded as zero.
-
- if (fFocalLength.As_real64 () <= 0.0)
- {
- fFocalLength.Clear ();
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FocalLength: %0.1f mm\n",
- fFocalLength.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcImageNumber:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fImageNumber = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("ImageNumber: %u\n", (unsigned) fImageNumber);
- }
-
- #endif
-
- break;
-
- }
-
- case tcExposureIndex:
- case tcExposureIndexExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fExposureIndex = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: ISO %0.1f\n",
- LookupTagCode (parentCode, tagCode),
- fExposureIndex.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcUserComment:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- ParseEncodedStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fUserComment);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("UserComment: ");
-
- DumpString (fUserComment);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSubsecTime:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- dng_string subsecs;
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- subsecs);
-
- fDateTime.SetSubseconds (subsecs);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SubsecTime: ");
-
- DumpString (subsecs);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSubsecTimeOriginal:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- dng_string subsecs;
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- subsecs);
-
- fDateTimeOriginal.SetSubseconds (subsecs);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SubsecTimeOriginal: ");
-
- DumpString (subsecs);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSubsecTimeDigitized:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- dng_string subsecs;
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- subsecs);
-
- fDateTimeDigitized.SetSubseconds (subsecs);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SubsecTimeDigitized: ");
-
- DumpString (subsecs);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFlashPixVersion:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- CheckTagCount (parentCode, tagCode, tagCount, 4);
-
- uint32 b0 = stream.Get_uint8 ();
- uint32 b1 = stream.Get_uint8 ();
- uint32 b2 = stream.Get_uint8 ();
- uint32 b3 = stream.Get_uint8 ();
-
- fFlashPixVersion = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- real64 x = (b0 - '0') * 10.00 +
- (b1 - '0') * 1.00 +
- (b2 - '0') * 0.10 +
- (b3 - '0') * 0.01;
-
- printf ("FlashPixVersion: %0.2f\n", x);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcColorSpace:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fColorSpace = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ColorSpace: %s\n",
- LookupColorSpace (fColorSpace));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcPixelXDimension:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fPixelXDimension = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("PixelXDimension: %u\n", (unsigned) fPixelXDimension);
- }
-
- #endif
-
- break;
-
- }
-
- case tcPixelYDimension:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fPixelYDimension = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("PixelYDimension: %u\n", (unsigned) fPixelYDimension);
- }
-
- #endif
-
- break;
-
- }
-
- case tcFocalPlaneXResolutionExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFocalPlaneXResolution = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FocalPlaneXResolutionExif: %0.4f\n",
- fFocalPlaneXResolution.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFocalPlaneYResolutionExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFocalPlaneYResolution = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FocalPlaneYResolutionExif: %0.4f\n",
- fFocalPlaneYResolution.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFocalPlaneResolutionUnitExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFocalPlaneResolutionUnit = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FocalPlaneResolutionUnitExif: %s\n",
- LookupResolutionUnit (fFocalPlaneResolutionUnit));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSensingMethodExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSensingMethod = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SensingMethodExif: %s\n",
- LookupSensingMethod (fSensingMethod));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFileSource:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFileSource = stream.Get_uint8 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FileSource: %s\n",
- LookupFileSource (fFileSource));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSceneType:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSceneType = stream.Get_uint8 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SceneType: %s\n",
- LookupSceneType (fSceneType));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCFAPatternExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- if (tagCount <= 4)
- {
- return false;
- }
-
- uint32 cols = stream.Get_uint16 ();
- uint32 rows = stream.Get_uint16 ();
-
- if (tagCount != 4 + cols * rows)
- {
- return false;
- }
-
- if (cols < 1 || cols > kMaxCFAPattern ||
- rows < 1 || rows > kMaxCFAPattern)
- {
- return false;
- }
-
- fCFARepeatPatternCols = cols;
- fCFARepeatPatternRows = rows;
-
- // Note that the Exif spec stores this array in a different
- // scan order than the TIFF-EP spec.
-
- for (uint32 j = 0; j < fCFARepeatPatternCols; j++)
- for (uint32 k = 0; k < fCFARepeatPatternRows; k++)
- {
-
- fCFAPattern [k] [j] = stream.Get_uint8 ();
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("CFAPatternExif:\n");
-
- for (uint32 j = 0; j < fCFARepeatPatternRows; j++)
- {
-
- int32 spaces = 4;
-
- for (uint32 k = 0; k < fCFARepeatPatternCols; k++)
- {
-
- while (spaces-- > 0)
- {
- printf (" ");
- }
-
- const char *name = LookupCFAColor (fCFAPattern [j] [k]);
-
- spaces = 9 - (int32) strlen (name);
-
- printf ("%s", name);
-
- }
-
- printf ("\n");
-
- }
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCustomRendered:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fCustomRendered = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("CustomRendered: %s\n",
- LookupCustomRendered (fCustomRendered));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcExposureMode:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fExposureMode = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ExposureMode: %s\n",
- LookupExposureMode (fExposureMode));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcWhiteBalance:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fWhiteBalance = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("WhiteBalance: %s\n",
- LookupWhiteBalance (fWhiteBalance));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcDigitalZoomRatio:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fDigitalZoomRatio = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("DigitalZoomRatio: ");
-
- if (fDigitalZoomRatio.n == 0 ||
- fDigitalZoomRatio.d == 0)
- {
-
- printf ("Not used\n");
-
- }
-
- else
- {
-
- printf ("%0.2f\n", fDigitalZoomRatio.As_real64 ());
-
- }
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFocalLengthIn35mmFilm:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFocalLengthIn35mmFilm = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("FocalLengthIn35mmFilm: %u mm\n",
- (unsigned) fFocalLengthIn35mmFilm);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSceneCaptureType:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSceneCaptureType = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SceneCaptureType: %s\n",
- LookupSceneCaptureType (fSceneCaptureType));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcGainControl:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fGainControl = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("GainControl: %s\n",
- LookupGainControl (fGainControl));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcContrast:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fContrast = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Contrast: %s\n",
- LookupContrast (fContrast));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSaturation:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSaturation = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Saturation: %s\n",
- LookupSaturation (fSaturation));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSharpness:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSharpness = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Sharpness: %s\n",
- LookupSharpness (fSharpness));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSubjectDistanceRange:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSubjectDistanceRange = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SubjectDistanceRange: %s\n",
- LookupSubjectDistanceRange (fSubjectDistanceRange));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSubjectArea:
- case tcSubjectLocation:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 2, 4))
- {
- return false;
- }
-
- if (tagCode == tcSubjectLocation)
- {
- CheckTagCount (parentCode, tagCode, tagCount, 2);
- }
-
- fSubjectAreaCount = tagCount;
-
- for (uint32 j = 0; j < tagCount; j++)
- {
-
- fSubjectArea [j] = stream.TagValue_uint32 (tagType);
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s:", LookupTagCode (parentCode, tagCode));
-
- for (uint32 j = 0; j < fSubjectAreaCount; j++)
- {
-
- printf (" %u", (unsigned) fSubjectArea [j]);
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcGamma:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fGamma = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Gamma: %0.2f\n",
- fGamma.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcImageUniqueID:
- {
-
- if (!CheckTagType (parentCode, tagCode, tagType, ttAscii))
- return false;
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 33))
- return false;
-
- dng_string s;
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- s);
-
- if (s.Length () != 32)
- return false;
-
- dng_fingerprint f;
-
- for (uint32 j = 0; j < 32; j++)
- {
-
- char c = ForceUppercase (s.Get () [j]);
-
- uint32 digit;
-
- if (c >= '0' && c <= '9')
- {
- digit = c - '0';
- }
-
- else if (c >= 'A' && c <= 'F')
- {
- digit = c - 'A' + 10;
- }
-
- else
- return false;
-
- f.data [j >> 1] *= 16;
- f.data [j >> 1] += (uint8) digit;
-
- }
-
- fImageUniqueID = f;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ImageUniqueID: ");
-
- DumpFingerprint (fImageUniqueID);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCameraOwnerNameExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fOwnerName);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("CameraOwnerName: ");
-
- DumpString (fOwnerName);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCameraSerialNumberExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fCameraSerialNumber);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: ", LookupTagCode (parentCode, tagCode));
-
- DumpString (fCameraSerialNumber);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcLensSpecificationExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
- return false;
-
- fLensInfo [0] = stream.TagValue_urational (tagType);
- fLensInfo [1] = stream.TagValue_urational (tagType);
- fLensInfo [2] = stream.TagValue_urational (tagType);
- fLensInfo [3] = stream.TagValue_urational (tagType);
-
- // Some third party software wrote zero rather than undefined values for
- // unknown entries. Work around this bug.
-
- for (uint32 j = 0; j < 4; j++)
- {
-
- if (fLensInfo [j].IsValid () && fLensInfo [j].As_real64 () <= 0.0)
- {
-
- fLensInfo [j] = dng_urational (0, 0);
-
- #if qDNGValidate
-
- ReportWarning ("Zero entry in LensSpecification tag--should be undefined");
-
- #endif
-
- }
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("LensSpecificationExif: ");
-
- real64 minFL = fLensInfo [0].As_real64 ();
- real64 maxFL = fLensInfo [1].As_real64 ();
-
- if (minFL == maxFL)
- printf ("%0.1f mm", minFL);
- else
- printf ("%0.1f-%0.1f mm", minFL, maxFL);
-
- if (fLensInfo [2].d)
- {
-
- real64 minFS = fLensInfo [2].As_real64 ();
- real64 maxFS = fLensInfo [3].As_real64 ();
-
- if (minFS == maxFS)
- printf (" f/%0.1f", minFS);
- else
- printf (" f/%0.1f-%0.1f", minFS, maxFS);
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcLensMakeExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fLensMake);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: ", LookupTagCode (parentCode, tagCode));
-
- DumpString (fLensMake);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcLensModelExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fLensName);
-
- fLensNameWasReadFromExif = fLensName.NotEmpty ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: ", LookupTagCode (parentCode, tagCode));
-
- DumpString (fLensName);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcLensSerialNumberExif:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fLensSerialNumber);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: ", LookupTagCode (parentCode, tagCode));
-
- DumpString (fLensSerialNumber);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- default:
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-// Parses tags that should only appear in GPS IFD
-
-bool dng_exif::Parse_gps (dng_stream &stream,
- dng_shared & /* shared */,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 /* tagOffset */)
- {
-
- switch (tagCode)
- {
-
- case tcGPSVersionID:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttByte);
-
- CheckTagCount (parentCode, tagCode, tagCount, 4);
-
- uint32 b0 = stream.Get_uint8 ();
- uint32 b1 = stream.Get_uint8 ();
- uint32 b2 = stream.Get_uint8 ();
- uint32 b3 = stream.Get_uint8 ();
-
- fGPSVersionID = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("GPSVersionID: %u.%u.%u.%u\n",
- (unsigned) b0,
- (unsigned) b1,
- (unsigned) b2,
- (unsigned) b3);
- }
-
- #endif
-
- break;
-
- }
-
- case tcGPSLatitudeRef:
- case tcGPSLongitudeRef:
- case tcGPSSatellites:
- case tcGPSStatus:
- case tcGPSMeasureMode:
- case tcGPSSpeedRef:
- case tcGPSTrackRef:
- case tcGPSImgDirectionRef:
- case tcGPSMapDatum:
- case tcGPSDestLatitudeRef:
- case tcGPSDestLongitudeRef:
- case tcGPSDestBearingRef:
- case tcGPSDestDistanceRef:
- case tcGPSDateStamp:
- {
-
- if (!CheckTagType (parentCode, tagCode, tagType, ttAscii))
- return false;
-
- dng_string *s;
-
- switch (tagCode)
- {
-
- case tcGPSLatitudeRef:
- s = &fGPSLatitudeRef;
- break;
-
- case tcGPSLongitudeRef:
- s = &fGPSLongitudeRef;
- break;
-
- case tcGPSSatellites:
- s = &fGPSSatellites;
- break;
-
- case tcGPSStatus:
- s = &fGPSStatus;
- break;
-
- case tcGPSMeasureMode:
- s = &fGPSMeasureMode;
- break;
-
- case tcGPSSpeedRef:
- s = &fGPSSpeedRef;
- break;
-
- case tcGPSTrackRef:
- s = &fGPSTrackRef;
- break;
-
- case tcGPSImgDirectionRef:
- s = &fGPSImgDirectionRef;
- break;
-
- case tcGPSMapDatum:
- s = &fGPSMapDatum;
- break;
-
- case tcGPSDestLatitudeRef:
- s = &fGPSDestLatitudeRef;
- break;
-
- case tcGPSDestLongitudeRef:
- s = &fGPSDestLongitudeRef;
- break;
-
- case tcGPSDestBearingRef:
- s = &fGPSDestBearingRef;
- break;
-
- case tcGPSDestDistanceRef:
- s = &fGPSDestDistanceRef;
- break;
-
- case tcGPSDateStamp:
- s = &fGPSDateStamp;
- break;
-
- default:
- return false;
-
- }
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- *s);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: ", LookupTagCode (parentCode, tagCode));
-
- DumpString (*s);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcGPSLatitude:
- case tcGPSLongitude:
- case tcGPSTimeStamp:
- case tcGPSDestLatitude:
- case tcGPSDestLongitude:
- {
-
- if (!CheckTagType (parentCode, tagCode, tagType, ttRational))
- return false;
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 3))
- return false;
-
- dng_urational *u;
-
- switch (tagCode)
- {
-
- case tcGPSLatitude:
- u = fGPSLatitude;
- break;
-
- case tcGPSLongitude:
- u = fGPSLongitude;
- break;
-
- case tcGPSTimeStamp:
- u = fGPSTimeStamp;
- break;
-
- case tcGPSDestLatitude:
- u = fGPSDestLatitude;
- break;
-
- case tcGPSDestLongitude:
- u = fGPSDestLongitude;
- break;
-
- default:
- return false;
-
- }
-
- u [0] = stream.TagValue_urational (tagType);
- u [1] = stream.TagValue_urational (tagType);
- u [2] = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s:", LookupTagCode (parentCode, tagCode));
-
- for (uint32 j = 0; j < 3; j++)
- {
-
- if (u [j].d == 0)
- printf (" -");
-
- else
- printf (" %0.4f", u [j].As_real64 ());
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcGPSAltitudeRef:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttByte);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fGPSAltitudeRef = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("GPSAltitudeRef: ");
-
- switch (fGPSAltitudeRef)
- {
-
- case 0:
- printf ("Sea level");
- break;
-
- case 1:
- printf ("Sea level reference (negative value)");
- break;
-
- default:
- printf ("%u", (unsigned) fGPSAltitudeRef);
- break;
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcGPSAltitude:
- case tcGPSDOP:
- case tcGPSSpeed:
- case tcGPSTrack:
- case tcGPSImgDirection:
- case tcGPSDestBearing:
- case tcGPSDestDistance:
- case tcGPSHPositioningError:
- {
-
- if (!CheckTagType (parentCode, tagCode, tagType, ttRational))
- return false;
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- dng_urational *u;
-
- switch (tagCode)
- {
-
- case tcGPSAltitude:
- u = &fGPSAltitude;
- break;
-
- case tcGPSDOP:
- u = &fGPSDOP;
- break;
-
- case tcGPSSpeed:
- u = &fGPSSpeed;
- break;
-
- case tcGPSTrack:
- u = &fGPSTrack;
- break;
-
- case tcGPSImgDirection:
- u = &fGPSImgDirection;
- break;
-
- case tcGPSDestBearing:
- u = &fGPSDestBearing;
- break;
-
- case tcGPSDestDistance:
- u = &fGPSDestDistance;
- break;
-
- case tcGPSHPositioningError:
- u = &fGPSHPositioningError;
- break;
-
- default:
- return false;
-
- }
-
- *u = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s:", LookupTagCode (parentCode, tagCode));
-
- if (u->d == 0)
- printf (" -");
-
- else
- printf (" %0.4f", u->As_real64 ());
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcGPSProcessingMethod:
- case tcGPSAreaInformation:
- {
-
- if (!CheckTagType (parentCode, tagCode, tagType, ttUndefined))
- return false;
-
- dng_string *s;
-
- switch (tagCode)
- {
-
- case tcGPSProcessingMethod:
- s = &fGPSProcessingMethod;
- break;
-
- case tcGPSAreaInformation:
- s = &fGPSAreaInformation;
- break;
-
- default:
- return false;
-
- }
-
- ParseEncodedStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- *s);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: ", LookupTagCode (parentCode, tagCode));
-
- DumpString (*s);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcGPSDifferential:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fGPSDifferential = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("GPSDifferential: ");
-
- switch (fGPSDifferential)
- {
-
- case 0:
- printf ("Measurement without differential correction");
- break;
-
- case 1:
- printf ("Differential correction applied");
- break;
-
- default:
- printf ("%u", (unsigned) fGPSDifferential);
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- default:
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-// Parses tags that should only appear in Interoperability IFD
-
-bool dng_exif::Parse_interoperability (dng_stream &stream,
- dng_shared & /* shared */,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 /* tagOffset */)
- {
-
- switch (tagCode)
- {
-
- case tcInteroperabilityIndex:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- CheckTagCount (parentCode, tagCode, tagCount, 4);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fInteroperabilityIndex);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("InteroperabilityIndex: ");
-
- DumpString (fInteroperabilityIndex);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcInteroperabilityVersion:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- CheckTagCount (parentCode, tagCode, tagCount, 4);
-
- uint32 b0 = stream.Get_uint8 ();
- uint32 b1 = stream.Get_uint8 ();
- uint32 b2 = stream.Get_uint8 ();
- uint32 b3 = stream.Get_uint8 ();
-
- fInteroperabilityVersion = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- real64 x = (b0 - '0') * 10.00 +
- (b1 - '0') * 1.00 +
- (b2 - '0') * 0.10 +
- (b3 - '0') * 0.01;
-
- printf ("InteroperabilityVersion: %0.2f\n", x);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcRelatedImageFileFormat:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fRelatedImageFileFormat);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("RelatedImageFileFormat: ");
-
- DumpString (fRelatedImageFileFormat);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcRelatedImageWidth:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fRelatedImageWidth = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("RelatedImageWidth: %u\n", (unsigned) fRelatedImageWidth);
- }
-
- #endif
-
- break;
-
- }
-
- case tcRelatedImageLength:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fRelatedImageLength = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("RelatedImageLength: %u\n", (unsigned) fRelatedImageLength);
- }
-
- #endif
-
- break;
-
- }
-
- default:
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-void dng_exif::PostParse (dng_host & /* host */,
- dng_shared & /* shared */)
- {
-
- #if qDNGValidate
-
- const real64 kAPEX_Slop = 0.25;
-
- // Sanity check on MaxApertureValue.
-
- if (fMaxApertureValue.d)
- {
-
- real64 mav = fMaxApertureValue.As_real64 ();
-
- // Compare against ApertureValue or FNumber.
-
- real64 av = mav;
-
- if (fApertureValue.d)
- {
-
- av = fApertureValue.As_real64 ();
-
- }
-
- else if (fFNumber.d)
- {
-
- real64 fs = fFNumber.As_real64 ();
-
- if (fs >= 1.0)
- {
-
- av = FNumberToApertureValue (fs);
-
- }
-
- }
-
- if (mav > av + kAPEX_Slop)
- {
-
- ReportWarning ("MaxApertureValue conflicts with ApertureValue and/or FNumber");
-
- }
-
- // Compare against LensInfo
-
- if (fLensInfo [2].d && fLensInfo [3].d)
- {
-
- real64 fs1 = fLensInfo [2].As_real64 ();
- real64 fs2 = fLensInfo [3].As_real64 ();
-
- if (fs1 >= 1.0 && fs2 >= 1.0 && fs2 >= fs1)
- {
-
- real64 av1 = FNumberToApertureValue (fs1);
- real64 av2 = FNumberToApertureValue (fs2);
-
- // Wide angle adapters might create an effective
- // wide FS, and tele-extenders always result
- // in a higher FS.
-
- if (mav < av1 - kAPEX_Slop - 1.0 ||
- mav > av2 + kAPEX_Slop + 2.0)
- {
-
- ReportWarning ("Possible MaxApertureValue conflict with LensInfo");
-
- }
-
- }
-
- }
-
- }
-
- // Sanity check on FocalLength.
-
- if (fFocalLength.d)
- {
-
- real64 fl = fFocalLength.As_real64 ();
-
- if (fl < 1.0)
- {
-
- ReportWarning ("FocalLength is less than 1.0 mm (legal but unlikely)");
-
- }
-
- else if (fLensInfo [0].d && fLensInfo [1].d)
- {
-
- real64 minFL = fLensInfo [0].As_real64 ();
- real64 maxFL = fLensInfo [1].As_real64 ();
-
- // Allow for wide-angle converters and tele-extenders.
-
- if (fl < minFL * 0.6 ||
- fl > maxFL * 2.1)
- {
-
- ReportWarning ("Possible FocalLength conflict with LensInfo");
-
- }
-
- }
-
- }
-
- #endif
-
- // Mirror DateTimeOriginal to DateTime.
-
- if (fDateTime.NotValid () && fDateTimeOriginal.IsValid ())
- {
-
- fDateTime = fDateTimeOriginal;
-
- }
-
- // Mirror EXIF 2.3 sensitivity tags to ISOSpeedRatings.
-
- if (fISOSpeedRatings [0] == 0 || fISOSpeedRatings [0] == 65535)
- {
-
- // Prefer Recommended Exposure Index, then Standard Output Sensitivity, then
- // ISO Speed, then Exposure Index.
-
- if (fRecommendedExposureIndex != 0 &&
- (fSensitivityType == stRecommendedExposureIndex ||
- fSensitivityType == stSOSandREI ||
- fSensitivityType == stREIandISOSpeed ||
- fSensitivityType == stSOSandREIandISOSpeed))
- {
-
- fISOSpeedRatings [0] = fRecommendedExposureIndex;
-
- }
-
- else if (fStandardOutputSensitivity != 0 &&
- (fSensitivityType == stStandardOutputSensitivity ||
- fSensitivityType == stSOSandREI ||
- fSensitivityType == stSOSandISOSpeed ||
- fSensitivityType == stSOSandREIandISOSpeed))
- {
-
- fISOSpeedRatings [0] = fStandardOutputSensitivity;
-
- }
-
- else if (fISOSpeed != 0 &&
- (fSensitivityType == stISOSpeed ||
- fSensitivityType == stSOSandISOSpeed ||
- fSensitivityType == stREIandISOSpeed ||
- fSensitivityType == stSOSandREIandISOSpeed))
- {
-
- fISOSpeedRatings [0] = fISOSpeed;
-
- }
-
- }
-
- // Mirror ExposureIndex to ISOSpeedRatings.
-
- if (fExposureIndex.IsValid () && fISOSpeedRatings [0] == 0)
- {
-
- fISOSpeedRatings [0] = Round_uint32 (fExposureIndex.As_real64 ());
-
- }
-
- // Kodak sets the GPSAltitudeRef without setting the GPSAltitude.
-
- if (fGPSAltitude.NotValid ())
- {
-
- fGPSAltitudeRef = 0xFFFFFFFF;
-
- }
-
- // If there is no valid GPS data, clear the GPS version number.
-
- if (fGPSLatitude [0].NotValid () &&
- fGPSLongitude [0].NotValid () &&
- fGPSAltitude .NotValid () &&
- fGPSTimeStamp [0].NotValid () &&
- fGPSDateStamp .IsEmpty ())
- {
-
- fGPSVersionID = 0;
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_exif.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_exif.h"
+
+#include "dng_tag_codes.h"
+#include "dng_tag_types.h"
+#include "dng_parse_utils.h"
+#include "dng_globals.h"
+#include "dng_exceptions.h"
+#include "dng_tag_values.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_exif::dng_exif ()
+
+ : fImageDescription ()
+ , fMake ()
+ , fModel ()
+ , fSoftware ()
+ , fArtist ()
+ , fCopyright ()
+ , fCopyright2 ()
+ , fUserComment ()
+
+ , fDateTime ()
+ , fDateTimeStorageInfo ()
+
+ , fDateTimeOriginal ()
+ , fDateTimeOriginalStorageInfo ()
+
+ , fDateTimeDigitized ()
+ , fDateTimeDigitizedStorageInfo ()
+
+ , fTIFF_EP_StandardID (0)
+ , fExifVersion (0)
+ , fFlashPixVersion (0)
+
+ , fExposureTime ()
+ , fFNumber ()
+ , fShutterSpeedValue ()
+ , fApertureValue ()
+ , fBrightnessValue ()
+ , fExposureBiasValue ()
+ , fMaxApertureValue ()
+ , fFocalLength ()
+ , fDigitalZoomRatio ()
+ , fExposureIndex ()
+ , fSubjectDistance ()
+ , fGamma ()
+
+ , fBatteryLevelR ()
+ , fBatteryLevelA ()
+
+ , fExposureProgram (0xFFFFFFFF)
+ , fMeteringMode (0xFFFFFFFF)
+ , fLightSource (0xFFFFFFFF)
+ , fFlash (0xFFFFFFFF)
+ , fFlashMask (0x0000FFFF)
+ , fSensingMethod (0xFFFFFFFF)
+ , fColorSpace (0xFFFFFFFF)
+ , fFileSource (0xFFFFFFFF)
+ , fSceneType (0xFFFFFFFF)
+ , fCustomRendered (0xFFFFFFFF)
+ , fExposureMode (0xFFFFFFFF)
+ , fWhiteBalance (0xFFFFFFFF)
+ , fSceneCaptureType (0xFFFFFFFF)
+ , fGainControl (0xFFFFFFFF)
+ , fContrast (0xFFFFFFFF)
+ , fSaturation (0xFFFFFFFF)
+ , fSharpness (0xFFFFFFFF)
+ , fSubjectDistanceRange (0xFFFFFFFF)
+ , fSelfTimerMode (0xFFFFFFFF)
+ , fImageNumber (0xFFFFFFFF)
+
+ , fFocalLengthIn35mmFilm (0)
+
+ , fSensitivityType (0)
+ , fStandardOutputSensitivity (0)
+ , fRecommendedExposureIndex (0)
+ , fISOSpeed (0)
+ , fISOSpeedLatitudeyyy (0)
+ , fISOSpeedLatitudezzz (0)
+
+ , fSubjectAreaCount (0)
+
+ , fComponentsConfiguration (0)
+
+ , fCompresssedBitsPerPixel ()
+
+ , fPixelXDimension (0)
+ , fPixelYDimension (0)
+
+ , fFocalPlaneXResolution ()
+ , fFocalPlaneYResolution ()
+
+ , fFocalPlaneResolutionUnit (0xFFFFFFFF)
+
+ , fCFARepeatPatternRows (0)
+ , fCFARepeatPatternCols (0)
+
+ , fImageUniqueID ()
+
+ , fGPSVersionID (0)
+ , fGPSLatitudeRef ()
+ , fGPSLongitudeRef ()
+ , fGPSAltitudeRef (0xFFFFFFFF)
+ , fGPSAltitude ()
+ , fGPSSatellites ()
+ , fGPSStatus ()
+ , fGPSMeasureMode ()
+ , fGPSDOP ()
+ , fGPSSpeedRef ()
+ , fGPSSpeed ()
+ , fGPSTrackRef ()
+ , fGPSTrack ()
+ , fGPSImgDirectionRef ()
+ , fGPSImgDirection ()
+ , fGPSMapDatum ()
+ , fGPSDestLatitudeRef ()
+ , fGPSDestLongitudeRef ()
+ , fGPSDestBearingRef ()
+ , fGPSDestBearing ()
+ , fGPSDestDistanceRef ()
+ , fGPSDestDistance ()
+ , fGPSProcessingMethod ()
+ , fGPSAreaInformation ()
+ , fGPSDateStamp ()
+ , fGPSDifferential (0xFFFFFFFF)
+ , fGPSHPositioningError ()
+
+ , fInteroperabilityIndex ()
+
+ , fInteroperabilityVersion (0)
+
+ , fRelatedImageFileFormat ()
+
+ , fRelatedImageWidth (0)
+ , fRelatedImageLength (0)
+
+ , fCameraSerialNumber ()
+
+ , fLensID ()
+ , fLensMake ()
+ , fLensName ()
+ , fLensSerialNumber ()
+
+ , fLensNameWasReadFromExif (false)
+
+ , fApproxFocusDistance ()
+
+ , fFlashCompensation ()
+
+ , fOwnerName ()
+ , fFirmware ()
+
+ {
+
+ uint32 j;
+ uint32 k;
+
+ fISOSpeedRatings [0] = 0;
+ fISOSpeedRatings [1] = 0;
+ fISOSpeedRatings [2] = 0;
+
+ for (j = 0; j < kMaxCFAPattern; j++)
+ for (k = 0; k < kMaxCFAPattern; k++)
+ {
+ fCFAPattern [j] [k] = 255;
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_exif::~dng_exif ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_exif * dng_exif::Clone () const
+ {
+
+ dng_exif *result = new dng_exif (*this);
+
+ if (!result)
+ {
+ ThrowMemoryFull ();
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+void dng_exif::SetEmpty ()
+ {
+
+ *this = dng_exif ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_exif::CopyGPSFrom (const dng_exif &exif)
+ {
+
+ fGPSVersionID = exif.fGPSVersionID;
+ fGPSLatitudeRef = exif.fGPSLatitudeRef;
+ fGPSLatitude [0] = exif.fGPSLatitude [0];
+ fGPSLatitude [1] = exif.fGPSLatitude [1];
+ fGPSLatitude [2] = exif.fGPSLatitude [2];
+ fGPSLongitudeRef = exif.fGPSLongitudeRef;
+ fGPSLongitude [0] = exif.fGPSLongitude [0];
+ fGPSLongitude [1] = exif.fGPSLongitude [1];
+ fGPSLongitude [2] = exif.fGPSLongitude [2];
+ fGPSAltitudeRef = exif.fGPSAltitudeRef;
+ fGPSAltitude = exif.fGPSAltitude;
+ fGPSTimeStamp [0] = exif.fGPSTimeStamp [0];
+ fGPSTimeStamp [1] = exif.fGPSTimeStamp [1];
+ fGPSTimeStamp [2] = exif.fGPSTimeStamp [2];
+ fGPSSatellites = exif.fGPSSatellites;
+ fGPSStatus = exif.fGPSStatus;
+ fGPSMeasureMode = exif.fGPSMeasureMode;
+ fGPSDOP = exif.fGPSDOP;
+ fGPSSpeedRef = exif.fGPSSpeedRef;
+ fGPSSpeed = exif.fGPSSpeed;
+ fGPSTrackRef = exif.fGPSTrackRef;
+ fGPSTrack = exif.fGPSTrack;
+ fGPSImgDirectionRef = exif.fGPSImgDirectionRef;
+ fGPSImgDirection = exif.fGPSImgDirection;
+ fGPSMapDatum = exif.fGPSMapDatum;
+ fGPSDestLatitudeRef = exif.fGPSDestLatitudeRef;
+ fGPSDestLatitude [0] = exif.fGPSDestLatitude [0];
+ fGPSDestLatitude [1] = exif.fGPSDestLatitude [1];
+ fGPSDestLatitude [2] = exif.fGPSDestLatitude [2];
+ fGPSDestLongitudeRef = exif.fGPSDestLongitudeRef;
+ fGPSDestLongitude [0] = exif.fGPSDestLongitude [0];
+ fGPSDestLongitude [1] = exif.fGPSDestLongitude [1];
+ fGPSDestLongitude [2] = exif.fGPSDestLongitude [2];
+ fGPSDestBearingRef = exif.fGPSDestBearingRef;
+ fGPSDestBearing = exif.fGPSDestBearing;
+ fGPSDestDistanceRef = exif.fGPSDestDistanceRef;
+ fGPSDestDistance = exif.fGPSDestDistance;
+ fGPSProcessingMethod = exif.fGPSProcessingMethod;
+ fGPSAreaInformation = exif.fGPSAreaInformation;
+ fGPSDateStamp = exif.fGPSDateStamp;
+ fGPSDifferential = exif.fGPSDifferential;
+ fGPSHPositioningError = exif.fGPSHPositioningError;
+
+ }
+
+/*****************************************************************************/
+
+// Fix up common errors and rounding issues with EXIF exposure times.
+
+real64 dng_exif::SnapExposureTime (real64 et)
+ {
+
+ // Protection against invalid values.
+
+ if (et <= 0.0)
+ return 0.0;
+
+ // If near a standard shutter speed, snap to it.
+
+ static const real64 kStandardSpeed [] =
+ {
+ 30.0,
+ 25.0,
+ 20.0,
+ 15.0,
+ 13.0,
+ 10.0,
+ 8.0,
+ 6.0,
+ 5.0,
+ 4.0,
+ 3.2,
+ 3.0,
+ 2.5,
+ 2.0,
+ 1.6,
+ 1.5,
+ 1.3,
+ 1.0,
+ 0.8,
+ 0.7,
+ 0.6,
+ 0.5,
+ 0.4,
+ 0.3,
+ 1.0 / 4.0,
+ 1.0 / 5.0,
+ 1.0 / 6.0,
+ 1.0 / 8.0,
+ 1.0 / 10.0,
+ 1.0 / 13.0,
+ 1.0 / 15.0,
+ 1.0 / 20.0,
+ 1.0 / 25.0,
+ 1.0 / 30.0,
+ 1.0 / 40.0,
+ 1.0 / 45.0,
+ 1.0 / 50.0,
+ 1.0 / 60.0,
+ 1.0 / 80.0,
+ 1.0 / 90.0,
+ 1.0 / 100.0,
+ 1.0 / 125.0,
+ 1.0 / 160.0,
+ 1.0 / 180.0,
+ 1.0 / 200.0,
+ 1.0 / 250.0,
+ 1.0 / 320.0,
+ 1.0 / 350.0,
+ 1.0 / 400.0,
+ 1.0 / 500.0,
+ 1.0 / 640.0,
+ 1.0 / 750.0,
+ 1.0 / 800.0,
+ 1.0 / 1000.0,
+ 1.0 / 1250.0,
+ 1.0 / 1500.0,
+ 1.0 / 1600.0,
+ 1.0 / 2000.0,
+ 1.0 / 2500.0,
+ 1.0 / 3000.0,
+ 1.0 / 3200.0,
+ 1.0 / 4000.0,
+ 1.0 / 5000.0,
+ 1.0 / 6000.0,
+ 1.0 / 6400.0,
+ 1.0 / 8000.0,
+ 1.0 / 10000.0,
+ 1.0 / 12000.0,
+ 1.0 / 12800.0,
+ 1.0 / 16000.0
+ };
+
+ uint32 count = sizeof (kStandardSpeed ) /
+ sizeof (kStandardSpeed [0]);
+
+ for (uint32 fudge = 0; fudge <= 1; fudge++)
+ {
+
+ real64 testSpeed = et;
+
+ if (fudge == 1)
+ {
+
+ // Often APEX values are rounded to a power of two,
+ // which results in non-standard shutter speeds.
+
+ if (et >= 0.1)
+ {
+
+ // No fudging slower than 1/10 second
+
+ break;
+
+ }
+
+ else if (et >= 0.01)
+ {
+
+ // Between 1/10 and 1/100 the commonly misrounded
+ // speeds are 1/15, 1/30, 1/60, which are often encoded as
+ // 1/16, 1/32, 1/64. Try fudging and see if we get
+ // near a standard speed.
+
+ testSpeed *= 16.0 / 15.0;
+
+ }
+
+ else
+ {
+
+ // Faster than 1/100, the commonly misrounded
+ // speeds are 1/125, 1/250, 1/500, etc., which
+ // are often encoded as 1/128, 1/256, 1/512.
+
+ testSpeed *= 128.0 / 125.0;
+
+ }
+
+ }
+
+ for (uint32 index = 0; index < count; index++)
+ {
+
+ if (testSpeed >= kStandardSpeed [index] * 0.98 &&
+ testSpeed <= kStandardSpeed [index] * 1.02)
+ {
+
+ return kStandardSpeed [index];
+
+ }
+
+ }
+
+ }
+
+ // We are not near any standard speeds. Round the non-standard value to something
+ // that looks reasonable.
+
+ if (et >= 10.0)
+ {
+
+ // Round to nearest second.
+
+ et = floor (et + 0.5);
+
+ }
+
+ else if (et >= 0.5)
+ {
+
+ // Round to nearest 1/10 second
+
+ et = floor (et * 10.0 + 0.5) * 0.1;
+
+ }
+
+ else if (et >= 1.0 / 20.0)
+ {
+
+ // Round to an exact inverse.
+
+ et = 1.0 / floor (1.0 / et + 0.5);
+
+ }
+
+ else if (et >= 1.0 / 130.0)
+ {
+
+ // Round inverse to multiple of 5
+
+ et = 0.2 / floor (0.2 / et + 0.5);
+
+ }
+
+ else if (et >= 1.0 / 750.0)
+ {
+
+ // Round inverse to multiple of 10
+
+ et = 0.1 / floor (0.1 / et + 0.5);
+
+ }
+
+ else if (et >= 1.0 / 1300.0)
+ {
+
+ // Round inverse to multiple of 50
+
+ et = 0.02 / floor (0.02 / et + 0.5);
+
+ }
+
+ else if (et >= 1.0 / 15000.0)
+ {
+
+ // Round inverse to multiple of 100
+
+ et = 0.01 / floor (0.01 / et + 0.5);
+
+ }
+
+ else
+ {
+
+ // Round inverse to multiple of 1000
+
+ et = 0.001 / floor (0.001 / et + 0.5);
+
+ }
+
+ return et;
+
+ }
+
+/*****************************************************************************/
+
+void dng_exif::SetExposureTime (real64 et, bool snap)
+ {
+
+ fExposureTime.Clear ();
+
+ fShutterSpeedValue.Clear ();
+
+ if (snap)
+ {
+
+ et = SnapExposureTime (et);
+
+ }
+
+ if (et >= 1.0 / 32768.0 && et <= 32768.0)
+ {
+
+ if (et >= 100.0)
+ {
+
+ fExposureTime.Set_real64 (et, 1);
+
+ }
+
+ else if (et >= 1.0)
+ {
+
+ fExposureTime.Set_real64 (et, 10);
+
+ fExposureTime.ReduceByFactor (10);
+
+ }
+
+ else if (et <= 0.1)
+ {
+
+ fExposureTime = dng_urational (1, Round_uint32 (1.0 / et));
+
+ }
+
+ else
+ {
+
+ fExposureTime.Set_real64 (et, 100);
+
+ fExposureTime.ReduceByFactor (10);
+
+ for (uint32 f = 2; f <= 9; f++)
+ {
+
+ real64 z = 1.0 / (real64) f / et;
+
+ if (z >= 0.99 && z <= 1.01)
+ {
+
+ fExposureTime = dng_urational (1, f);
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ // Now mirror this value to the ShutterSpeedValue field.
+
+ et = fExposureTime.As_real64 ();
+
+ fShutterSpeedValue.Set_real64 (-log (et) / log (2.0), 1000000);
+
+ fShutterSpeedValue.ReduceByFactor (10);
+ fShutterSpeedValue.ReduceByFactor (10);
+ fShutterSpeedValue.ReduceByFactor (10);
+ fShutterSpeedValue.ReduceByFactor (10);
+ fShutterSpeedValue.ReduceByFactor (10);
+ fShutterSpeedValue.ReduceByFactor (10);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_exif::SetShutterSpeedValue (real64 ss)
+ {
+
+ if (fExposureTime.NotValid ())
+ {
+
+ real64 et = pow (2.0, -ss);
+
+ SetExposureTime (et, true);
+
+ }
+
+ }
+
+/******************************************************************************/
+
+dng_urational dng_exif::EncodeFNumber (real64 fs)
+ {
+
+ dng_urational y;
+
+ if (fs > 10.0)
+ {
+
+ y.Set_real64 (fs, 1);
+
+ }
+
+ else if (fs < 1.0)
+ {
+
+ y.Set_real64 (fs, 100);
+
+ y.ReduceByFactor (10);
+ y.ReduceByFactor (10);
+
+ }
+
+ else
+ {
+
+ y.Set_real64 (fs, 10);
+
+ y.ReduceByFactor (10);
+
+ }
+
+ return y;
+
+ }
+
+/*****************************************************************************/
+
+void dng_exif::SetFNumber (real64 fs)
+ {
+
+ fFNumber.Clear ();
+
+ fApertureValue.Clear ();
+
+ // Allow f-number values less than 1.0 (e.g., f/0.95), even though they would
+ // correspond to negative APEX values, which the EXIF specification does not
+ // support (ApertureValue is a rational, not srational). The ApertureValue tag
+ // will be omitted in the case where fs < 1.0.
+
+ if (fs > 0.0 && fs <= 32768.0)
+ {
+
+ fFNumber = EncodeFNumber (fs);
+
+ // Now mirror this value to the ApertureValue field.
+
+ real64 av = FNumberToApertureValue (fFNumber);
+
+ if (av >= 0.0 && av <= 99.99)
+ {
+
+ fApertureValue.Set_real64 (av, 1000000);
+
+ fApertureValue.ReduceByFactor (10);
+ fApertureValue.ReduceByFactor (10);
+ fApertureValue.ReduceByFactor (10);
+ fApertureValue.ReduceByFactor (10);
+ fApertureValue.ReduceByFactor (10);
+ fApertureValue.ReduceByFactor (10);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_exif::SetApertureValue (real64 av)
+ {
+
+ if (fFNumber.NotValid ())
+ {
+
+ SetFNumber (ApertureValueToFNumber (av));
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_exif::ApertureValueToFNumber (real64 av)
+ {
+
+ return pow (2.0, 0.5 * av);
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_exif::ApertureValueToFNumber (const dng_urational &av)
+ {
+
+ return ApertureValueToFNumber (av.As_real64 ());
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_exif::FNumberToApertureValue (real64 fNumber)
+ {
+
+ return 2.0 * log (fNumber) / log (2.0);
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_exif::FNumberToApertureValue (const dng_urational &fNumber)
+ {
+
+ return FNumberToApertureValue (fNumber.As_real64 ());
+
+ }
+
+/*****************************************************************************/
+
+void dng_exif::UpdateDateTime (const dng_date_time_info &dt)
+ {
+
+ fDateTime = dt;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_exif::AtLeastVersion0230 () const
+ {
+
+ uint32 b0 = (fExifVersion >> 24) & 0xff;
+ uint32 b1 = (fExifVersion >> 16) & 0xff;
+ uint32 b2 = (fExifVersion >> 8) & 0xff;
+
+ return (b0 > 0) || (b1 >= 2 && b2 >= 3);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_exif::ParseTag (dng_stream &stream,
+ dng_shared &shared,
+ uint32 parentCode,
+ bool isMainIFD,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset)
+ {
+
+ if (parentCode == 0)
+ {
+
+ if (Parse_ifd0 (stream,
+ shared,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset))
+ {
+
+ return true;
+
+ }
+
+ }
+
+ if (parentCode == 0 || isMainIFD)
+ {
+
+ if (Parse_ifd0_main (stream,
+ shared,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset))
+ {
+
+ return true;
+
+ }
+
+ }
+
+ if (parentCode == 0 ||
+ parentCode == tcExifIFD)
+ {
+
+ if (Parse_ifd0_exif (stream,
+ shared,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset))
+ {
+
+ return true;
+
+ }
+
+ }
+
+ if (parentCode == tcGPSInfo)
+ {
+
+ if (Parse_gps (stream,
+ shared,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset))
+ {
+
+ return true;
+
+ }
+
+ }
+
+ if (parentCode == tcInteroperabilityIFD)
+ {
+
+ if (Parse_interoperability (stream,
+ shared,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset))
+ {
+
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+// Parses tags that should only appear in IFD 0.
+
+bool dng_exif::Parse_ifd0 (dng_stream &stream,
+ dng_shared & /* shared */,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 /* tagOffset */)
+ {
+
+ switch (tagCode)
+ {
+
+ case tcImageDescription:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fImageDescription);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ImageDescription: ");
+
+ DumpString (fImageDescription);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcMake:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fMake);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Make: ");
+
+ DumpString (fMake);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcModel:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fModel);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Model: ");
+
+ DumpString (fModel);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSoftware:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fSoftware);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Software: ");
+
+ DumpString (fSoftware);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcDateTime:
+ {
+
+ uint64 tagPosition = stream.PositionInOriginalFile ();
+
+ dng_date_time dt;
+
+ if (!ParseDateTimeTag (stream,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ dt))
+ {
+ return false;
+ }
+
+ fDateTime.SetDateTime (dt);
+
+ fDateTimeStorageInfo = dng_date_time_storage_info (tagPosition,
+ dng_date_time_format_exif);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("DateTime: ");
+
+ DumpDateTime (fDateTime.DateTime ());
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcArtist:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fArtist);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Artist: ");
+
+ DumpString (fArtist);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCopyright:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseDualStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fCopyright,
+ fCopyright2);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Copyright: ");
+
+ DumpString (fCopyright);
+
+ if (fCopyright2.Get () [0] != 0)
+ {
+
+ printf (" ");
+
+ DumpString (fCopyright2);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcTIFF_EP_StandardID:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttByte);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 4);
+
+ uint32 b0 = stream.Get_uint8 ();
+ uint32 b1 = stream.Get_uint8 ();
+ uint32 b2 = stream.Get_uint8 ();
+ uint32 b3 = stream.Get_uint8 ();
+
+ fTIFF_EP_StandardID = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("TIFF/EPStandardID: %u.%u.%u.%u\n",
+ (unsigned) b0,
+ (unsigned) b1,
+ (unsigned) b2,
+ (unsigned) b3);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCameraSerialNumber:
+ case tcKodakCameraSerialNumber: // Kodak uses a very similar tag.
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fCameraSerialNumber);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: ", LookupTagCode (parentCode, tagCode));
+
+ DumpString (fCameraSerialNumber);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcLensInfo:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
+ return false;
+
+ fLensInfo [0] = stream.TagValue_urational (tagType);
+ fLensInfo [1] = stream.TagValue_urational (tagType);
+ fLensInfo [2] = stream.TagValue_urational (tagType);
+ fLensInfo [3] = stream.TagValue_urational (tagType);
+
+ // Some third party software wrote zero rather and undefined values
+ // for unknown entries. Work around this bug.
+
+ for (uint32 j = 0; j < 4; j++)
+ {
+
+ if (fLensInfo [j].IsValid () && fLensInfo [j].As_real64 () <= 0.0)
+ {
+
+ fLensInfo [j] = dng_urational (0, 0);
+
+ #if qDNGValidate
+
+ ReportWarning ("Zero entry in LensInfo tag--should be undefined");
+
+ #endif
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("LensInfo: ");
+
+ real64 minFL = fLensInfo [0].As_real64 ();
+ real64 maxFL = fLensInfo [1].As_real64 ();
+
+ if (minFL == maxFL)
+ printf ("%0.1f mm", minFL);
+ else
+ printf ("%0.1f-%0.1f mm", minFL, maxFL);
+
+ if (fLensInfo [2].d)
+ {
+
+ real64 minFS = fLensInfo [2].As_real64 ();
+ real64 maxFS = fLensInfo [3].As_real64 ();
+
+ if (minFS == maxFS)
+ printf (" f/%0.1f", minFS);
+ else
+ printf (" f/%0.1f-%0.1f", minFS, maxFS);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ default:
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+// Parses tags that should only appear in IFD 0 or the main image IFD.
+
+bool dng_exif::Parse_ifd0_main (dng_stream &stream,
+ dng_shared & /* shared */,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 /* tagOffset */)
+ {
+
+ switch (tagCode)
+ {
+
+ case tcFocalPlaneXResolution:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFocalPlaneXResolution = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FocalPlaneXResolution: %0.4f\n",
+ fFocalPlaneXResolution.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFocalPlaneYResolution:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFocalPlaneYResolution = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FocalPlaneYResolution: %0.4f\n",
+ fFocalPlaneYResolution.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFocalPlaneResolutionUnit:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFocalPlaneResolutionUnit = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FocalPlaneResolutionUnit: %s\n",
+ LookupResolutionUnit (fFocalPlaneResolutionUnit));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSensingMethod:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSensingMethod = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SensingMethod: %s\n",
+ LookupSensingMethod (fSensingMethod));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ default:
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+// Parses tags that should only appear in IFD 0 or EXIF IFD.
+
+bool dng_exif::Parse_ifd0_exif (dng_stream &stream,
+ dng_shared & /* shared */,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 /* tagOffset */)
+ {
+
+ switch (tagCode)
+ {
+
+ case tcBatteryLevel:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational, ttAscii);
+
+ if (tagType == ttAscii)
+ {
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fBatteryLevelA);
+
+ }
+
+ else
+ {
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fBatteryLevelR = stream.TagValue_urational (tagType);
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("BatteryLevel: ");
+
+ if (tagType == ttAscii)
+ {
+
+ DumpString (fBatteryLevelA);
+
+ }
+
+ else
+ {
+
+ printf ("%0.2f", fBatteryLevelR.As_real64 ());
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcExposureTime:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ dng_urational et = stream.TagValue_urational (tagType);
+
+ SetExposureTime (et.As_real64 (), true);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ExposureTime: ");
+
+ DumpExposureTime (et.As_real64 ());
+
+ printf ("\n");
+
+ }
+
+ if (et.As_real64 () <= 0.0)
+ {
+
+ ReportWarning ("The ExposureTime is <= 0");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFNumber:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ dng_urational fs = stream.TagValue_urational (tagType);
+
+ // Sometimes "unknown" is recorded as zero.
+
+ if (fs.As_real64 () <= 0.0)
+ {
+ fs.Clear ();
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FNumber: f/%0.2f\n",
+ fs.As_real64 ());
+
+ }
+
+ #endif
+
+ SetFNumber (fs.As_real64 ());
+
+ break;
+
+ }
+
+ case tcExposureProgram:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fExposureProgram = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ExposureProgram: %s\n",
+ LookupExposureProgram (fExposureProgram));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcISOSpeedRatings:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1, 3);
+
+ for (uint32 j = 0; j < tagCount && j < 3; j++)
+ {
+
+ fISOSpeedRatings [j] = stream.TagValue_uint32 (tagType);
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ISOSpeedRatings:");
+
+ for (uint32 j = 0; j < tagCount && j < 3; j++)
+ {
+
+ printf (" %u", (unsigned) fISOSpeedRatings [j]);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSensitivityType:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSensitivityType = (uint32) stream.Get_uint16 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SensitivityType: %s\n",
+ LookupSensitivityType (fSensitivityType));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcStandardOutputSensitivity:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fStandardOutputSensitivity = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("StandardOutputSensitivity: %u\n",
+ (unsigned) fStandardOutputSensitivity);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcRecommendedExposureIndex:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fRecommendedExposureIndex = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("RecommendedExposureIndex: %u\n",
+ (unsigned) fRecommendedExposureIndex);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcISOSpeed:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fISOSpeed = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ISOSpeed: %u\n",
+ (unsigned) fISOSpeed);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcISOSpeedLatitudeyyy:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fISOSpeedLatitudeyyy = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ISOSpeedLatitudeyyy: %u\n",
+ (unsigned) fISOSpeedLatitudeyyy);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcISOSpeedLatitudezzz:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fISOSpeedLatitudezzz = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ISOSpeedLatitudezzz: %u\n",
+ (unsigned) fISOSpeedLatitudezzz);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcTimeZoneOffset:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttSShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1, 2);
+
+ dng_time_zone zoneOriginal;
+
+ zoneOriginal.SetOffsetHours (stream.TagValue_int32 (tagType));
+
+ fDateTimeOriginal.SetZone (zoneOriginal);
+
+ #if 0 // MWG: Not filling in time zones unless we are sure.
+
+ // Note that there is no "TimeZoneOffsetDigitized" field, so
+ // we assume the same tone zone as the original.
+
+ fDateTimeDigitized.SetZone (zoneOriginal);
+
+ #endif
+
+ dng_time_zone zoneCurrent;
+
+ if (tagCount >= 2)
+ {
+
+ zoneCurrent.SetOffsetHours (stream.TagValue_int32 (tagType));
+
+ fDateTime.SetZone (zoneCurrent);
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("TimeZoneOffset: DateTimeOriginal = %d",
+ (int) zoneOriginal.ExactHourOffset ());
+
+ if (tagCount >= 2)
+ {
+
+ printf (", DateTime = %d",
+ (int) zoneCurrent.ExactHourOffset ());
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSelfTimerMode:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSelfTimerMode = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SelfTimerMode: ");
+
+ if (fSelfTimerMode)
+ {
+
+ printf ("%u sec", (unsigned) fSelfTimerMode);
+
+ }
+
+ else
+ {
+
+ printf ("Off");
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcExifVersion:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 4);
+
+ uint32 b0 = stream.Get_uint8 ();
+ uint32 b1 = stream.Get_uint8 ();
+ uint32 b2 = stream.Get_uint8 ();
+ uint32 b3 = stream.Get_uint8 ();
+
+ fExifVersion = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ real64 x = (b0 - '0') * 10.00 +
+ (b1 - '0') * 1.00 +
+ (b2 - '0') * 0.10 +
+ (b3 - '0') * 0.01;
+
+ printf ("ExifVersion: %0.2f\n", x);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcDateTimeOriginal:
+ {
+
+ uint64 tagPosition = stream.PositionInOriginalFile ();
+
+ dng_date_time dt;
+
+ if (!ParseDateTimeTag (stream,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ dt))
+ {
+ return false;
+ }
+
+ fDateTimeOriginal.SetDateTime (dt);
+
+ fDateTimeOriginalStorageInfo = dng_date_time_storage_info (tagPosition,
+ dng_date_time_format_exif);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("DateTimeOriginal: ");
+
+ DumpDateTime (fDateTimeOriginal.DateTime ());
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcDateTimeDigitized:
+ {
+
+ uint64 tagPosition = stream.PositionInOriginalFile ();
+
+ dng_date_time dt;
+
+ if (!ParseDateTimeTag (stream,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ dt))
+ {
+ return false;
+ }
+
+ fDateTimeDigitized.SetDateTime (dt);
+
+ fDateTimeDigitizedStorageInfo = dng_date_time_storage_info (tagPosition,
+ dng_date_time_format_exif);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("DateTimeDigitized: ");
+
+ DumpDateTime (fDateTimeDigitized.DateTime ());
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcComponentsConfiguration:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 4);
+
+ uint32 b0 = stream.Get_uint8 ();
+ uint32 b1 = stream.Get_uint8 ();
+ uint32 b2 = stream.Get_uint8 ();
+ uint32 b3 = stream.Get_uint8 ();
+
+ fComponentsConfiguration = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ComponentsConfiguration: %s %s %s %s\n",
+ LookupComponent (b0),
+ LookupComponent (b1),
+ LookupComponent (b2),
+ LookupComponent (b3));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCompressedBitsPerPixel:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fCompresssedBitsPerPixel = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("CompressedBitsPerPixel: %0.2f\n",
+ fCompresssedBitsPerPixel.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcShutterSpeedValue:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttSRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ dng_srational ss = stream.TagValue_srational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ShutterSpeedValue: ");
+
+ real64 x = pow (2.0, -ss.As_real64 ());
+
+ DumpExposureTime (x);
+
+ printf ("\n");
+
+ }
+
+ // The ExposureTime and ShutterSpeedValue tags should be consistent.
+
+ if (fExposureTime.IsValid ())
+ {
+
+ real64 et = fExposureTime.As_real64 ();
+
+ real64 tv1 = -1.0 * log (et) / log (2.0);
+
+ real64 tv2 = ss.As_real64 ();
+
+ // Make sure they are within 0.25 APEX values.
+
+ if (Abs_real64 (tv1 - tv2) > 0.25)
+ {
+
+ ReportWarning ("The ExposureTime and ShutterSpeedValue tags have conflicting values");
+
+ }
+
+ }
+
+ #endif
+
+ SetShutterSpeedValue (ss.As_real64 ());
+
+ break;
+
+ }
+
+ case tcApertureValue:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ dng_urational av = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ real64 x = pow (2.0, 0.5 * av.As_real64 ());
+
+ printf ("ApertureValue: f/%0.2f\n", x);
+
+ }
+
+ // The FNumber and ApertureValue tags should be consistent.
+
+ if (fFNumber.IsValid () && av.IsValid ())
+ {
+
+ real64 fs = fFNumber.As_real64 ();
+
+ real64 av1 = FNumberToApertureValue (fs);
+
+ real64 av2 = av.As_real64 ();
+
+ if (Abs_real64 (av1 - av2) > 0.25)
+ {
+
+ ReportWarning ("The FNumber and ApertureValue tags have conflicting values");
+
+ }
+
+ }
+
+ #endif
+
+ SetApertureValue (av.As_real64 ());
+
+ break;
+
+ }
+
+ case tcBrightnessValue:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttSRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fBrightnessValue = stream.TagValue_srational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("BrightnessValue: %0.2f\n",
+ fBrightnessValue.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcExposureBiasValue:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttSRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fExposureBiasValue = stream.TagValue_srational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ExposureBiasValue: %0.2f\n",
+ fExposureBiasValue.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcMaxApertureValue:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fMaxApertureValue = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ real64 x = pow (2.0, 0.5 * fMaxApertureValue.As_real64 ());
+
+ printf ("MaxApertureValue: f/%0.1f\n", x);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSubjectDistance:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSubjectDistance = stream.TagValue_urational (tagType);
+
+ fApproxFocusDistance = fSubjectDistance;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SubjectDistance: %u/%u\n",
+ (unsigned) fSubjectDistance.n,
+ (unsigned) fSubjectDistance.d);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcMeteringMode:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fMeteringMode = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("MeteringMode: %s\n",
+ LookupMeteringMode (fMeteringMode));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcLightSource:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fLightSource = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("LightSource: %s\n",
+ LookupLightSource (fLightSource));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFlash:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFlash = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Flash: %u\n", (unsigned) fFlash);
+
+ if ((fFlash >> 5) & 1)
+ {
+ printf (" No flash function\n");
+ }
+
+ else
+ {
+
+ if (fFlash & 0x1)
+ {
+
+ printf (" Flash fired\n");
+
+ switch ((fFlash >> 1) & 0x3)
+ {
+
+ case 2:
+ printf (" Strobe return light not detected\n");
+ break;
+
+ case 3:
+ printf (" Strobe return light detected\n");
+ break;
+
+ }
+
+ }
+
+ else
+ {
+ printf (" Flash did not fire\n");
+ }
+
+ switch ((fFlash >> 3) & 0x3)
+ {
+
+ case 1:
+ printf (" Compulsory flash firing\n");
+ break;
+
+ case 2:
+ printf (" Compulsory flash suppression\n");
+ break;
+
+ case 3:
+ printf (" Auto mode\n");
+ break;
+
+ }
+
+ if ((fFlash >> 6) & 1)
+ {
+ printf (" Red-eye reduction supported\n");
+ }
+
+ }
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFocalLength:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFocalLength = stream.TagValue_urational (tagType);
+
+ // Sometimes "unknown" is recorded as zero.
+
+ if (fFocalLength.As_real64 () <= 0.0)
+ {
+ fFocalLength.Clear ();
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FocalLength: %0.1f mm\n",
+ fFocalLength.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcImageNumber:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fImageNumber = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("ImageNumber: %u\n", (unsigned) fImageNumber);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcExposureIndex:
+ case tcExposureIndexExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fExposureIndex = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: ISO %0.1f\n",
+ LookupTagCode (parentCode, tagCode),
+ fExposureIndex.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcUserComment:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ ParseEncodedStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fUserComment);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("UserComment: ");
+
+ DumpString (fUserComment);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSubsecTime:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ dng_string subsecs;
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ subsecs);
+
+ fDateTime.SetSubseconds (subsecs);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SubsecTime: ");
+
+ DumpString (subsecs);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSubsecTimeOriginal:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ dng_string subsecs;
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ subsecs);
+
+ fDateTimeOriginal.SetSubseconds (subsecs);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SubsecTimeOriginal: ");
+
+ DumpString (subsecs);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSubsecTimeDigitized:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ dng_string subsecs;
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ subsecs);
+
+ fDateTimeDigitized.SetSubseconds (subsecs);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SubsecTimeDigitized: ");
+
+ DumpString (subsecs);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFlashPixVersion:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 4);
+
+ uint32 b0 = stream.Get_uint8 ();
+ uint32 b1 = stream.Get_uint8 ();
+ uint32 b2 = stream.Get_uint8 ();
+ uint32 b3 = stream.Get_uint8 ();
+
+ fFlashPixVersion = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ real64 x = (b0 - '0') * 10.00 +
+ (b1 - '0') * 1.00 +
+ (b2 - '0') * 0.10 +
+ (b3 - '0') * 0.01;
+
+ printf ("FlashPixVersion: %0.2f\n", x);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcColorSpace:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fColorSpace = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ColorSpace: %s\n",
+ LookupColorSpace (fColorSpace));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPixelXDimension:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fPixelXDimension = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("PixelXDimension: %u\n", (unsigned) fPixelXDimension);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPixelYDimension:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fPixelYDimension = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("PixelYDimension: %u\n", (unsigned) fPixelYDimension);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFocalPlaneXResolutionExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFocalPlaneXResolution = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FocalPlaneXResolutionExif: %0.4f\n",
+ fFocalPlaneXResolution.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFocalPlaneYResolutionExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFocalPlaneYResolution = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FocalPlaneYResolutionExif: %0.4f\n",
+ fFocalPlaneYResolution.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFocalPlaneResolutionUnitExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFocalPlaneResolutionUnit = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FocalPlaneResolutionUnitExif: %s\n",
+ LookupResolutionUnit (fFocalPlaneResolutionUnit));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSensingMethodExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSensingMethod = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SensingMethodExif: %s\n",
+ LookupSensingMethod (fSensingMethod));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFileSource:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFileSource = stream.Get_uint8 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FileSource: %s\n",
+ LookupFileSource (fFileSource));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSceneType:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSceneType = stream.Get_uint8 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SceneType: %s\n",
+ LookupSceneType (fSceneType));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCFAPatternExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ if (tagCount <= 4)
+ {
+ return false;
+ }
+
+ uint32 cols = stream.Get_uint16 ();
+ uint32 rows = stream.Get_uint16 ();
+
+ if (tagCount != 4 + cols * rows)
+ {
+ return false;
+ }
+
+ if (cols < 1 || cols > kMaxCFAPattern ||
+ rows < 1 || rows > kMaxCFAPattern)
+ {
+ return false;
+ }
+
+ fCFARepeatPatternCols = cols;
+ fCFARepeatPatternRows = rows;
+
+ // Note that the Exif spec stores this array in a different
+ // scan order than the TIFF-EP spec.
+
+ for (uint32 j = 0; j < fCFARepeatPatternCols; j++)
+ for (uint32 k = 0; k < fCFARepeatPatternRows; k++)
+ {
+
+ fCFAPattern [k] [j] = stream.Get_uint8 ();
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("CFAPatternExif:\n");
+
+ for (uint32 j = 0; j < fCFARepeatPatternRows; j++)
+ {
+
+ int32 spaces = 4;
+
+ for (uint32 k = 0; k < fCFARepeatPatternCols; k++)
+ {
+
+ while (spaces-- > 0)
+ {
+ printf (" ");
+ }
+
+ const char *name = LookupCFAColor (fCFAPattern [j] [k]);
+
+ spaces = 9 - (int32) strlen (name);
+
+ printf ("%s", name);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCustomRendered:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fCustomRendered = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("CustomRendered: %s\n",
+ LookupCustomRendered (fCustomRendered));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcExposureMode:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fExposureMode = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ExposureMode: %s\n",
+ LookupExposureMode (fExposureMode));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcWhiteBalance:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fWhiteBalance = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("WhiteBalance: %s\n",
+ LookupWhiteBalance (fWhiteBalance));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcDigitalZoomRatio:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fDigitalZoomRatio = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("DigitalZoomRatio: ");
+
+ if (fDigitalZoomRatio.n == 0 ||
+ fDigitalZoomRatio.d == 0)
+ {
+
+ printf ("Not used\n");
+
+ }
+
+ else
+ {
+
+ printf ("%0.2f\n", fDigitalZoomRatio.As_real64 ());
+
+ }
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFocalLengthIn35mmFilm:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFocalLengthIn35mmFilm = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("FocalLengthIn35mmFilm: %u mm\n",
+ (unsigned) fFocalLengthIn35mmFilm);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSceneCaptureType:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSceneCaptureType = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SceneCaptureType: %s\n",
+ LookupSceneCaptureType (fSceneCaptureType));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcGainControl:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fGainControl = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("GainControl: %s\n",
+ LookupGainControl (fGainControl));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcContrast:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fContrast = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Contrast: %s\n",
+ LookupContrast (fContrast));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSaturation:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSaturation = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Saturation: %s\n",
+ LookupSaturation (fSaturation));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSharpness:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSharpness = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Sharpness: %s\n",
+ LookupSharpness (fSharpness));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSubjectDistanceRange:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSubjectDistanceRange = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SubjectDistanceRange: %s\n",
+ LookupSubjectDistanceRange (fSubjectDistanceRange));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSubjectArea:
+ case tcSubjectLocation:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 2, 4))
+ {
+ return false;
+ }
+
+ if (tagCode == tcSubjectLocation)
+ {
+ CheckTagCount (parentCode, tagCode, tagCount, 2);
+ }
+
+ fSubjectAreaCount = tagCount;
+
+ for (uint32 j = 0; j < tagCount; j++)
+ {
+
+ fSubjectArea [j] = stream.TagValue_uint32 (tagType);
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s:", LookupTagCode (parentCode, tagCode));
+
+ for (uint32 j = 0; j < fSubjectAreaCount; j++)
+ {
+
+ printf (" %u", (unsigned) fSubjectArea [j]);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcGamma:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fGamma = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Gamma: %0.2f\n",
+ fGamma.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcImageUniqueID:
+ {
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttAscii))
+ return false;
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 33))
+ return false;
+
+ dng_string s;
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ s);
+
+ if (s.Length () != 32)
+ return false;
+
+ dng_fingerprint f;
+
+ for (uint32 j = 0; j < 32; j++)
+ {
+
+ char c = ForceUppercase (s.Get () [j]);
+
+ uint32 digit;
+
+ if (c >= '0' && c <= '9')
+ {
+ digit = c - '0';
+ }
+
+ else if (c >= 'A' && c <= 'F')
+ {
+ digit = c - 'A' + 10;
+ }
+
+ else
+ return false;
+
+ f.data [j >> 1] *= 16;
+ f.data [j >> 1] += (uint8) digit;
+
+ }
+
+ fImageUniqueID = f;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ImageUniqueID: ");
+
+ DumpFingerprint (fImageUniqueID);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCameraOwnerNameExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fOwnerName);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("CameraOwnerName: ");
+
+ DumpString (fOwnerName);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCameraSerialNumberExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fCameraSerialNumber);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: ", LookupTagCode (parentCode, tagCode));
+
+ DumpString (fCameraSerialNumber);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcLensSpecificationExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
+ return false;
+
+ fLensInfo [0] = stream.TagValue_urational (tagType);
+ fLensInfo [1] = stream.TagValue_urational (tagType);
+ fLensInfo [2] = stream.TagValue_urational (tagType);
+ fLensInfo [3] = stream.TagValue_urational (tagType);
+
+ // Some third party software wrote zero rather than undefined values for
+ // unknown entries. Work around this bug.
+
+ for (uint32 j = 0; j < 4; j++)
+ {
+
+ if (fLensInfo [j].IsValid () && fLensInfo [j].As_real64 () <= 0.0)
+ {
+
+ fLensInfo [j] = dng_urational (0, 0);
+
+ #if qDNGValidate
+
+ ReportWarning ("Zero entry in LensSpecification tag--should be undefined");
+
+ #endif
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("LensSpecificationExif: ");
+
+ real64 minFL = fLensInfo [0].As_real64 ();
+ real64 maxFL = fLensInfo [1].As_real64 ();
+
+ if (minFL == maxFL)
+ printf ("%0.1f mm", minFL);
+ else
+ printf ("%0.1f-%0.1f mm", minFL, maxFL);
+
+ if (fLensInfo [2].d)
+ {
+
+ real64 minFS = fLensInfo [2].As_real64 ();
+ real64 maxFS = fLensInfo [3].As_real64 ();
+
+ if (minFS == maxFS)
+ printf (" f/%0.1f", minFS);
+ else
+ printf (" f/%0.1f-%0.1f", minFS, maxFS);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcLensMakeExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fLensMake);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: ", LookupTagCode (parentCode, tagCode));
+
+ DumpString (fLensMake);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcLensModelExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fLensName);
+
+ fLensNameWasReadFromExif = fLensName.NotEmpty ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: ", LookupTagCode (parentCode, tagCode));
+
+ DumpString (fLensName);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcLensSerialNumberExif:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fLensSerialNumber);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: ", LookupTagCode (parentCode, tagCode));
+
+ DumpString (fLensSerialNumber);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ default:
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+// Parses tags that should only appear in GPS IFD
+
+bool dng_exif::Parse_gps (dng_stream &stream,
+ dng_shared & /* shared */,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 /* tagOffset */)
+ {
+
+ switch (tagCode)
+ {
+
+ case tcGPSVersionID:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttByte);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 4);
+
+ uint32 b0 = stream.Get_uint8 ();
+ uint32 b1 = stream.Get_uint8 ();
+ uint32 b2 = stream.Get_uint8 ();
+ uint32 b3 = stream.Get_uint8 ();
+
+ fGPSVersionID = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("GPSVersionID: %u.%u.%u.%u\n",
+ (unsigned) b0,
+ (unsigned) b1,
+ (unsigned) b2,
+ (unsigned) b3);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcGPSLatitudeRef:
+ case tcGPSLongitudeRef:
+ case tcGPSSatellites:
+ case tcGPSStatus:
+ case tcGPSMeasureMode:
+ case tcGPSSpeedRef:
+ case tcGPSTrackRef:
+ case tcGPSImgDirectionRef:
+ case tcGPSMapDatum:
+ case tcGPSDestLatitudeRef:
+ case tcGPSDestLongitudeRef:
+ case tcGPSDestBearingRef:
+ case tcGPSDestDistanceRef:
+ case tcGPSDateStamp:
+ {
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttAscii))
+ return false;
+
+ dng_string *s;
+
+ switch (tagCode)
+ {
+
+ case tcGPSLatitudeRef:
+ s = &fGPSLatitudeRef;
+ break;
+
+ case tcGPSLongitudeRef:
+ s = &fGPSLongitudeRef;
+ break;
+
+ case tcGPSSatellites:
+ s = &fGPSSatellites;
+ break;
+
+ case tcGPSStatus:
+ s = &fGPSStatus;
+ break;
+
+ case tcGPSMeasureMode:
+ s = &fGPSMeasureMode;
+ break;
+
+ case tcGPSSpeedRef:
+ s = &fGPSSpeedRef;
+ break;
+
+ case tcGPSTrackRef:
+ s = &fGPSTrackRef;
+ break;
+
+ case tcGPSImgDirectionRef:
+ s = &fGPSImgDirectionRef;
+ break;
+
+ case tcGPSMapDatum:
+ s = &fGPSMapDatum;
+ break;
+
+ case tcGPSDestLatitudeRef:
+ s = &fGPSDestLatitudeRef;
+ break;
+
+ case tcGPSDestLongitudeRef:
+ s = &fGPSDestLongitudeRef;
+ break;
+
+ case tcGPSDestBearingRef:
+ s = &fGPSDestBearingRef;
+ break;
+
+ case tcGPSDestDistanceRef:
+ s = &fGPSDestDistanceRef;
+ break;
+
+ case tcGPSDateStamp:
+ s = &fGPSDateStamp;
+ break;
+
+ default:
+ return false;
+
+ }
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ *s);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: ", LookupTagCode (parentCode, tagCode));
+
+ DumpString (*s);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcGPSLatitude:
+ case tcGPSLongitude:
+ case tcGPSTimeStamp:
+ case tcGPSDestLatitude:
+ case tcGPSDestLongitude:
+ {
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttRational))
+ return false;
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 3))
+ return false;
+
+ dng_urational *u;
+
+ switch (tagCode)
+ {
+
+ case tcGPSLatitude:
+ u = fGPSLatitude;
+ break;
+
+ case tcGPSLongitude:
+ u = fGPSLongitude;
+ break;
+
+ case tcGPSTimeStamp:
+ u = fGPSTimeStamp;
+ break;
+
+ case tcGPSDestLatitude:
+ u = fGPSDestLatitude;
+ break;
+
+ case tcGPSDestLongitude:
+ u = fGPSDestLongitude;
+ break;
+
+ default:
+ return false;
+
+ }
+
+ u [0] = stream.TagValue_urational (tagType);
+ u [1] = stream.TagValue_urational (tagType);
+ u [2] = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s:", LookupTagCode (parentCode, tagCode));
+
+ for (uint32 j = 0; j < 3; j++)
+ {
+
+ if (u [j].d == 0)
+ printf (" -");
+
+ else
+ printf (" %0.4f", u [j].As_real64 ());
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcGPSAltitudeRef:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttByte);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fGPSAltitudeRef = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("GPSAltitudeRef: ");
+
+ switch (fGPSAltitudeRef)
+ {
+
+ case 0:
+ printf ("Sea level");
+ break;
+
+ case 1:
+ printf ("Sea level reference (negative value)");
+ break;
+
+ default:
+ printf ("%u", (unsigned) fGPSAltitudeRef);
+ break;
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcGPSAltitude:
+ case tcGPSDOP:
+ case tcGPSSpeed:
+ case tcGPSTrack:
+ case tcGPSImgDirection:
+ case tcGPSDestBearing:
+ case tcGPSDestDistance:
+ case tcGPSHPositioningError:
+ {
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttRational))
+ return false;
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ dng_urational *u;
+
+ switch (tagCode)
+ {
+
+ case tcGPSAltitude:
+ u = &fGPSAltitude;
+ break;
+
+ case tcGPSDOP:
+ u = &fGPSDOP;
+ break;
+
+ case tcGPSSpeed:
+ u = &fGPSSpeed;
+ break;
+
+ case tcGPSTrack:
+ u = &fGPSTrack;
+ break;
+
+ case tcGPSImgDirection:
+ u = &fGPSImgDirection;
+ break;
+
+ case tcGPSDestBearing:
+ u = &fGPSDestBearing;
+ break;
+
+ case tcGPSDestDistance:
+ u = &fGPSDestDistance;
+ break;
+
+ case tcGPSHPositioningError:
+ u = &fGPSHPositioningError;
+ break;
+
+ default:
+ return false;
+
+ }
+
+ *u = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s:", LookupTagCode (parentCode, tagCode));
+
+ if (u->d == 0)
+ printf (" -");
+
+ else
+ printf (" %0.4f", u->As_real64 ());
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcGPSProcessingMethod:
+ case tcGPSAreaInformation:
+ {
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttUndefined))
+ return false;
+
+ dng_string *s;
+
+ switch (tagCode)
+ {
+
+ case tcGPSProcessingMethod:
+ s = &fGPSProcessingMethod;
+ break;
+
+ case tcGPSAreaInformation:
+ s = &fGPSAreaInformation;
+ break;
+
+ default:
+ return false;
+
+ }
+
+ ParseEncodedStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ *s);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: ", LookupTagCode (parentCode, tagCode));
+
+ DumpString (*s);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcGPSDifferential:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fGPSDifferential = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("GPSDifferential: ");
+
+ switch (fGPSDifferential)
+ {
+
+ case 0:
+ printf ("Measurement without differential correction");
+ break;
+
+ case 1:
+ printf ("Differential correction applied");
+ break;
+
+ default:
+ printf ("%u", (unsigned) fGPSDifferential);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ default:
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+// Parses tags that should only appear in Interoperability IFD
+
+bool dng_exif::Parse_interoperability (dng_stream &stream,
+ dng_shared & /* shared */,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 /* tagOffset */)
+ {
+
+ switch (tagCode)
+ {
+
+ case tcInteroperabilityIndex:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 4);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fInteroperabilityIndex);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("InteroperabilityIndex: ");
+
+ DumpString (fInteroperabilityIndex);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcInteroperabilityVersion:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 4);
+
+ uint32 b0 = stream.Get_uint8 ();
+ uint32 b1 = stream.Get_uint8 ();
+ uint32 b2 = stream.Get_uint8 ();
+ uint32 b3 = stream.Get_uint8 ();
+
+ fInteroperabilityVersion = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ real64 x = (b0 - '0') * 10.00 +
+ (b1 - '0') * 1.00 +
+ (b2 - '0') * 0.10 +
+ (b3 - '0') * 0.01;
+
+ printf ("InteroperabilityVersion: %0.2f\n", x);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcRelatedImageFileFormat:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fRelatedImageFileFormat);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("RelatedImageFileFormat: ");
+
+ DumpString (fRelatedImageFileFormat);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcRelatedImageWidth:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fRelatedImageWidth = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("RelatedImageWidth: %u\n", (unsigned) fRelatedImageWidth);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcRelatedImageLength:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fRelatedImageLength = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("RelatedImageLength: %u\n", (unsigned) fRelatedImageLength);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ default:
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+void dng_exif::PostParse (dng_host & /* host */,
+ dng_shared & /* shared */)
+ {
+
+ #if qDNGValidate
+
+ const real64 kAPEX_Slop = 0.25;
+
+ // Sanity check on MaxApertureValue.
+
+ if (fMaxApertureValue.d)
+ {
+
+ real64 mav = fMaxApertureValue.As_real64 ();
+
+ // Compare against ApertureValue or FNumber.
+
+ real64 av = mav;
+
+ if (fApertureValue.d)
+ {
+
+ av = fApertureValue.As_real64 ();
+
+ }
+
+ else if (fFNumber.d)
+ {
+
+ real64 fs = fFNumber.As_real64 ();
+
+ if (fs >= 1.0)
+ {
+
+ av = FNumberToApertureValue (fs);
+
+ }
+
+ }
+
+ if (mav > av + kAPEX_Slop)
+ {
+
+ ReportWarning ("MaxApertureValue conflicts with ApertureValue and/or FNumber");
+
+ }
+
+ // Compare against LensInfo
+
+ if (fLensInfo [2].d && fLensInfo [3].d)
+ {
+
+ real64 fs1 = fLensInfo [2].As_real64 ();
+ real64 fs2 = fLensInfo [3].As_real64 ();
+
+ if (fs1 >= 1.0 && fs2 >= 1.0 && fs2 >= fs1)
+ {
+
+ real64 av1 = FNumberToApertureValue (fs1);
+ real64 av2 = FNumberToApertureValue (fs2);
+
+ // Wide angle adapters might create an effective
+ // wide FS, and tele-extenders always result
+ // in a higher FS.
+
+ if (mav < av1 - kAPEX_Slop - 1.0 ||
+ mav > av2 + kAPEX_Slop + 2.0)
+ {
+
+ ReportWarning ("Possible MaxApertureValue conflict with LensInfo");
+
+ }
+
+ }
+
+ }
+
+ }
+
+ // Sanity check on FocalLength.
+
+ if (fFocalLength.d)
+ {
+
+ real64 fl = fFocalLength.As_real64 ();
+
+ if (fl < 1.0)
+ {
+
+ ReportWarning ("FocalLength is less than 1.0 mm (legal but unlikely)");
+
+ }
+
+ else if (fLensInfo [0].d && fLensInfo [1].d)
+ {
+
+ real64 minFL = fLensInfo [0].As_real64 ();
+ real64 maxFL = fLensInfo [1].As_real64 ();
+
+ // Allow for wide-angle converters and tele-extenders.
+
+ if (fl < minFL * 0.6 ||
+ fl > maxFL * 2.1)
+ {
+
+ ReportWarning ("Possible FocalLength conflict with LensInfo");
+
+ }
+
+ }
+
+ }
+
+ #endif
+
+ // Mirror DateTimeOriginal to DateTime.
+
+ if (fDateTime.NotValid () && fDateTimeOriginal.IsValid ())
+ {
+
+ fDateTime = fDateTimeOriginal;
+
+ }
+
+ // Mirror EXIF 2.3 sensitivity tags to ISOSpeedRatings.
+
+ if (fISOSpeedRatings [0] == 0 || fISOSpeedRatings [0] == 65535)
+ {
+
+ // Prefer Recommended Exposure Index, then Standard Output Sensitivity, then
+ // ISO Speed, then Exposure Index.
+
+ if (fRecommendedExposureIndex != 0 &&
+ (fSensitivityType == stRecommendedExposureIndex ||
+ fSensitivityType == stSOSandREI ||
+ fSensitivityType == stREIandISOSpeed ||
+ fSensitivityType == stSOSandREIandISOSpeed))
+ {
+
+ fISOSpeedRatings [0] = fRecommendedExposureIndex;
+
+ }
+
+ else if (fStandardOutputSensitivity != 0 &&
+ (fSensitivityType == stStandardOutputSensitivity ||
+ fSensitivityType == stSOSandREI ||
+ fSensitivityType == stSOSandISOSpeed ||
+ fSensitivityType == stSOSandREIandISOSpeed))
+ {
+
+ fISOSpeedRatings [0] = fStandardOutputSensitivity;
+
+ }
+
+ else if (fISOSpeed != 0 &&
+ (fSensitivityType == stISOSpeed ||
+ fSensitivityType == stSOSandISOSpeed ||
+ fSensitivityType == stREIandISOSpeed ||
+ fSensitivityType == stSOSandREIandISOSpeed))
+ {
+
+ fISOSpeedRatings [0] = fISOSpeed;
+
+ }
+
+ }
+
+ // Mirror ExposureIndex to ISOSpeedRatings.
+
+ if (fExposureIndex.IsValid () && fISOSpeedRatings [0] == 0)
+ {
+
+ fISOSpeedRatings [0] = Round_uint32 (fExposureIndex.As_real64 ());
+
+ }
+
+ // Kodak sets the GPSAltitudeRef without setting the GPSAltitude.
+
+ if (fGPSAltitude.NotValid ())
+ {
+
+ fGPSAltitudeRef = 0xFFFFFFFF;
+
+ }
+
+ // If there is no valid GPS data, clear the GPS version number.
+
+ if (fGPSLatitude [0].NotValid () &&
+ fGPSLongitude [0].NotValid () &&
+ fGPSAltitude .NotValid () &&
+ fGPSTimeStamp [0].NotValid () &&
+ fGPSDateStamp .IsEmpty ())
+ {
+
+ fGPSVersionID = 0;
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_exif.h b/source/dng_exif.h
index a85fc7d..5504431 100644
--- a/source/dng_exif.h
+++ b/source/dng_exif.h
@@ -1,351 +1,351 @@
-/*****************************************************************************/
-// Copyright 2006-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_exif.h#2 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * EXIF read access support. See the \ref spec_exif "EXIF specification" for full
- * description of tags.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_exif__
-#define __dng_exif__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_date_time.h"
-#include "dng_fingerprint.h"
-#include "dng_types.h"
-#include "dng_matrix.h"
-#include "dng_rational.h"
-#include "dng_string.h"
-#include "dng_stream.h"
-#include "dng_sdk_limits.h"
-
-/*****************************************************************************/
-
-/// \brief Container class for parsing and holding EXIF tags.
-///
-/// Public member fields are documented in \ref spec_exif "EXIF specification."
-
-class dng_exif
- {
-
- public:
-
- dng_string fImageDescription;
- dng_string fMake;
- dng_string fModel;
- dng_string fSoftware;
- dng_string fArtist;
- dng_string fCopyright;
- dng_string fCopyright2;
- dng_string fUserComment;
-
- dng_date_time_info fDateTime;
- dng_date_time_storage_info fDateTimeStorageInfo;
-
- dng_date_time_info fDateTimeOriginal;
- dng_date_time_storage_info fDateTimeOriginalStorageInfo;
-
- dng_date_time_info fDateTimeDigitized;
- dng_date_time_storage_info fDateTimeDigitizedStorageInfo;
-
- uint32 fTIFF_EP_StandardID;
- uint32 fExifVersion;
- uint32 fFlashPixVersion;
-
- dng_urational fExposureTime;
- dng_urational fFNumber;
- dng_srational fShutterSpeedValue;
- dng_urational fApertureValue;
- dng_srational fBrightnessValue;
- dng_srational fExposureBiasValue;
- dng_urational fMaxApertureValue;
- dng_urational fFocalLength;
- dng_urational fDigitalZoomRatio;
- dng_urational fExposureIndex;
- dng_urational fSubjectDistance;
- dng_urational fGamma;
-
- dng_urational fBatteryLevelR;
- dng_string fBatteryLevelA;
-
- uint32 fExposureProgram;
- uint32 fMeteringMode;
- uint32 fLightSource;
- uint32 fFlash;
- uint32 fFlashMask;
- uint32 fSensingMethod;
- uint32 fColorSpace;
- uint32 fFileSource;
- uint32 fSceneType;
- uint32 fCustomRendered;
- uint32 fExposureMode;
- uint32 fWhiteBalance;
- uint32 fSceneCaptureType;
- uint32 fGainControl;
- uint32 fContrast;
- uint32 fSaturation;
- uint32 fSharpness;
- uint32 fSubjectDistanceRange;
- uint32 fSelfTimerMode;
- uint32 fImageNumber;
-
- uint32 fFocalLengthIn35mmFilm;
-
- uint32 fISOSpeedRatings [3]; // EXIF 2.3: PhotographicSensitivity.
-
- // Sensitivity tags added in EXIF 2.3.
-
- uint32 fSensitivityType;
- uint32 fStandardOutputSensitivity;
- uint32 fRecommendedExposureIndex;
- uint32 fISOSpeed;
- uint32 fISOSpeedLatitudeyyy;
- uint32 fISOSpeedLatitudezzz;
-
- uint32 fSubjectAreaCount;
- uint32 fSubjectArea [4];
-
- uint32 fComponentsConfiguration;
-
- dng_urational fCompresssedBitsPerPixel;
-
- uint32 fPixelXDimension;
- uint32 fPixelYDimension;
-
- dng_urational fFocalPlaneXResolution;
- dng_urational fFocalPlaneYResolution;
-
- uint32 fFocalPlaneResolutionUnit;
-
- uint32 fCFARepeatPatternRows;
- uint32 fCFARepeatPatternCols;
-
- uint8 fCFAPattern [kMaxCFAPattern] [kMaxCFAPattern];
-
- dng_fingerprint fImageUniqueID;
-
- uint32 fGPSVersionID;
- dng_string fGPSLatitudeRef;
- dng_urational fGPSLatitude [3];
- dng_string fGPSLongitudeRef;
- dng_urational fGPSLongitude [3];
- uint32 fGPSAltitudeRef;
- dng_urational fGPSAltitude;
- dng_urational fGPSTimeStamp [3];
- dng_string fGPSSatellites;
- dng_string fGPSStatus;
- dng_string fGPSMeasureMode;
- dng_urational fGPSDOP;
- dng_string fGPSSpeedRef;
- dng_urational fGPSSpeed;
- dng_string fGPSTrackRef;
- dng_urational fGPSTrack;
- dng_string fGPSImgDirectionRef;
- dng_urational fGPSImgDirection;
- dng_string fGPSMapDatum;
- dng_string fGPSDestLatitudeRef;
- dng_urational fGPSDestLatitude [3];
- dng_string fGPSDestLongitudeRef;
- dng_urational fGPSDestLongitude [3];
- dng_string fGPSDestBearingRef;
- dng_urational fGPSDestBearing;
- dng_string fGPSDestDistanceRef;
- dng_urational fGPSDestDistance;
- dng_string fGPSProcessingMethod;
- dng_string fGPSAreaInformation;
- dng_string fGPSDateStamp;
- uint32 fGPSDifferential;
- dng_urational fGPSHPositioningError;
-
- dng_string fInteroperabilityIndex;
-
- uint32 fInteroperabilityVersion;
-
- dng_string fRelatedImageFileFormat;
-
- uint32 fRelatedImageWidth;
- uint32 fRelatedImageLength;
-
- dng_string fCameraSerialNumber; // EXIF 2.3: BodySerialNumber.
-
- dng_urational fLensInfo [4]; // EXIF 2.3: LensSpecification.
-
- dng_string fLensID;
- dng_string fLensMake;
- dng_string fLensName; // EXIF 2.3: LensModel.
- dng_string fLensSerialNumber;
-
- // Was the lens name field read from a LensModel tag?
-
- bool fLensNameWasReadFromExif;
-
- // Private field to hold the approximate focus distance of the lens, in
- // meters. This value is often coarsely measured/reported and hence should be
- // interpreted only as a rough estimate of the true distance from the plane
- // of focus (in object space) to the focal plane. It is still useful for the
- // purposes of applying lens corrections.
-
- dng_urational fApproxFocusDistance;
-
- dng_srational fFlashCompensation;
-
- dng_string fOwnerName; // EXIF 2.3: CameraOwnerName.
- dng_string fFirmware;
-
- public:
-
- dng_exif ();
-
- virtual ~dng_exif ();
-
- /// Make clone.
-
- virtual dng_exif * Clone () const;
-
- /// Clear all EXIF fields.
-
- void SetEmpty ();
-
- /// Copy all GPS-related fields.
- /// \param exif Source object from which to copy GPS fields.
-
- void CopyGPSFrom (const dng_exif &exif);
-
- /// Utility to fix up common errors and rounding issues with EXIF exposure
- /// times.
-
- static real64 SnapExposureTime (real64 et);
-
- /// Set exposure time and shutter speed fields. Optionally fix up common
- /// errors and rounding issues with EXIF exposure times.
- /// \param et Exposure time in seconds.
- /// \param snap Set to true to fix up common errors and rounding issues with
- /// EXIF exposure times.
-
- void SetExposureTime (real64 et,
- bool snap = true);
-
- /// Set shutter speed value (APEX units) and exposure time.
- /// \param Shutter speed in APEX units.
-
- void SetShutterSpeedValue (real64 ss);
-
- /// Utility to encode f-number as a rational.
- /// \param fs The f-number to encode.
-
- static dng_urational EncodeFNumber (real64 fs);
-
- /// Set the FNumber and ApertureValue fields.
- /// \param fs The f-number to set.
-
- void SetFNumber (real64 fs);
-
- /// Set the FNumber and ApertureValue fields.
- /// \param av The aperture value (APEX units).
-
- void SetApertureValue (real64 av);
-
- /// Utility to convert aperture value (APEX units) to f-number.
- /// \param av The aperture value (APEX units) to convert.
-
- static real64 ApertureValueToFNumber (real64 av);
-
- /// Utility to convert aperture value (APEX units) to f-number.
- /// \param av The aperture value (APEX units) to convert.
-
- static real64 ApertureValueToFNumber (const dng_urational &av);
-
- /// Utility to convert f-number to aperture value (APEX units).
- /// \param fNumber The f-number to convert.
-
- static real64 FNumberToApertureValue (real64 fNumber);
-
- /// Utility to convert f-number to aperture value (APEX units).
- /// \param fNumber The f-number to convert.
-
- static real64 FNumberToApertureValue (const dng_urational &fNumber);
-
- /// Set the DateTime field.
- /// \param dt The DateTime value.
-
- void UpdateDateTime (const dng_date_time_info &dt);
-
- /// Returns true iff the EXIF version is at least 2.3.
-
- bool AtLeastVersion0230 () const;
-
- virtual bool ParseTag (dng_stream &stream,
- dng_shared &shared,
- uint32 parentCode,
- bool isMainIFD,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- virtual void PostParse (dng_host &host,
- dng_shared &shared);
-
- protected:
-
- virtual bool Parse_ifd0 (dng_stream &stream,
- dng_shared &shared,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- virtual bool Parse_ifd0_main (dng_stream &stream,
- dng_shared &shared,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- virtual bool Parse_ifd0_exif (dng_stream &stream,
- dng_shared &shared,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- virtual bool Parse_gps (dng_stream &stream,
- dng_shared &shared,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- virtual bool Parse_interoperability (dng_stream &stream,
- dng_shared &shared,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_exif.h#2 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * EXIF read access support. See the \ref spec_exif "EXIF specification" for full
+ * description of tags.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_exif__
+#define __dng_exif__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_date_time.h"
+#include "dng_fingerprint.h"
+#include "dng_types.h"
+#include "dng_matrix.h"
+#include "dng_rational.h"
+#include "dng_string.h"
+#include "dng_stream.h"
+#include "dng_sdk_limits.h"
+
+/*****************************************************************************/
+
+/// \brief Container class for parsing and holding EXIF tags.
+///
+/// Public member fields are documented in \ref spec_exif "EXIF specification."
+
+class dng_exif
+ {
+
+ public:
+
+ dng_string fImageDescription;
+ dng_string fMake;
+ dng_string fModel;
+ dng_string fSoftware;
+ dng_string fArtist;
+ dng_string fCopyright;
+ dng_string fCopyright2;
+ dng_string fUserComment;
+
+ dng_date_time_info fDateTime;
+ dng_date_time_storage_info fDateTimeStorageInfo;
+
+ dng_date_time_info fDateTimeOriginal;
+ dng_date_time_storage_info fDateTimeOriginalStorageInfo;
+
+ dng_date_time_info fDateTimeDigitized;
+ dng_date_time_storage_info fDateTimeDigitizedStorageInfo;
+
+ uint32 fTIFF_EP_StandardID;
+ uint32 fExifVersion;
+ uint32 fFlashPixVersion;
+
+ dng_urational fExposureTime;
+ dng_urational fFNumber;
+ dng_srational fShutterSpeedValue;
+ dng_urational fApertureValue;
+ dng_srational fBrightnessValue;
+ dng_srational fExposureBiasValue;
+ dng_urational fMaxApertureValue;
+ dng_urational fFocalLength;
+ dng_urational fDigitalZoomRatio;
+ dng_urational fExposureIndex;
+ dng_urational fSubjectDistance;
+ dng_urational fGamma;
+
+ dng_urational fBatteryLevelR;
+ dng_string fBatteryLevelA;
+
+ uint32 fExposureProgram;
+ uint32 fMeteringMode;
+ uint32 fLightSource;
+ uint32 fFlash;
+ uint32 fFlashMask;
+ uint32 fSensingMethod;
+ uint32 fColorSpace;
+ uint32 fFileSource;
+ uint32 fSceneType;
+ uint32 fCustomRendered;
+ uint32 fExposureMode;
+ uint32 fWhiteBalance;
+ uint32 fSceneCaptureType;
+ uint32 fGainControl;
+ uint32 fContrast;
+ uint32 fSaturation;
+ uint32 fSharpness;
+ uint32 fSubjectDistanceRange;
+ uint32 fSelfTimerMode;
+ uint32 fImageNumber;
+
+ uint32 fFocalLengthIn35mmFilm;
+
+ uint32 fISOSpeedRatings [3]; // EXIF 2.3: PhotographicSensitivity.
+
+ // Sensitivity tags added in EXIF 2.3.
+
+ uint32 fSensitivityType;
+ uint32 fStandardOutputSensitivity;
+ uint32 fRecommendedExposureIndex;
+ uint32 fISOSpeed;
+ uint32 fISOSpeedLatitudeyyy;
+ uint32 fISOSpeedLatitudezzz;
+
+ uint32 fSubjectAreaCount;
+ uint32 fSubjectArea [4];
+
+ uint32 fComponentsConfiguration;
+
+ dng_urational fCompresssedBitsPerPixel;
+
+ uint32 fPixelXDimension;
+ uint32 fPixelYDimension;
+
+ dng_urational fFocalPlaneXResolution;
+ dng_urational fFocalPlaneYResolution;
+
+ uint32 fFocalPlaneResolutionUnit;
+
+ uint32 fCFARepeatPatternRows;
+ uint32 fCFARepeatPatternCols;
+
+ uint8 fCFAPattern [kMaxCFAPattern] [kMaxCFAPattern];
+
+ dng_fingerprint fImageUniqueID;
+
+ uint32 fGPSVersionID;
+ dng_string fGPSLatitudeRef;
+ dng_urational fGPSLatitude [3];
+ dng_string fGPSLongitudeRef;
+ dng_urational fGPSLongitude [3];
+ uint32 fGPSAltitudeRef;
+ dng_urational fGPSAltitude;
+ dng_urational fGPSTimeStamp [3];
+ dng_string fGPSSatellites;
+ dng_string fGPSStatus;
+ dng_string fGPSMeasureMode;
+ dng_urational fGPSDOP;
+ dng_string fGPSSpeedRef;
+ dng_urational fGPSSpeed;
+ dng_string fGPSTrackRef;
+ dng_urational fGPSTrack;
+ dng_string fGPSImgDirectionRef;
+ dng_urational fGPSImgDirection;
+ dng_string fGPSMapDatum;
+ dng_string fGPSDestLatitudeRef;
+ dng_urational fGPSDestLatitude [3];
+ dng_string fGPSDestLongitudeRef;
+ dng_urational fGPSDestLongitude [3];
+ dng_string fGPSDestBearingRef;
+ dng_urational fGPSDestBearing;
+ dng_string fGPSDestDistanceRef;
+ dng_urational fGPSDestDistance;
+ dng_string fGPSProcessingMethod;
+ dng_string fGPSAreaInformation;
+ dng_string fGPSDateStamp;
+ uint32 fGPSDifferential;
+ dng_urational fGPSHPositioningError;
+
+ dng_string fInteroperabilityIndex;
+
+ uint32 fInteroperabilityVersion;
+
+ dng_string fRelatedImageFileFormat;
+
+ uint32 fRelatedImageWidth;
+ uint32 fRelatedImageLength;
+
+ dng_string fCameraSerialNumber; // EXIF 2.3: BodySerialNumber.
+
+ dng_urational fLensInfo [4]; // EXIF 2.3: LensSpecification.
+
+ dng_string fLensID;
+ dng_string fLensMake;
+ dng_string fLensName; // EXIF 2.3: LensModel.
+ dng_string fLensSerialNumber;
+
+ // Was the lens name field read from a LensModel tag?
+
+ bool fLensNameWasReadFromExif;
+
+ // Private field to hold the approximate focus distance of the lens, in
+ // meters. This value is often coarsely measured/reported and hence should be
+ // interpreted only as a rough estimate of the true distance from the plane
+ // of focus (in object space) to the focal plane. It is still useful for the
+ // purposes of applying lens corrections.
+
+ dng_urational fApproxFocusDistance;
+
+ dng_srational fFlashCompensation;
+
+ dng_string fOwnerName; // EXIF 2.3: CameraOwnerName.
+ dng_string fFirmware;
+
+ public:
+
+ dng_exif ();
+
+ virtual ~dng_exif ();
+
+ /// Make clone.
+
+ virtual dng_exif * Clone () const;
+
+ /// Clear all EXIF fields.
+
+ void SetEmpty ();
+
+ /// Copy all GPS-related fields.
+ /// \param exif Source object from which to copy GPS fields.
+
+ void CopyGPSFrom (const dng_exif &exif);
+
+ /// Utility to fix up common errors and rounding issues with EXIF exposure
+ /// times.
+
+ static real64 SnapExposureTime (real64 et);
+
+ /// Set exposure time and shutter speed fields. Optionally fix up common
+ /// errors and rounding issues with EXIF exposure times.
+ /// \param et Exposure time in seconds.
+ /// \param snap Set to true to fix up common errors and rounding issues with
+ /// EXIF exposure times.
+
+ void SetExposureTime (real64 et,
+ bool snap = true);
+
+ /// Set shutter speed value (APEX units) and exposure time.
+ /// \param Shutter speed in APEX units.
+
+ void SetShutterSpeedValue (real64 ss);
+
+ /// Utility to encode f-number as a rational.
+ /// \param fs The f-number to encode.
+
+ static dng_urational EncodeFNumber (real64 fs);
+
+ /// Set the FNumber and ApertureValue fields.
+ /// \param fs The f-number to set.
+
+ void SetFNumber (real64 fs);
+
+ /// Set the FNumber and ApertureValue fields.
+ /// \param av The aperture value (APEX units).
+
+ void SetApertureValue (real64 av);
+
+ /// Utility to convert aperture value (APEX units) to f-number.
+ /// \param av The aperture value (APEX units) to convert.
+
+ static real64 ApertureValueToFNumber (real64 av);
+
+ /// Utility to convert aperture value (APEX units) to f-number.
+ /// \param av The aperture value (APEX units) to convert.
+
+ static real64 ApertureValueToFNumber (const dng_urational &av);
+
+ /// Utility to convert f-number to aperture value (APEX units).
+ /// \param fNumber The f-number to convert.
+
+ static real64 FNumberToApertureValue (real64 fNumber);
+
+ /// Utility to convert f-number to aperture value (APEX units).
+ /// \param fNumber The f-number to convert.
+
+ static real64 FNumberToApertureValue (const dng_urational &fNumber);
+
+ /// Set the DateTime field.
+ /// \param dt The DateTime value.
+
+ void UpdateDateTime (const dng_date_time_info &dt);
+
+ /// Returns true iff the EXIF version is at least 2.3.
+
+ bool AtLeastVersion0230 () const;
+
+ virtual bool ParseTag (dng_stream &stream,
+ dng_shared &shared,
+ uint32 parentCode,
+ bool isMainIFD,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ virtual void PostParse (dng_host &host,
+ dng_shared &shared);
+
+ protected:
+
+ virtual bool Parse_ifd0 (dng_stream &stream,
+ dng_shared &shared,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ virtual bool Parse_ifd0_main (dng_stream &stream,
+ dng_shared &shared,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ virtual bool Parse_ifd0_exif (dng_stream &stream,
+ dng_shared &shared,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ virtual bool Parse_gps (dng_stream &stream,
+ dng_shared &shared,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ virtual bool Parse_interoperability (dng_stream &stream,
+ dng_shared &shared,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_fast_module.h b/source/dng_fast_module.h
index ee6a10f..f3dbd78 100644
--- a/source/dng_fast_module.h
+++ b/source/dng_fast_module.h
@@ -1,31 +1,31 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_fast_module.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Include file to set optimization to highest level for performance-critical routines.
- * Normal files should have otpimization set to normal level to save code size as there is less
- * cache pollution this way.
- */
-
-/*****************************************************************************/
-
-// Include this file in modules that contain routines that should be as fast
-// as possible, even at the expense of slight code size increases.
-
-/*****************************************************************************/
-
-#ifdef _MSC_VER
-#pragma optimize ("t", on)
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_fast_module.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Include file to set optimization to highest level for performance-critical routines.
+ * Normal files should have otpimization set to normal level to save code size as there is less
+ * cache pollution this way.
+ */
+
+/*****************************************************************************/
+
+// Include this file in modules that contain routines that should be as fast
+// as possible, even at the expense of slight code size increases.
+
+/*****************************************************************************/
+
+#ifdef _MSC_VER
+#pragma optimize ("t", on)
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_file_stream.cpp b/source/dng_file_stream.cpp
index 4a8a79f..56682d8 100644
--- a/source/dng_file_stream.cpp
+++ b/source/dng_file_stream.cpp
@@ -1,135 +1,135 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_file_stream.cpp#2 $ */
-/* $DateTime: 2012/06/01 07:28:57 $ */
-/* $Change: 832715 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_file_stream.h"
-
-#include "dng_exceptions.h"
-
-/*****************************************************************************/
-
-dng_file_stream::dng_file_stream (const char *filename,
- bool output,
- uint32 bufferSize)
-
- : dng_stream ((dng_abort_sniffer *) NULL,
- bufferSize,
- 0)
-
- , fFile (NULL)
-
- {
-
- fFile = fopen (filename, output ? "wb" : "rb");
-
- if (!fFile)
- {
-
- #if qDNGValidate
-
- ReportError ("Unable to open file",
- filename);
-
- ThrowSilentError ();
-
- #else
-
- ThrowOpenFile ();
-
- #endif
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_file_stream::~dng_file_stream ()
- {
-
- if (fFile)
- {
- fclose (fFile);
- fFile = NULL;
- }
-
- }
-
-/*****************************************************************************/
-
-uint64 dng_file_stream::DoGetLength ()
- {
-
- if (fseek (fFile, 0, SEEK_END) != 0)
- {
-
- ThrowReadFile ();
-
- }
-
- return (uint64) ftell (fFile);
-
- }
-
-/*****************************************************************************/
-
-void dng_file_stream::DoRead (void *data,
- uint32 count,
- uint64 offset)
- {
-
- if (fseek (fFile, (long) offset, SEEK_SET) != 0)
- {
-
- ThrowReadFile ();
-
- }
-
- uint32 bytesRead = (uint32) fread (data, 1, count, fFile);
-
- if (bytesRead != count)
- {
-
- ThrowReadFile ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_file_stream::DoWrite (const void *data,
- uint32 count,
- uint64 offset)
- {
-
- if (fseek (fFile, (uint32) offset, SEEK_SET) != 0)
- {
-
- ThrowWriteFile ();
-
- }
-
- uint32 bytesWritten = (uint32) fwrite (data, 1, count, fFile);
-
- if (bytesWritten != count)
- {
-
- ThrowWriteFile ();
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_file_stream.cpp#2 $ */
+/* $DateTime: 2012/06/01 07:28:57 $ */
+/* $Change: 832715 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_file_stream.h"
+
+#include "dng_exceptions.h"
+
+/*****************************************************************************/
+
+dng_file_stream::dng_file_stream (const char *filename,
+ bool output,
+ uint32 bufferSize)
+
+ : dng_stream ((dng_abort_sniffer *) NULL,
+ bufferSize,
+ 0)
+
+ , fFile (NULL)
+
+ {
+
+ fFile = fopen (filename, output ? "wb" : "rb");
+
+ if (!fFile)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unable to open file",
+ filename);
+
+ ThrowSilentError ();
+
+ #else
+
+ ThrowOpenFile ();
+
+ #endif
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_file_stream::~dng_file_stream ()
+ {
+
+ if (fFile)
+ {
+ fclose (fFile);
+ fFile = NULL;
+ }
+
+ }
+
+/*****************************************************************************/
+
+uint64 dng_file_stream::DoGetLength ()
+ {
+
+ if (fseek (fFile, 0, SEEK_END) != 0)
+ {
+
+ ThrowReadFile ();
+
+ }
+
+ return (uint64) ftell (fFile);
+
+ }
+
+/*****************************************************************************/
+
+void dng_file_stream::DoRead (void *data,
+ uint32 count,
+ uint64 offset)
+ {
+
+ if (fseek (fFile, (long) offset, SEEK_SET) != 0)
+ {
+
+ ThrowReadFile ();
+
+ }
+
+ uint32 bytesRead = (uint32) fread (data, 1, count, fFile);
+
+ if (bytesRead != count)
+ {
+
+ ThrowReadFile ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_file_stream::DoWrite (const void *data,
+ uint32 count,
+ uint64 offset)
+ {
+
+ if (fseek (fFile, (uint32) offset, SEEK_SET) != 0)
+ {
+
+ ThrowWriteFile ();
+
+ }
+
+ uint32 bytesWritten = (uint32) fwrite (data, 1, count, fFile);
+
+ if (bytesWritten != count)
+ {
+
+ ThrowWriteFile ();
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_file_stream.h b/source/dng_file_stream.h
index 2326c4e..6df6da9 100644
--- a/source/dng_file_stream.h
+++ b/source/dng_file_stream.h
@@ -1,77 +1,77 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_file_stream.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Simple, portable, file read/write support.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_file_stream__
-#define __dng_file_stream__
-
-/*****************************************************************************/
-
-#include "dng_stream.h"
-
-/*****************************************************************************/
-
-/// \brief A stream to/from a disk file. See dng_stream for read/write interface
-
-class dng_file_stream: public dng_stream
- {
-
- private:
-
- FILE *fFile;
-
- public:
-
- /// Open a stream on a file.
- /// \param filename Pathname in platform synax.
- /// \param output Set to true if writing, false otherwise.
- /// \param bufferSize size of internal buffer to use. Defaults to 4k.
-
- dng_file_stream (const char *filename,
- bool output = false,
- uint32 bufferSize = kDefaultBufferSize);
-
- virtual ~dng_file_stream ();
-
- protected:
-
- virtual uint64 DoGetLength ();
-
- virtual void DoRead (void *data,
- uint32 count,
- uint64 offset);
-
- virtual void DoWrite (const void *data,
- uint32 count,
- uint64 offset);
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_file_stream (const dng_file_stream &stream);
-
- dng_file_stream & operator= (const dng_file_stream &stream);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_file_stream.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Simple, portable, file read/write support.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_file_stream__
+#define __dng_file_stream__
+
+/*****************************************************************************/
+
+#include "dng_stream.h"
+
+/*****************************************************************************/
+
+/// \brief A stream to/from a disk file. See dng_stream for read/write interface
+
+class dng_file_stream: public dng_stream
+ {
+
+ private:
+
+ FILE *fFile;
+
+ public:
+
+ /// Open a stream on a file.
+ /// \param filename Pathname in platform synax.
+ /// \param output Set to true if writing, false otherwise.
+ /// \param bufferSize size of internal buffer to use. Defaults to 4k.
+
+ dng_file_stream (const char *filename,
+ bool output = false,
+ uint32 bufferSize = kDefaultBufferSize);
+
+ virtual ~dng_file_stream ();
+
+ protected:
+
+ virtual uint64 DoGetLength ();
+
+ virtual void DoRead (void *data,
+ uint32 count,
+ uint64 offset);
+
+ virtual void DoWrite (const void *data,
+ uint32 count,
+ uint64 offset);
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_file_stream (const dng_file_stream &stream);
+
+ dng_file_stream & operator= (const dng_file_stream &stream);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_filter_task.h b/source/dng_filter_task.h
index fa79a6f..1ef7b33 100644
--- a/source/dng_filter_task.h
+++ b/source/dng_filter_task.h
@@ -1,158 +1,158 @@
-/*****************************************************************************/
-// Copyright 2006 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_filter_task.h#2 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Specialization of dng_area_task for processing an area from one dng_image to an
- * area of another.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_filter_task__
-#define __dng_filter_task__
-
-/*****************************************************************************/
-
-#include "dng_area_task.h"
-#include "dng_auto_ptr.h"
-#include "dng_point.h"
-#include "dng_rect.h"
-#include "dng_sdk_limits.h"
-
-/*****************************************************************************/
-
-/// \brief Represents a task which filters an area of a source dng_image to an area
-/// of a destination dng_image.
-
-class dng_filter_task: public dng_area_task
- {
-
- protected:
-
- const dng_image &fSrcImage;
-
- dng_image &fDstImage;
-
- uint32 fSrcPlane;
- uint32 fSrcPlanes;
- uint32 fSrcPixelType;
-
- uint32 fDstPlane;
- uint32 fDstPlanes;
- uint32 fDstPixelType;
-
- dng_point fSrcRepeat;
- dng_point fSrcTileSize;
-
- AutoPtr<dng_memory_block> fSrcBuffer [kMaxMPThreads];
- AutoPtr<dng_memory_block> fDstBuffer [kMaxMPThreads];
-
- public:
-
- /// Construct a filter task given a source and destination images.
- /// \param srcImage Image from which source pixels are read.
- /// \param dstImage Image to which result pixels are written.
-
- dng_filter_task (const dng_image &srcImage,
- dng_image &dstImage);
-
- virtual ~dng_filter_task ();
-
- /// Compute the source area needed for a given destination area. Default
- /// implementation assumes destination area is equal to source area for all
- /// cases.
- ///
- /// \param dstArea Area to for which pixels will be computed.
- ///
- /// \retval The source area needed as input to calculate the requested
- /// destination area.
-
- virtual dng_rect SrcArea (const dng_rect &dstArea)
- {
- return dstArea;
- }
-
- /// Given a destination tile size, calculate input tile size. Simlar to
- /// SrcArea, and should seldom be overridden.
- ///
- /// \param dstTileSize The destination tile size that is targeted for output.
- ///
- /// \retval The source tile size needed to compute a tile of the destination
- /// size.
-
- virtual dng_point SrcTileSize (const dng_point &dstTileSize)
- {
- return SrcArea (dng_rect (dstTileSize)).Size ();
- }
-
- /// Implements filtering operation from one buffer to another. Source and
- /// destination pixels are set up in member fields of this class. Ideally, no
- /// allocation should be done in this routine.
- ///
- /// \param threadIndex The thread on which this routine is being called,
- /// between 0 and threadCount - 1 for the threadCount passed to Start method.
- ///
- /// \param srcBuffer Input area and source pixels.
- ///
- /// \param dstBuffer Output area and destination pixels.
-
- virtual void ProcessArea (uint32 threadIndex,
- dng_pixel_buffer &srcBuffer,
- dng_pixel_buffer &dstBuffer) = 0;
-
- /// Called prior to processing on specific threads. Can be used to allocate
- /// per-thread memory buffers, etc.
- ///
- /// \param threadCount Total number of threads that will be used for
- /// processing. Less than or equal to MaxThreads of dng_area_task.
- ///
- /// \param tileSize Size of source tiles which will be processed. (Not all
- /// tiles will be this size due to edge conditions.)
- ///
- /// \param allocator dng_memory_allocator to use for allocating temporary
- /// buffers, etc.
- ///
- /// \param sniffer Sniffer to test for user cancellation and to set up
- /// progress.
-
- virtual void Start (uint32 threadCount,
- const dng_point &tileSize,
- dng_memory_allocator *allocator,
- dng_abort_sniffer *sniffer);
-
- /// Process one tile or partitioned area. Should not be overridden. Instead,
- /// override ProcessArea, which is where to implement filter processing for a
- /// specific type of dng_filter_task. There is no allocator parameter as all
- /// allocation should be done in Start.
- ///
- /// \param threadIndex 0 to threadCount - 1 index indicating which thread
- /// this is. (Can be used to get a thread-specific buffer allocated in the
- /// Start method.)
- ///
- /// \param area Size of tiles to be used for sizing buffers, etc. (Edges of
- /// processing can be smaller.)
- ///
- /// \param sniffer dng_abort_sniffer to use to check for user cancellation
- /// and progress updates.
-
- virtual void Process (uint32 threadIndex,
- const dng_rect &area,
- dng_abort_sniffer *sniffer);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_filter_task.h#2 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Specialization of dng_area_task for processing an area from one dng_image to an
+ * area of another.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_filter_task__
+#define __dng_filter_task__
+
+/*****************************************************************************/
+
+#include "dng_area_task.h"
+#include "dng_auto_ptr.h"
+#include "dng_point.h"
+#include "dng_rect.h"
+#include "dng_sdk_limits.h"
+
+/*****************************************************************************/
+
+/// \brief Represents a task which filters an area of a source dng_image to an area
+/// of a destination dng_image.
+
+class dng_filter_task: public dng_area_task
+ {
+
+ protected:
+
+ const dng_image &fSrcImage;
+
+ dng_image &fDstImage;
+
+ uint32 fSrcPlane;
+ uint32 fSrcPlanes;
+ uint32 fSrcPixelType;
+
+ uint32 fDstPlane;
+ uint32 fDstPlanes;
+ uint32 fDstPixelType;
+
+ dng_point fSrcRepeat;
+ dng_point fSrcTileSize;
+
+ AutoPtr<dng_memory_block> fSrcBuffer [kMaxMPThreads];
+ AutoPtr<dng_memory_block> fDstBuffer [kMaxMPThreads];
+
+ public:
+
+ /// Construct a filter task given a source and destination images.
+ /// \param srcImage Image from which source pixels are read.
+ /// \param dstImage Image to which result pixels are written.
+
+ dng_filter_task (const dng_image &srcImage,
+ dng_image &dstImage);
+
+ virtual ~dng_filter_task ();
+
+ /// Compute the source area needed for a given destination area. Default
+ /// implementation assumes destination area is equal to source area for all
+ /// cases.
+ ///
+ /// \param dstArea Area to for which pixels will be computed.
+ ///
+ /// \retval The source area needed as input to calculate the requested
+ /// destination area.
+
+ virtual dng_rect SrcArea (const dng_rect &dstArea)
+ {
+ return dstArea;
+ }
+
+ /// Given a destination tile size, calculate input tile size. Simlar to
+ /// SrcArea, and should seldom be overridden.
+ ///
+ /// \param dstTileSize The destination tile size that is targeted for output.
+ ///
+ /// \retval The source tile size needed to compute a tile of the destination
+ /// size.
+
+ virtual dng_point SrcTileSize (const dng_point &dstTileSize)
+ {
+ return SrcArea (dng_rect (dstTileSize)).Size ();
+ }
+
+ /// Implements filtering operation from one buffer to another. Source and
+ /// destination pixels are set up in member fields of this class. Ideally, no
+ /// allocation should be done in this routine.
+ ///
+ /// \param threadIndex The thread on which this routine is being called,
+ /// between 0 and threadCount - 1 for the threadCount passed to Start method.
+ ///
+ /// \param srcBuffer Input area and source pixels.
+ ///
+ /// \param dstBuffer Output area and destination pixels.
+
+ virtual void ProcessArea (uint32 threadIndex,
+ dng_pixel_buffer &srcBuffer,
+ dng_pixel_buffer &dstBuffer) = 0;
+
+ /// Called prior to processing on specific threads. Can be used to allocate
+ /// per-thread memory buffers, etc.
+ ///
+ /// \param threadCount Total number of threads that will be used for
+ /// processing. Less than or equal to MaxThreads of dng_area_task.
+ ///
+ /// \param tileSize Size of source tiles which will be processed. (Not all
+ /// tiles will be this size due to edge conditions.)
+ ///
+ /// \param allocator dng_memory_allocator to use for allocating temporary
+ /// buffers, etc.
+ ///
+ /// \param sniffer Sniffer to test for user cancellation and to set up
+ /// progress.
+
+ virtual void Start (uint32 threadCount,
+ const dng_point &tileSize,
+ dng_memory_allocator *allocator,
+ dng_abort_sniffer *sniffer);
+
+ /// Process one tile or partitioned area. Should not be overridden. Instead,
+ /// override ProcessArea, which is where to implement filter processing for a
+ /// specific type of dng_filter_task. There is no allocator parameter as all
+ /// allocation should be done in Start.
+ ///
+ /// \param threadIndex 0 to threadCount - 1 index indicating which thread
+ /// this is. (Can be used to get a thread-specific buffer allocated in the
+ /// Start method.)
+ ///
+ /// \param area Size of tiles to be used for sizing buffers, etc. (Edges of
+ /// processing can be smaller.)
+ ///
+ /// \param sniffer dng_abort_sniffer to use to check for user cancellation
+ /// and progress updates.
+
+ virtual void Process (uint32 threadIndex,
+ const dng_rect &area,
+ dng_abort_sniffer *sniffer);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_fingerprint.cpp b/source/dng_fingerprint.cpp
index e31787e..141b712 100644
--- a/source/dng_fingerprint.cpp
+++ b/source/dng_fingerprint.cpp
@@ -1,594 +1,594 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_fingerprint.cpp#3 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_fingerprint.h"
-
-#include "dng_assertions.h"
-#include "dng_flags.h"
-
-/*****************************************************************************/
-
-dng_fingerprint::dng_fingerprint ()
- {
-
- for (uint32 j = 0; j < 16; j++)
- {
-
- data [j] = 0;
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_fingerprint::IsNull () const
- {
-
- for (uint32 j = 0; j < 16; j++)
- {
-
- if (data [j] != 0)
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool dng_fingerprint::operator== (const dng_fingerprint &print) const
- {
-
- for (uint32 j = 0; j < 16; j++)
- {
-
- if (data [j] != print.data [j])
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/******************************************************************************/
-
-uint32 dng_fingerprint::Collapse32 () const
- {
-
- uint32 x = 0;
-
- for (uint32 j = 0; j < 4; j++)
- {
-
- uint32 y = 0;
-
- for (uint32 k = 0; k < 4; k++)
- {
-
- y = (y << 8) + (uint32) data [j * 4 + k];
-
- }
-
- x = x ^ y;
-
- }
-
- return x;
-
- }
-
-/******************************************************************************/
-
-static char NumToHexChar (unsigned int c)
- {
-
- if (c < 10)
- {
- return (char) ('0' + c);
- }
-
- else
- {
- return (char) ('A' + c - 10);
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_fingerprint::ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const
- {
-
- for (size_t i = 0; i < kDNGFingerprintSize; i++)
- {
-
- unsigned char c = data [i];
-
- resultStr [i * 2] = NumToHexChar (c >> 4);
- resultStr [i * 2 + 1] = NumToHexChar (c & 15);
-
- }
-
- resultStr [kDNGFingerprintSize * 2] = '\0';
-
- }
-
-/******************************************************************************/
-
-static int HexCharToNum (char hexChar)
- {
-
- if (hexChar >= '0' && hexChar <= '9')
- {
- return hexChar - '0';
- }
-
- else if (hexChar >= 'A' && hexChar <= 'F')
- {
- return hexChar - 'A' + 10;
- }
-
- else if (hexChar >= 'a' && hexChar <= 'f')
- {
- return hexChar - 'a' + 10;
- }
-
- return -1;
-
- }
-
-/*****************************************************************************/
-
-bool dng_fingerprint::FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1])
- {
-
- for (size_t i = 0; i < kDNGFingerprintSize; i++)
- {
-
- int highNibble = HexCharToNum (inputStr [i * 2]);
-
- if (highNibble < 0)
- {
- return false;
- }
-
- int lowNibble = HexCharToNum (inputStr [i * 2 + 1]);
-
- if (lowNibble < 0)
- {
- return false;
- }
-
- data [i] = (uint8) ((highNibble << 4) + lowNibble);
-
- }
-
- return true;
-
- }
-
-/******************************************************************************/
-
-// Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
-
-// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-// rights reserved.
-//
-// License to copy and use this software is granted provided that it
-// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-// Algorithm" in all material mentioning or referencing this software
-// or this function.
-//
-// License is also granted to make and use derivative works provided
-// that such works are identified as "derived from the RSA Data
-// Security, Inc. MD5 Message-Digest Algorithm" in all material
-// mentioning or referencing the derived work.
-//
-// RSA Data Security, Inc. makes no representations concerning either
-// the merchantability of this software or the suitability of this
-// software for any particular purpose. It is provided "as is"
-// without express or implied warranty of any kind.
-//
-// These notices must be retained in any copies of any part of this
-// documentation and/or software.
-
-/******************************************************************************/
-
-dng_md5_printer::dng_md5_printer ()
-
- : final (false)
- , result ()
-
- {
-
- Reset ();
-
- }
-
-/******************************************************************************/
-
-void dng_md5_printer::Reset ()
- {
-
- // No bits processed yet.
-
- count [0] = 0;
- count [1] = 0;
-
- // Load magic initialization constants.
-
- state [0] = 0x67452301;
- state [1] = 0xefcdab89;
- state [2] = 0x98badcfe;
- state [3] = 0x10325476;
-
- // Not finalized yet.
-
- final = false;
-
- }
-
-/******************************************************************************/
-
-void dng_md5_printer::Process (const void *data,
- uint32 inputLen)
- {
-
- DNG_ASSERT (!final, "Fingerprint already finalized!");
-
- const uint8 *input = (const uint8 *) data;
-
- // Compute number of bytes mod 64
-
- uint32 index = (count [0] >> 3) & 0x3F;
-
- // Update number of bits
-
- if ((count [0] += inputLen << 3) < (inputLen << 3))
- {
- count [1]++;
- }
-
- count [1] += inputLen >> 29;
-
- // Transform as many times as possible.
-
- uint32 i = 0;
-
- uint32 partLen = 64 - index;
-
- if (inputLen >= partLen)
- {
-
- memcpy (&buffer [index],
- input,
- partLen);
-
- MD5Transform (state, buffer);
-
- for (i = partLen; i + 63 < inputLen; i += 64)
- {
-
- MD5Transform (state, &input [i]);
-
- }
-
- index = 0;
-
- }
-
- // Buffer remaining input
-
- memcpy (&buffer [index],
- &input [i],
- inputLen - i);
-
- }
-
-/******************************************************************************/
-
-const dng_fingerprint & dng_md5_printer::Result ()
- {
-
- if (!final)
- {
-
- static uint8 PADDING [64] =
- {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- };
-
- // Save number of bits
-
- uint8 bits [8];
-
- Encode (bits, count, 8);
-
- // Pad out to 56 mod 64.
-
- uint32 index = (count [0] >> 3) & 0x3f;
-
- uint32 padLen = (index < 56) ? (56 - index) : (120 - index);
-
- Process (PADDING, padLen);
-
- // Append length (before padding)
-
- Process (bits, 8);
-
- // Store state in digest
-
- Encode (result.data, state, 16);
-
- // We are now finalized.
-
- final = true;
-
- }
-
- return result;
-
- }
-
-/******************************************************************************/
-
-// Encodes input (uint32) into output (uint8). Assumes len is
-// a multiple of 4.
-
-void dng_md5_printer::Encode (uint8 *output,
- const uint32 *input,
- uint32 len)
- {
-
- uint32 i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- {
- output [j ] = (uint8) ((input [i] ) & 0xff);
- output [j+1] = (uint8) ((input [i] >> 8) & 0xff);
- output [j+2] = (uint8) ((input [i] >> 16) & 0xff);
- output [j+3] = (uint8) ((input [i] >> 24) & 0xff);
- }
-
- }
-
-/******************************************************************************/
-
-// Decodes input (uint8) into output (uint32). Assumes len is
-// a multiple of 4.
-
-void dng_md5_printer::Decode (uint32 *output,
- const uint8 *input,
- uint32 len)
- {
-
- // Check for non-aligned case.
-
- if (((uintptr) input) & 3)
- {
-
- uint32 i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- {
-
- output [i] = (((uint32) input [j ]) ) |
- (((uint32) input [j+1]) << 8) |
- (((uint32) input [j+2]) << 16) |
- (((uint32) input [j+3]) << 24);
-
- }
-
- }
-
- // Else use optimized code for aligned case.
-
- else
- {
-
- len = len >> 2;
-
- const uint32 *sPtr = (const uint32 *) input;
-
- uint32 *dPtr = output;
-
- while (len--)
- {
-
- #if qDNGBigEndian
-
- uint32 data = *(sPtr++);
-
- data = (data >> 24) |
- ((data >> 8) & 0x0000FF00) |
- ((data << 8) & 0x00FF0000) |
- (data << 24);
-
- *(dPtr++) = data;
-
- #else
-
- *(dPtr++) = *(sPtr++);
-
- #endif
-
- }
-
- }
-
- }
-
-/******************************************************************************/
-
-// MD5 basic transformation. Transforms state based on block.
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-void dng_md5_printer::MD5Transform (uint32 state [4],
- const uint8 block [64])
- {
-
- enum
- {
- S11 = 7,
- S12 = 12,
- S13 = 17,
- S14 = 22,
- S21 = 5,
- S22 = 9,
- S23 = 14,
- S24 = 20,
- S31 = 4,
- S32 = 11,
- S33 = 16,
- S34 = 23,
- S41 = 6,
- S42 = 10,
- S43 = 15,
- S44 = 21
- };
-
- #if qDNGBigEndian
-
- uint32 x [16];
-
- Decode (x, block, 64);
-
- #else
-
- uint32 temp [16];
-
- const uint32 *x;
-
- if (((uintptr) block) & 3)
- {
-
- Decode (temp, block, 64);
-
- x = temp;
-
- }
-
- else
- x = (const uint32 *) block;
-
- #endif
-
- uint32 a = state [0];
- uint32 b = state [1];
- uint32 c = state [2];
- uint32 d = state [3];
-
- /* Round 1 */
- FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
- FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
- FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
- FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
- FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
- FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
- FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
- FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
- FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
- FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
- FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
- FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
- FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
- FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
- FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
- FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
- GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
- GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
- GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
- GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
- GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
- GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
- GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
- GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
- GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
- GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
- GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
- GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
- GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
- GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
- GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
- GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
- /* Round 3 */
- HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
- HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
- HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
- HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
- HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
- HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
- HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
- HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
- HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
- HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
- HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
- HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
- HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
- HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
- HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
- HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
- /* Round 4 */
- II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
- II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
- II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
- II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
- II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
- II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
- II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
- II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
- II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
- II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
- II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
- II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
- II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
- II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
- II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
- II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-
- state [0] += a;
- state [1] += b;
- state [2] += c;
- state [3] += d;
-
- }
-
-/*****************************************************************************/
-
-// End of RSA Data Security, Inc. derived code.
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_fingerprint.cpp#3 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_fingerprint.h"
+
+#include "dng_assertions.h"
+#include "dng_flags.h"
+
+/*****************************************************************************/
+
+dng_fingerprint::dng_fingerprint ()
+ {
+
+ for (uint32 j = 0; j < 16; j++)
+ {
+
+ data [j] = 0;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_fingerprint::IsNull () const
+ {
+
+ for (uint32 j = 0; j < 16; j++)
+ {
+
+ if (data [j] != 0)
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_fingerprint::operator== (const dng_fingerprint &print) const
+ {
+
+ for (uint32 j = 0; j < 16; j++)
+ {
+
+ if (data [j] != print.data [j])
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+uint32 dng_fingerprint::Collapse32 () const
+ {
+
+ uint32 x = 0;
+
+ for (uint32 j = 0; j < 4; j++)
+ {
+
+ uint32 y = 0;
+
+ for (uint32 k = 0; k < 4; k++)
+ {
+
+ y = (y << 8) + (uint32) data [j * 4 + k];
+
+ }
+
+ x = x ^ y;
+
+ }
+
+ return x;
+
+ }
+
+/******************************************************************************/
+
+static char NumToHexChar (unsigned int c)
+ {
+
+ if (c < 10)
+ {
+ return (char) ('0' + c);
+ }
+
+ else
+ {
+ return (char) ('A' + c - 10);
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_fingerprint::ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const
+ {
+
+ for (size_t i = 0; i < kDNGFingerprintSize; i++)
+ {
+
+ unsigned char c = data [i];
+
+ resultStr [i * 2] = NumToHexChar (c >> 4);
+ resultStr [i * 2 + 1] = NumToHexChar (c & 15);
+
+ }
+
+ resultStr [kDNGFingerprintSize * 2] = '\0';
+
+ }
+
+/******************************************************************************/
+
+static int HexCharToNum (char hexChar)
+ {
+
+ if (hexChar >= '0' && hexChar <= '9')
+ {
+ return hexChar - '0';
+ }
+
+ else if (hexChar >= 'A' && hexChar <= 'F')
+ {
+ return hexChar - 'A' + 10;
+ }
+
+ else if (hexChar >= 'a' && hexChar <= 'f')
+ {
+ return hexChar - 'a' + 10;
+ }
+
+ return -1;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_fingerprint::FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1])
+ {
+
+ for (size_t i = 0; i < kDNGFingerprintSize; i++)
+ {
+
+ int highNibble = HexCharToNum (inputStr [i * 2]);
+
+ if (highNibble < 0)
+ {
+ return false;
+ }
+
+ int lowNibble = HexCharToNum (inputStr [i * 2 + 1]);
+
+ if (lowNibble < 0)
+ {
+ return false;
+ }
+
+ data [i] = (uint8) ((highNibble << 4) + lowNibble);
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+// Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
+
+// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+// rights reserved.
+//
+// License to copy and use this software is granted provided that it
+// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+// Algorithm" in all material mentioning or referencing this software
+// or this function.
+//
+// License is also granted to make and use derivative works provided
+// that such works are identified as "derived from the RSA Data
+// Security, Inc. MD5 Message-Digest Algorithm" in all material
+// mentioning or referencing the derived work.
+//
+// RSA Data Security, Inc. makes no representations concerning either
+// the merchantability of this software or the suitability of this
+// software for any particular purpose. It is provided "as is"
+// without express or implied warranty of any kind.
+//
+// These notices must be retained in any copies of any part of this
+// documentation and/or software.
+
+/******************************************************************************/
+
+dng_md5_printer::dng_md5_printer ()
+
+ : final (false)
+ , result ()
+
+ {
+
+ Reset ();
+
+ }
+
+/******************************************************************************/
+
+void dng_md5_printer::Reset ()
+ {
+
+ // No bits processed yet.
+
+ count [0] = 0;
+ count [1] = 0;
+
+ // Load magic initialization constants.
+
+ state [0] = 0x67452301;
+ state [1] = 0xefcdab89;
+ state [2] = 0x98badcfe;
+ state [3] = 0x10325476;
+
+ // Not finalized yet.
+
+ final = false;
+
+ }
+
+/******************************************************************************/
+
+void dng_md5_printer::Process (const void *data,
+ uint32 inputLen)
+ {
+
+ DNG_ASSERT (!final, "Fingerprint already finalized!");
+
+ const uint8 *input = (const uint8 *) data;
+
+ // Compute number of bytes mod 64
+
+ uint32 index = (count [0] >> 3) & 0x3F;
+
+ // Update number of bits
+
+ if ((count [0] += inputLen << 3) < (inputLen << 3))
+ {
+ count [1]++;
+ }
+
+ count [1] += inputLen >> 29;
+
+ // Transform as many times as possible.
+
+ uint32 i = 0;
+
+ uint32 partLen = 64 - index;
+
+ if (inputLen >= partLen)
+ {
+
+ memcpy (&buffer [index],
+ input,
+ partLen);
+
+ MD5Transform (state, buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ {
+
+ MD5Transform (state, &input [i]);
+
+ }
+
+ index = 0;
+
+ }
+
+ // Buffer remaining input
+
+ memcpy (&buffer [index],
+ &input [i],
+ inputLen - i);
+
+ }
+
+/******************************************************************************/
+
+const dng_fingerprint & dng_md5_printer::Result ()
+ {
+
+ if (!final)
+ {
+
+ static uint8 PADDING [64] =
+ {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+ // Save number of bits
+
+ uint8 bits [8];
+
+ Encode (bits, count, 8);
+
+ // Pad out to 56 mod 64.
+
+ uint32 index = (count [0] >> 3) & 0x3f;
+
+ uint32 padLen = (index < 56) ? (56 - index) : (120 - index);
+
+ Process (PADDING, padLen);
+
+ // Append length (before padding)
+
+ Process (bits, 8);
+
+ // Store state in digest
+
+ Encode (result.data, state, 16);
+
+ // We are now finalized.
+
+ final = true;
+
+ }
+
+ return result;
+
+ }
+
+/******************************************************************************/
+
+// Encodes input (uint32) into output (uint8). Assumes len is
+// a multiple of 4.
+
+void dng_md5_printer::Encode (uint8 *output,
+ const uint32 *input,
+ uint32 len)
+ {
+
+ uint32 i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ {
+ output [j ] = (uint8) ((input [i] ) & 0xff);
+ output [j+1] = (uint8) ((input [i] >> 8) & 0xff);
+ output [j+2] = (uint8) ((input [i] >> 16) & 0xff);
+ output [j+3] = (uint8) ((input [i] >> 24) & 0xff);
+ }
+
+ }
+
+/******************************************************************************/
+
+// Decodes input (uint8) into output (uint32). Assumes len is
+// a multiple of 4.
+
+void dng_md5_printer::Decode (uint32 *output,
+ const uint8 *input,
+ uint32 len)
+ {
+
+ // Check for non-aligned case.
+
+ if (((uintptr) input) & 3)
+ {
+
+ uint32 i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ {
+
+ output [i] = (((uint32) input [j ]) ) |
+ (((uint32) input [j+1]) << 8) |
+ (((uint32) input [j+2]) << 16) |
+ (((uint32) input [j+3]) << 24);
+
+ }
+
+ }
+
+ // Else use optimized code for aligned case.
+
+ else
+ {
+
+ len = len >> 2;
+
+ const uint32 *sPtr = (const uint32 *) input;
+
+ uint32 *dPtr = output;
+
+ while (len--)
+ {
+
+ #if qDNGBigEndian
+
+ uint32 data = *(sPtr++);
+
+ data = (data >> 24) |
+ ((data >> 8) & 0x0000FF00) |
+ ((data << 8) & 0x00FF0000) |
+ (data << 24);
+
+ *(dPtr++) = data;
+
+ #else
+
+ *(dPtr++) = *(sPtr++);
+
+ #endif
+
+ }
+
+ }
+
+ }
+
+/******************************************************************************/
+
+// MD5 basic transformation. Transforms state based on block.
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+void dng_md5_printer::MD5Transform (uint32 state [4],
+ const uint8 block [64])
+ {
+
+ enum
+ {
+ S11 = 7,
+ S12 = 12,
+ S13 = 17,
+ S14 = 22,
+ S21 = 5,
+ S22 = 9,
+ S23 = 14,
+ S24 = 20,
+ S31 = 4,
+ S32 = 11,
+ S33 = 16,
+ S34 = 23,
+ S41 = 6,
+ S42 = 10,
+ S43 = 15,
+ S44 = 21
+ };
+
+ #if qDNGBigEndian
+
+ uint32 x [16];
+
+ Decode (x, block, 64);
+
+ #else
+
+ uint32 temp [16];
+
+ const uint32 *x;
+
+ if (((uintptr) block) & 3)
+ {
+
+ Decode (temp, block, 64);
+
+ x = temp;
+
+ }
+
+ else
+ x = (const uint32 *) block;
+
+ #endif
+
+ uint32 a = state [0];
+ uint32 b = state [1];
+ uint32 c = state [2];
+ uint32 d = state [3];
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
+ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+ state [0] += a;
+ state [1] += b;
+ state [2] += c;
+ state [3] += d;
+
+ }
+
+/*****************************************************************************/
+
+// End of RSA Data Security, Inc. derived code.
+
+/*****************************************************************************/
diff --git a/source/dng_fingerprint.h b/source/dng_fingerprint.h
index bafcff5..74830e9 100644
--- a/source/dng_fingerprint.h
+++ b/source/dng_fingerprint.h
@@ -1,397 +1,397 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_fingerprint.h#2 $ */
-/* $DateTime: 2012/07/11 10:36:56 $ */
-/* $Change: 838485 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Fingerprint (cryptographic hashing) support for generating strong hashes of image
- * data.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_fingerprint__
-#define __dng_fingerprint__
-
-/*****************************************************************************/
-
-#include "dng_exceptions.h"
-#include "dng_types.h"
-#include "dng_stream.h"
-
-#include <cstring>
-
-/*****************************************************************************/
-
-/// \brief Container fingerprint (MD5 only at present).
-
-class dng_fingerprint
- {
-
- public:
-
- static const size_t kDNGFingerprintSize = 16;
-
- uint8 data [kDNGFingerprintSize];
-
- public:
-
- dng_fingerprint ();
-
- /// Check if fingerprint is all zeros.
-
- bool IsNull () const;
-
- /// Same as IsNull but expresses intention of testing validity.
-
- bool IsValid () const
- {
- return !IsNull ();
- }
-
- /// Set to all zeros, a value used to indicate an invalid fingerprint.
-
- void Clear ()
- {
- *this = dng_fingerprint ();
- }
-
- /// Test if two fingerprints are equal.
-
- bool operator== (const dng_fingerprint &print) const;
-
- /// Test if two fingerprints are not equal.
-
- bool operator!= (const dng_fingerprint &print) const
- {
- return !(*this == print);
- }
-
- /// Produce a 32-bit hash value from fingerprint used for faster hashing of
- /// fingerprints.
-
- uint32 Collapse32 () const;
-
- /// Convert fingerprint to UTF-8 string.
- ///
- /// \param resultStr The output array to which the UTF-8 encoding of the
- /// fingerprint will be written.
-
- void ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const;
-
- /// Convert UTF-8 string to fingerprint. Returns true on success, false on
- /// failure.
- ///
- /// \param inputStr The input array from which the UTF-8 encoding of the
- /// fingerprint will be read.
- ///
- /// \retval True indicates success.
-
- bool FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1]);
-
- };
-
-/*****************************************************************************/
-
-/// \brief Utility to compare fingerprints (e.g., for sorting).
-
-struct dng_fingerprint_less_than
- {
-
- /// Less-than comparison.
-
- bool operator() (const dng_fingerprint &a,
- const dng_fingerprint &b) const
- {
-
- return memcmp (a.data,
- b.data,
- sizeof (a.data)) < 0;
-
- }
-
- };
-
-/******************************************************************************/
-
-// Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
-
-// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-// rights reserved.
-//
-// License to copy and use this software is granted provided that it
-// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-// Algorithm" in all material mentioning or referencing this software
-// or this function.
-//
-// License is also granted to make and use derivative works provided
-// that such works are identified as "derived from the RSA Data
-// Security, Inc. MD5 Message-Digest Algorithm" in all material
-// mentioning or referencing the derived work.
-//
-// RSA Data Security, Inc. makes no representations concerning either
-// the merchantability of this software or the suitability of this
-// software for any particular purpose. It is provided "as is"
-// without express or implied warranty of any kind.
-//
-// These notices must be retained in any copies of any part of this
-// documentation and/or software.
-
-/// \brief Class to hash binary data to a fingerprint using the MD5 Message-Digest
-/// Algorithm.
-
-class dng_md5_printer
- {
-
- public:
-
- dng_md5_printer ();
-
- virtual ~dng_md5_printer ()
- {
- }
-
- /// Reset the fingerprint.
-
- void Reset ();
-
- /// Append the data to the stream to be hashed.
- /// \param data The data to be hashed.
- /// \param inputLen The length of data, in bytes.
-
- void Process (const void *data,
- uint32 inputLen);
-
- /// Append the string to the stream to be hashed.
- /// \param text The string to be hashed.
-
- void Process (const char *text)
- {
-
- Process (text, (uint32) strlen (text));
-
- }
-
- /// Get the fingerprint (i.e., result of the hash).
-
- const dng_fingerprint & Result ();
-
- private:
-
- static void Encode (uint8 *output,
- const uint32 *input,
- uint32 len);
-
- static void Decode (uint32 *output,
- const uint8 *input,
- uint32 len);
-
- // F, G, H and I are basic MD5 functions.
-
- static inline uint32 F (uint32 x,
- uint32 y,
- uint32 z)
- {
- return (x & y) | (~x & z);
- }
-
- static inline uint32 G (uint32 x,
- uint32 y,
- uint32 z)
- {
- return (x & z) | (y & ~z);
- }
-
- static inline uint32 H (uint32 x,
- uint32 y,
- uint32 z)
- {
- return x ^ y ^ z;
- }
-
- static inline uint32 I (uint32 x,
- uint32 y,
- uint32 z)
- {
- return y ^ (x | ~z);
- }
-
- // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
- __attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
- static inline void FF (uint32 &a,
- uint32 b,
- uint32 c,
- uint32 d,
- uint32 x,
- uint32 s,
- uint32 ac)
- {
- a += F (b, c, d) + x + ac;
- a = (a << s) | (a >> (32 - s));
- a += b;
- }
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
- __attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
- static inline void GG (uint32 &a,
- uint32 b,
- uint32 c,
- uint32 d,
- uint32 x,
- uint32 s,
- uint32 ac)
- {
- a += G (b, c, d) + x + ac;
- a = (a << s) | (a >> (32 - s));
- a += b;
- }
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
- __attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
- static inline void HH (uint32 &a,
- uint32 b,
- uint32 c,
- uint32 d,
- uint32 x,
- uint32 s,
- uint32 ac)
- {
- a += H (b, c, d) + x + ac;
- a = (a << s) | (a >> (32 - s));
- a += b;
- }
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
- __attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
- static inline void II (uint32 &a,
- uint32 b,
- uint32 c,
- uint32 d,
- uint32 x,
- uint32 s,
- uint32 ac)
- {
- a += I (b, c, d) + x + ac;
- a = (a << s) | (a >> (32 - s));
- a += b;
- }
-
- static void MD5Transform (uint32 state [4],
- const uint8 block [64]);
-
- private:
-
- uint32 state [4];
-
- uint32 count [2];
-
- uint8 buffer [64];
-
- bool final;
-
- dng_fingerprint result;
-
- };
-
-/*****************************************************************************/
-
-/// \brief A dng_stream based interface to the MD5 printing logic.
-
-class dng_md5_printer_stream : public dng_stream, dng_md5_printer
- {
-
- private:
-
- uint64 fNextOffset;
-
- public:
-
- /// Create an empty MD5 printer stream.
-
- dng_md5_printer_stream ()
-
- : fNextOffset (0)
-
- {
- }
-
- virtual uint64 DoGetLength ()
- {
-
- return fNextOffset;
-
- }
-
- virtual void DoRead (void * /* data */,
- uint32 /* count */,
- uint64 /* offset */)
- {
-
- ThrowProgramError ();
-
- }
-
- virtual void DoSetLength (uint64 length)
- {
-
- if (length != fNextOffset)
- {
- ThrowProgramError ();
- }
-
- }
-
- virtual void DoWrite (const void *data,
- uint32 count2,
- uint64 offset)
- {
-
- if (offset != fNextOffset)
- {
- ThrowProgramError ();
- }
-
- Process (data, count2);
-
- fNextOffset += count2;
-
- }
-
- const dng_fingerprint & Result ()
- {
-
- Flush ();
-
- return dng_md5_printer::Result ();
-
- }
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_fingerprint.h#2 $ */
+/* $DateTime: 2012/07/11 10:36:56 $ */
+/* $Change: 838485 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Fingerprint (cryptographic hashing) support for generating strong hashes of image
+ * data.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_fingerprint__
+#define __dng_fingerprint__
+
+/*****************************************************************************/
+
+#include "dng_exceptions.h"
+#include "dng_types.h"
+#include "dng_stream.h"
+
+#include <cstring>
+
+/*****************************************************************************/
+
+/// \brief Container fingerprint (MD5 only at present).
+
+class dng_fingerprint
+ {
+
+ public:
+
+ static const size_t kDNGFingerprintSize = 16;
+
+ uint8 data [kDNGFingerprintSize];
+
+ public:
+
+ dng_fingerprint ();
+
+ /// Check if fingerprint is all zeros.
+
+ bool IsNull () const;
+
+ /// Same as IsNull but expresses intention of testing validity.
+
+ bool IsValid () const
+ {
+ return !IsNull ();
+ }
+
+ /// Set to all zeros, a value used to indicate an invalid fingerprint.
+
+ void Clear ()
+ {
+ *this = dng_fingerprint ();
+ }
+
+ /// Test if two fingerprints are equal.
+
+ bool operator== (const dng_fingerprint &print) const;
+
+ /// Test if two fingerprints are not equal.
+
+ bool operator!= (const dng_fingerprint &print) const
+ {
+ return !(*this == print);
+ }
+
+ /// Produce a 32-bit hash value from fingerprint used for faster hashing of
+ /// fingerprints.
+
+ uint32 Collapse32 () const;
+
+ /// Convert fingerprint to UTF-8 string.
+ ///
+ /// \param resultStr The output array to which the UTF-8 encoding of the
+ /// fingerprint will be written.
+
+ void ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const;
+
+ /// Convert UTF-8 string to fingerprint. Returns true on success, false on
+ /// failure.
+ ///
+ /// \param inputStr The input array from which the UTF-8 encoding of the
+ /// fingerprint will be read.
+ ///
+ /// \retval True indicates success.
+
+ bool FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1]);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Utility to compare fingerprints (e.g., for sorting).
+
+struct dng_fingerprint_less_than
+ {
+
+ /// Less-than comparison.
+
+ bool operator() (const dng_fingerprint &a,
+ const dng_fingerprint &b) const
+ {
+
+ return memcmp (a.data,
+ b.data,
+ sizeof (a.data)) < 0;
+
+ }
+
+ };
+
+/******************************************************************************/
+
+// Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm.
+
+// Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+// rights reserved.
+//
+// License to copy and use this software is granted provided that it
+// is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+// Algorithm" in all material mentioning or referencing this software
+// or this function.
+//
+// License is also granted to make and use derivative works provided
+// that such works are identified as "derived from the RSA Data
+// Security, Inc. MD5 Message-Digest Algorithm" in all material
+// mentioning or referencing the derived work.
+//
+// RSA Data Security, Inc. makes no representations concerning either
+// the merchantability of this software or the suitability of this
+// software for any particular purpose. It is provided "as is"
+// without express or implied warranty of any kind.
+//
+// These notices must be retained in any copies of any part of this
+// documentation and/or software.
+
+/// \brief Class to hash binary data to a fingerprint using the MD5 Message-Digest
+/// Algorithm.
+
+class dng_md5_printer
+ {
+
+ public:
+
+ dng_md5_printer ();
+
+ virtual ~dng_md5_printer ()
+ {
+ }
+
+ /// Reset the fingerprint.
+
+ void Reset ();
+
+ /// Append the data to the stream to be hashed.
+ /// \param data The data to be hashed.
+ /// \param inputLen The length of data, in bytes.
+
+ void Process (const void *data,
+ uint32 inputLen);
+
+ /// Append the string to the stream to be hashed.
+ /// \param text The string to be hashed.
+
+ void Process (const char *text)
+ {
+
+ Process (text, (uint32) strlen (text));
+
+ }
+
+ /// Get the fingerprint (i.e., result of the hash).
+
+ const dng_fingerprint & Result ();
+
+ private:
+
+ static void Encode (uint8 *output,
+ const uint32 *input,
+ uint32 len);
+
+ static void Decode (uint32 *output,
+ const uint8 *input,
+ uint32 len);
+
+ // F, G, H and I are basic MD5 functions.
+
+ static inline uint32 F (uint32 x,
+ uint32 y,
+ uint32 z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ static inline uint32 G (uint32 x,
+ uint32 y,
+ uint32 z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ static inline uint32 H (uint32 x,
+ uint32 y,
+ uint32 z)
+ {
+ return x ^ y ^ z;
+ }
+
+ static inline uint32 I (uint32 x,
+ uint32 y,
+ uint32 z)
+ {
+ return y ^ (x | ~z);
+ }
+
+ // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+ __attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+ static inline void FF (uint32 &a,
+ uint32 b,
+ uint32 c,
+ uint32 d,
+ uint32 x,
+ uint32 s,
+ uint32 ac)
+ {
+ a += F (b, c, d) + x + ac;
+ a = (a << s) | (a >> (32 - s));
+ a += b;
+ }
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+ __attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+ static inline void GG (uint32 &a,
+ uint32 b,
+ uint32 c,
+ uint32 d,
+ uint32 x,
+ uint32 s,
+ uint32 ac)
+ {
+ a += G (b, c, d) + x + ac;
+ a = (a << s) | (a >> (32 - s));
+ a += b;
+ }
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+ __attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+ static inline void HH (uint32 &a,
+ uint32 b,
+ uint32 c,
+ uint32 d,
+ uint32 x,
+ uint32 s,
+ uint32 ac)
+ {
+ a += H (b, c, d) + x + ac;
+ a = (a << s) | (a >> (32 - s));
+ a += b;
+ }
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+ __attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+ static inline void II (uint32 &a,
+ uint32 b,
+ uint32 c,
+ uint32 d,
+ uint32 x,
+ uint32 s,
+ uint32 ac)
+ {
+ a += I (b, c, d) + x + ac;
+ a = (a << s) | (a >> (32 - s));
+ a += b;
+ }
+
+ static void MD5Transform (uint32 state [4],
+ const uint8 block [64]);
+
+ private:
+
+ uint32 state [4];
+
+ uint32 count [2];
+
+ uint8 buffer [64];
+
+ bool final;
+
+ dng_fingerprint result;
+
+ };
+
+/*****************************************************************************/
+
+/// \brief A dng_stream based interface to the MD5 printing logic.
+
+class dng_md5_printer_stream : public dng_stream, dng_md5_printer
+ {
+
+ private:
+
+ uint64 fNextOffset;
+
+ public:
+
+ /// Create an empty MD5 printer stream.
+
+ dng_md5_printer_stream ()
+
+ : fNextOffset (0)
+
+ {
+ }
+
+ virtual uint64 DoGetLength ()
+ {
+
+ return fNextOffset;
+
+ }
+
+ virtual void DoRead (void * /* data */,
+ uint32 /* count */,
+ uint64 /* offset */)
+ {
+
+ ThrowProgramError ();
+
+ }
+
+ virtual void DoSetLength (uint64 length)
+ {
+
+ if (length != fNextOffset)
+ {
+ ThrowProgramError ();
+ }
+
+ }
+
+ virtual void DoWrite (const void *data,
+ uint32 count2,
+ uint64 offset)
+ {
+
+ if (offset != fNextOffset)
+ {
+ ThrowProgramError ();
+ }
+
+ Process (data, count2);
+
+ fNextOffset += count2;
+
+ }
+
+ const dng_fingerprint & Result ()
+ {
+
+ Flush ();
+
+ return dng_md5_printer::Result ();
+
+ }
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_gain_map.cpp b/source/dng_gain_map.cpp
index 2638efd..489fca0 100644
--- a/source/dng_gain_map.cpp
+++ b/source/dng_gain_map.cpp
@@ -1,604 +1,604 @@
-/*****************************************************************************/
-// Copyright 2008-2009 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_gain_map.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_gain_map.h"
-
-#include "dng_exceptions.h"
-#include "dng_globals.h"
-#include "dng_host.h"
-#include "dng_pixel_buffer.h"
-#include "dng_stream.h"
-#include "dng_tag_values.h"
-
-/*****************************************************************************/
-
-class dng_gain_map_interpolator
- {
-
- private:
-
- const dng_gain_map &fMap;
-
- dng_point_real64 fScale;
- dng_point_real64 fOffset;
-
- int32 fColumn;
- int32 fPlane;
-
- uint32 fRowIndex1;
- uint32 fRowIndex2;
- real32 fRowFract;
-
- int32 fResetColumn;
-
- real32 fValueBase;
- real32 fValueStep;
- real32 fValueIndex;
-
- public:
-
- dng_gain_map_interpolator (const dng_gain_map &map,
- const dng_rect &mapBounds,
- int32 row,
- int32 column,
- uint32 plane);
-
- real32 Interpolate () const
- {
-
- return fValueBase + fValueStep * fValueIndex;
-
- }
-
- void Increment ()
- {
-
- if (++fColumn >= fResetColumn)
- {
-
- ResetColumn ();
-
- }
-
- else
- {
-
- fValueIndex += 1.0f;
-
- }
-
- }
-
- private:
-
- real32 InterpolateEntry (uint32 colIndex);
-
- void ResetColumn ();
-
- };
-
-/*****************************************************************************/
-
-dng_gain_map_interpolator::dng_gain_map_interpolator (const dng_gain_map &map,
- const dng_rect &mapBounds,
- int32 row,
- int32 column,
- uint32 plane)
-
- : fMap (map)
-
- , fScale (1.0 / mapBounds.H (),
- 1.0 / mapBounds.W ())
-
- , fOffset (0.5 - mapBounds.t,
- 0.5 - mapBounds.l)
-
- , fColumn (column)
- , fPlane (plane)
-
- , fRowIndex1 (0)
- , fRowIndex2 (0)
- , fRowFract (0.0f)
-
- , fResetColumn (0)
-
- , fValueBase (0.0f)
- , fValueStep (0.0f)
- , fValueIndex (0.0f)
-
- {
-
- real64 rowIndexF = (fScale.v * (row + fOffset.v) -
- fMap.Origin ().v) / fMap.Spacing ().v;
-
- if (rowIndexF <= 0.0)
- {
-
- fRowIndex1 = 0;
- fRowIndex2 = 0;
-
- fRowFract = 0.0f;
-
- }
-
- else
- {
-
- if (fMap.Points ().v < 1)
- {
- ThrowProgramError ("Empty gain map");
- }
- uint32 lastRow = static_cast<uint32> (fMap.Points ().v - 1);
-
- if (rowIndexF >= static_cast<real64> (lastRow))
- {
-
- fRowIndex1 = lastRow;
- fRowIndex2 = fRowIndex1;
-
- fRowFract = 0.0f;
-
- }
-
- else
- {
-
- // If we got here, we know that rowIndexF can safely be converted to
- // a uint32 and that static_cast<uint32> (rowIndexF) < lastRow. This
- // implies fRowIndex2 <= lastRow below.
- fRowIndex1 = static_cast<uint32> (rowIndexF);
- fRowIndex2 = fRowIndex1 + 1;
-
- fRowFract = (real32) (rowIndexF - (real64) fRowIndex1);
-
- }
-
- }
-
- ResetColumn ();
-
- }
-
-/*****************************************************************************/
-
-real32 dng_gain_map_interpolator::InterpolateEntry (uint32 colIndex)
- {
-
- return fMap.Entry (fRowIndex1, colIndex, fPlane) * (1.0f - fRowFract) +
- fMap.Entry (fRowIndex2, colIndex, fPlane) * ( fRowFract);
-
- }
-
-/*****************************************************************************/
-
-void dng_gain_map_interpolator::ResetColumn ()
- {
-
- real64 colIndexF = ((fScale.h * (fColumn + fOffset.h)) -
- fMap.Origin ().h) / fMap.Spacing ().h;
-
- if (colIndexF <= 0.0)
- {
-
- fValueBase = InterpolateEntry (0);
-
- fValueStep = 0.0f;
-
- fResetColumn = (int32) ceil (fMap.Origin ().h / fScale.h - fOffset.h);
-
- }
-
- else
- {
-
- if (fMap.Points ().h < 1)
- {
- ThrowProgramError ("Empty gain map");
- }
- uint32 lastCol = static_cast<uint32> (fMap.Points ().h - 1);
-
- if (colIndexF >= static_cast<real64> (lastCol))
- {
-
- fValueBase = InterpolateEntry (lastCol);
-
- fValueStep = 0.0f;
-
- fResetColumn = 0x7FFFFFFF;
-
- }
-
- else
- {
-
- // If we got here, we know that colIndexF can safely be converted to
- // a uint32 and that static_cast<uint32> (colIndexF) < lastCol. This
- // implies colIndex + 1 <= lastCol, i.e. the argument to
- // InterpolateEntry() below is valid.
- uint32 colIndex = static_cast<uint32> (colIndexF);
- real64 base = InterpolateEntry (colIndex);
- real64 delta = InterpolateEntry (colIndex + 1) - base;
-
- fValueBase = (real32) (base + delta * (colIndexF - (real64) colIndex));
-
- fValueStep = (real32) ((delta * fScale.h) / fMap.Spacing ().h);
-
- fResetColumn = (int32) ceil (((colIndex + 1) * fMap.Spacing ().h +
- fMap.Origin ().h) / fScale.h - fOffset.h);
-
- }
-
- }
-
- fValueIndex = 0.0f;
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-dng_gain_map::dng_gain_map (dng_memory_allocator &allocator,
- const dng_point &points,
- const dng_point_real64 &spacing,
- const dng_point_real64 &origin,
- uint32 planes)
-
- : fPoints (points)
- , fSpacing (spacing)
- , fOrigin (origin)
- , fPlanes (planes)
-
- , fRowStep (planes * points.h)
-
- , fBuffer ()
-
- {
-
- fBuffer.Reset (allocator.Allocate (
- ComputeBufferSize (ttFloat, fPoints, fPlanes, pad16Bytes)));
-
- }
-
-/*****************************************************************************/
-
-real32 dng_gain_map::Interpolate (int32 row,
- int32 col,
- uint32 plane,
- const dng_rect &bounds) const
- {
-
- dng_gain_map_interpolator interp (*this,
- bounds,
- row,
- col,
- plane);
-
- return interp.Interpolate ();
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_gain_map::PutStreamSize () const
- {
-
- return 44 + fPoints.v * fPoints.h * fPlanes * 4;
-
- }
-
-/*****************************************************************************/
-
-void dng_gain_map::PutStream (dng_stream &stream) const
- {
-
- stream.Put_uint32 (fPoints.v);
- stream.Put_uint32 (fPoints.h);
-
- stream.Put_real64 (fSpacing.v);
- stream.Put_real64 (fSpacing.h);
-
- stream.Put_real64 (fOrigin.v);
- stream.Put_real64 (fOrigin.h);
-
- stream.Put_uint32 (fPlanes);
-
- for (int32 rowIndex = 0; rowIndex < fPoints.v; rowIndex++)
- {
-
- for (int32 colIndex = 0; colIndex < fPoints.h; colIndex++)
- {
-
- for (uint32 plane = 0; plane < fPlanes; plane++)
- {
-
- stream.Put_real32 (Entry (rowIndex,
- colIndex,
- plane));
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_gain_map * dng_gain_map::GetStream (dng_host &host,
- dng_stream &stream)
- {
-
- dng_point mapPoints;
-
- mapPoints.v = stream.Get_uint32 ();
- mapPoints.h = stream.Get_uint32 ();
-
- dng_point_real64 mapSpacing;
-
- mapSpacing.v = stream.Get_real64 ();
- mapSpacing.h = stream.Get_real64 ();
-
- dng_point_real64 mapOrigin;
-
- mapOrigin.v = stream.Get_real64 ();
- mapOrigin.h = stream.Get_real64 ();
-
- uint32 mapPlanes = stream.Get_uint32 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Points: v=%d, h=%d\n",
- (int) mapPoints.v,
- (int) mapPoints.h);
-
- printf ("Spacing: v=%.6f, h=%.6f\n",
- mapSpacing.v,
- mapSpacing.h);
-
- printf ("Origin: v=%.6f, h=%.6f\n",
- mapOrigin.v,
- mapOrigin.h);
-
- printf ("Planes: %u\n",
- (unsigned) mapPlanes);
-
- }
-
- #endif
-
- if (mapPoints.v == 1)
- {
- mapSpacing.v = 1.0;
- mapOrigin.v = 0.0;
- }
-
- if (mapPoints.h == 1)
- {
- mapSpacing.h = 1.0;
- mapOrigin.h = 0.0;
- }
-
- if (mapPoints.v < 1 ||
- mapPoints.h < 1 ||
- mapSpacing.v <= 0.0 ||
- mapSpacing.h <= 0.0 ||
- mapPlanes < 1)
- {
- ThrowBadFormat ();
- }
-
- AutoPtr<dng_gain_map> map (new dng_gain_map (host.Allocator (),
- mapPoints,
- mapSpacing,
- mapOrigin,
- mapPlanes));
-
- #if qDNGValidate
-
- uint32 linesPrinted = 0;
- uint32 linesSkipped = 0;
-
- #endif
-
- for (int32 rowIndex = 0; rowIndex < mapPoints.v; rowIndex++)
- {
-
- for (int32 colIndex = 0; colIndex < mapPoints.h; colIndex++)
- {
-
- for (uint32 plane = 0; plane < mapPlanes; plane++)
- {
-
- real32 x = stream.Get_real32 ();
-
- map->Entry (rowIndex, colIndex, plane) = x;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- if (linesPrinted < gDumpLineLimit)
- {
-
- printf (" Map [%3u] [%3u] [%u] = %.4f\n",
- (unsigned) rowIndex,
- (unsigned) colIndex,
- (unsigned) plane,
- x);
-
- linesPrinted++;
-
- }
-
- else
- linesSkipped++;
-
- }
-
- #endif
-
- }
-
- }
-
- }
-
- #if qDNGValidate
-
- if (linesSkipped)
- {
-
- printf (" ... %u map entries skipped\n", (unsigned) linesSkipped);
-
- }
-
- #endif
-
- return map.Release ();
-
- }
-
-/*****************************************************************************/
-
-dng_opcode_GainMap::dng_opcode_GainMap (const dng_area_spec &areaSpec,
- AutoPtr<dng_gain_map> &gainMap)
-
- : dng_inplace_opcode (dngOpcode_GainMap,
- dngVersion_1_3_0_0,
- kFlag_None)
-
- , fAreaSpec (areaSpec)
-
- , fGainMap ()
-
- {
-
- fGainMap.Reset (gainMap.Release ());
-
- }
-
-/*****************************************************************************/
-
-dng_opcode_GainMap::dng_opcode_GainMap (dng_host &host,
- dng_stream &stream)
-
- : dng_inplace_opcode (dngOpcode_GainMap,
- stream,
- "GainMap")
-
- , fAreaSpec ()
-
- , fGainMap ()
-
- {
-
- uint32 byteCount = stream.Get_uint32 ();
-
- uint64 startPosition = stream.Position ();
-
- fAreaSpec.GetData (stream);
-
- fGainMap.Reset (dng_gain_map::GetStream (host, stream));
-
- if (stream.Position () != startPosition + byteCount)
- {
- ThrowBadFormat ();
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_GainMap::PutData (dng_stream &stream) const
- {
-
- stream.Put_uint32 (dng_area_spec::kDataSize +
- fGainMap->PutStreamSize ());
-
- fAreaSpec.PutData (stream);
-
- fGainMap->PutStream (stream);
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_GainMap::ProcessArea (dng_negative & /* negative */,
- uint32 /* threadIndex */,
- dng_pixel_buffer &buffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds)
- {
-
- dng_rect overlap = fAreaSpec.Overlap (dstArea);
-
- if (overlap.NotEmpty ())
- {
-
- uint32 cols = overlap.W ();
-
- uint32 colPitch = fAreaSpec.ColPitch ();
-
- for (uint32 plane = fAreaSpec.Plane ();
- plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
- plane < buffer.Planes ();
- plane++)
- {
-
- uint32 mapPlane = Min_uint32 (plane, fGainMap->Planes () - 1);
-
- for (int32 row = overlap.t; row < overlap.b; row += fAreaSpec.RowPitch ())
- {
-
- real32 *dPtr = buffer.DirtyPixel_real32 (row, overlap.l, plane);
-
- dng_gain_map_interpolator interp (*fGainMap,
- imageBounds,
- row,
- overlap.l,
- mapPlane);
-
- for (uint32 col = 0; col < cols; col += colPitch)
- {
-
- real32 gain = interp.Interpolate ();
-
- dPtr [col] = Min_real32 (dPtr [col] * gain, 1.0f);
-
- for (uint32 j = 0; j < colPitch; j++)
- {
- interp.Increment ();
- }
-
- }
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2008-2009 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_gain_map.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_gain_map.h"
+
+#include "dng_exceptions.h"
+#include "dng_globals.h"
+#include "dng_host.h"
+#include "dng_pixel_buffer.h"
+#include "dng_stream.h"
+#include "dng_tag_values.h"
+
+/*****************************************************************************/
+
+class dng_gain_map_interpolator
+ {
+
+ private:
+
+ const dng_gain_map &fMap;
+
+ dng_point_real64 fScale;
+ dng_point_real64 fOffset;
+
+ int32 fColumn;
+ int32 fPlane;
+
+ uint32 fRowIndex1;
+ uint32 fRowIndex2;
+ real32 fRowFract;
+
+ int32 fResetColumn;
+
+ real32 fValueBase;
+ real32 fValueStep;
+ real32 fValueIndex;
+
+ public:
+
+ dng_gain_map_interpolator (const dng_gain_map &map,
+ const dng_rect &mapBounds,
+ int32 row,
+ int32 column,
+ uint32 plane);
+
+ real32 Interpolate () const
+ {
+
+ return fValueBase + fValueStep * fValueIndex;
+
+ }
+
+ void Increment ()
+ {
+
+ if (++fColumn >= fResetColumn)
+ {
+
+ ResetColumn ();
+
+ }
+
+ else
+ {
+
+ fValueIndex += 1.0f;
+
+ }
+
+ }
+
+ private:
+
+ real32 InterpolateEntry (uint32 colIndex);
+
+ void ResetColumn ();
+
+ };
+
+/*****************************************************************************/
+
+dng_gain_map_interpolator::dng_gain_map_interpolator (const dng_gain_map &map,
+ const dng_rect &mapBounds,
+ int32 row,
+ int32 column,
+ uint32 plane)
+
+ : fMap (map)
+
+ , fScale (1.0 / mapBounds.H (),
+ 1.0 / mapBounds.W ())
+
+ , fOffset (0.5 - mapBounds.t,
+ 0.5 - mapBounds.l)
+
+ , fColumn (column)
+ , fPlane (plane)
+
+ , fRowIndex1 (0)
+ , fRowIndex2 (0)
+ , fRowFract (0.0f)
+
+ , fResetColumn (0)
+
+ , fValueBase (0.0f)
+ , fValueStep (0.0f)
+ , fValueIndex (0.0f)
+
+ {
+
+ real64 rowIndexF = (fScale.v * (row + fOffset.v) -
+ fMap.Origin ().v) / fMap.Spacing ().v;
+
+ if (rowIndexF <= 0.0)
+ {
+
+ fRowIndex1 = 0;
+ fRowIndex2 = 0;
+
+ fRowFract = 0.0f;
+
+ }
+
+ else
+ {
+
+ if (fMap.Points ().v < 1)
+ {
+ ThrowProgramError ("Empty gain map");
+ }
+ uint32 lastRow = static_cast<uint32> (fMap.Points ().v - 1);
+
+ if (rowIndexF >= static_cast<real64> (lastRow))
+ {
+
+ fRowIndex1 = lastRow;
+ fRowIndex2 = fRowIndex1;
+
+ fRowFract = 0.0f;
+
+ }
+
+ else
+ {
+
+ // If we got here, we know that rowIndexF can safely be converted to
+ // a uint32 and that static_cast<uint32> (rowIndexF) < lastRow. This
+ // implies fRowIndex2 <= lastRow below.
+ fRowIndex1 = static_cast<uint32> (rowIndexF);
+ fRowIndex2 = fRowIndex1 + 1;
+
+ fRowFract = (real32) (rowIndexF - (real64) fRowIndex1);
+
+ }
+
+ }
+
+ ResetColumn ();
+
+ }
+
+/*****************************************************************************/
+
+real32 dng_gain_map_interpolator::InterpolateEntry (uint32 colIndex)
+ {
+
+ return fMap.Entry (fRowIndex1, colIndex, fPlane) * (1.0f - fRowFract) +
+ fMap.Entry (fRowIndex2, colIndex, fPlane) * ( fRowFract);
+
+ }
+
+/*****************************************************************************/
+
+void dng_gain_map_interpolator::ResetColumn ()
+ {
+
+ real64 colIndexF = ((fScale.h * (fColumn + fOffset.h)) -
+ fMap.Origin ().h) / fMap.Spacing ().h;
+
+ if (colIndexF <= 0.0)
+ {
+
+ fValueBase = InterpolateEntry (0);
+
+ fValueStep = 0.0f;
+
+ fResetColumn = (int32) ceil (fMap.Origin ().h / fScale.h - fOffset.h);
+
+ }
+
+ else
+ {
+
+ if (fMap.Points ().h < 1)
+ {
+ ThrowProgramError ("Empty gain map");
+ }
+ uint32 lastCol = static_cast<uint32> (fMap.Points ().h - 1);
+
+ if (colIndexF >= static_cast<real64> (lastCol))
+ {
+
+ fValueBase = InterpolateEntry (lastCol);
+
+ fValueStep = 0.0f;
+
+ fResetColumn = 0x7FFFFFFF;
+
+ }
+
+ else
+ {
+
+ // If we got here, we know that colIndexF can safely be converted to
+ // a uint32 and that static_cast<uint32> (colIndexF) < lastCol. This
+ // implies colIndex + 1 <= lastCol, i.e. the argument to
+ // InterpolateEntry() below is valid.
+ uint32 colIndex = static_cast<uint32> (colIndexF);
+ real64 base = InterpolateEntry (colIndex);
+ real64 delta = InterpolateEntry (colIndex + 1) - base;
+
+ fValueBase = (real32) (base + delta * (colIndexF - (real64) colIndex));
+
+ fValueStep = (real32) ((delta * fScale.h) / fMap.Spacing ().h);
+
+ fResetColumn = (int32) ceil (((colIndex + 1) * fMap.Spacing ().h +
+ fMap.Origin ().h) / fScale.h - fOffset.h);
+
+ }
+
+ }
+
+ fValueIndex = 0.0f;
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+dng_gain_map::dng_gain_map (dng_memory_allocator &allocator,
+ const dng_point &points,
+ const dng_point_real64 &spacing,
+ const dng_point_real64 &origin,
+ uint32 planes)
+
+ : fPoints (points)
+ , fSpacing (spacing)
+ , fOrigin (origin)
+ , fPlanes (planes)
+
+ , fRowStep (planes * points.h)
+
+ , fBuffer ()
+
+ {
+
+ fBuffer.Reset (allocator.Allocate (
+ ComputeBufferSize (ttFloat, fPoints, fPlanes, pad16Bytes)));
+
+ }
+
+/*****************************************************************************/
+
+real32 dng_gain_map::Interpolate (int32 row,
+ int32 col,
+ uint32 plane,
+ const dng_rect &bounds) const
+ {
+
+ dng_gain_map_interpolator interp (*this,
+ bounds,
+ row,
+ col,
+ plane);
+
+ return interp.Interpolate ();
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_gain_map::PutStreamSize () const
+ {
+
+ return 44 + fPoints.v * fPoints.h * fPlanes * 4;
+
+ }
+
+/*****************************************************************************/
+
+void dng_gain_map::PutStream (dng_stream &stream) const
+ {
+
+ stream.Put_uint32 (fPoints.v);
+ stream.Put_uint32 (fPoints.h);
+
+ stream.Put_real64 (fSpacing.v);
+ stream.Put_real64 (fSpacing.h);
+
+ stream.Put_real64 (fOrigin.v);
+ stream.Put_real64 (fOrigin.h);
+
+ stream.Put_uint32 (fPlanes);
+
+ for (int32 rowIndex = 0; rowIndex < fPoints.v; rowIndex++)
+ {
+
+ for (int32 colIndex = 0; colIndex < fPoints.h; colIndex++)
+ {
+
+ for (uint32 plane = 0; plane < fPlanes; plane++)
+ {
+
+ stream.Put_real32 (Entry (rowIndex,
+ colIndex,
+ plane));
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_gain_map * dng_gain_map::GetStream (dng_host &host,
+ dng_stream &stream)
+ {
+
+ dng_point mapPoints;
+
+ mapPoints.v = stream.Get_uint32 ();
+ mapPoints.h = stream.Get_uint32 ();
+
+ dng_point_real64 mapSpacing;
+
+ mapSpacing.v = stream.Get_real64 ();
+ mapSpacing.h = stream.Get_real64 ();
+
+ dng_point_real64 mapOrigin;
+
+ mapOrigin.v = stream.Get_real64 ();
+ mapOrigin.h = stream.Get_real64 ();
+
+ uint32 mapPlanes = stream.Get_uint32 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Points: v=%d, h=%d\n",
+ (int) mapPoints.v,
+ (int) mapPoints.h);
+
+ printf ("Spacing: v=%.6f, h=%.6f\n",
+ mapSpacing.v,
+ mapSpacing.h);
+
+ printf ("Origin: v=%.6f, h=%.6f\n",
+ mapOrigin.v,
+ mapOrigin.h);
+
+ printf ("Planes: %u\n",
+ (unsigned) mapPlanes);
+
+ }
+
+ #endif
+
+ if (mapPoints.v == 1)
+ {
+ mapSpacing.v = 1.0;
+ mapOrigin.v = 0.0;
+ }
+
+ if (mapPoints.h == 1)
+ {
+ mapSpacing.h = 1.0;
+ mapOrigin.h = 0.0;
+ }
+
+ if (mapPoints.v < 1 ||
+ mapPoints.h < 1 ||
+ mapSpacing.v <= 0.0 ||
+ mapSpacing.h <= 0.0 ||
+ mapPlanes < 1)
+ {
+ ThrowBadFormat ();
+ }
+
+ AutoPtr<dng_gain_map> map (new dng_gain_map (host.Allocator (),
+ mapPoints,
+ mapSpacing,
+ mapOrigin,
+ mapPlanes));
+
+ #if qDNGValidate
+
+ uint32 linesPrinted = 0;
+ uint32 linesSkipped = 0;
+
+ #endif
+
+ for (int32 rowIndex = 0; rowIndex < mapPoints.v; rowIndex++)
+ {
+
+ for (int32 colIndex = 0; colIndex < mapPoints.h; colIndex++)
+ {
+
+ for (uint32 plane = 0; plane < mapPlanes; plane++)
+ {
+
+ real32 x = stream.Get_real32 ();
+
+ map->Entry (rowIndex, colIndex, plane) = x;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ if (linesPrinted < gDumpLineLimit)
+ {
+
+ printf (" Map [%3u] [%3u] [%u] = %.4f\n",
+ (unsigned) rowIndex,
+ (unsigned) colIndex,
+ (unsigned) plane,
+ x);
+
+ linesPrinted++;
+
+ }
+
+ else
+ linesSkipped++;
+
+ }
+
+ #endif
+
+ }
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (linesSkipped)
+ {
+
+ printf (" ... %u map entries skipped\n", (unsigned) linesSkipped);
+
+ }
+
+ #endif
+
+ return map.Release ();
+
+ }
+
+/*****************************************************************************/
+
+dng_opcode_GainMap::dng_opcode_GainMap (const dng_area_spec &areaSpec,
+ AutoPtr<dng_gain_map> &gainMap)
+
+ : dng_inplace_opcode (dngOpcode_GainMap,
+ dngVersion_1_3_0_0,
+ kFlag_None)
+
+ , fAreaSpec (areaSpec)
+
+ , fGainMap ()
+
+ {
+
+ fGainMap.Reset (gainMap.Release ());
+
+ }
+
+/*****************************************************************************/
+
+dng_opcode_GainMap::dng_opcode_GainMap (dng_host &host,
+ dng_stream &stream)
+
+ : dng_inplace_opcode (dngOpcode_GainMap,
+ stream,
+ "GainMap")
+
+ , fAreaSpec ()
+
+ , fGainMap ()
+
+ {
+
+ uint32 byteCount = stream.Get_uint32 ();
+
+ uint64 startPosition = stream.Position ();
+
+ fAreaSpec.GetData (stream);
+
+ fGainMap.Reset (dng_gain_map::GetStream (host, stream));
+
+ if (stream.Position () != startPosition + byteCount)
+ {
+ ThrowBadFormat ();
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_GainMap::PutData (dng_stream &stream) const
+ {
+
+ stream.Put_uint32 (dng_area_spec::kDataSize +
+ fGainMap->PutStreamSize ());
+
+ fAreaSpec.PutData (stream);
+
+ fGainMap->PutStream (stream);
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_GainMap::ProcessArea (dng_negative & /* negative */,
+ uint32 /* threadIndex */,
+ dng_pixel_buffer &buffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds)
+ {
+
+ dng_rect overlap = fAreaSpec.Overlap (dstArea);
+
+ if (overlap.NotEmpty ())
+ {
+
+ uint32 cols = overlap.W ();
+
+ uint32 colPitch = fAreaSpec.ColPitch ();
+
+ for (uint32 plane = fAreaSpec.Plane ();
+ plane < fAreaSpec.Plane () + fAreaSpec.Planes () &&
+ plane < buffer.Planes ();
+ plane++)
+ {
+
+ uint32 mapPlane = Min_uint32 (plane, fGainMap->Planes () - 1);
+
+ for (int32 row = overlap.t; row < overlap.b; row += fAreaSpec.RowPitch ())
+ {
+
+ real32 *dPtr = buffer.DirtyPixel_real32 (row, overlap.l, plane);
+
+ dng_gain_map_interpolator interp (*fGainMap,
+ imageBounds,
+ row,
+ overlap.l,
+ mapPlane);
+
+ for (uint32 col = 0; col < cols; col += colPitch)
+ {
+
+ real32 gain = interp.Interpolate ();
+
+ dPtr [col] = Min_real32 (dPtr [col] * gain, 1.0f);
+
+ for (uint32 j = 0; j < colPitch; j++)
+ {
+ interp.Increment ();
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_gain_map.h b/source/dng_gain_map.h
index a8db499..8ac1b30 100644
--- a/source/dng_gain_map.h
+++ b/source/dng_gain_map.h
@@ -1,219 +1,219 @@
-/*****************************************************************************/
-// Copyright 2008-2009 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_gain_map.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Opcode to fix 2D uniformity defects, such as shading.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_gain_map__
-#define __dng_gain_map__
-
-/*****************************************************************************/
-
-#include "dng_memory.h"
-#include "dng_misc_opcodes.h"
-#include "dng_tag_types.h"
-
-/*****************************************************************************/
-
-/// \brief Holds a discrete (i.e., sampled) 2D representation of a gain map. This is
-/// effectively an image containing scale factors.
-
-class dng_gain_map
- {
-
- private:
-
- dng_point fPoints;
-
- dng_point_real64 fSpacing;
-
- dng_point_real64 fOrigin;
-
- uint32 fPlanes;
-
- uint32 fRowStep;
-
- AutoPtr<dng_memory_block> fBuffer;
-
- public:
-
- /// Construct a gain map with the specified memory allocator, number of
- /// samples (points), sample spacing, origin, and number of color planes.
-
- dng_gain_map (dng_memory_allocator &allocator,
- const dng_point &points,
- const dng_point_real64 &spacing,
- const dng_point_real64 &origin,
- uint32 planes);
-
- /// The number of samples in the horizontal and vertical directions.
-
- const dng_point & Points () const
- {
- return fPoints;
- }
-
- /// The space between adjacent samples in the horizontal and vertical
- /// directions.
-
- const dng_point_real64 & Spacing () const
- {
- return fSpacing;
- }
-
- /// The 2D coordinate for the first (i.e., top-left-most) sample.
-
- const dng_point_real64 & Origin () const
- {
- return fOrigin;
- }
-
- /// The number of color planes.
-
- uint32 Planes () const
- {
- return fPlanes;
- }
-
- /// Getter for a gain map sample (specified by row, column, and plane).
-
- real32 & Entry (uint32 rowIndex,
- uint32 colIndex,
- uint32 plane)
- {
-
- return *(fBuffer->Buffer_real32 () +
- rowIndex * fRowStep +
- colIndex * fPlanes +
- plane);
-
- }
-
- /// Getter for a gain map sample (specified by row index, column index, and
- /// plane index).
-
- const real32 & Entry (uint32 rowIndex,
- uint32 colIndex,
- uint32 plane) const
- {
-
- return *(fBuffer->Buffer_real32 () +
- rowIndex * fRowStep +
- colIndex * fPlanes +
- plane);
-
- }
-
- /// Compute the interpolated gain (i.e., scale factor) at the specified pixel
- /// position and color plane, within the specified image bounds (in pixels).
-
- real32 Interpolate (int32 row,
- int32 col,
- uint32 plane,
- const dng_rect &bounds) const;
-
- /// The number of bytes needed to hold the gain map data.
-
- uint32 PutStreamSize () const;
-
- /// Write the gain map to the specified stream.
-
- void PutStream (dng_stream &stream) const;
-
- /// Read a gain map from the specified stream.
-
- static dng_gain_map * GetStream (dng_host &host,
- dng_stream &stream);
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_gain_map (const dng_gain_map &map);
-
- dng_gain_map & operator= (const dng_gain_map &map);
-
- };
-
-/*****************************************************************************/
-
-/// \brief An opcode to fix 2D spatially-varying light falloff or color casts (i.e.,
-/// uniformity issues). This is commonly due to shading.
-
-class dng_opcode_GainMap: public dng_inplace_opcode
- {
-
- private:
-
- dng_area_spec fAreaSpec;
-
- AutoPtr<dng_gain_map> fGainMap;
-
- public:
-
- /// Construct a GainMap opcode for the specified image area and the specified
- /// gain map.
-
- dng_opcode_GainMap (const dng_area_spec &areaSpec,
- AutoPtr<dng_gain_map> &gainMap);
-
- /// Construct a GainMap opcode from the specified stream.
-
- dng_opcode_GainMap (dng_host &host,
- dng_stream &stream);
-
- /// Write the opcode to the specified stream.
-
- virtual void PutData (dng_stream &stream) const;
-
- /// The pixel data type of this opcode.
-
- virtual uint32 BufferPixelType (uint32 /* imagePixelType */)
- {
- return ttFloat;
- }
-
- /// The adjusted bounds (processing area) of this opcode. It is limited to
- /// the intersection of the specified image area and the GainMap area.
-
- virtual dng_rect ModifiedBounds (const dng_rect &imageBounds)
- {
- return fAreaSpec.Overlap (imageBounds);
- }
-
- /// Apply the gain map.
-
- virtual void ProcessArea (dng_negative &negative,
- uint32 threadIndex,
- dng_pixel_buffer &buffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_opcode_GainMap (const dng_opcode_GainMap &opcode);
-
- dng_opcode_GainMap & operator= (const dng_opcode_GainMap &opcode);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2008-2009 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_gain_map.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Opcode to fix 2D uniformity defects, such as shading.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_gain_map__
+#define __dng_gain_map__
+
+/*****************************************************************************/
+
+#include "dng_memory.h"
+#include "dng_misc_opcodes.h"
+#include "dng_tag_types.h"
+
+/*****************************************************************************/
+
+/// \brief Holds a discrete (i.e., sampled) 2D representation of a gain map. This is
+/// effectively an image containing scale factors.
+
+class dng_gain_map
+ {
+
+ private:
+
+ dng_point fPoints;
+
+ dng_point_real64 fSpacing;
+
+ dng_point_real64 fOrigin;
+
+ uint32 fPlanes;
+
+ uint32 fRowStep;
+
+ AutoPtr<dng_memory_block> fBuffer;
+
+ public:
+
+ /// Construct a gain map with the specified memory allocator, number of
+ /// samples (points), sample spacing, origin, and number of color planes.
+
+ dng_gain_map (dng_memory_allocator &allocator,
+ const dng_point &points,
+ const dng_point_real64 &spacing,
+ const dng_point_real64 &origin,
+ uint32 planes);
+
+ /// The number of samples in the horizontal and vertical directions.
+
+ const dng_point & Points () const
+ {
+ return fPoints;
+ }
+
+ /// The space between adjacent samples in the horizontal and vertical
+ /// directions.
+
+ const dng_point_real64 & Spacing () const
+ {
+ return fSpacing;
+ }
+
+ /// The 2D coordinate for the first (i.e., top-left-most) sample.
+
+ const dng_point_real64 & Origin () const
+ {
+ return fOrigin;
+ }
+
+ /// The number of color planes.
+
+ uint32 Planes () const
+ {
+ return fPlanes;
+ }
+
+ /// Getter for a gain map sample (specified by row, column, and plane).
+
+ real32 & Entry (uint32 rowIndex,
+ uint32 colIndex,
+ uint32 plane)
+ {
+
+ return *(fBuffer->Buffer_real32 () +
+ rowIndex * fRowStep +
+ colIndex * fPlanes +
+ plane);
+
+ }
+
+ /// Getter for a gain map sample (specified by row index, column index, and
+ /// plane index).
+
+ const real32 & Entry (uint32 rowIndex,
+ uint32 colIndex,
+ uint32 plane) const
+ {
+
+ return *(fBuffer->Buffer_real32 () +
+ rowIndex * fRowStep +
+ colIndex * fPlanes +
+ plane);
+
+ }
+
+ /// Compute the interpolated gain (i.e., scale factor) at the specified pixel
+ /// position and color plane, within the specified image bounds (in pixels).
+
+ real32 Interpolate (int32 row,
+ int32 col,
+ uint32 plane,
+ const dng_rect &bounds) const;
+
+ /// The number of bytes needed to hold the gain map data.
+
+ uint32 PutStreamSize () const;
+
+ /// Write the gain map to the specified stream.
+
+ void PutStream (dng_stream &stream) const;
+
+ /// Read a gain map from the specified stream.
+
+ static dng_gain_map * GetStream (dng_host &host,
+ dng_stream &stream);
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_gain_map (const dng_gain_map &map);
+
+ dng_gain_map & operator= (const dng_gain_map &map);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief An opcode to fix 2D spatially-varying light falloff or color casts (i.e.,
+/// uniformity issues). This is commonly due to shading.
+
+class dng_opcode_GainMap: public dng_inplace_opcode
+ {
+
+ private:
+
+ dng_area_spec fAreaSpec;
+
+ AutoPtr<dng_gain_map> fGainMap;
+
+ public:
+
+ /// Construct a GainMap opcode for the specified image area and the specified
+ /// gain map.
+
+ dng_opcode_GainMap (const dng_area_spec &areaSpec,
+ AutoPtr<dng_gain_map> &gainMap);
+
+ /// Construct a GainMap opcode from the specified stream.
+
+ dng_opcode_GainMap (dng_host &host,
+ dng_stream &stream);
+
+ /// Write the opcode to the specified stream.
+
+ virtual void PutData (dng_stream &stream) const;
+
+ /// The pixel data type of this opcode.
+
+ virtual uint32 BufferPixelType (uint32 /* imagePixelType */)
+ {
+ return ttFloat;
+ }
+
+ /// The adjusted bounds (processing area) of this opcode. It is limited to
+ /// the intersection of the specified image area and the GainMap area.
+
+ virtual dng_rect ModifiedBounds (const dng_rect &imageBounds)
+ {
+ return fAreaSpec.Overlap (imageBounds);
+ }
+
+ /// Apply the gain map.
+
+ virtual void ProcessArea (dng_negative &negative,
+ uint32 threadIndex,
+ dng_pixel_buffer &buffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_opcode_GainMap (const dng_opcode_GainMap &opcode);
+
+ dng_opcode_GainMap & operator= (const dng_opcode_GainMap &opcode);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_globals.cpp b/source/dng_globals.cpp
index b279295..3271f69 100644
--- a/source/dng_globals.cpp
+++ b/source/dng_globals.cpp
@@ -1,28 +1,28 @@
-/*****************************************************************************/
-// Copyright 2006 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_globals.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_globals.h"
-
-/*****************************************************************************/
-
-#if qDNGValidate
-
-bool gVerbose = false;
-
-uint32 gDumpLineLimit = 100;
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_globals.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_globals.h"
+
+/*****************************************************************************/
+
+#if qDNGValidate
+
+bool gVerbose = false;
+
+uint32 gDumpLineLimit = 100;
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_globals.h b/source/dng_globals.h
index ad48017..a78f754 100644
--- a/source/dng_globals.h
+++ b/source/dng_globals.h
@@ -1,46 +1,46 @@
-/*****************************************************************************/
-// Copyright 2006 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_globals.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Definitions of global variables controling DNG SDK behavior. Currenntly only used for validation control.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_globals__
-#define __dng_globals__
-
-/*****************************************************************************/
-
-#include "dng_flags.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-#if qDNGValidate
-
-/// When validation (qValidate) is turned on, this globale enables verbose output about DNG tags and other properties.
-
-extern bool gVerbose;
-
-/// When validation (qValidate) is turned on, and verbose mode (gVerbose) is enabled, limits the number of lines of text that are dumped for each tag.
-
-extern uint32 gDumpLineLimit;
-
-#endif
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_globals.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Definitions of global variables controling DNG SDK behavior. Currenntly only used for validation control.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_globals__
+#define __dng_globals__
+
+/*****************************************************************************/
+
+#include "dng_flags.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+#if qDNGValidate
+
+/// When validation (qValidate) is turned on, this globale enables verbose output about DNG tags and other properties.
+
+extern bool gVerbose;
+
+/// When validation (qValidate) is turned on, and verbose mode (gVerbose) is enabled, limits the number of lines of text that are dumped for each tag.
+
+extern uint32 gDumpLineLimit;
+
+#endif
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_hue_sat_map.cpp b/source/dng_hue_sat_map.cpp
index 92a0e1e..4740e82 100644
--- a/source/dng_hue_sat_map.cpp
+++ b/source/dng_hue_sat_map.cpp
@@ -1,370 +1,370 @@
-/*****************************************************************************/
-// Copyright 2007 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_hue_sat_map.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_hue_sat_map.h"
-
-#include "dng_assertions.h"
-#include "dng_auto_ptr.h"
-#include "dng_bottlenecks.h"
-#include "dng_exceptions.h"
-#include "dng_host.h"
-
-/*****************************************************************************/
-
-dng_hue_sat_map::dng_hue_sat_map ()
-
- : fHueDivisions (0)
- , fSatDivisions (0)
- , fValDivisions (0)
- , fHueStep (0)
- , fValStep (0)
- , fDeltas ()
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_hue_sat_map::dng_hue_sat_map (const dng_hue_sat_map &src)
-
- : fHueDivisions (0)
- , fSatDivisions (0)
- , fValDivisions (0)
- , fHueStep (0)
- , fValStep (0)
- , fDeltas ()
-
- {
-
- *this = src;
-
- }
-
-/*****************************************************************************/
-
-dng_hue_sat_map &dng_hue_sat_map::operator= (const dng_hue_sat_map &rhs)
- {
-
- if (this != &rhs)
- {
-
- if (!rhs.IsValid ())
- {
-
- SetInvalid ();
-
- }
-
- else
- {
-
- fHueDivisions = rhs.fHueDivisions;
- fSatDivisions = rhs.fSatDivisions;
- fValDivisions = rhs.fValDivisions;
-
- fHueStep = rhs.fHueStep;
- fValStep = rhs.fValStep;
-
- fDeltas = rhs.fDeltas;
-
- }
-
- }
-
- return *this;
-
- }
-
-/*****************************************************************************/
-
-dng_hue_sat_map::~dng_hue_sat_map ()
- {
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-void dng_hue_sat_map::SetDivisions (uint32 hueDivisions,
- uint32 satDivisions,
- uint32 valDivisions)
- {
-
- DNG_ASSERT (hueDivisions >= 1, "Must have at least 1 hue division.");
- DNG_ASSERT (satDivisions >= 2, "Must have at least 2 sat divisions.");
-
- if (valDivisions == 0)
- valDivisions = 1;
-
- if (hueDivisions == fHueDivisions &&
- satDivisions == fSatDivisions &&
- valDivisions == fValDivisions)
- {
- return;
- }
-
- fHueDivisions = hueDivisions;
- fSatDivisions = satDivisions;
- fValDivisions = valDivisions;
-
- fHueStep = satDivisions;
- fValStep = hueDivisions * fHueStep;
-
- uint32 size = DeltasCount () * (uint32) sizeof (HSBModify);
-
- fDeltas.Allocate (size);
-
- DoZeroBytes (fDeltas.Buffer (), size);
-
- }
-
-/*****************************************************************************/
-
-void dng_hue_sat_map::GetDelta (uint32 hueDiv,
- uint32 satDiv,
- uint32 valDiv,
- HSBModify &modify) const
- {
-
- if (hueDiv >= fHueDivisions ||
- satDiv >= fSatDivisions ||
- valDiv >= fValDivisions ||
- fDeltas.Buffer () == NULL)
- {
-
- DNG_REPORT ("Bad parameters to dng_hue_sat_map::GetDelta");
-
- ThrowProgramError ();
-
- }
-
- int32 offset = valDiv * fValStep +
- hueDiv * fHueStep +
- satDiv;
-
- const HSBModify *deltas = GetConstDeltas ();
-
- modify.fHueShift = deltas [offset].fHueShift;
- modify.fSatScale = deltas [offset].fSatScale;
- modify.fValScale = deltas [offset].fValScale;
-
- }
-
-/*****************************************************************************/
-
-void dng_hue_sat_map::SetDeltaKnownWriteable (uint32 hueDiv,
- uint32 satDiv,
- uint32 valDiv,
- const HSBModify &modify)
- {
-
- if (hueDiv >= fHueDivisions ||
- satDiv >= fSatDivisions ||
- valDiv >= fValDivisions ||
- fDeltas.Buffer () == NULL)
- {
-
- DNG_REPORT ("Bad parameters to dng_hue_sat_map::SetDelta");
-
- ThrowProgramError ();
-
- }
-
- // Set this entry.
-
- int32 offset = valDiv * fValStep +
- hueDiv * fHueStep +
- satDiv;
-
- SafeGetDeltas () [offset] = modify;
-
- // The zero saturation entry is required to have a value scale
- // of 1.0f.
-
- if (satDiv == 0)
- {
-
- if (modify.fValScale != 1.0f)
- {
-
- #if qDNGValidate
-
- ReportWarning ("Value scale for zero saturation entries must be 1.0");
-
- #endif
-
- SafeGetDeltas () [offset] . fValScale = 1.0f;
-
- }
-
- }
-
- // If we are settings the first saturation entry and we have not
- // set the zero saturation entry yet, fill in the zero saturation entry
- // by extrapolating first saturation entry.
-
- if (satDiv == 1)
- {
-
- HSBModify zeroSatModify;
-
- GetDelta (hueDiv, 0, valDiv, zeroSatModify);
-
- if (zeroSatModify.fValScale != 1.0f)
- {
-
- zeroSatModify.fHueShift = modify.fHueShift;
- zeroSatModify.fSatScale = modify.fSatScale;
- zeroSatModify.fValScale = 1.0f;
-
- SetDelta (hueDiv, 0, valDiv, zeroSatModify);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_hue_sat_map::operator== (const dng_hue_sat_map &rhs) const
- {
-
- if (fHueDivisions != rhs.fHueDivisions ||
- fSatDivisions != rhs.fSatDivisions ||
- fValDivisions != rhs.fValDivisions)
- return false;
-
- if (!IsValid ())
- return true;
-
- return memcmp (GetConstDeltas (),
- rhs.GetConstDeltas (),
- DeltasCount () * sizeof (HSBModify)) == 0;
-
- }
-
-/*****************************************************************************/
-
-dng_hue_sat_map * dng_hue_sat_map::Interpolate (const dng_hue_sat_map &map1,
- const dng_hue_sat_map &map2,
- real64 weight1)
- {
-
- if (weight1 >= 1.0)
- {
-
- if (!map1.IsValid ())
- {
-
- DNG_REPORT ("map1 is not valid");
-
- ThrowProgramError ();
-
- }
-
- return new dng_hue_sat_map (map1);
-
- }
-
- if (weight1 <= 0.0)
- {
-
- if (!map2.IsValid ())
- {
- DNG_REPORT ("map2 is not valid");
-
- ThrowProgramError ();
-
- }
-
- return new dng_hue_sat_map (map2);
-
- }
-
- // Both maps must be valid if we are using both.
-
- if (!map1.IsValid () || !map2.IsValid ())
- {
-
- DNG_REPORT ("map1 or map2 is not valid");
-
- ThrowProgramError ();
-
- }
-
- // Must have the same dimensions.
-
- if (map1.fHueDivisions != map2.fHueDivisions ||
- map1.fSatDivisions != map2.fSatDivisions ||
- map1.fValDivisions != map2.fValDivisions)
- {
-
- DNG_REPORT ("map1 and map2 have different sizes");
-
- ThrowProgramError ();
-
- }
-
- // Make table to hold interpolated results.
-
- AutoPtr<dng_hue_sat_map> result (new dng_hue_sat_map);
-
- result->SetDivisions (map1.fHueDivisions,
- map1.fSatDivisions,
- map1.fValDivisions);
-
- // Interpolate between the tables.
-
- real32 w1 = (real32) weight1;
- real32 w2 = 1.0f - w1;
-
- const HSBModify *data1 = map1.GetConstDeltas ();
- const HSBModify *data2 = map2.GetConstDeltas ();
-
- HSBModify *data3 = result->SafeGetDeltas ();
-
- uint32 count = map1.DeltasCount ();
-
- for (uint32 index = 0; index < count; index++)
- {
-
- data3->fHueShift = w1 * data1->fHueShift +
- w2 * data2->fHueShift;
-
- data3->fSatScale = w1 * data1->fSatScale +
- w2 * data2->fSatScale;
-
- data3->fValScale = w1 * data1->fValScale +
- w2 * data2->fValScale;
-
- data1++;
- data2++;
- data3++;
-
- }
-
- // Return interpolated tables.
-
- return result.Release ();
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2007 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_hue_sat_map.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_hue_sat_map.h"
+
+#include "dng_assertions.h"
+#include "dng_auto_ptr.h"
+#include "dng_bottlenecks.h"
+#include "dng_exceptions.h"
+#include "dng_host.h"
+
+/*****************************************************************************/
+
+dng_hue_sat_map::dng_hue_sat_map ()
+
+ : fHueDivisions (0)
+ , fSatDivisions (0)
+ , fValDivisions (0)
+ , fHueStep (0)
+ , fValStep (0)
+ , fDeltas ()
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_hue_sat_map::dng_hue_sat_map (const dng_hue_sat_map &src)
+
+ : fHueDivisions (0)
+ , fSatDivisions (0)
+ , fValDivisions (0)
+ , fHueStep (0)
+ , fValStep (0)
+ , fDeltas ()
+
+ {
+
+ *this = src;
+
+ }
+
+/*****************************************************************************/
+
+dng_hue_sat_map &dng_hue_sat_map::operator= (const dng_hue_sat_map &rhs)
+ {
+
+ if (this != &rhs)
+ {
+
+ if (!rhs.IsValid ())
+ {
+
+ SetInvalid ();
+
+ }
+
+ else
+ {
+
+ fHueDivisions = rhs.fHueDivisions;
+ fSatDivisions = rhs.fSatDivisions;
+ fValDivisions = rhs.fValDivisions;
+
+ fHueStep = rhs.fHueStep;
+ fValStep = rhs.fValStep;
+
+ fDeltas = rhs.fDeltas;
+
+ }
+
+ }
+
+ return *this;
+
+ }
+
+/*****************************************************************************/
+
+dng_hue_sat_map::~dng_hue_sat_map ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+void dng_hue_sat_map::SetDivisions (uint32 hueDivisions,
+ uint32 satDivisions,
+ uint32 valDivisions)
+ {
+
+ DNG_ASSERT (hueDivisions >= 1, "Must have at least 1 hue division.");
+ DNG_ASSERT (satDivisions >= 2, "Must have at least 2 sat divisions.");
+
+ if (valDivisions == 0)
+ valDivisions = 1;
+
+ if (hueDivisions == fHueDivisions &&
+ satDivisions == fSatDivisions &&
+ valDivisions == fValDivisions)
+ {
+ return;
+ }
+
+ fHueDivisions = hueDivisions;
+ fSatDivisions = satDivisions;
+ fValDivisions = valDivisions;
+
+ fHueStep = satDivisions;
+ fValStep = hueDivisions * fHueStep;
+
+ uint32 size = DeltasCount () * (uint32) sizeof (HSBModify);
+
+ fDeltas.Allocate (size);
+
+ DoZeroBytes (fDeltas.Buffer (), size);
+
+ }
+
+/*****************************************************************************/
+
+void dng_hue_sat_map::GetDelta (uint32 hueDiv,
+ uint32 satDiv,
+ uint32 valDiv,
+ HSBModify &modify) const
+ {
+
+ if (hueDiv >= fHueDivisions ||
+ satDiv >= fSatDivisions ||
+ valDiv >= fValDivisions ||
+ fDeltas.Buffer () == NULL)
+ {
+
+ DNG_REPORT ("Bad parameters to dng_hue_sat_map::GetDelta");
+
+ ThrowProgramError ();
+
+ }
+
+ int32 offset = valDiv * fValStep +
+ hueDiv * fHueStep +
+ satDiv;
+
+ const HSBModify *deltas = GetConstDeltas ();
+
+ modify.fHueShift = deltas [offset].fHueShift;
+ modify.fSatScale = deltas [offset].fSatScale;
+ modify.fValScale = deltas [offset].fValScale;
+
+ }
+
+/*****************************************************************************/
+
+void dng_hue_sat_map::SetDeltaKnownWriteable (uint32 hueDiv,
+ uint32 satDiv,
+ uint32 valDiv,
+ const HSBModify &modify)
+ {
+
+ if (hueDiv >= fHueDivisions ||
+ satDiv >= fSatDivisions ||
+ valDiv >= fValDivisions ||
+ fDeltas.Buffer () == NULL)
+ {
+
+ DNG_REPORT ("Bad parameters to dng_hue_sat_map::SetDelta");
+
+ ThrowProgramError ();
+
+ }
+
+ // Set this entry.
+
+ int32 offset = valDiv * fValStep +
+ hueDiv * fHueStep +
+ satDiv;
+
+ SafeGetDeltas () [offset] = modify;
+
+ // The zero saturation entry is required to have a value scale
+ // of 1.0f.
+
+ if (satDiv == 0)
+ {
+
+ if (modify.fValScale != 1.0f)
+ {
+
+ #if qDNGValidate
+
+ ReportWarning ("Value scale for zero saturation entries must be 1.0");
+
+ #endif
+
+ SafeGetDeltas () [offset] . fValScale = 1.0f;
+
+ }
+
+ }
+
+ // If we are settings the first saturation entry and we have not
+ // set the zero saturation entry yet, fill in the zero saturation entry
+ // by extrapolating first saturation entry.
+
+ if (satDiv == 1)
+ {
+
+ HSBModify zeroSatModify;
+
+ GetDelta (hueDiv, 0, valDiv, zeroSatModify);
+
+ if (zeroSatModify.fValScale != 1.0f)
+ {
+
+ zeroSatModify.fHueShift = modify.fHueShift;
+ zeroSatModify.fSatScale = modify.fSatScale;
+ zeroSatModify.fValScale = 1.0f;
+
+ SetDelta (hueDiv, 0, valDiv, zeroSatModify);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_hue_sat_map::operator== (const dng_hue_sat_map &rhs) const
+ {
+
+ if (fHueDivisions != rhs.fHueDivisions ||
+ fSatDivisions != rhs.fSatDivisions ||
+ fValDivisions != rhs.fValDivisions)
+ return false;
+
+ if (!IsValid ())
+ return true;
+
+ return memcmp (GetConstDeltas (),
+ rhs.GetConstDeltas (),
+ DeltasCount () * sizeof (HSBModify)) == 0;
+
+ }
+
+/*****************************************************************************/
+
+dng_hue_sat_map * dng_hue_sat_map::Interpolate (const dng_hue_sat_map &map1,
+ const dng_hue_sat_map &map2,
+ real64 weight1)
+ {
+
+ if (weight1 >= 1.0)
+ {
+
+ if (!map1.IsValid ())
+ {
+
+ DNG_REPORT ("map1 is not valid");
+
+ ThrowProgramError ();
+
+ }
+
+ return new dng_hue_sat_map (map1);
+
+ }
+
+ if (weight1 <= 0.0)
+ {
+
+ if (!map2.IsValid ())
+ {
+ DNG_REPORT ("map2 is not valid");
+
+ ThrowProgramError ();
+
+ }
+
+ return new dng_hue_sat_map (map2);
+
+ }
+
+ // Both maps must be valid if we are using both.
+
+ if (!map1.IsValid () || !map2.IsValid ())
+ {
+
+ DNG_REPORT ("map1 or map2 is not valid");
+
+ ThrowProgramError ();
+
+ }
+
+ // Must have the same dimensions.
+
+ if (map1.fHueDivisions != map2.fHueDivisions ||
+ map1.fSatDivisions != map2.fSatDivisions ||
+ map1.fValDivisions != map2.fValDivisions)
+ {
+
+ DNG_REPORT ("map1 and map2 have different sizes");
+
+ ThrowProgramError ();
+
+ }
+
+ // Make table to hold interpolated results.
+
+ AutoPtr<dng_hue_sat_map> result (new dng_hue_sat_map);
+
+ result->SetDivisions (map1.fHueDivisions,
+ map1.fSatDivisions,
+ map1.fValDivisions);
+
+ // Interpolate between the tables.
+
+ real32 w1 = (real32) weight1;
+ real32 w2 = 1.0f - w1;
+
+ const HSBModify *data1 = map1.GetConstDeltas ();
+ const HSBModify *data2 = map2.GetConstDeltas ();
+
+ HSBModify *data3 = result->SafeGetDeltas ();
+
+ uint32 count = map1.DeltasCount ();
+
+ for (uint32 index = 0; index < count; index++)
+ {
+
+ data3->fHueShift = w1 * data1->fHueShift +
+ w2 * data2->fHueShift;
+
+ data3->fSatScale = w1 * data1->fSatScale +
+ w2 * data2->fSatScale;
+
+ data3->fValScale = w1 * data1->fValScale +
+ w2 * data2->fValScale;
+
+ data1++;
+ data2++;
+ data3++;
+
+ }
+
+ // Return interpolated tables.
+
+ return result.Release ();
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_ifd.cpp b/source/dng_ifd.cpp
index 8fc9001..b0ff06b 100644
--- a/source/dng_ifd.cpp
+++ b/source/dng_ifd.cpp
@@ -1,4283 +1,4283 @@
-/*****************************************************************************/
-// Copyright 2006-2012 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_ifd.cpp#3 $ */
-/* $DateTime: 2012/06/05 11:05:39 $ */
-/* $Change: 833352 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_ifd.h"
-
-#include "dng_exceptions.h"
-#include "dng_flags.h"
-#include "dng_globals.h"
-#include "dng_ifd.h"
-#include "dng_types.h"
-#include "dng_parse_utils.h"
-#include "dng_read_image.h"
-#include "dng_stream.h"
-#include "dng_tag_codes.h"
-#include "dng_tag_types.h"
-#include "dng_tag_values.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_preview_info::dng_preview_info ()
-
- : fIsPrimary (true)
- , fApplicationName ()
- , fApplicationVersion ()
- , fSettingsName ()
- , fSettingsDigest ()
- , fColorSpace (previewColorSpace_MaxEnum)
- , fDateTime ()
- , fRawToPreviewGain (1.0)
- , fCacheVersion (0)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_preview_info::~dng_preview_info ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_ifd::dng_ifd ()
-
- : fUsesNewSubFileType (false)
- , fNewSubFileType (0)
-
- , fImageWidth (0)
- , fImageLength (0)
-
- , fCompression (ccUncompressed)
- , fPredictor (cpNullPredictor)
-
- , fPhotometricInterpretation (0xFFFFFFFF)
-
- , fFillOrder (1)
-
- , fOrientation (0)
- , fOrientationType (0)
- , fOrientationOffset (kDNGStreamInvalidOffset)
- , fOrientationBigEndian (false)
-
- , fSamplesPerPixel (1)
-
- , fPlanarConfiguration (pcInterleaved)
-
- , fXResolution (0.0)
- , fYResolution (0.0)
- , fResolutionUnit (0)
-
- , fUsesStrips (false)
- , fUsesTiles (false)
-
- , fTileWidth (0)
- , fTileLength (0)
-
- , fTileOffsetsType (0)
- , fTileOffsetsCount (0)
- , fTileOffsetsOffset (0)
-
- , fTileByteCountsType (0)
- , fTileByteCountsCount (0)
- , fTileByteCountsOffset (0)
-
- , fSubIFDsCount (0)
- , fSubIFDsOffset (0)
-
- , fExtraSamplesCount (0)
-
- , fJPEGTablesCount (0)
- , fJPEGTablesOffset (0)
-
- , fJPEGInterchangeFormat (0)
- , fJPEGInterchangeFormatLength (0)
-
- , fYCbCrCoefficientR (0.0)
- , fYCbCrCoefficientG (0.0)
- , fYCbCrCoefficientB (0.0)
-
- , fYCbCrSubSampleH (0)
- , fYCbCrSubSampleV (0)
-
- , fYCbCrPositioning (0)
-
- , fCFARepeatPatternRows (0)
- , fCFARepeatPatternCols (0)
-
- , fCFALayout (1)
-
- , fLinearizationTableType (0)
- , fLinearizationTableCount (0)
- , fLinearizationTableOffset (0)
-
- , fBlackLevelRepeatRows (1)
- , fBlackLevelRepeatCols (1)
-
- , fBlackLevelDeltaHType (0)
- , fBlackLevelDeltaHCount (0)
- , fBlackLevelDeltaHOffset (0)
-
- , fBlackLevelDeltaVType (0)
- , fBlackLevelDeltaVCount (0)
- , fBlackLevelDeltaVOffset (0)
-
- , fDefaultScaleH (1, 1)
- , fDefaultScaleV (1, 1)
-
- , fBestQualityScale (1, 1)
-
- , fDefaultCropOriginH (0, 1)
- , fDefaultCropOriginV (0, 1)
-
- , fDefaultCropSizeH ()
- , fDefaultCropSizeV ()
-
- , fDefaultUserCropT (0, 1)
- , fDefaultUserCropL (0, 1)
- , fDefaultUserCropB (1, 1)
- , fDefaultUserCropR (1, 1)
-
- , fBayerGreenSplit (0)
-
- , fChromaBlurRadius ()
-
- , fAntiAliasStrength (1, 1)
-
- , fActiveArea ()
-
- , fMaskedAreaCount (0)
-
- , fRowInterleaveFactor (1)
-
- , fSubTileBlockRows (1)
- , fSubTileBlockCols (1)
-
- , fPreviewInfo ()
-
- , fOpcodeList1Count (0)
- , fOpcodeList1Offset (0)
-
- , fOpcodeList2Count (0)
- , fOpcodeList2Offset (0)
-
- , fOpcodeList3Count (0)
- , fOpcodeList3Offset (0)
-
- , fLosslessJPEGBug16 (false)
-
- , fSampleBitShift (0)
-
- , fThisIFD (0)
- , fNextIFD (0)
-
- , fCompressionQuality (-1)
-
- , fPatchFirstJPEGByte (false)
-
- {
-
- uint32 j;
- uint32 k;
- uint32 n;
-
- for (j = 0; j < kMaxSamplesPerPixel; j++)
- {
- fBitsPerSample [j] = 0;
- }
-
- for (j = 0; j < kMaxTileInfo; j++)
- {
- fTileOffset [j] = 0;
- fTileByteCount [j] = 0;
- }
-
- for (j = 0; j < kMaxSamplesPerPixel; j++)
- {
- fExtraSamples [j] = esUnspecified;
- }
-
- for (j = 0; j < kMaxSamplesPerPixel; j++)
- {
- fSampleFormat [j] = sfUnsignedInteger;
- }
-
- for (j = 0; j < 6; j++)
- {
- fReferenceBlackWhite [j] = 0.0;
- }
-
- for (j = 0; j < kMaxCFAPattern; j++)
- for (k = 0; k < kMaxCFAPattern; k++)
- {
- fCFAPattern [j] [k] = 255;
- }
-
- for (j = 0; j < kMaxColorPlanes; j++)
- {
- fCFAPlaneColor [j] = (uint8) (j < 3 ? j : 255);
- }
-
- for (j = 0; j < kMaxBlackPattern; j++)
- for (k = 0; k < kMaxBlackPattern; k++)
- for (n = 0; n < kMaxSamplesPerPixel; n++)
- {
- fBlackLevel [j] [k] [n] = 0.0;
- }
-
- for (j = 0; j < kMaxSamplesPerPixel; j++)
- {
- fWhiteLevel [j] = -1.0; // Don't know real default yet.
- }
-
- }
-
-/*****************************************************************************/
-
-dng_ifd::~dng_ifd ()
- {
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-// Parses tags that should only appear in IFDs that contain images.
-
-bool dng_ifd::ParseTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset)
- {
-
- uint32 j;
- uint32 k;
- uint32 n;
-
- switch (tagCode)
- {
-
- case tcNewSubFileType:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fUsesNewSubFileType = true;
-
- fNewSubFileType = stream.TagValue_uint32 (tagType);
-
- fPreviewInfo.fIsPrimary = (fNewSubFileType == sfPreviewImage);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("NewSubFileType: %s\n",
- LookupNewSubFileType (fNewSubFileType));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcImageWidth:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fImageWidth = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("ImageWidth: %u\n", (unsigned) fImageWidth);
- }
-
- #endif
-
- break;
-
- }
-
- case tcImageLength:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fImageLength = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("ImageLength: %u\n", (unsigned) fImageLength);
- }
-
- #endif
-
- break;
-
- }
-
- case tcBitsPerSample:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1, 0x0FFFF);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("BitsPerSample:");
- }
-
- #endif
-
- bool extrasMatch = true;
-
- for (j = 0; j < tagCount; j++)
- {
-
- uint32 x = stream.TagValue_uint32 (tagType);
-
- const uint32 maxBitsPerSample = 32;
-
- if (j < kMaxSamplesPerPixel)
- {
-
- if (x > maxBitsPerSample)
- {
- ThrowBadFormat ("BitsPerSample out of bounds.");
- }
-
- fBitsPerSample [j] = x;
- }
-
- else if (x != fBitsPerSample [kMaxSamplesPerPixel - 1])
- {
- extrasMatch = false;
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf (" %u", (unsigned) x);
- }
-
- #endif
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("\n");
- }
-
- #endif
-
- if (!extrasMatch)
- {
-
- #if qDNGValidate
-
- ReportError ("BitsPerSample not constant");
-
- #endif
-
- ThrowBadFormat ();
-
- }
-
- break;
-
- }
-
- case tcCompression:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fCompression = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Compression: %s\n",
- LookupCompression (fCompression));
-
- }
-
- #endif
-
- // Correct a common TIFF writer mistake.
-
- if (fCompression == 0)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s has invalid zero compression code",
- LookupParentCode (parentCode));
-
- ReportWarning (message);
-
- }
-
- #endif
-
- fCompression = ccUncompressed;
-
- }
-
- break;
-
- }
-
- case tcPhotometricInterpretation:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fPhotometricInterpretation = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("PhotometricInterpretation: %s\n",
- LookupPhotometricInterpretation (fPhotometricInterpretation));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcFillOrder:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fFillOrder = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("FillOrder: %u\n", (unsigned) fFillOrder);
- }
-
- #endif
-
- break;
-
- }
-
- case tcStripOffsets:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- fUsesStrips = true;
-
- fTileOffsetsType = tagType;
- fTileOffsetsCount = tagCount;
- fTileOffsetsOffset = tagOffset;
-
- if (tagCount <= kMaxTileInfo)
- {
-
- for (j = 0; j < tagCount; j++)
- {
-
- fTileOffset [j] = stream.TagValue_uint32 (tagType);
-
- }
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- stream.SetReadPosition (tagOffset);
-
- DumpTagValues (stream,
- "Offset",
- parentCode,
- tagCode,
- tagType,
- tagCount);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcOrientation:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fOrientationType = tagType;
- fOrientationOffset = stream.PositionInOriginalFile ();
- fOrientationBigEndian = stream.BigEndian ();
-
- fOrientation = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Orientation: %s\n",
- LookupOrientation (fOrientation));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSamplesPerPixel:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fSamplesPerPixel = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("SamplesPerPixel: %u\n", (unsigned) fSamplesPerPixel);
- }
-
- #endif
-
- break;
-
- }
-
- case tcRowsPerStrip:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fUsesStrips = true;
-
- fTileLength = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("RowsPerStrip: %u\n", (unsigned) fTileLength);
- }
-
- #endif
-
- break;
-
- }
-
- case tcStripByteCounts:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- fUsesStrips = true;
-
- fTileByteCountsType = tagType;
- fTileByteCountsCount = tagCount;
- fTileByteCountsOffset = tagOffset;
-
- if (tagCount <= kMaxTileInfo)
- {
-
- for (j = 0; j < tagCount; j++)
- {
-
- fTileByteCount [j] = stream.TagValue_uint32 (tagType);
-
- }
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- stream.SetReadPosition (tagOffset);
-
- DumpTagValues (stream,
- "Count",
- parentCode,
- tagCode,
- tagType,
- tagCount);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcXResolution:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fXResolution = stream.TagValue_real64 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("XResolution: %0.2f\n", fXResolution);
- }
-
- #endif
-
- break;
-
- }
-
- case tcYResolution:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fYResolution = stream.TagValue_real64 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("YResolution: %0.2f\n", fYResolution);
- }
-
- #endif
-
- break;
-
- }
-
- case tcPlanarConfiguration:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fPlanarConfiguration = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("PlanarConfiguration: %u\n", (unsigned) fPlanarConfiguration);
- }
-
- #endif
-
- break;
-
- }
-
- case tcResolutionUnit:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fResolutionUnit = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ResolutionUnit: %s\n",
- LookupResolutionUnit (fResolutionUnit));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcPredictor:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fPredictor = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("Predictor: %s\n",
- LookupPredictor (fPredictor));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcTileWidth:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fUsesTiles = true;
-
- fTileWidth = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("TileWidth: %u\n", (unsigned) fTileWidth);
- }
-
- #endif
-
- break;
-
- }
-
- case tcTileLength:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fUsesTiles = true;
-
- fTileLength = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("TileLength: %u\n", (unsigned) fTileLength);
- }
-
- #endif
-
- break;
-
- }
-
- case tcTileOffsets:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- fUsesTiles = true;
-
- fTileOffsetsType = tagType;
- fTileOffsetsCount = tagCount;
- fTileOffsetsOffset = tagOffset;
-
- if (tagCount <= kMaxTileInfo)
- {
-
- for (j = 0; j < tagCount; j++)
- {
-
- fTileOffset [j] = stream.TagValue_uint32 (tagType);
-
- }
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- stream.SetReadPosition (tagOffset);
-
- DumpTagValues (stream,
- "Offset",
- parentCode,
- tagCode,
- tagType,
- tagCount);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcTileByteCounts:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- fUsesTiles = true;
-
- fTileByteCountsType = tagType;
- fTileByteCountsCount = tagCount;
- fTileByteCountsOffset = tagOffset;
-
- if (tagCount <= kMaxTileInfo)
- {
-
- for (j = 0; j < tagCount; j++)
- {
-
- fTileByteCount [j] = stream.TagValue_uint32 (tagType);
-
- }
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- stream.SetReadPosition (tagOffset);
-
- DumpTagValues (stream,
- "Count",
- parentCode,
- tagCode,
- tagType,
- tagCount);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSubIFDs:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong, ttIFD);
-
- fSubIFDsCount = tagCount;
- fSubIFDsOffset = tagOffset;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- DumpTagValues (stream,
- "IFD",
- parentCode,
- tagCode,
- ttLong,
- tagCount);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcExtraSamples:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1, fSamplesPerPixel);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("ExtraSamples:");
- }
-
- #endif
-
- fExtraSamplesCount = tagCount;
-
- for (j = 0; j < tagCount; j++)
- {
-
- uint32 x = stream.TagValue_uint32 (tagType);
-
- if (j < kMaxSamplesPerPixel)
- {
- fExtraSamples [j] = x;
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf (" %u", (unsigned) x);
- }
-
- #endif
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("\n");
- }
-
- #endif
-
- break;
-
- }
-
- case tcSampleFormat:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("SampleFormat:");
- }
-
- #endif
-
- bool extrasMatch = true;
-
- for (j = 0; j < tagCount; j++)
- {
-
- uint32 x = stream.TagValue_uint32 (tagType);
-
- if (j < kMaxSamplesPerPixel)
- {
- fSampleFormat [j] = x;
- }
-
- else if (x != fSampleFormat [kMaxSamplesPerPixel - 1])
- {
- extrasMatch = false;
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf (" %s", LookupSampleFormat (x));
- }
-
- #endif
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("\n");
- }
-
- #endif
-
- if (!extrasMatch)
- {
-
- #if qDNGValidate
-
- ReportError ("SampleFormat not constant");
-
- #endif
-
- ThrowBadFormat ();
-
- }
-
- break;
-
- }
-
- case tcJPEGTables:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- fJPEGTablesCount = tagCount;
- fJPEGTablesOffset = tagOffset;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("JPEGTables: count = %u, offset = %u\n",
- (unsigned) fJPEGTablesCount,
- (unsigned) fJPEGTablesOffset);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcJPEGInterchangeFormat:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fJPEGInterchangeFormat = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("JPEGInterchangeFormat: %u\n",
- (unsigned) fJPEGInterchangeFormat);
- }
-
- #endif
-
- break;
-
- }
-
- case tcJPEGInterchangeFormatLength:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fJPEGInterchangeFormatLength = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("JPEGInterchangeFormatLength: %u\n",
- (unsigned) fJPEGInterchangeFormatLength);
- }
-
- #endif
-
- break;
-
- }
-
- case tcYCbCrCoefficients:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 3))
- {
- return false;
- }
-
- fYCbCrCoefficientR = stream.TagValue_real64 (tagType);
- fYCbCrCoefficientG = stream.TagValue_real64 (tagType);
- fYCbCrCoefficientB = stream.TagValue_real64 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("YCbCrCoefficients: R = %0.3f, G = %0.3f, B = %0.3f\n",
- fYCbCrCoefficientR,
- fYCbCrCoefficientG,
- fYCbCrCoefficientB);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcYCbCrSubSampling:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
- {
- return false;
- }
-
- fYCbCrSubSampleH = stream.TagValue_uint32 (tagType);
- fYCbCrSubSampleV = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("YCbCrSubSampling: H = %u, V = %u\n",
- (unsigned) fYCbCrSubSampleH,
- (unsigned) fYCbCrSubSampleV);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcYCbCrPositioning:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fYCbCrPositioning = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("YCbCrPositioning: %u\n",
- (unsigned) fYCbCrPositioning);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcReferenceBlackWhite:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 6))
- {
- return false;
- }
-
- for (j = 0; j < 6; j++)
- {
- fReferenceBlackWhite [j] = stream.TagValue_real64 (tagType);
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ReferenceBlackWhite: %0.1f %0.1f %0.1f %0.1f %0.1f %0.1f\n",
- fReferenceBlackWhite [0],
- fReferenceBlackWhite [1],
- fReferenceBlackWhite [2],
- fReferenceBlackWhite [3],
- fReferenceBlackWhite [4],
- fReferenceBlackWhite [5]);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCFARepeatPatternDim:
- {
-
- CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
- {
- return false;
- }
-
- fCFARepeatPatternRows = stream.TagValue_uint32 (tagType);
- fCFARepeatPatternCols = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("CFARepeatPatternDim: Rows = %u, Cols = %u\n",
- (unsigned) fCFARepeatPatternRows,
- (unsigned) fCFARepeatPatternCols);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCFAPattern:
- {
-
- CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
-
- if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
- {
- return false;
- }
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, fCFARepeatPatternRows *
- fCFARepeatPatternCols))
- {
- return false;
- }
-
- if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
- fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
- {
- return false;
- }
-
- // Note that the Exif spec stores this array in a different
- // scan order than the TIFF-EP spec.
-
- for (j = 0; j < fCFARepeatPatternRows; j++)
- for (k = 0; k < fCFARepeatPatternCols; k++)
- {
-
- fCFAPattern [j] [k] = stream.Get_uint8 ();
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("CFAPattern:\n");
-
- for (j = 0; j < fCFARepeatPatternRows; j++)
- {
-
- int32 spaces = 4;
-
- for (k = 0; k < fCFARepeatPatternCols; k++)
- {
-
- while (spaces-- > 0)
- {
- printf (" ");
- }
-
- const char *name = LookupCFAColor (fCFAPattern [j] [k]);
-
- spaces = 9 - (int32) strlen (name);
-
- printf ("%s", name);
-
- }
-
- printf ("\n");
-
- }
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCFAPlaneColor:
- {
-
- CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
-
- if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
- {
- return false;
- }
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 3, kMaxColorPlanes))
- {
- return false;
- }
-
- for (j = 0; j < kMaxColorPlanes; j++)
- {
-
- if (j < tagCount)
- fCFAPlaneColor [j] = stream.Get_uint8 ();
-
- else
- fCFAPlaneColor [j] = 255;
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("CFAPlaneColor:");
-
- for (j = 0; j < tagCount; j++)
- {
-
- printf (" %s", LookupCFAColor (fCFAPlaneColor [j]));
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCFALayout:
- {
-
- CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fCFALayout = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("CFALayout: %s\n",
- LookupCFALayout (fCFALayout));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcLinearizationTable:
- {
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- fLinearizationTableType = tagType;
- fLinearizationTableCount = tagCount;
- fLinearizationTableOffset = tagOffset;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- DumpTagValues (stream,
- "Table",
- parentCode,
- tagCode,
- tagType,
- tagCount);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcBlackLevelRepeatDim:
- {
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
- {
- return false;
- }
-
- fBlackLevelRepeatRows = stream.TagValue_uint32 (tagType);
- fBlackLevelRepeatCols = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("BlackLevelRepeatDim: Rows = %u, Cols = %u\n",
- (unsigned) fBlackLevelRepeatRows,
- (unsigned) fBlackLevelRepeatCols);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcBlackLevel:
- {
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, fBlackLevelRepeatRows *
- fBlackLevelRepeatCols *
- fSamplesPerPixel))
- {
- return false;
- }
-
- if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern ||
- fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern ||
- fSamplesPerPixel < 1 || fSamplesPerPixel > kMaxSamplesPerPixel)
- {
- return false;
- }
-
- for (j = 0; j < fBlackLevelRepeatRows; j++)
- for (k = 0; k < fBlackLevelRepeatCols; k++)
- for (n = 0; n < fSamplesPerPixel; n++)
- {
-
- fBlackLevel [j] [k] [n] = stream.TagValue_real64 (tagType);
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("BlackLevel:");
-
- if (fBlackLevelRepeatRows == 1 &&
- fBlackLevelRepeatCols == 1)
- {
-
- for (n = 0; n < fSamplesPerPixel; n++)
- {
- printf (" %0.2f", fBlackLevel [0] [0] [n]);
- }
-
- printf ("\n");
-
- }
-
- else
- {
-
- printf ("\n");
-
- for (n = 0; n < fSamplesPerPixel; n++)
- {
-
- if (fSamplesPerPixel > 1)
- {
- printf (" Sample: %u\n", (unsigned) n);
- }
-
- for (j = 0; j < fBlackLevelRepeatRows; j++)
- {
-
- printf (" ");
-
- for (k = 0; k < fBlackLevelRepeatCols; k++)
- {
-
- printf (" %8.2f", fBlackLevel [j] [k] [n]);
-
- }
-
- printf ("\n");
-
- }
-
- }
-
- }
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcBlackLevelDeltaH:
- {
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttSRational);
-
- fBlackLevelDeltaHType = tagType;
- fBlackLevelDeltaHCount = tagCount;
- fBlackLevelDeltaHOffset = tagOffset;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- DumpTagValues (stream,
- "Delta",
- parentCode,
- tagCode,
- tagType,
- tagCount);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcBlackLevelDeltaV:
- {
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttSRational);
-
- fBlackLevelDeltaVType = tagType;
- fBlackLevelDeltaVCount = tagCount;
- fBlackLevelDeltaVOffset = tagOffset;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- DumpTagValues (stream,
- "Delta",
- parentCode,
- tagCode,
- tagType,
- tagCount);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcWhiteLevel:
- {
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel))
- return false;
-
- for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++)
- {
-
- fWhiteLevel [j] = stream.TagValue_real64 (tagType);
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("WhiteLevel:");
-
- for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++)
- {
-
- printf (" %0.0f", fWhiteLevel [j]);
-
- }
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcDefaultScale:
- {
-
- CheckMainIFD (parentCode, tagCode, fNewSubFileType);
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
- return false;
-
- fDefaultScaleH = stream.TagValue_urational (tagType);
- fDefaultScaleV = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("DefaultScale: H = %0.4f V = %0.4f\n",
- fDefaultScaleH.As_real64 (),
- fDefaultScaleV.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcDefaultCropOrigin:
- {
-
- CheckMainIFD (parentCode, tagCode, fNewSubFileType);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
- return false;
-
- fDefaultCropOriginH = stream.TagValue_urational (tagType);
- fDefaultCropOriginV = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("DefaultCropOrigin: H = %0.2f V = %0.2f\n",
- fDefaultCropOriginH.As_real64 (),
- fDefaultCropOriginV.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcDefaultCropSize:
- {
-
- CheckMainIFD (parentCode, tagCode, fNewSubFileType);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
- return false;
-
- fDefaultCropSizeH = stream.TagValue_urational (tagType);
- fDefaultCropSizeV = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("DefaultCropSize: H = %0.2f V = %0.2f\n",
- fDefaultCropSizeH.As_real64 (),
- fDefaultCropSizeV.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcDefaultUserCrop:
- {
-
- CheckMainIFD (parentCode, tagCode, fNewSubFileType);
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
- return false;
-
- fDefaultUserCropT = stream.TagValue_urational (tagType);
- fDefaultUserCropL = stream.TagValue_urational (tagType);
- fDefaultUserCropB = stream.TagValue_urational (tagType);
- fDefaultUserCropR = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("DefaultUserCrop: T = %0.2lf L = %0.2lf B = %0.2lf R = %0.2lf\n",
- (double) fDefaultUserCropT.As_real64 (),
- (double) fDefaultUserCropL.As_real64 (),
- (double) fDefaultUserCropB.As_real64 (),
- (double) fDefaultUserCropR.As_real64 ());
-
-
- }
-
- #endif // qDNGValidate
-
- break;
-
- }
-
- case tcBayerGreenSplit:
- {
-
- CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fBayerGreenSplit = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("BayerGreenSplit: %u\n", (unsigned) fBayerGreenSplit);
- }
-
- #endif
-
- break;
-
- }
-
- case tcChromaBlurRadius:
- {
-
- CheckMainIFD (parentCode, tagCode, fNewSubFileType);
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fChromaBlurRadius = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ChromaBlurRadius: %0.2f\n",
- fChromaBlurRadius.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcAntiAliasStrength:
- {
-
- CheckMainIFD (parentCode, tagCode, fNewSubFileType);
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fAntiAliasStrength = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("AntiAliasStrength: %0.2f\n",
- fAntiAliasStrength.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcBestQualityScale:
- {
-
- CheckMainIFD (parentCode, tagCode, fNewSubFileType);
-
- CheckTagType (parentCode, tagCode, tagType, ttRational);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fBestQualityScale = stream.TagValue_urational (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("BestQualityScale: %0.4f\n",
- fBestQualityScale.As_real64 ());
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcActiveArea:
- {
-
- CheckMainIFD (parentCode, tagCode, fNewSubFileType);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
- return false;
-
- fActiveArea.t = stream.TagValue_int32 (tagType);
- fActiveArea.l = stream.TagValue_int32 (tagType);
- fActiveArea.b = stream.TagValue_int32 (tagType);
- fActiveArea.r = stream.TagValue_int32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("ActiveArea: T = %d L = %d B = %d R = %d\n",
- (int) fActiveArea.t,
- (int) fActiveArea.l,
- (int) fActiveArea.b,
- (int) fActiveArea.r);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcMaskedAreas:
- {
-
- CheckMainIFD (parentCode, tagCode, fNewSubFileType);
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- uint32 rect_count = tagCount / 4;
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, rect_count * 4))
- return false;
-
- fMaskedAreaCount = rect_count;
-
- if (fMaskedAreaCount > kMaxMaskedAreas)
- fMaskedAreaCount = kMaxMaskedAreas;
-
- for (j = 0; j < fMaskedAreaCount; j++)
- {
-
- fMaskedArea [j].t = stream.TagValue_int32 (tagType);
- fMaskedArea [j].l = stream.TagValue_int32 (tagType);
- fMaskedArea [j].b = stream.TagValue_int32 (tagType);
- fMaskedArea [j].r = stream.TagValue_int32 (tagType);
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("MaskedAreas: %u\n", (unsigned) fMaskedAreaCount);
-
- for (j = 0; j < fMaskedAreaCount; j++)
- {
-
- printf (" Area [%u]: T = %d L = %d B = %d R = %d\n",
- (unsigned) j,
- (int) fMaskedArea [j].t,
- (int) fMaskedArea [j].l,
- (int) fMaskedArea [j].b,
- (int) fMaskedArea [j].r);
-
- }
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcPreviewApplicationName:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fPreviewInfo.fApplicationName,
- false);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("PreviewApplicationName: ");
-
- DumpString (fPreviewInfo.fApplicationName);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcPreviewApplicationVersion:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fPreviewInfo.fApplicationVersion,
- false);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("PreviewApplicationVersion: ");
-
- DumpString (fPreviewInfo.fApplicationVersion);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcPreviewSettingsName:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fPreviewInfo.fSettingsName,
- false);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("PreviewSettingsName: ");
-
- DumpString (fPreviewInfo.fSettingsName);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcPreviewSettingsDigest:
- {
-
- if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
- return false;
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 16))
- return false;
-
- stream.Get (fPreviewInfo.fSettingsDigest.data, 16);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("PreviewSettingsDigest: ");
-
- DumpFingerprint (fPreviewInfo.fSettingsDigest);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcPreviewColorSpace:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- CheckTagCount (parentCode, tagCode, tagCount, 1);
-
- fPreviewInfo.fColorSpace = (PreviewColorSpaceEnum)
- stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("PreviewColorSpace: %s\n",
- LookupPreviewColorSpace ((uint32) fPreviewInfo.fColorSpace));
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcPreviewDateTime:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttAscii);
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- fPreviewInfo.fDateTime,
- false);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("PreviewDateTime: ");
-
- DumpString (fPreviewInfo.fDateTime);
-
- printf ("\n");
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcRowInterleaveFactor:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
- return false;
-
- fRowInterleaveFactor = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("RowInterleaveFactor: %u\n",
- (unsigned) fRowInterleaveFactor);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcSubTileBlockSize:
- {
-
- CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
- return false;
-
- fSubTileBlockRows = stream.TagValue_uint32 (tagType);
- fSubTileBlockCols = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("SubTileBlockSize: rows = %u, cols = %u\n",
- (unsigned) fSubTileBlockRows,
- (unsigned) fSubTileBlockCols);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcOpcodeList1:
- {
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- fOpcodeList1Count = tagCount;
- fOpcodeList1Offset = tagOffset;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("OpcodeList1: count = %u, offset = %u\n",
- (unsigned) fOpcodeList1Count,
- (unsigned) fOpcodeList1Offset);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcOpcodeList2:
- {
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- fOpcodeList2Count = tagCount;
- fOpcodeList2Offset = tagOffset;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("OpcodeList2: count = %u, offset = %u\n",
- (unsigned) fOpcodeList2Count,
- (unsigned) fOpcodeList2Offset);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcOpcodeList3:
- {
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttUndefined);
-
- fOpcodeList3Count = tagCount;
- fOpcodeList3Offset = tagOffset;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("OpcodeList3: count = %u, offset = %u\n",
- (unsigned) fOpcodeList3Count,
- (unsigned) fOpcodeList3Offset);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcRawToPreviewGain:
- {
-
- #if qDNGValidate
-
- if (fNewSubFileType != sfPreviewImage)
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not allowed IFDs with NewSubFileType != PreviewImage",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #endif
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttDouble);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
- return false;
-
- fPreviewInfo.fRawToPreviewGain = stream.TagValue_real64 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("RawToPreviewGain = %f\n",
- fPreviewInfo.fRawToPreviewGain);
-
- }
-
- #endif
-
- break;
-
- }
-
- case tcCacheVersion:
- {
-
- #if qDNGValidate
-
- if (fNewSubFileType != sfPreviewImage)
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not allowed IFDs with NewSubFileType != PreviewImage",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #endif
-
- CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
-
- CheckTagType (parentCode, tagCode, tagType, ttLong);
-
- if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
- return false;
-
- fPreviewInfo.fCacheVersion = stream.TagValue_uint32 (tagType);
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("CacheVersion = 0x%x\n",
- (unsigned) fPreviewInfo.fCacheVersion);
-
- }
-
- #endif
-
- break;
-
- }
-
- default:
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-void dng_ifd::PostParse ()
- {
-
- uint32 j;
- uint32 k;
-
- // There is only one PlanarConfiguration for single sample imaages.
-
- if (fSamplesPerPixel == 1)
- {
- fPlanarConfiguration = pcInterleaved;
- }
-
- // Default tile size.
-
- if (fTileWidth == 0)
- {
- fTileWidth = fImageWidth;
- }
-
- if (fTileLength == 0)
- {
- fTileLength = fImageLength;
- }
-
- // Default ActiveArea.
-
- dng_rect imageArea (0, 0, fImageLength, fImageWidth);
-
- if (fActiveArea.IsZero ())
- {
- fActiveArea = imageArea;
- }
-
- // Default crop size.
-
- if (fDefaultCropSizeH.d == 0)
- {
- fDefaultCropSizeH = dng_urational (fActiveArea.W (), 1);
- }
-
- if (fDefaultCropSizeV.d == 0)
- {
- fDefaultCropSizeV = dng_urational (fActiveArea.H (), 1);
- }
-
- // Default white level.
-
- uint32 defaultWhite = (fSampleFormat [0] == sfFloatingPoint) ?
- 1 :
- (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
-
- for (j = 0; j < kMaxSamplesPerPixel; j++)
- {
-
- if (fWhiteLevel [j] < 0.0)
- {
- fWhiteLevel [j] = (real64) defaultWhite;
- }
-
- }
-
- // Check AntiAliasStrength.
-
- if (fAntiAliasStrength.As_real64 () < 0.0 ||
- fAntiAliasStrength.As_real64 () > 1.0)
- {
-
- #if qDNGValidate
-
- ReportWarning ("Invalid AntiAliasStrength");
-
- #endif
-
- fAntiAliasStrength = dng_urational (1, 1);
-
- }
-
- // Check MaskedAreas.
-
- for (j = 0; j < fMaskedAreaCount; j++)
- {
-
- const dng_rect &r = fMaskedArea [j];
-
- if (r.IsEmpty () || ((r & imageArea) != r))
- {
-
- #if qDNGValidate
-
- ReportWarning ("Invalid MaskedArea");
-
- #endif
-
- fMaskedAreaCount = 0;
-
- break;
-
- }
-
- if ((r & fActiveArea).NotEmpty ())
- {
-
- #if qDNGValidate
-
- ReportWarning ("MaskedArea overlaps ActiveArea");
-
- #endif
-
- fMaskedAreaCount = 0;
-
- break;
-
- }
-
- for (k = 0; k < j; k++)
- {
-
- if ((r & fMaskedArea [k]).NotEmpty ())
- {
-
- #if qDNGValidate
-
- ReportWarning ("MaskedAreas overlap each other");
-
- #endif
-
- fMaskedAreaCount = 0;
-
- break;
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_ifd::IsValidCFA (dng_shared &shared,
- uint32 parentCode)
- {
-
- uint32 j;
- uint32 k;
- uint32 n;
-
- #if !qDNGValidate
-
- (void) parentCode; // Unused
-
- #endif
-
- if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
- fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
- {
-
- #if qDNGValidate
-
- ReportError ("Missing or invalid CFAPatternRepeatDim",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- uint32 count [kMaxColorPlanes];
-
- for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
- {
- count [n] = 0;
- }
-
- for (j = 0; j < fCFARepeatPatternRows; j++)
- {
-
- for (k = 0; k < fCFARepeatPatternCols; k++)
- {
-
- bool found = false;
-
- for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
- {
-
- if (fCFAPattern [j] [k] == fCFAPlaneColor [n])
- {
- found = true;
- count [n] ++;
- break;
- }
-
- }
-
- if (!found)
- {
-
- #if qDNGValidate
-
- ReportError ("CFAPattern contains colors not included in the CFAPlaneColor tag",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- }
-
- for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
- {
-
- if (count [n] == 0)
- {
-
- #if qDNGValidate
-
- ReportError ("CFAPattern does not contain all the colors in the CFAPlaneColor tag",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- if (fCFALayout < 1 || fCFALayout > 9)
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid CFALayout",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-bool dng_ifd::IsValidDNG (dng_shared &shared,
- uint32 parentCode)
- {
-
- uint32 j;
-
- bool isFloatingPoint = (fSampleFormat [0] == sfFloatingPoint);
-
- dng_rect imageArea (0, 0, fImageLength, fImageWidth);
-
- uint32 defaultWhite = isFloatingPoint ?
- 1 :
- (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
-
- bool isMonochrome = (shared.fCameraProfile.fColorPlanes == 1);
- bool isColor = !isMonochrome;
-
- bool isMainIFD = (fNewSubFileType == sfMainImage);
-
- // Check NewSubFileType.
-
- if (!fUsesNewSubFileType)
- {
-
- #if qDNGValidate
-
- ReportError ("Missing NewSubFileType",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (fNewSubFileType != sfMainImage &&
- fNewSubFileType != sfPreviewImage &&
- fNewSubFileType != sfTransparencyMask &&
- fNewSubFileType != sfPreviewMask &&
- fNewSubFileType != sfAltPreviewImage)
- {
-
- #if qDNGValidate
-
- ReportError ("Unexpected NewSubFileType",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check ImageWidth and ImageLength.
-
- if (fImageWidth < 1)
- {
-
- #if qDNGValidate
-
- ReportError ("Missing or invalid ImageWidth",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (fImageLength < 1)
- {
-
- #if qDNGValidate
-
- ReportError ("Missing or invalid ImageLength",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (fImageWidth > kMaxImageSide ||
- fImageLength > kMaxImageSide)
- {
-
- #if qDNGValidate
-
- ReportWarning ("Image size is larger than supported");
-
- #endif
-
- return false;
-
- }
-
- // Check PhotometricInterpretation.
-
- if (fNewSubFileType == sfTransparencyMask ||
- fNewSubFileType == sfPreviewMask)
- {
-
- if (fPhotometricInterpretation != piTransparencyMask)
- {
-
- #if qDNGValidate
-
- ReportError ("NewSubFileType requires PhotometricInterpretation = TransparencyMask",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- else
- {
-
- switch (fPhotometricInterpretation)
- {
-
- case piBlackIsZero:
- case piRGB:
- case piYCbCr:
- {
-
- if (isMainIFD)
- {
-
- #if qDNGValidate
-
- ReportError ("PhotometricInterpretation requires NewSubFileType = 1",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- break;
-
- }
-
- case piCFA:
- {
-
- if (!isMainIFD)
- {
-
- #if qDNGValidate
-
- ReportError ("PhotometricInterpretation requires NewSubFileType = 0",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- break;
-
- }
-
- case piLinearRaw:
- break;
-
- default:
- {
-
- #if qDNGValidate
-
- ReportError ("Missing or invalid PhotometricInterpretation",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- }
-
- switch (fPhotometricInterpretation)
- {
-
- case piBlackIsZero:
- {
-
- // Allow black in white previews even in color images since the
- // raw processing software may be converting to grayscale.
-
- if (isColor && isMainIFD)
- {
-
- #if qDNGValidate
-
- ReportError ("PhotometricInterpretation forbids use of ColorMatrix1 tag",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- break;
-
- }
-
- case piRGB:
- case piYCbCr:
- {
-
- // Allow color previews even in monochrome DNG files, since the
- // raw procesing software may be adding color effects.
-
- break;
-
- }
-
- case piCFA:
- {
-
- if (isMonochrome)
- {
-
- #if qDNGValidate
-
- ReportError ("PhotometricInterpretation requires use of ColorMatrix1 tag",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- break;
-
- }
-
- }
-
- if (isFloatingPoint)
- {
-
- if (fPhotometricInterpretation != piCFA &&
- fPhotometricInterpretation != piLinearRaw &&
- fPhotometricInterpretation != piTransparencyMask)
- {
-
- #if qDNGValidate
-
- ReportError ("Floating point data requires PhotometricInterpretation CFA or LinearRaw or TransparencyMask",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- // Check SamplesPerPixel and BitsPerSample.
-
- uint32 minSamplesPerPixel = 1;
- uint32 maxSamplesPerPixel = 1;
-
- uint32 minBitsPerSample = 8;
- uint32 maxBitsPerSample = 16;
-
- switch (fPhotometricInterpretation)
- {
-
- case piBlackIsZero:
- break;
-
- case piRGB:
- case piYCbCr:
- {
- minSamplesPerPixel = 3;
- maxSamplesPerPixel = 3;
- break;
- }
-
- case piCFA:
- {
- maxSamplesPerPixel = kMaxSamplesPerPixel;
- maxBitsPerSample = 32;
- break;
- }
-
- case piLinearRaw:
- {
- minSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
- maxSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
- maxBitsPerSample = 32;
- break;
- }
-
- case piTransparencyMask:
- {
- minBitsPerSample = 8;
- maxBitsPerSample = 16;
- break;
- }
-
- }
-
- if (isFloatingPoint)
- {
- minBitsPerSample = 16;
- maxBitsPerSample = 32;
- }
-
- if (fSamplesPerPixel < minSamplesPerPixel ||
- fSamplesPerPixel > maxSamplesPerPixel)
- {
-
- #if qDNGValidate
-
- ReportError ("Missing or invalid SamplesPerPixel",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- for (j = 0; j < kMaxSamplesPerPixel; j++)
- {
-
- if (j < fSamplesPerPixel)
- {
-
- if (fBitsPerSample [j] < minBitsPerSample ||
- fBitsPerSample [j] > maxBitsPerSample)
- {
-
- #if qDNGValidate
-
- ReportError ("Missing or invalid BitsPerSample",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (isFloatingPoint &&
- fBitsPerSample [j] != 16 &&
- fBitsPerSample [j] != 24 &&
- fBitsPerSample [j] != 32)
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid BitsPerSample for floating point",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (minBitsPerSample == 8 &&
- maxBitsPerSample == 16 &&
- fBitsPerSample [j] != 8 &&
- fBitsPerSample [j] != 16)
- {
-
- #if qDNGValidate
-
- ReportError ("Rendered previews and integer masks require 8 or 16 bits per sample",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (j > 0 && fBitsPerSample [j] != fBitsPerSample [0])
- {
-
- #if qDNGValidate
-
- ReportError ("BitsPerSample not equal for all samples",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- else
- {
-
- if (fBitsPerSample [j] != 0)
- {
-
- #if qDNGValidate
-
- ReportError ("Too many values specified in BitsPerSample",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- }
-
- // Check Compression.
-
- switch (fCompression)
- {
-
- case ccUncompressed:
- break;
-
- case ccJPEG:
- {
-
- if (fPhotometricInterpretation == piRGB)
- {
-
- #if qDNGValidate
-
- ReportError ("JPEG previews should use PhotometricInterpretation = YCbYb",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (fBitsPerSample [0] > 16)
- {
-
- #if qDNGValidate
-
- ReportError ("JPEG compression is limited to 16 bits/sample",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- break;
-
- }
-
- case ccLossyJPEG:
- {
-
- if (fPhotometricInterpretation != piLinearRaw)
- {
-
- #if qDNGValidate
-
- ReportError ("Lossy JPEG compression code requires PhotometricInterpretation = LinearRaw",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (fBitsPerSample [0] != 8)
- {
-
- #if qDNGValidate
-
- ReportError ("Lossy JPEG compression is limited to 8 bits/sample",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- break;
-
- }
-
- case ccDeflate:
- {
-
- if (!isFloatingPoint &&
- fBitsPerSample [0] != 32 &&
- fPhotometricInterpretation != piTransparencyMask)
- {
-
- #if qDNGValidate
-
- ReportError ("ZIP compression is limited to floating point and 32-bit integer and transparency masks",
- LookupParentCode (parentCode));
-
- #endif
-
- }
-
- break;
-
- }
-
- default:
- {
-
- #if qDNGValidate
-
- ReportError ("Unsupported Compression",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- // Check Predictor.
-
- if (isFloatingPoint && fCompression == ccDeflate &&
- (fPredictor == cpFloatingPoint ||
- fPredictor == cpFloatingPointX2 ||
- fPredictor == cpFloatingPointX4))
- {
-
- // These combinations are supported.
-
- }
-
- else if (!isFloatingPoint && fCompression == ccDeflate &&
- (fPredictor == cpHorizontalDifference ||
- fPredictor == cpHorizontalDifferenceX2 ||
- fPredictor == cpHorizontalDifferenceX4))
- {
-
- // These combinations are supported.
-
- }
-
- else if (fPredictor != cpNullPredictor)
- {
-
- #if qDNGValidate
-
- ReportError ("Unsupported Predictor",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check FillOrder.
-
- if (fFillOrder != 1)
- {
-
- #if qDNGValidate
-
- ReportError ("Unsupported FillOrder",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check PlanarConfiguration.
-
- if (fPlanarConfiguration != pcInterleaved)
- {
-
- #if qDNGValidate
-
- ReportError ("Unsupported PlanarConfiguration",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check ExtraSamples.
-
- if (fExtraSamplesCount != 0)
- {
-
- #if qDNGValidate
-
- ReportError ("Unsupported ExtraSamples",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check SampleFormat.
-
- for (j = 0; j < fSamplesPerPixel; j++)
- {
-
- if (fSampleFormat [j] != (isFloatingPoint ? sfFloatingPoint : sfUnsignedInteger))
- {
-
- #if qDNGValidate
-
- ReportError ("Unsupported SampleFormat",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- // Check Orientation.
-
- if (fOrientation > 9)
- {
-
- #if qDNGValidate
-
- ReportError ("Unknown Orientation",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- #if qDNGValidate
-
- if (fOrientation != 0 && parentCode != 0)
- {
-
- ReportWarning ("Unexpected Orientation tag",
- LookupParentCode (parentCode));
-
- }
-
- if (fOrientation == 0 && parentCode == 0)
- {
-
- ReportWarning ("Missing Orientation tag",
- LookupParentCode (parentCode));
-
- }
-
- #endif
-
- // Check Strips vs. Tiles.
-
- if (!fUsesStrips && !fUsesTiles)
- {
-
- #if qDNGValidate
-
- ReportError ("IFD uses neither strips nor tiles",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (fUsesStrips && fUsesTiles)
- {
-
- #if qDNGValidate
-
- ReportError ("IFD uses both strips and tiles",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check tile info.
-
- uint32 tilesWide = (fImageWidth + fTileWidth - 1) / fTileWidth;
- uint32 tilesHigh = (fImageLength + fTileLength - 1) / fTileLength;
-
- uint32 tileCount = tilesWide * tilesHigh;
-
- if (fTileOffsetsCount != tileCount)
- {
-
- #if qDNGValidate
-
- ReportError ("Missing or invalid Strip/TileOffsets",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (fTileByteCountsCount != tileCount)
- {
-
- #if qDNGValidate
-
- ReportError ("Missing or invalid Strip/TileByteCounts",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check CFA pattern.
-
- if (fPhotometricInterpretation == piCFA)
- {
-
- if (!IsValidCFA (shared, parentCode))
- {
-
- return false;
-
- }
-
- }
-
- // Check ActiveArea.
-
- if (((fActiveArea & imageArea) != fActiveArea) || fActiveArea.IsEmpty ())
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid ActiveArea",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (fActiveArea != imageArea)
- {
-
- if (shared.fDNGBackwardVersion < dngVersion_1_1_0_0)
- {
-
- #if qDNGValidate
-
- ReportError ("Non-default ActiveArea tag not allowed in this DNG version",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- // Check LinearizationTable.
-
- if (fLinearizationTableCount)
- {
-
- if (fLinearizationTableType != ttShort)
- {
-
- #if qDNGValidate
-
- ReportError ("Invalidate LinearizationTable type",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (fLinearizationTableCount < 2 ||
- fLinearizationTableCount > 65536)
- {
-
- #if qDNGValidate
-
- ReportError ("Invalidate LinearizationTable count",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (isFloatingPoint || fBitsPerSample [0] > 16)
- {
-
- #if qDNGValidate
-
- ReportError ("Linearization table not allowed for this data type",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- // Check BlackLevelRepeatDim.
-
- if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern ||
- fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern)
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid BlackLevelRepeatDim",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check BlackLevelDeltaH.
-
- if (fBlackLevelDeltaHCount != 0 &&
- fBlackLevelDeltaHCount != fActiveArea.W ())
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid BlackLevelDeltaH count",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check BlackLevelDeltaV.
-
- if (fBlackLevelDeltaVCount != 0 &&
- fBlackLevelDeltaVCount != fActiveArea.H ())
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid BlackLevelDeltaV count",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- // Check WhiteLevel.
-
- real64 maxWhite = fLinearizationTableCount ? 65535.0
- : (real64) defaultWhite;
-
- for (j = 0; j < fSamplesPerPixel; j++)
- {
-
- if (fWhiteLevel [j] < 1.0 || (fWhiteLevel [j] > maxWhite && !isFloatingPoint))
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid WhiteLevel",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- // Check BlackLevel.
-
- for (j = 0; j < kMaxBlackPattern; j++)
- {
-
- for (uint32 k = 0; k < kMaxBlackPattern; k++)
- {
-
- for (uint32 s = 0; s < kMaxSamplesPerPixel; s++)
- {
-
- const real64 black = fBlackLevel [j][k][s];
-
- if (black >= fWhiteLevel [s])
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid BlackLevel",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- }
-
- }
-
- // Check DefaultScale.
-
- if (fDefaultScaleH.As_real64 () <= 0.0 ||
- fDefaultScaleV.As_real64 () <= 0.0)
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid DefaultScale");
-
- #endif
-
- return false;
-
- }
-
- // Check BestQualityScale.
-
- if (fBestQualityScale.As_real64 () < 1.0)
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid BestQualityScale");
-
- #endif
-
- return false;
-
- }
-
- // Check DefaultCropOrigin.
-
- if (fDefaultCropOriginH.As_real64 () < 0.0 ||
- fDefaultCropOriginV.As_real64 () < 0.0 ||
- fDefaultCropOriginH.As_real64 () >= (real64) fActiveArea.W () ||
- fDefaultCropOriginV.As_real64 () >= (real64) fActiveArea.H ())
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid DefaultCropOrigin");
-
- #endif
-
- return false;
-
- }
-
- // Check DefaultCropSize.
-
- if (fDefaultCropSizeH.As_real64 () <= 0.0 ||
- fDefaultCropSizeV.As_real64 () <= 0.0 ||
- fDefaultCropSizeH.As_real64 () > (real64) fActiveArea.W () ||
- fDefaultCropSizeV.As_real64 () > (real64) fActiveArea.H ())
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid DefaultCropSize");
-
- #endif
-
- return false;
-
- }
-
- // Check DefaultCrop area.
-
- if (fDefaultCropOriginH.As_real64 () +
- fDefaultCropSizeH .As_real64 () > (real64) fActiveArea.W () ||
- fDefaultCropOriginV.As_real64 () +
- fDefaultCropSizeV .As_real64 () > (real64) fActiveArea.H ())
- {
-
- #if qDNGValidate
-
- ReportError ("Default crop extends outside ActiveArea");
-
- #endif
-
- return false;
-
- }
-
- // Check DefaultUserCrop.
-
- if (fDefaultUserCropT.As_real64 () < 0.0 ||
- fDefaultUserCropL.As_real64 () < 0.0 ||
- fDefaultUserCropB.As_real64 () > 1.0 ||
- fDefaultUserCropR.As_real64 () > 1.0 ||
- fDefaultUserCropT.As_real64 () >= fDefaultUserCropB.As_real64 () ||
- fDefaultUserCropL.As_real64 () >= fDefaultUserCropR.As_real64 ())
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid DefaultUserCrop");
-
- #endif // qDNGValidate
-
- return false;
-
- }
-
- // The default crop and default user crop tags are not allowed for the
- // non-main image. If they are there, at least require that they be NOPs.
-
- if (!isMainIFD)
- {
-
- if (Round_int32 (fDefaultCropOriginH.As_real64 ()) != 0 ||
- Round_int32 (fDefaultCropOriginV.As_real64 ()) != 0)
- {
-
- #if qDNGValidate
-
- ReportError ("non-default DefaultCropOrigin on non-main image");
-
- #endif
-
- return false;
-
- }
-
- if (Round_int32 (fDefaultCropSizeH.As_real64 ()) != (int32) fImageWidth ||
- Round_int32 (fDefaultCropSizeV.As_real64 ()) != (int32) fImageLength)
- {
-
- #if qDNGValidate
-
- ReportError ("non-default DefaultCropSize on non-main image");
-
- #endif
-
- return false;
-
- }
-
- if (fDefaultUserCropT.As_real64 () != 0.0 ||
- fDefaultUserCropL.As_real64 () != 0.0 ||
- fDefaultUserCropB.As_real64 () != 1.0 ||
- fDefaultUserCropR.As_real64 () != 1.0)
- {
-
- #if qDNGValidate
-
- ReportError ("non-default DefaultCUserCrop on non-main image");
-
- #endif // qDNGValidate
-
- return false;
-
- }
-
- }
-
- // Warning if too little padding on CFA image.
-
- #if qDNGValidate
-
- if (fPhotometricInterpretation == piCFA)
- {
-
- const real64 kMinPad = 1.9;
-
- if (fDefaultCropOriginH.As_real64 () < kMinPad)
- {
-
- ReportWarning ("Too little padding on left edge of CFA image",
- "possible interpolation artifacts");
-
- }
-
- if (fDefaultCropOriginV.As_real64 () < kMinPad)
- {
-
- ReportWarning ("Too little padding on top edge of CFA image",
- "possible interpolation artifacts");
-
- }
-
- if (fDefaultCropOriginH.As_real64 () +
- fDefaultCropSizeH .As_real64 () > (real64) fActiveArea.W () - kMinPad)
- {
-
- ReportWarning ("Too little padding on right edge of CFA image",
- "possible interpolation artifacts");
-
- }
-
- if (fDefaultCropOriginV.As_real64 () +
- fDefaultCropSizeV .As_real64 () > (real64) fActiveArea.H () - kMinPad)
- {
-
- ReportWarning ("Too little padding on bottom edge of CFA image",
- "possible interpolation artifacts");
-
- }
-
- }
-
- #endif
-
- // Check RowInterleaveFactor
-
- if (fRowInterleaveFactor != 1)
- {
-
- if (fRowInterleaveFactor < 1 ||
- fRowInterleaveFactor > fImageLength)
- {
-
- #if qDNGValidate
-
- ReportError ("RowInterleaveFactor out of valid range",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
- {
-
- #if qDNGValidate
-
- ReportError ("Non-default RowInterleaveFactor tag not allowed in this DNG version",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- // Check SubTileBlockSize
-
- if (fSubTileBlockRows != 1 || fSubTileBlockCols != 1)
- {
-
- if (fSubTileBlockRows < 2 || fSubTileBlockRows > fTileLength ||
- fSubTileBlockCols < 1 || fSubTileBlockCols > fTileWidth)
- {
-
- #if qDNGValidate
-
- ReportError ("SubTileBlockSize out of valid range",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if ((fTileLength % fSubTileBlockRows) != 0 ||
- (fTileWidth % fSubTileBlockCols) != 0)
- {
-
- #if qDNGValidate
-
- ReportError ("TileSize not exact multiple of SubTileBlockSize",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
- {
-
- #if qDNGValidate
-
- ReportError ("Non-default SubTileBlockSize tag not allowed in this DNG version",
- LookupParentCode (parentCode));
-
- #endif
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_ifd::TilesAcross () const
- {
-
- if (fTileWidth)
- {
-
- return (fImageWidth + fTileWidth - 1) / fTileWidth;
-
- }
-
- return 0;
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_ifd::TilesDown () const
- {
-
- if (fTileLength)
- {
-
- return (fImageLength + fTileLength - 1) / fTileLength;
-
- }
-
- return 0;
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_ifd::TilesPerImage () const
- {
-
- uint32 total = TilesAcross () * TilesDown ();
-
- if (fPlanarConfiguration == pcPlanar)
- {
-
- total *= fSamplesPerPixel;
-
- }
-
- return total;
-
- }
-
-/*****************************************************************************/
-
-dng_rect dng_ifd::TileArea (uint32 rowIndex,
- uint32 colIndex) const
- {
-
- dng_rect r;
-
- r.t = rowIndex * fTileLength;
- r.b = r.t + fTileLength;
-
- r.l = colIndex * fTileWidth;
- r.r = r.l + fTileWidth;
-
- // If this IFD is using strips rather than tiles, the last strip
- // is trimmed so it does not extend beyond the end of the image.
-
- if (fUsesStrips)
- {
-
- r.b = Min_uint32 (r.b, fImageLength);
-
- }
-
- return r;
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-uint32 dng_ifd::TileByteCount (const dng_rect &tile) const
- {
-
- if (fCompression == ccUncompressed)
- {
-
- uint32 bitsPerRow = tile.W () *
- fBitsPerSample [0];
-
- if (fPlanarConfiguration == pcInterleaved)
- {
-
- bitsPerRow *= fSamplesPerPixel;
-
- }
-
- uint32 bytesPerRow = (bitsPerRow + 7) >> 3;
-
- if (fPlanarConfiguration == pcRowInterleaved)
- {
-
- bytesPerRow *= fSamplesPerPixel;
-
- }
-
- return bytesPerRow * tile.H ();
-
- }
-
- return 0;
-
- }
-
-/*****************************************************************************/
-
-void dng_ifd::SetSingleStrip ()
- {
-
- fTileWidth = fImageWidth;
- fTileLength = fImageLength;
-
- fUsesTiles = false;
- fUsesStrips = true;
-
- }
-
-/*****************************************************************************/
-
-void dng_ifd::FindTileSize (uint32 bytesPerTile,
- uint32 cellH,
- uint32 cellV)
- {
-
- uint32 bytesPerSample = fSamplesPerPixel *
- ((fBitsPerSample [0] + 7) >> 3);
-
- uint32 samplesPerTile = bytesPerTile / bytesPerSample;
-
- uint32 tileSide = Round_uint32 (sqrt ((real64) samplesPerTile));
-
- fTileWidth = Min_uint32 (fImageWidth, tileSide);
-
- uint32 across = TilesAcross ();
-
- fTileWidth = (fImageWidth + across - 1) / across;
-
- fTileWidth = ((fTileWidth + cellH - 1) / cellH) * cellH;
-
- fTileLength = Pin_uint32 (1,
- samplesPerTile / fTileWidth,
- fImageLength);
-
- uint32 down = TilesDown ();
-
- fTileLength = (fImageLength + down - 1) / down;
-
- fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
-
- fUsesTiles = true;
- fUsesStrips = false;
-
- }
-
-/*****************************************************************************/
-
-void dng_ifd::FindStripSize (uint32 bytesPerStrip,
- uint32 cellV)
- {
-
- uint32 bytesPerSample = fSamplesPerPixel *
- ((fBitsPerSample [0] + 7) >> 3);
-
- uint32 samplesPerStrip = bytesPerStrip / bytesPerSample;
-
- fTileWidth = fImageWidth;
-
- fTileLength = Pin_uint32 (1,
- samplesPerStrip / fTileWidth,
- fImageLength);
-
- uint32 down = TilesDown ();
-
- fTileLength = (fImageLength + down - 1) / down;
-
- fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
-
- fUsesTiles = false;
- fUsesStrips = true;
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_ifd::PixelType () const
- {
-
- if (fSampleFormat [0] == sfFloatingPoint)
- {
- return ttFloat;
- }
-
- if (fBitsPerSample [0] <= 8)
- {
- return ttByte;
- }
-
- else if (fBitsPerSample [0] <= 16)
- {
- return ttShort;
- }
-
- return ttLong;
-
- }
-
-/*****************************************************************************/
-
-bool dng_ifd::IsBaselineJPEG () const
- {
-
- if (fBitsPerSample [0] != 8)
- {
- return false;
- }
-
- if (fSampleFormat [0] != sfUnsignedInteger)
- {
- return false;
- }
-
- if (fCompression == ccLossyJPEG)
- {
- return true;
- }
-
- if (fCompression != ccJPEG)
- {
- return false;
- }
-
- switch (fPhotometricInterpretation)
- {
-
- case piBlackIsZero:
- {
- return (fSamplesPerPixel == 1);
- }
-
- case piYCbCr:
- {
- return (fSamplesPerPixel == 3 ) &&
- (fPlanarConfiguration == pcInterleaved);
- }
-
- default:
- break;
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-bool dng_ifd::CanRead () const
- {
-
- dng_read_image reader;
-
- return reader.CanRead (*this);
-
- }
-
-/*****************************************************************************/
-
-void dng_ifd::ReadImage (dng_host &host,
- dng_stream &stream,
- dng_image &image,
- dng_jpeg_image *jpegImage,
- dng_fingerprint *jpegDigest) const
- {
-
- dng_read_image reader;
-
- reader.Read (host,
- *this,
- stream,
- image,
- jpegImage,
- jpegDigest);
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2012 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_ifd.cpp#3 $ */
+/* $DateTime: 2012/06/05 11:05:39 $ */
+/* $Change: 833352 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_ifd.h"
+
+#include "dng_exceptions.h"
+#include "dng_flags.h"
+#include "dng_globals.h"
+#include "dng_ifd.h"
+#include "dng_types.h"
+#include "dng_parse_utils.h"
+#include "dng_read_image.h"
+#include "dng_stream.h"
+#include "dng_tag_codes.h"
+#include "dng_tag_types.h"
+#include "dng_tag_values.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_preview_info::dng_preview_info ()
+
+ : fIsPrimary (true)
+ , fApplicationName ()
+ , fApplicationVersion ()
+ , fSettingsName ()
+ , fSettingsDigest ()
+ , fColorSpace (previewColorSpace_MaxEnum)
+ , fDateTime ()
+ , fRawToPreviewGain (1.0)
+ , fCacheVersion (0)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_preview_info::~dng_preview_info ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_ifd::dng_ifd ()
+
+ : fUsesNewSubFileType (false)
+ , fNewSubFileType (0)
+
+ , fImageWidth (0)
+ , fImageLength (0)
+
+ , fCompression (ccUncompressed)
+ , fPredictor (cpNullPredictor)
+
+ , fPhotometricInterpretation (0xFFFFFFFF)
+
+ , fFillOrder (1)
+
+ , fOrientation (0)
+ , fOrientationType (0)
+ , fOrientationOffset (kDNGStreamInvalidOffset)
+ , fOrientationBigEndian (false)
+
+ , fSamplesPerPixel (1)
+
+ , fPlanarConfiguration (pcInterleaved)
+
+ , fXResolution (0.0)
+ , fYResolution (0.0)
+ , fResolutionUnit (0)
+
+ , fUsesStrips (false)
+ , fUsesTiles (false)
+
+ , fTileWidth (0)
+ , fTileLength (0)
+
+ , fTileOffsetsType (0)
+ , fTileOffsetsCount (0)
+ , fTileOffsetsOffset (0)
+
+ , fTileByteCountsType (0)
+ , fTileByteCountsCount (0)
+ , fTileByteCountsOffset (0)
+
+ , fSubIFDsCount (0)
+ , fSubIFDsOffset (0)
+
+ , fExtraSamplesCount (0)
+
+ , fJPEGTablesCount (0)
+ , fJPEGTablesOffset (0)
+
+ , fJPEGInterchangeFormat (0)
+ , fJPEGInterchangeFormatLength (0)
+
+ , fYCbCrCoefficientR (0.0)
+ , fYCbCrCoefficientG (0.0)
+ , fYCbCrCoefficientB (0.0)
+
+ , fYCbCrSubSampleH (0)
+ , fYCbCrSubSampleV (0)
+
+ , fYCbCrPositioning (0)
+
+ , fCFARepeatPatternRows (0)
+ , fCFARepeatPatternCols (0)
+
+ , fCFALayout (1)
+
+ , fLinearizationTableType (0)
+ , fLinearizationTableCount (0)
+ , fLinearizationTableOffset (0)
+
+ , fBlackLevelRepeatRows (1)
+ , fBlackLevelRepeatCols (1)
+
+ , fBlackLevelDeltaHType (0)
+ , fBlackLevelDeltaHCount (0)
+ , fBlackLevelDeltaHOffset (0)
+
+ , fBlackLevelDeltaVType (0)
+ , fBlackLevelDeltaVCount (0)
+ , fBlackLevelDeltaVOffset (0)
+
+ , fDefaultScaleH (1, 1)
+ , fDefaultScaleV (1, 1)
+
+ , fBestQualityScale (1, 1)
+
+ , fDefaultCropOriginH (0, 1)
+ , fDefaultCropOriginV (0, 1)
+
+ , fDefaultCropSizeH ()
+ , fDefaultCropSizeV ()
+
+ , fDefaultUserCropT (0, 1)
+ , fDefaultUserCropL (0, 1)
+ , fDefaultUserCropB (1, 1)
+ , fDefaultUserCropR (1, 1)
+
+ , fBayerGreenSplit (0)
+
+ , fChromaBlurRadius ()
+
+ , fAntiAliasStrength (1, 1)
+
+ , fActiveArea ()
+
+ , fMaskedAreaCount (0)
+
+ , fRowInterleaveFactor (1)
+
+ , fSubTileBlockRows (1)
+ , fSubTileBlockCols (1)
+
+ , fPreviewInfo ()
+
+ , fOpcodeList1Count (0)
+ , fOpcodeList1Offset (0)
+
+ , fOpcodeList2Count (0)
+ , fOpcodeList2Offset (0)
+
+ , fOpcodeList3Count (0)
+ , fOpcodeList3Offset (0)
+
+ , fLosslessJPEGBug16 (false)
+
+ , fSampleBitShift (0)
+
+ , fThisIFD (0)
+ , fNextIFD (0)
+
+ , fCompressionQuality (-1)
+
+ , fPatchFirstJPEGByte (false)
+
+ {
+
+ uint32 j;
+ uint32 k;
+ uint32 n;
+
+ for (j = 0; j < kMaxSamplesPerPixel; j++)
+ {
+ fBitsPerSample [j] = 0;
+ }
+
+ for (j = 0; j < kMaxTileInfo; j++)
+ {
+ fTileOffset [j] = 0;
+ fTileByteCount [j] = 0;
+ }
+
+ for (j = 0; j < kMaxSamplesPerPixel; j++)
+ {
+ fExtraSamples [j] = esUnspecified;
+ }
+
+ for (j = 0; j < kMaxSamplesPerPixel; j++)
+ {
+ fSampleFormat [j] = sfUnsignedInteger;
+ }
+
+ for (j = 0; j < 6; j++)
+ {
+ fReferenceBlackWhite [j] = 0.0;
+ }
+
+ for (j = 0; j < kMaxCFAPattern; j++)
+ for (k = 0; k < kMaxCFAPattern; k++)
+ {
+ fCFAPattern [j] [k] = 255;
+ }
+
+ for (j = 0; j < kMaxColorPlanes; j++)
+ {
+ fCFAPlaneColor [j] = (uint8) (j < 3 ? j : 255);
+ }
+
+ for (j = 0; j < kMaxBlackPattern; j++)
+ for (k = 0; k < kMaxBlackPattern; k++)
+ for (n = 0; n < kMaxSamplesPerPixel; n++)
+ {
+ fBlackLevel [j] [k] [n] = 0.0;
+ }
+
+ for (j = 0; j < kMaxSamplesPerPixel; j++)
+ {
+ fWhiteLevel [j] = -1.0; // Don't know real default yet.
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_ifd::~dng_ifd ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+// Parses tags that should only appear in IFDs that contain images.
+
+bool dng_ifd::ParseTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset)
+ {
+
+ uint32 j;
+ uint32 k;
+ uint32 n;
+
+ switch (tagCode)
+ {
+
+ case tcNewSubFileType:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fUsesNewSubFileType = true;
+
+ fNewSubFileType = stream.TagValue_uint32 (tagType);
+
+ fPreviewInfo.fIsPrimary = (fNewSubFileType == sfPreviewImage);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("NewSubFileType: %s\n",
+ LookupNewSubFileType (fNewSubFileType));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcImageWidth:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fImageWidth = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("ImageWidth: %u\n", (unsigned) fImageWidth);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcImageLength:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fImageLength = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("ImageLength: %u\n", (unsigned) fImageLength);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcBitsPerSample:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1, 0x0FFFF);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("BitsPerSample:");
+ }
+
+ #endif
+
+ bool extrasMatch = true;
+
+ for (j = 0; j < tagCount; j++)
+ {
+
+ uint32 x = stream.TagValue_uint32 (tagType);
+
+ const uint32 maxBitsPerSample = 32;
+
+ if (j < kMaxSamplesPerPixel)
+ {
+
+ if (x > maxBitsPerSample)
+ {
+ ThrowBadFormat ("BitsPerSample out of bounds.");
+ }
+
+ fBitsPerSample [j] = x;
+ }
+
+ else if (x != fBitsPerSample [kMaxSamplesPerPixel - 1])
+ {
+ extrasMatch = false;
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf (" %u", (unsigned) x);
+ }
+
+ #endif
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("\n");
+ }
+
+ #endif
+
+ if (!extrasMatch)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("BitsPerSample not constant");
+
+ #endif
+
+ ThrowBadFormat ();
+
+ }
+
+ break;
+
+ }
+
+ case tcCompression:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fCompression = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Compression: %s\n",
+ LookupCompression (fCompression));
+
+ }
+
+ #endif
+
+ // Correct a common TIFF writer mistake.
+
+ if (fCompression == 0)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s has invalid zero compression code",
+ LookupParentCode (parentCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ fCompression = ccUncompressed;
+
+ }
+
+ break;
+
+ }
+
+ case tcPhotometricInterpretation:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fPhotometricInterpretation = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("PhotometricInterpretation: %s\n",
+ LookupPhotometricInterpretation (fPhotometricInterpretation));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcFillOrder:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fFillOrder = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("FillOrder: %u\n", (unsigned) fFillOrder);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcStripOffsets:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ fUsesStrips = true;
+
+ fTileOffsetsType = tagType;
+ fTileOffsetsCount = tagCount;
+ fTileOffsetsOffset = tagOffset;
+
+ if (tagCount <= kMaxTileInfo)
+ {
+
+ for (j = 0; j < tagCount; j++)
+ {
+
+ fTileOffset [j] = stream.TagValue_uint32 (tagType);
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ stream.SetReadPosition (tagOffset);
+
+ DumpTagValues (stream,
+ "Offset",
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcOrientation:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fOrientationType = tagType;
+ fOrientationOffset = stream.PositionInOriginalFile ();
+ fOrientationBigEndian = stream.BigEndian ();
+
+ fOrientation = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Orientation: %s\n",
+ LookupOrientation (fOrientation));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSamplesPerPixel:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fSamplesPerPixel = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("SamplesPerPixel: %u\n", (unsigned) fSamplesPerPixel);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcRowsPerStrip:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fUsesStrips = true;
+
+ fTileLength = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("RowsPerStrip: %u\n", (unsigned) fTileLength);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcStripByteCounts:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ fUsesStrips = true;
+
+ fTileByteCountsType = tagType;
+ fTileByteCountsCount = tagCount;
+ fTileByteCountsOffset = tagOffset;
+
+ if (tagCount <= kMaxTileInfo)
+ {
+
+ for (j = 0; j < tagCount; j++)
+ {
+
+ fTileByteCount [j] = stream.TagValue_uint32 (tagType);
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ stream.SetReadPosition (tagOffset);
+
+ DumpTagValues (stream,
+ "Count",
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcXResolution:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fXResolution = stream.TagValue_real64 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("XResolution: %0.2f\n", fXResolution);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcYResolution:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fYResolution = stream.TagValue_real64 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("YResolution: %0.2f\n", fYResolution);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPlanarConfiguration:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fPlanarConfiguration = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("PlanarConfiguration: %u\n", (unsigned) fPlanarConfiguration);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcResolutionUnit:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fResolutionUnit = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ResolutionUnit: %s\n",
+ LookupResolutionUnit (fResolutionUnit));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPredictor:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fPredictor = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("Predictor: %s\n",
+ LookupPredictor (fPredictor));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcTileWidth:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fUsesTiles = true;
+
+ fTileWidth = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("TileWidth: %u\n", (unsigned) fTileWidth);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcTileLength:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fUsesTiles = true;
+
+ fTileLength = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("TileLength: %u\n", (unsigned) fTileLength);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcTileOffsets:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ fUsesTiles = true;
+
+ fTileOffsetsType = tagType;
+ fTileOffsetsCount = tagCount;
+ fTileOffsetsOffset = tagOffset;
+
+ if (tagCount <= kMaxTileInfo)
+ {
+
+ for (j = 0; j < tagCount; j++)
+ {
+
+ fTileOffset [j] = stream.TagValue_uint32 (tagType);
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ stream.SetReadPosition (tagOffset);
+
+ DumpTagValues (stream,
+ "Offset",
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcTileByteCounts:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ fUsesTiles = true;
+
+ fTileByteCountsType = tagType;
+ fTileByteCountsCount = tagCount;
+ fTileByteCountsOffset = tagOffset;
+
+ if (tagCount <= kMaxTileInfo)
+ {
+
+ for (j = 0; j < tagCount; j++)
+ {
+
+ fTileByteCount [j] = stream.TagValue_uint32 (tagType);
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ stream.SetReadPosition (tagOffset);
+
+ DumpTagValues (stream,
+ "Count",
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSubIFDs:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong, ttIFD);
+
+ fSubIFDsCount = tagCount;
+ fSubIFDsOffset = tagOffset;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ DumpTagValues (stream,
+ "IFD",
+ parentCode,
+ tagCode,
+ ttLong,
+ tagCount);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcExtraSamples:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1, fSamplesPerPixel);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("ExtraSamples:");
+ }
+
+ #endif
+
+ fExtraSamplesCount = tagCount;
+
+ for (j = 0; j < tagCount; j++)
+ {
+
+ uint32 x = stream.TagValue_uint32 (tagType);
+
+ if (j < kMaxSamplesPerPixel)
+ {
+ fExtraSamples [j] = x;
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf (" %u", (unsigned) x);
+ }
+
+ #endif
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("\n");
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSampleFormat:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("SampleFormat:");
+ }
+
+ #endif
+
+ bool extrasMatch = true;
+
+ for (j = 0; j < tagCount; j++)
+ {
+
+ uint32 x = stream.TagValue_uint32 (tagType);
+
+ if (j < kMaxSamplesPerPixel)
+ {
+ fSampleFormat [j] = x;
+ }
+
+ else if (x != fSampleFormat [kMaxSamplesPerPixel - 1])
+ {
+ extrasMatch = false;
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf (" %s", LookupSampleFormat (x));
+ }
+
+ #endif
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("\n");
+ }
+
+ #endif
+
+ if (!extrasMatch)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("SampleFormat not constant");
+
+ #endif
+
+ ThrowBadFormat ();
+
+ }
+
+ break;
+
+ }
+
+ case tcJPEGTables:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ fJPEGTablesCount = tagCount;
+ fJPEGTablesOffset = tagOffset;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("JPEGTables: count = %u, offset = %u\n",
+ (unsigned) fJPEGTablesCount,
+ (unsigned) fJPEGTablesOffset);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcJPEGInterchangeFormat:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fJPEGInterchangeFormat = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("JPEGInterchangeFormat: %u\n",
+ (unsigned) fJPEGInterchangeFormat);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcJPEGInterchangeFormatLength:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fJPEGInterchangeFormatLength = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("JPEGInterchangeFormatLength: %u\n",
+ (unsigned) fJPEGInterchangeFormatLength);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcYCbCrCoefficients:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 3))
+ {
+ return false;
+ }
+
+ fYCbCrCoefficientR = stream.TagValue_real64 (tagType);
+ fYCbCrCoefficientG = stream.TagValue_real64 (tagType);
+ fYCbCrCoefficientB = stream.TagValue_real64 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("YCbCrCoefficients: R = %0.3f, G = %0.3f, B = %0.3f\n",
+ fYCbCrCoefficientR,
+ fYCbCrCoefficientG,
+ fYCbCrCoefficientB);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcYCbCrSubSampling:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
+ {
+ return false;
+ }
+
+ fYCbCrSubSampleH = stream.TagValue_uint32 (tagType);
+ fYCbCrSubSampleV = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("YCbCrSubSampling: H = %u, V = %u\n",
+ (unsigned) fYCbCrSubSampleH,
+ (unsigned) fYCbCrSubSampleV);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcYCbCrPositioning:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fYCbCrPositioning = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("YCbCrPositioning: %u\n",
+ (unsigned) fYCbCrPositioning);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcReferenceBlackWhite:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 6))
+ {
+ return false;
+ }
+
+ for (j = 0; j < 6; j++)
+ {
+ fReferenceBlackWhite [j] = stream.TagValue_real64 (tagType);
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ReferenceBlackWhite: %0.1f %0.1f %0.1f %0.1f %0.1f %0.1f\n",
+ fReferenceBlackWhite [0],
+ fReferenceBlackWhite [1],
+ fReferenceBlackWhite [2],
+ fReferenceBlackWhite [3],
+ fReferenceBlackWhite [4],
+ fReferenceBlackWhite [5]);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCFARepeatPatternDim:
+ {
+
+ CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
+ {
+ return false;
+ }
+
+ fCFARepeatPatternRows = stream.TagValue_uint32 (tagType);
+ fCFARepeatPatternCols = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("CFARepeatPatternDim: Rows = %u, Cols = %u\n",
+ (unsigned) fCFARepeatPatternRows,
+ (unsigned) fCFARepeatPatternCols);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCFAPattern:
+ {
+
+ CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
+ {
+ return false;
+ }
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, fCFARepeatPatternRows *
+ fCFARepeatPatternCols))
+ {
+ return false;
+ }
+
+ if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
+ fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
+ {
+ return false;
+ }
+
+ // Note that the Exif spec stores this array in a different
+ // scan order than the TIFF-EP spec.
+
+ for (j = 0; j < fCFARepeatPatternRows; j++)
+ for (k = 0; k < fCFARepeatPatternCols; k++)
+ {
+
+ fCFAPattern [j] [k] = stream.Get_uint8 ();
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("CFAPattern:\n");
+
+ for (j = 0; j < fCFARepeatPatternRows; j++)
+ {
+
+ int32 spaces = 4;
+
+ for (k = 0; k < fCFARepeatPatternCols; k++)
+ {
+
+ while (spaces-- > 0)
+ {
+ printf (" ");
+ }
+
+ const char *name = LookupCFAColor (fCFAPattern [j] [k]);
+
+ spaces = 9 - (int32) strlen (name);
+
+ printf ("%s", name);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCFAPlaneColor:
+ {
+
+ CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
+ {
+ return false;
+ }
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 3, kMaxColorPlanes))
+ {
+ return false;
+ }
+
+ for (j = 0; j < kMaxColorPlanes; j++)
+ {
+
+ if (j < tagCount)
+ fCFAPlaneColor [j] = stream.Get_uint8 ();
+
+ else
+ fCFAPlaneColor [j] = 255;
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("CFAPlaneColor:");
+
+ for (j = 0; j < tagCount; j++)
+ {
+
+ printf (" %s", LookupCFAColor (fCFAPlaneColor [j]));
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCFALayout:
+ {
+
+ CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fCFALayout = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("CFALayout: %s\n",
+ LookupCFALayout (fCFALayout));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcLinearizationTable:
+ {
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ fLinearizationTableType = tagType;
+ fLinearizationTableCount = tagCount;
+ fLinearizationTableOffset = tagOffset;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ DumpTagValues (stream,
+ "Table",
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcBlackLevelRepeatDim:
+ {
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
+ {
+ return false;
+ }
+
+ fBlackLevelRepeatRows = stream.TagValue_uint32 (tagType);
+ fBlackLevelRepeatCols = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("BlackLevelRepeatDim: Rows = %u, Cols = %u\n",
+ (unsigned) fBlackLevelRepeatRows,
+ (unsigned) fBlackLevelRepeatCols);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcBlackLevel:
+ {
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, fBlackLevelRepeatRows *
+ fBlackLevelRepeatCols *
+ fSamplesPerPixel))
+ {
+ return false;
+ }
+
+ if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern ||
+ fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern ||
+ fSamplesPerPixel < 1 || fSamplesPerPixel > kMaxSamplesPerPixel)
+ {
+ return false;
+ }
+
+ for (j = 0; j < fBlackLevelRepeatRows; j++)
+ for (k = 0; k < fBlackLevelRepeatCols; k++)
+ for (n = 0; n < fSamplesPerPixel; n++)
+ {
+
+ fBlackLevel [j] [k] [n] = stream.TagValue_real64 (tagType);
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("BlackLevel:");
+
+ if (fBlackLevelRepeatRows == 1 &&
+ fBlackLevelRepeatCols == 1)
+ {
+
+ for (n = 0; n < fSamplesPerPixel; n++)
+ {
+ printf (" %0.2f", fBlackLevel [0] [0] [n]);
+ }
+
+ printf ("\n");
+
+ }
+
+ else
+ {
+
+ printf ("\n");
+
+ for (n = 0; n < fSamplesPerPixel; n++)
+ {
+
+ if (fSamplesPerPixel > 1)
+ {
+ printf (" Sample: %u\n", (unsigned) n);
+ }
+
+ for (j = 0; j < fBlackLevelRepeatRows; j++)
+ {
+
+ printf (" ");
+
+ for (k = 0; k < fBlackLevelRepeatCols; k++)
+ {
+
+ printf (" %8.2f", fBlackLevel [j] [k] [n]);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ }
+
+ }
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcBlackLevelDeltaH:
+ {
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttSRational);
+
+ fBlackLevelDeltaHType = tagType;
+ fBlackLevelDeltaHCount = tagCount;
+ fBlackLevelDeltaHOffset = tagOffset;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ DumpTagValues (stream,
+ "Delta",
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcBlackLevelDeltaV:
+ {
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttSRational);
+
+ fBlackLevelDeltaVType = tagType;
+ fBlackLevelDeltaVCount = tagCount;
+ fBlackLevelDeltaVOffset = tagOffset;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ DumpTagValues (stream,
+ "Delta",
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcWhiteLevel:
+ {
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel))
+ return false;
+
+ for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++)
+ {
+
+ fWhiteLevel [j] = stream.TagValue_real64 (tagType);
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("WhiteLevel:");
+
+ for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++)
+ {
+
+ printf (" %0.0f", fWhiteLevel [j]);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcDefaultScale:
+ {
+
+ CheckMainIFD (parentCode, tagCode, fNewSubFileType);
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
+ return false;
+
+ fDefaultScaleH = stream.TagValue_urational (tagType);
+ fDefaultScaleV = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("DefaultScale: H = %0.4f V = %0.4f\n",
+ fDefaultScaleH.As_real64 (),
+ fDefaultScaleV.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcDefaultCropOrigin:
+ {
+
+ CheckMainIFD (parentCode, tagCode, fNewSubFileType);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
+ return false;
+
+ fDefaultCropOriginH = stream.TagValue_urational (tagType);
+ fDefaultCropOriginV = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("DefaultCropOrigin: H = %0.2f V = %0.2f\n",
+ fDefaultCropOriginH.As_real64 (),
+ fDefaultCropOriginV.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcDefaultCropSize:
+ {
+
+ CheckMainIFD (parentCode, tagCode, fNewSubFileType);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
+ return false;
+
+ fDefaultCropSizeH = stream.TagValue_urational (tagType);
+ fDefaultCropSizeV = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("DefaultCropSize: H = %0.2f V = %0.2f\n",
+ fDefaultCropSizeH.As_real64 (),
+ fDefaultCropSizeV.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcDefaultUserCrop:
+ {
+
+ CheckMainIFD (parentCode, tagCode, fNewSubFileType);
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
+ return false;
+
+ fDefaultUserCropT = stream.TagValue_urational (tagType);
+ fDefaultUserCropL = stream.TagValue_urational (tagType);
+ fDefaultUserCropB = stream.TagValue_urational (tagType);
+ fDefaultUserCropR = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("DefaultUserCrop: T = %0.2lf L = %0.2lf B = %0.2lf R = %0.2lf\n",
+ (double) fDefaultUserCropT.As_real64 (),
+ (double) fDefaultUserCropL.As_real64 (),
+ (double) fDefaultUserCropB.As_real64 (),
+ (double) fDefaultUserCropR.As_real64 ());
+
+
+ }
+
+ #endif // qDNGValidate
+
+ break;
+
+ }
+
+ case tcBayerGreenSplit:
+ {
+
+ CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fBayerGreenSplit = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("BayerGreenSplit: %u\n", (unsigned) fBayerGreenSplit);
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcChromaBlurRadius:
+ {
+
+ CheckMainIFD (parentCode, tagCode, fNewSubFileType);
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fChromaBlurRadius = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ChromaBlurRadius: %0.2f\n",
+ fChromaBlurRadius.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcAntiAliasStrength:
+ {
+
+ CheckMainIFD (parentCode, tagCode, fNewSubFileType);
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fAntiAliasStrength = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("AntiAliasStrength: %0.2f\n",
+ fAntiAliasStrength.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcBestQualityScale:
+ {
+
+ CheckMainIFD (parentCode, tagCode, fNewSubFileType);
+
+ CheckTagType (parentCode, tagCode, tagType, ttRational);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fBestQualityScale = stream.TagValue_urational (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("BestQualityScale: %0.4f\n",
+ fBestQualityScale.As_real64 ());
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcActiveArea:
+ {
+
+ CheckMainIFD (parentCode, tagCode, fNewSubFileType);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
+ return false;
+
+ fActiveArea.t = stream.TagValue_int32 (tagType);
+ fActiveArea.l = stream.TagValue_int32 (tagType);
+ fActiveArea.b = stream.TagValue_int32 (tagType);
+ fActiveArea.r = stream.TagValue_int32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("ActiveArea: T = %d L = %d B = %d R = %d\n",
+ (int) fActiveArea.t,
+ (int) fActiveArea.l,
+ (int) fActiveArea.b,
+ (int) fActiveArea.r);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcMaskedAreas:
+ {
+
+ CheckMainIFD (parentCode, tagCode, fNewSubFileType);
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ uint32 rect_count = tagCount / 4;
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, rect_count * 4))
+ return false;
+
+ fMaskedAreaCount = rect_count;
+
+ if (fMaskedAreaCount > kMaxMaskedAreas)
+ fMaskedAreaCount = kMaxMaskedAreas;
+
+ for (j = 0; j < fMaskedAreaCount; j++)
+ {
+
+ fMaskedArea [j].t = stream.TagValue_int32 (tagType);
+ fMaskedArea [j].l = stream.TagValue_int32 (tagType);
+ fMaskedArea [j].b = stream.TagValue_int32 (tagType);
+ fMaskedArea [j].r = stream.TagValue_int32 (tagType);
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("MaskedAreas: %u\n", (unsigned) fMaskedAreaCount);
+
+ for (j = 0; j < fMaskedAreaCount; j++)
+ {
+
+ printf (" Area [%u]: T = %d L = %d B = %d R = %d\n",
+ (unsigned) j,
+ (int) fMaskedArea [j].t,
+ (int) fMaskedArea [j].l,
+ (int) fMaskedArea [j].b,
+ (int) fMaskedArea [j].r);
+
+ }
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPreviewApplicationName:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fPreviewInfo.fApplicationName,
+ false);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("PreviewApplicationName: ");
+
+ DumpString (fPreviewInfo.fApplicationName);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPreviewApplicationVersion:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fPreviewInfo.fApplicationVersion,
+ false);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("PreviewApplicationVersion: ");
+
+ DumpString (fPreviewInfo.fApplicationVersion);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPreviewSettingsName:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fPreviewInfo.fSettingsName,
+ false);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("PreviewSettingsName: ");
+
+ DumpString (fPreviewInfo.fSettingsName);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPreviewSettingsDigest:
+ {
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
+ return false;
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 16))
+ return false;
+
+ stream.Get (fPreviewInfo.fSettingsDigest.data, 16);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("PreviewSettingsDigest: ");
+
+ DumpFingerprint (fPreviewInfo.fSettingsDigest);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPreviewColorSpace:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ CheckTagCount (parentCode, tagCode, tagCount, 1);
+
+ fPreviewInfo.fColorSpace = (PreviewColorSpaceEnum)
+ stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("PreviewColorSpace: %s\n",
+ LookupPreviewColorSpace ((uint32) fPreviewInfo.fColorSpace));
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcPreviewDateTime:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttAscii);
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ fPreviewInfo.fDateTime,
+ false);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("PreviewDateTime: ");
+
+ DumpString (fPreviewInfo.fDateTime);
+
+ printf ("\n");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcRowInterleaveFactor:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
+ return false;
+
+ fRowInterleaveFactor = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("RowInterleaveFactor: %u\n",
+ (unsigned) fRowInterleaveFactor);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcSubTileBlockSize:
+ {
+
+ CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
+ return false;
+
+ fSubTileBlockRows = stream.TagValue_uint32 (tagType);
+ fSubTileBlockCols = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("SubTileBlockSize: rows = %u, cols = %u\n",
+ (unsigned) fSubTileBlockRows,
+ (unsigned) fSubTileBlockCols);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcOpcodeList1:
+ {
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ fOpcodeList1Count = tagCount;
+ fOpcodeList1Offset = tagOffset;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("OpcodeList1: count = %u, offset = %u\n",
+ (unsigned) fOpcodeList1Count,
+ (unsigned) fOpcodeList1Offset);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcOpcodeList2:
+ {
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ fOpcodeList2Count = tagCount;
+ fOpcodeList2Offset = tagOffset;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("OpcodeList2: count = %u, offset = %u\n",
+ (unsigned) fOpcodeList2Count,
+ (unsigned) fOpcodeList2Offset);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcOpcodeList3:
+ {
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttUndefined);
+
+ fOpcodeList3Count = tagCount;
+ fOpcodeList3Offset = tagOffset;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("OpcodeList3: count = %u, offset = %u\n",
+ (unsigned) fOpcodeList3Count,
+ (unsigned) fOpcodeList3Offset);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcRawToPreviewGain:
+ {
+
+ #if qDNGValidate
+
+ if (fNewSubFileType != sfPreviewImage)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed IFDs with NewSubFileType != PreviewImage",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttDouble);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
+ return false;
+
+ fPreviewInfo.fRawToPreviewGain = stream.TagValue_real64 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("RawToPreviewGain = %f\n",
+ fPreviewInfo.fRawToPreviewGain);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ case tcCacheVersion:
+ {
+
+ #if qDNGValidate
+
+ if (fNewSubFileType != sfPreviewImage)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed IFDs with NewSubFileType != PreviewImage",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
+
+ CheckTagType (parentCode, tagCode, tagType, ttLong);
+
+ if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
+ return false;
+
+ fPreviewInfo.fCacheVersion = stream.TagValue_uint32 (tagType);
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("CacheVersion = 0x%x\n",
+ (unsigned) fPreviewInfo.fCacheVersion);
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ default:
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+void dng_ifd::PostParse ()
+ {
+
+ uint32 j;
+ uint32 k;
+
+ // There is only one PlanarConfiguration for single sample imaages.
+
+ if (fSamplesPerPixel == 1)
+ {
+ fPlanarConfiguration = pcInterleaved;
+ }
+
+ // Default tile size.
+
+ if (fTileWidth == 0)
+ {
+ fTileWidth = fImageWidth;
+ }
+
+ if (fTileLength == 0)
+ {
+ fTileLength = fImageLength;
+ }
+
+ // Default ActiveArea.
+
+ dng_rect imageArea (0, 0, fImageLength, fImageWidth);
+
+ if (fActiveArea.IsZero ())
+ {
+ fActiveArea = imageArea;
+ }
+
+ // Default crop size.
+
+ if (fDefaultCropSizeH.d == 0)
+ {
+ fDefaultCropSizeH = dng_urational (fActiveArea.W (), 1);
+ }
+
+ if (fDefaultCropSizeV.d == 0)
+ {
+ fDefaultCropSizeV = dng_urational (fActiveArea.H (), 1);
+ }
+
+ // Default white level.
+
+ uint32 defaultWhite = (fSampleFormat [0] == sfFloatingPoint) ?
+ 1 :
+ (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
+
+ for (j = 0; j < kMaxSamplesPerPixel; j++)
+ {
+
+ if (fWhiteLevel [j] < 0.0)
+ {
+ fWhiteLevel [j] = (real64) defaultWhite;
+ }
+
+ }
+
+ // Check AntiAliasStrength.
+
+ if (fAntiAliasStrength.As_real64 () < 0.0 ||
+ fAntiAliasStrength.As_real64 () > 1.0)
+ {
+
+ #if qDNGValidate
+
+ ReportWarning ("Invalid AntiAliasStrength");
+
+ #endif
+
+ fAntiAliasStrength = dng_urational (1, 1);
+
+ }
+
+ // Check MaskedAreas.
+
+ for (j = 0; j < fMaskedAreaCount; j++)
+ {
+
+ const dng_rect &r = fMaskedArea [j];
+
+ if (r.IsEmpty () || ((r & imageArea) != r))
+ {
+
+ #if qDNGValidate
+
+ ReportWarning ("Invalid MaskedArea");
+
+ #endif
+
+ fMaskedAreaCount = 0;
+
+ break;
+
+ }
+
+ if ((r & fActiveArea).NotEmpty ())
+ {
+
+ #if qDNGValidate
+
+ ReportWarning ("MaskedArea overlaps ActiveArea");
+
+ #endif
+
+ fMaskedAreaCount = 0;
+
+ break;
+
+ }
+
+ for (k = 0; k < j; k++)
+ {
+
+ if ((r & fMaskedArea [k]).NotEmpty ())
+ {
+
+ #if qDNGValidate
+
+ ReportWarning ("MaskedAreas overlap each other");
+
+ #endif
+
+ fMaskedAreaCount = 0;
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_ifd::IsValidCFA (dng_shared &shared,
+ uint32 parentCode)
+ {
+
+ uint32 j;
+ uint32 k;
+ uint32 n;
+
+ #if !qDNGValidate
+
+ (void) parentCode; // Unused
+
+ #endif
+
+ if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
+ fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Missing or invalid CFAPatternRepeatDim",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ uint32 count [kMaxColorPlanes];
+
+ for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
+ {
+ count [n] = 0;
+ }
+
+ for (j = 0; j < fCFARepeatPatternRows; j++)
+ {
+
+ for (k = 0; k < fCFARepeatPatternCols; k++)
+ {
+
+ bool found = false;
+
+ for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
+ {
+
+ if (fCFAPattern [j] [k] == fCFAPlaneColor [n])
+ {
+ found = true;
+ count [n] ++;
+ break;
+ }
+
+ }
+
+ if (!found)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("CFAPattern contains colors not included in the CFAPlaneColor tag",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ }
+
+ for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
+ {
+
+ if (count [n] == 0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("CFAPattern does not contain all the colors in the CFAPlaneColor tag",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ if (fCFALayout < 1 || fCFALayout > 9)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid CFALayout",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+bool dng_ifd::IsValidDNG (dng_shared &shared,
+ uint32 parentCode)
+ {
+
+ uint32 j;
+
+ bool isFloatingPoint = (fSampleFormat [0] == sfFloatingPoint);
+
+ dng_rect imageArea (0, 0, fImageLength, fImageWidth);
+
+ uint32 defaultWhite = isFloatingPoint ?
+ 1 :
+ (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
+
+ bool isMonochrome = (shared.fCameraProfile.fColorPlanes == 1);
+ bool isColor = !isMonochrome;
+
+ bool isMainIFD = (fNewSubFileType == sfMainImage);
+
+ // Check NewSubFileType.
+
+ if (!fUsesNewSubFileType)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Missing NewSubFileType",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fNewSubFileType != sfMainImage &&
+ fNewSubFileType != sfPreviewImage &&
+ fNewSubFileType != sfTransparencyMask &&
+ fNewSubFileType != sfPreviewMask &&
+ fNewSubFileType != sfAltPreviewImage)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unexpected NewSubFileType",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check ImageWidth and ImageLength.
+
+ if (fImageWidth < 1)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Missing or invalid ImageWidth",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fImageLength < 1)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Missing or invalid ImageLength",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fImageWidth > kMaxImageSide ||
+ fImageLength > kMaxImageSide)
+ {
+
+ #if qDNGValidate
+
+ ReportWarning ("Image size is larger than supported");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check PhotometricInterpretation.
+
+ if (fNewSubFileType == sfTransparencyMask ||
+ fNewSubFileType == sfPreviewMask)
+ {
+
+ if (fPhotometricInterpretation != piTransparencyMask)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("NewSubFileType requires PhotometricInterpretation = TransparencyMask",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ else
+ {
+
+ switch (fPhotometricInterpretation)
+ {
+
+ case piBlackIsZero:
+ case piRGB:
+ case piYCbCr:
+ {
+
+ if (isMainIFD)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("PhotometricInterpretation requires NewSubFileType = 1",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ break;
+
+ }
+
+ case piCFA:
+ {
+
+ if (!isMainIFD)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("PhotometricInterpretation requires NewSubFileType = 0",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ break;
+
+ }
+
+ case piLinearRaw:
+ break;
+
+ default:
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Missing or invalid PhotometricInterpretation",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ }
+
+ switch (fPhotometricInterpretation)
+ {
+
+ case piBlackIsZero:
+ {
+
+ // Allow black in white previews even in color images since the
+ // raw processing software may be converting to grayscale.
+
+ if (isColor && isMainIFD)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("PhotometricInterpretation forbids use of ColorMatrix1 tag",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ break;
+
+ }
+
+ case piRGB:
+ case piYCbCr:
+ {
+
+ // Allow color previews even in monochrome DNG files, since the
+ // raw procesing software may be adding color effects.
+
+ break;
+
+ }
+
+ case piCFA:
+ {
+
+ if (isMonochrome)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("PhotometricInterpretation requires use of ColorMatrix1 tag",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ break;
+
+ }
+
+ }
+
+ if (isFloatingPoint)
+ {
+
+ if (fPhotometricInterpretation != piCFA &&
+ fPhotometricInterpretation != piLinearRaw &&
+ fPhotometricInterpretation != piTransparencyMask)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Floating point data requires PhotometricInterpretation CFA or LinearRaw or TransparencyMask",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // Check SamplesPerPixel and BitsPerSample.
+
+ uint32 minSamplesPerPixel = 1;
+ uint32 maxSamplesPerPixel = 1;
+
+ uint32 minBitsPerSample = 8;
+ uint32 maxBitsPerSample = 16;
+
+ switch (fPhotometricInterpretation)
+ {
+
+ case piBlackIsZero:
+ break;
+
+ case piRGB:
+ case piYCbCr:
+ {
+ minSamplesPerPixel = 3;
+ maxSamplesPerPixel = 3;
+ break;
+ }
+
+ case piCFA:
+ {
+ maxSamplesPerPixel = kMaxSamplesPerPixel;
+ maxBitsPerSample = 32;
+ break;
+ }
+
+ case piLinearRaw:
+ {
+ minSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
+ maxSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
+ maxBitsPerSample = 32;
+ break;
+ }
+
+ case piTransparencyMask:
+ {
+ minBitsPerSample = 8;
+ maxBitsPerSample = 16;
+ break;
+ }
+
+ }
+
+ if (isFloatingPoint)
+ {
+ minBitsPerSample = 16;
+ maxBitsPerSample = 32;
+ }
+
+ if (fSamplesPerPixel < minSamplesPerPixel ||
+ fSamplesPerPixel > maxSamplesPerPixel)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Missing or invalid SamplesPerPixel",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ for (j = 0; j < kMaxSamplesPerPixel; j++)
+ {
+
+ if (j < fSamplesPerPixel)
+ {
+
+ if (fBitsPerSample [j] < minBitsPerSample ||
+ fBitsPerSample [j] > maxBitsPerSample)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Missing or invalid BitsPerSample",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (isFloatingPoint &&
+ fBitsPerSample [j] != 16 &&
+ fBitsPerSample [j] != 24 &&
+ fBitsPerSample [j] != 32)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid BitsPerSample for floating point",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (minBitsPerSample == 8 &&
+ maxBitsPerSample == 16 &&
+ fBitsPerSample [j] != 8 &&
+ fBitsPerSample [j] != 16)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Rendered previews and integer masks require 8 or 16 bits per sample",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (j > 0 && fBitsPerSample [j] != fBitsPerSample [0])
+ {
+
+ #if qDNGValidate
+
+ ReportError ("BitsPerSample not equal for all samples",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ else
+ {
+
+ if (fBitsPerSample [j] != 0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Too many values specified in BitsPerSample",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ }
+
+ // Check Compression.
+
+ switch (fCompression)
+ {
+
+ case ccUncompressed:
+ break;
+
+ case ccJPEG:
+ {
+
+ if (fPhotometricInterpretation == piRGB)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("JPEG previews should use PhotometricInterpretation = YCbYb",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fBitsPerSample [0] > 16)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("JPEG compression is limited to 16 bits/sample",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ break;
+
+ }
+
+ case ccLossyJPEG:
+ {
+
+ if (fPhotometricInterpretation != piLinearRaw)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Lossy JPEG compression code requires PhotometricInterpretation = LinearRaw",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fBitsPerSample [0] != 8)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Lossy JPEG compression is limited to 8 bits/sample",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ break;
+
+ }
+
+ case ccDeflate:
+ {
+
+ if (!isFloatingPoint &&
+ fBitsPerSample [0] != 32 &&
+ fPhotometricInterpretation != piTransparencyMask)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("ZIP compression is limited to floating point and 32-bit integer and transparency masks",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ }
+
+ break;
+
+ }
+
+ default:
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unsupported Compression",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // Check Predictor.
+
+ if (isFloatingPoint && fCompression == ccDeflate &&
+ (fPredictor == cpFloatingPoint ||
+ fPredictor == cpFloatingPointX2 ||
+ fPredictor == cpFloatingPointX4))
+ {
+
+ // These combinations are supported.
+
+ }
+
+ else if (!isFloatingPoint && fCompression == ccDeflate &&
+ (fPredictor == cpHorizontalDifference ||
+ fPredictor == cpHorizontalDifferenceX2 ||
+ fPredictor == cpHorizontalDifferenceX4))
+ {
+
+ // These combinations are supported.
+
+ }
+
+ else if (fPredictor != cpNullPredictor)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unsupported Predictor",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check FillOrder.
+
+ if (fFillOrder != 1)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unsupported FillOrder",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check PlanarConfiguration.
+
+ if (fPlanarConfiguration != pcInterleaved)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unsupported PlanarConfiguration",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check ExtraSamples.
+
+ if (fExtraSamplesCount != 0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unsupported ExtraSamples",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check SampleFormat.
+
+ for (j = 0; j < fSamplesPerPixel; j++)
+ {
+
+ if (fSampleFormat [j] != (isFloatingPoint ? sfFloatingPoint : sfUnsignedInteger))
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unsupported SampleFormat",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // Check Orientation.
+
+ if (fOrientation > 9)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unknown Orientation",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ #if qDNGValidate
+
+ if (fOrientation != 0 && parentCode != 0)
+ {
+
+ ReportWarning ("Unexpected Orientation tag",
+ LookupParentCode (parentCode));
+
+ }
+
+ if (fOrientation == 0 && parentCode == 0)
+ {
+
+ ReportWarning ("Missing Orientation tag",
+ LookupParentCode (parentCode));
+
+ }
+
+ #endif
+
+ // Check Strips vs. Tiles.
+
+ if (!fUsesStrips && !fUsesTiles)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("IFD uses neither strips nor tiles",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fUsesStrips && fUsesTiles)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("IFD uses both strips and tiles",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check tile info.
+
+ uint32 tilesWide = (fImageWidth + fTileWidth - 1) / fTileWidth;
+ uint32 tilesHigh = (fImageLength + fTileLength - 1) / fTileLength;
+
+ uint32 tileCount = tilesWide * tilesHigh;
+
+ if (fTileOffsetsCount != tileCount)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Missing or invalid Strip/TileOffsets",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fTileByteCountsCount != tileCount)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Missing or invalid Strip/TileByteCounts",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check CFA pattern.
+
+ if (fPhotometricInterpretation == piCFA)
+ {
+
+ if (!IsValidCFA (shared, parentCode))
+ {
+
+ return false;
+
+ }
+
+ }
+
+ // Check ActiveArea.
+
+ if (((fActiveArea & imageArea) != fActiveArea) || fActiveArea.IsEmpty ())
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid ActiveArea",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fActiveArea != imageArea)
+ {
+
+ if (shared.fDNGBackwardVersion < dngVersion_1_1_0_0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Non-default ActiveArea tag not allowed in this DNG version",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // Check LinearizationTable.
+
+ if (fLinearizationTableCount)
+ {
+
+ if (fLinearizationTableType != ttShort)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalidate LinearizationTable type",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fLinearizationTableCount < 2 ||
+ fLinearizationTableCount > 65536)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalidate LinearizationTable count",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (isFloatingPoint || fBitsPerSample [0] > 16)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Linearization table not allowed for this data type",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // Check BlackLevelRepeatDim.
+
+ if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern ||
+ fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid BlackLevelRepeatDim",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check BlackLevelDeltaH.
+
+ if (fBlackLevelDeltaHCount != 0 &&
+ fBlackLevelDeltaHCount != fActiveArea.W ())
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid BlackLevelDeltaH count",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check BlackLevelDeltaV.
+
+ if (fBlackLevelDeltaVCount != 0 &&
+ fBlackLevelDeltaVCount != fActiveArea.H ())
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid BlackLevelDeltaV count",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check WhiteLevel.
+
+ real64 maxWhite = fLinearizationTableCount ? 65535.0
+ : (real64) defaultWhite;
+
+ for (j = 0; j < fSamplesPerPixel; j++)
+ {
+
+ if (fWhiteLevel [j] < 1.0 || (fWhiteLevel [j] > maxWhite && !isFloatingPoint))
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid WhiteLevel",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // Check BlackLevel.
+
+ for (j = 0; j < kMaxBlackPattern; j++)
+ {
+
+ for (uint32 k = 0; k < kMaxBlackPattern; k++)
+ {
+
+ for (uint32 s = 0; s < kMaxSamplesPerPixel; s++)
+ {
+
+ const real64 black = fBlackLevel [j][k][s];
+
+ if (black >= fWhiteLevel [s])
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid BlackLevel",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ // Check DefaultScale.
+
+ if (fDefaultScaleH.As_real64 () <= 0.0 ||
+ fDefaultScaleV.As_real64 () <= 0.0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid DefaultScale");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check BestQualityScale.
+
+ if (fBestQualityScale.As_real64 () < 1.0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid BestQualityScale");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check DefaultCropOrigin.
+
+ if (fDefaultCropOriginH.As_real64 () < 0.0 ||
+ fDefaultCropOriginV.As_real64 () < 0.0 ||
+ fDefaultCropOriginH.As_real64 () >= (real64) fActiveArea.W () ||
+ fDefaultCropOriginV.As_real64 () >= (real64) fActiveArea.H ())
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid DefaultCropOrigin");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check DefaultCropSize.
+
+ if (fDefaultCropSizeH.As_real64 () <= 0.0 ||
+ fDefaultCropSizeV.As_real64 () <= 0.0 ||
+ fDefaultCropSizeH.As_real64 () > (real64) fActiveArea.W () ||
+ fDefaultCropSizeV.As_real64 () > (real64) fActiveArea.H ())
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid DefaultCropSize");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check DefaultCrop area.
+
+ if (fDefaultCropOriginH.As_real64 () +
+ fDefaultCropSizeH .As_real64 () > (real64) fActiveArea.W () ||
+ fDefaultCropOriginV.As_real64 () +
+ fDefaultCropSizeV .As_real64 () > (real64) fActiveArea.H ())
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Default crop extends outside ActiveArea");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Check DefaultUserCrop.
+
+ if (fDefaultUserCropT.As_real64 () < 0.0 ||
+ fDefaultUserCropL.As_real64 () < 0.0 ||
+ fDefaultUserCropB.As_real64 () > 1.0 ||
+ fDefaultUserCropR.As_real64 () > 1.0 ||
+ fDefaultUserCropT.As_real64 () >= fDefaultUserCropB.As_real64 () ||
+ fDefaultUserCropL.As_real64 () >= fDefaultUserCropR.As_real64 ())
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid DefaultUserCrop");
+
+ #endif // qDNGValidate
+
+ return false;
+
+ }
+
+ // The default crop and default user crop tags are not allowed for the
+ // non-main image. If they are there, at least require that they be NOPs.
+
+ if (!isMainIFD)
+ {
+
+ if (Round_int32 (fDefaultCropOriginH.As_real64 ()) != 0 ||
+ Round_int32 (fDefaultCropOriginV.As_real64 ()) != 0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("non-default DefaultCropOrigin on non-main image");
+
+ #endif
+
+ return false;
+
+ }
+
+ if (Round_int32 (fDefaultCropSizeH.As_real64 ()) != (int32) fImageWidth ||
+ Round_int32 (fDefaultCropSizeV.As_real64 ()) != (int32) fImageLength)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("non-default DefaultCropSize on non-main image");
+
+ #endif
+
+ return false;
+
+ }
+
+ if (fDefaultUserCropT.As_real64 () != 0.0 ||
+ fDefaultUserCropL.As_real64 () != 0.0 ||
+ fDefaultUserCropB.As_real64 () != 1.0 ||
+ fDefaultUserCropR.As_real64 () != 1.0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("non-default DefaultCUserCrop on non-main image");
+
+ #endif // qDNGValidate
+
+ return false;
+
+ }
+
+ }
+
+ // Warning if too little padding on CFA image.
+
+ #if qDNGValidate
+
+ if (fPhotometricInterpretation == piCFA)
+ {
+
+ const real64 kMinPad = 1.9;
+
+ if (fDefaultCropOriginH.As_real64 () < kMinPad)
+ {
+
+ ReportWarning ("Too little padding on left edge of CFA image",
+ "possible interpolation artifacts");
+
+ }
+
+ if (fDefaultCropOriginV.As_real64 () < kMinPad)
+ {
+
+ ReportWarning ("Too little padding on top edge of CFA image",
+ "possible interpolation artifacts");
+
+ }
+
+ if (fDefaultCropOriginH.As_real64 () +
+ fDefaultCropSizeH .As_real64 () > (real64) fActiveArea.W () - kMinPad)
+ {
+
+ ReportWarning ("Too little padding on right edge of CFA image",
+ "possible interpolation artifacts");
+
+ }
+
+ if (fDefaultCropOriginV.As_real64 () +
+ fDefaultCropSizeV .As_real64 () > (real64) fActiveArea.H () - kMinPad)
+ {
+
+ ReportWarning ("Too little padding on bottom edge of CFA image",
+ "possible interpolation artifacts");
+
+ }
+
+ }
+
+ #endif
+
+ // Check RowInterleaveFactor
+
+ if (fRowInterleaveFactor != 1)
+ {
+
+ if (fRowInterleaveFactor < 1 ||
+ fRowInterleaveFactor > fImageLength)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("RowInterleaveFactor out of valid range",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Non-default RowInterleaveFactor tag not allowed in this DNG version",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ // Check SubTileBlockSize
+
+ if (fSubTileBlockRows != 1 || fSubTileBlockCols != 1)
+ {
+
+ if (fSubTileBlockRows < 2 || fSubTileBlockRows > fTileLength ||
+ fSubTileBlockCols < 1 || fSubTileBlockCols > fTileWidth)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("SubTileBlockSize out of valid range",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if ((fTileLength % fSubTileBlockRows) != 0 ||
+ (fTileWidth % fSubTileBlockCols) != 0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("TileSize not exact multiple of SubTileBlockSize",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Non-default SubTileBlockSize tag not allowed in this DNG version",
+ LookupParentCode (parentCode));
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_ifd::TilesAcross () const
+ {
+
+ if (fTileWidth)
+ {
+
+ return (fImageWidth + fTileWidth - 1) / fTileWidth;
+
+ }
+
+ return 0;
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_ifd::TilesDown () const
+ {
+
+ if (fTileLength)
+ {
+
+ return (fImageLength + fTileLength - 1) / fTileLength;
+
+ }
+
+ return 0;
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_ifd::TilesPerImage () const
+ {
+
+ uint32 total = TilesAcross () * TilesDown ();
+
+ if (fPlanarConfiguration == pcPlanar)
+ {
+
+ total *= fSamplesPerPixel;
+
+ }
+
+ return total;
+
+ }
+
+/*****************************************************************************/
+
+dng_rect dng_ifd::TileArea (uint32 rowIndex,
+ uint32 colIndex) const
+ {
+
+ dng_rect r;
+
+ r.t = rowIndex * fTileLength;
+ r.b = r.t + fTileLength;
+
+ r.l = colIndex * fTileWidth;
+ r.r = r.l + fTileWidth;
+
+ // If this IFD is using strips rather than tiles, the last strip
+ // is trimmed so it does not extend beyond the end of the image.
+
+ if (fUsesStrips)
+ {
+
+ r.b = Min_uint32 (r.b, fImageLength);
+
+ }
+
+ return r;
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+uint32 dng_ifd::TileByteCount (const dng_rect &tile) const
+ {
+
+ if (fCompression == ccUncompressed)
+ {
+
+ uint32 bitsPerRow = tile.W () *
+ fBitsPerSample [0];
+
+ if (fPlanarConfiguration == pcInterleaved)
+ {
+
+ bitsPerRow *= fSamplesPerPixel;
+
+ }
+
+ uint32 bytesPerRow = (bitsPerRow + 7) >> 3;
+
+ if (fPlanarConfiguration == pcRowInterleaved)
+ {
+
+ bytesPerRow *= fSamplesPerPixel;
+
+ }
+
+ return bytesPerRow * tile.H ();
+
+ }
+
+ return 0;
+
+ }
+
+/*****************************************************************************/
+
+void dng_ifd::SetSingleStrip ()
+ {
+
+ fTileWidth = fImageWidth;
+ fTileLength = fImageLength;
+
+ fUsesTiles = false;
+ fUsesStrips = true;
+
+ }
+
+/*****************************************************************************/
+
+void dng_ifd::FindTileSize (uint32 bytesPerTile,
+ uint32 cellH,
+ uint32 cellV)
+ {
+
+ uint32 bytesPerSample = fSamplesPerPixel *
+ ((fBitsPerSample [0] + 7) >> 3);
+
+ uint32 samplesPerTile = bytesPerTile / bytesPerSample;
+
+ uint32 tileSide = Round_uint32 (sqrt ((real64) samplesPerTile));
+
+ fTileWidth = Min_uint32 (fImageWidth, tileSide);
+
+ uint32 across = TilesAcross ();
+
+ fTileWidth = (fImageWidth + across - 1) / across;
+
+ fTileWidth = ((fTileWidth + cellH - 1) / cellH) * cellH;
+
+ fTileLength = Pin_uint32 (1,
+ samplesPerTile / fTileWidth,
+ fImageLength);
+
+ uint32 down = TilesDown ();
+
+ fTileLength = (fImageLength + down - 1) / down;
+
+ fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
+
+ fUsesTiles = true;
+ fUsesStrips = false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_ifd::FindStripSize (uint32 bytesPerStrip,
+ uint32 cellV)
+ {
+
+ uint32 bytesPerSample = fSamplesPerPixel *
+ ((fBitsPerSample [0] + 7) >> 3);
+
+ uint32 samplesPerStrip = bytesPerStrip / bytesPerSample;
+
+ fTileWidth = fImageWidth;
+
+ fTileLength = Pin_uint32 (1,
+ samplesPerStrip / fTileWidth,
+ fImageLength);
+
+ uint32 down = TilesDown ();
+
+ fTileLength = (fImageLength + down - 1) / down;
+
+ fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
+
+ fUsesTiles = false;
+ fUsesStrips = true;
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_ifd::PixelType () const
+ {
+
+ if (fSampleFormat [0] == sfFloatingPoint)
+ {
+ return ttFloat;
+ }
+
+ if (fBitsPerSample [0] <= 8)
+ {
+ return ttByte;
+ }
+
+ else if (fBitsPerSample [0] <= 16)
+ {
+ return ttShort;
+ }
+
+ return ttLong;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_ifd::IsBaselineJPEG () const
+ {
+
+ if (fBitsPerSample [0] != 8)
+ {
+ return false;
+ }
+
+ if (fSampleFormat [0] != sfUnsignedInteger)
+ {
+ return false;
+ }
+
+ if (fCompression == ccLossyJPEG)
+ {
+ return true;
+ }
+
+ if (fCompression != ccJPEG)
+ {
+ return false;
+ }
+
+ switch (fPhotometricInterpretation)
+ {
+
+ case piBlackIsZero:
+ {
+ return (fSamplesPerPixel == 1);
+ }
+
+ case piYCbCr:
+ {
+ return (fSamplesPerPixel == 3 ) &&
+ (fPlanarConfiguration == pcInterleaved);
+ }
+
+ default:
+ break;
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_ifd::CanRead () const
+ {
+
+ dng_read_image reader;
+
+ return reader.CanRead (*this);
+
+ }
+
+/*****************************************************************************/
+
+void dng_ifd::ReadImage (dng_host &host,
+ dng_stream &stream,
+ dng_image &image,
+ dng_jpeg_image *jpegImage,
+ dng_fingerprint *jpegDigest) const
+ {
+
+ dng_read_image reader;
+
+ reader.Read (host,
+ *this,
+ stream,
+ image,
+ jpegImage,
+ jpegDigest);
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_ifd.h b/source/dng_ifd.h
index c0b681d..943c28d 100644
--- a/source/dng_ifd.h
+++ b/source/dng_ifd.h
@@ -1,305 +1,305 @@
-/*****************************************************************************/
-// Copyright 2006-2012 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_ifd.h#3 $ */
-/* $DateTime: 2012/06/05 11:05:39 $ */
-/* $Change: 833352 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * DNG image file directory support.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_ifd__
-#define __dng_ifd__
-
-/*****************************************************************************/
-
-#include "dng_fingerprint.h"
-#include "dng_rect.h"
-#include "dng_shared.h"
-#include "dng_stream.h"
-#include "dng_string.h"
-#include "dng_sdk_limits.h"
-#include "dng_tag_values.h"
-
-/*****************************************************************************/
-
-class dng_preview_info
- {
-
- public:
-
- bool fIsPrimary;
-
- dng_string fApplicationName;
-
- dng_string fApplicationVersion;
-
- dng_string fSettingsName;
-
- dng_fingerprint fSettingsDigest;
-
- PreviewColorSpaceEnum fColorSpace;
-
- dng_string fDateTime;
-
- real64 fRawToPreviewGain;
-
- uint32 fCacheVersion;
-
- public:
-
- dng_preview_info ();
-
- ~dng_preview_info ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief Container for a single image file directory of a digital negative.
-///
-/// See \ref spec_dng "DNG 1.1.0 specification" for documentation of specific tags.
-
-class dng_ifd
- {
-
- public:
-
- bool fUsesNewSubFileType;
-
- uint32 fNewSubFileType;
-
- uint32 fImageWidth;
- uint32 fImageLength;
-
- uint32 fBitsPerSample [kMaxSamplesPerPixel];
-
- uint32 fCompression;
-
- uint32 fPredictor;
-
- uint32 fPhotometricInterpretation;
-
- uint32 fFillOrder;
-
- uint32 fOrientation;
- uint32 fOrientationType;
- uint64 fOrientationOffset;
- bool fOrientationBigEndian;
-
- uint32 fSamplesPerPixel;
-
- uint32 fPlanarConfiguration;
-
- real64 fXResolution;
- real64 fYResolution;
-
- uint32 fResolutionUnit;
-
- bool fUsesStrips;
- bool fUsesTiles;
-
- uint32 fTileWidth;
- uint32 fTileLength;
-
- enum
- {
- kMaxTileInfo = 32
- };
-
- uint32 fTileOffsetsType;
- uint32 fTileOffsetsCount;
- uint64 fTileOffsetsOffset;
- uint64 fTileOffset [kMaxTileInfo];
-
- uint32 fTileByteCountsType;
- uint32 fTileByteCountsCount;
- uint64 fTileByteCountsOffset;
- uint32 fTileByteCount [kMaxTileInfo];
-
- uint32 fSubIFDsCount;
- uint64 fSubIFDsOffset;
-
- uint32 fExtraSamplesCount;
- uint32 fExtraSamples [kMaxSamplesPerPixel];
-
- uint32 fSampleFormat [kMaxSamplesPerPixel];
-
- uint32 fJPEGTablesCount;
- uint64 fJPEGTablesOffset;
-
- uint64 fJPEGInterchangeFormat;
- uint32 fJPEGInterchangeFormatLength;
-
- real64 fYCbCrCoefficientR;
- real64 fYCbCrCoefficientG;
- real64 fYCbCrCoefficientB;
-
- uint32 fYCbCrSubSampleH;
- uint32 fYCbCrSubSampleV;
-
- uint32 fYCbCrPositioning;
-
- real64 fReferenceBlackWhite [6];
-
- uint32 fCFARepeatPatternRows;
- uint32 fCFARepeatPatternCols;
-
- uint8 fCFAPattern [kMaxCFAPattern] [kMaxCFAPattern];
-
- uint8 fCFAPlaneColor [kMaxColorPlanes];
-
- uint32 fCFALayout;
-
- uint32 fLinearizationTableType;
- uint32 fLinearizationTableCount;
- uint64 fLinearizationTableOffset;
-
- uint32 fBlackLevelRepeatRows;
- uint32 fBlackLevelRepeatCols;
-
- real64 fBlackLevel [kMaxBlackPattern] [kMaxBlackPattern] [kMaxSamplesPerPixel];
-
- uint32 fBlackLevelDeltaHType;
- uint32 fBlackLevelDeltaHCount;
- uint64 fBlackLevelDeltaHOffset;
-
- uint32 fBlackLevelDeltaVType;
- uint32 fBlackLevelDeltaVCount;
- uint64 fBlackLevelDeltaVOffset;
-
- real64 fWhiteLevel [kMaxSamplesPerPixel];
-
- dng_urational fDefaultScaleH;
- dng_urational fDefaultScaleV;
-
- dng_urational fBestQualityScale;
-
- dng_urational fDefaultCropOriginH;
- dng_urational fDefaultCropOriginV;
-
- dng_urational fDefaultCropSizeH;
- dng_urational fDefaultCropSizeV;
-
- dng_urational fDefaultUserCropT;
- dng_urational fDefaultUserCropL;
- dng_urational fDefaultUserCropB;
- dng_urational fDefaultUserCropR;
-
- uint32 fBayerGreenSplit;
-
- dng_urational fChromaBlurRadius;
-
- dng_urational fAntiAliasStrength;
-
- dng_rect fActiveArea;
-
- uint32 fMaskedAreaCount;
- dng_rect fMaskedArea [kMaxMaskedAreas];
-
- uint32 fRowInterleaveFactor;
-
- uint32 fSubTileBlockRows;
- uint32 fSubTileBlockCols;
-
- dng_preview_info fPreviewInfo;
-
- uint32 fOpcodeList1Count;
- uint64 fOpcodeList1Offset;
-
- uint32 fOpcodeList2Count;
- uint64 fOpcodeList2Offset;
-
- uint32 fOpcodeList3Count;
- uint64 fOpcodeList3Offset;
-
- bool fLosslessJPEGBug16;
-
- uint32 fSampleBitShift;
-
- uint64 fThisIFD;
- uint64 fNextIFD;
-
- int32 fCompressionQuality;
-
- bool fPatchFirstJPEGByte;
-
- public:
-
- dng_ifd ();
-
- virtual ~dng_ifd ();
-
- virtual bool ParseTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- virtual void PostParse ();
-
- virtual bool IsValidDNG (dng_shared &shared,
- uint32 parentCode);
-
- dng_rect Bounds () const
- {
- return dng_rect (0,
- 0,
- fImageLength,
- fImageWidth);
- }
-
- uint32 TilesAcross () const;
-
- uint32 TilesDown () const;
-
- uint32 TilesPerImage () const;
-
- dng_rect TileArea (uint32 rowIndex,
- uint32 colIndex) const;
-
- virtual uint32 TileByteCount (const dng_rect &tile) const;
-
- void SetSingleStrip ();
-
- void FindTileSize (uint32 bytesPerTile = 128 * 1024,
- uint32 cellH = 16,
- uint32 cellV = 16);
-
- void FindStripSize (uint32 bytesPerStrip = 128 * 1024,
- uint32 cellV = 16);
-
- virtual uint32 PixelType () const;
-
- virtual bool IsBaselineJPEG () const;
-
- virtual bool CanRead () const;
-
- virtual void ReadImage (dng_host &host,
- dng_stream &stream,
- dng_image &image,
- dng_jpeg_image *jpegImage = NULL,
- dng_fingerprint *jpegDigest = NULL) const;
-
- protected:
-
- virtual bool IsValidCFA (dng_shared &shared,
- uint32 parentCode);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2012 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_ifd.h#3 $ */
+/* $DateTime: 2012/06/05 11:05:39 $ */
+/* $Change: 833352 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * DNG image file directory support.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_ifd__
+#define __dng_ifd__
+
+/*****************************************************************************/
+
+#include "dng_fingerprint.h"
+#include "dng_rect.h"
+#include "dng_shared.h"
+#include "dng_stream.h"
+#include "dng_string.h"
+#include "dng_sdk_limits.h"
+#include "dng_tag_values.h"
+
+/*****************************************************************************/
+
+class dng_preview_info
+ {
+
+ public:
+
+ bool fIsPrimary;
+
+ dng_string fApplicationName;
+
+ dng_string fApplicationVersion;
+
+ dng_string fSettingsName;
+
+ dng_fingerprint fSettingsDigest;
+
+ PreviewColorSpaceEnum fColorSpace;
+
+ dng_string fDateTime;
+
+ real64 fRawToPreviewGain;
+
+ uint32 fCacheVersion;
+
+ public:
+
+ dng_preview_info ();
+
+ ~dng_preview_info ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Container for a single image file directory of a digital negative.
+///
+/// See \ref spec_dng "DNG 1.1.0 specification" for documentation of specific tags.
+
+class dng_ifd
+ {
+
+ public:
+
+ bool fUsesNewSubFileType;
+
+ uint32 fNewSubFileType;
+
+ uint32 fImageWidth;
+ uint32 fImageLength;
+
+ uint32 fBitsPerSample [kMaxSamplesPerPixel];
+
+ uint32 fCompression;
+
+ uint32 fPredictor;
+
+ uint32 fPhotometricInterpretation;
+
+ uint32 fFillOrder;
+
+ uint32 fOrientation;
+ uint32 fOrientationType;
+ uint64 fOrientationOffset;
+ bool fOrientationBigEndian;
+
+ uint32 fSamplesPerPixel;
+
+ uint32 fPlanarConfiguration;
+
+ real64 fXResolution;
+ real64 fYResolution;
+
+ uint32 fResolutionUnit;
+
+ bool fUsesStrips;
+ bool fUsesTiles;
+
+ uint32 fTileWidth;
+ uint32 fTileLength;
+
+ enum
+ {
+ kMaxTileInfo = 32
+ };
+
+ uint32 fTileOffsetsType;
+ uint32 fTileOffsetsCount;
+ uint64 fTileOffsetsOffset;
+ uint64 fTileOffset [kMaxTileInfo];
+
+ uint32 fTileByteCountsType;
+ uint32 fTileByteCountsCount;
+ uint64 fTileByteCountsOffset;
+ uint32 fTileByteCount [kMaxTileInfo];
+
+ uint32 fSubIFDsCount;
+ uint64 fSubIFDsOffset;
+
+ uint32 fExtraSamplesCount;
+ uint32 fExtraSamples [kMaxSamplesPerPixel];
+
+ uint32 fSampleFormat [kMaxSamplesPerPixel];
+
+ uint32 fJPEGTablesCount;
+ uint64 fJPEGTablesOffset;
+
+ uint64 fJPEGInterchangeFormat;
+ uint32 fJPEGInterchangeFormatLength;
+
+ real64 fYCbCrCoefficientR;
+ real64 fYCbCrCoefficientG;
+ real64 fYCbCrCoefficientB;
+
+ uint32 fYCbCrSubSampleH;
+ uint32 fYCbCrSubSampleV;
+
+ uint32 fYCbCrPositioning;
+
+ real64 fReferenceBlackWhite [6];
+
+ uint32 fCFARepeatPatternRows;
+ uint32 fCFARepeatPatternCols;
+
+ uint8 fCFAPattern [kMaxCFAPattern] [kMaxCFAPattern];
+
+ uint8 fCFAPlaneColor [kMaxColorPlanes];
+
+ uint32 fCFALayout;
+
+ uint32 fLinearizationTableType;
+ uint32 fLinearizationTableCount;
+ uint64 fLinearizationTableOffset;
+
+ uint32 fBlackLevelRepeatRows;
+ uint32 fBlackLevelRepeatCols;
+
+ real64 fBlackLevel [kMaxBlackPattern] [kMaxBlackPattern] [kMaxSamplesPerPixel];
+
+ uint32 fBlackLevelDeltaHType;
+ uint32 fBlackLevelDeltaHCount;
+ uint64 fBlackLevelDeltaHOffset;
+
+ uint32 fBlackLevelDeltaVType;
+ uint32 fBlackLevelDeltaVCount;
+ uint64 fBlackLevelDeltaVOffset;
+
+ real64 fWhiteLevel [kMaxSamplesPerPixel];
+
+ dng_urational fDefaultScaleH;
+ dng_urational fDefaultScaleV;
+
+ dng_urational fBestQualityScale;
+
+ dng_urational fDefaultCropOriginH;
+ dng_urational fDefaultCropOriginV;
+
+ dng_urational fDefaultCropSizeH;
+ dng_urational fDefaultCropSizeV;
+
+ dng_urational fDefaultUserCropT;
+ dng_urational fDefaultUserCropL;
+ dng_urational fDefaultUserCropB;
+ dng_urational fDefaultUserCropR;
+
+ uint32 fBayerGreenSplit;
+
+ dng_urational fChromaBlurRadius;
+
+ dng_urational fAntiAliasStrength;
+
+ dng_rect fActiveArea;
+
+ uint32 fMaskedAreaCount;
+ dng_rect fMaskedArea [kMaxMaskedAreas];
+
+ uint32 fRowInterleaveFactor;
+
+ uint32 fSubTileBlockRows;
+ uint32 fSubTileBlockCols;
+
+ dng_preview_info fPreviewInfo;
+
+ uint32 fOpcodeList1Count;
+ uint64 fOpcodeList1Offset;
+
+ uint32 fOpcodeList2Count;
+ uint64 fOpcodeList2Offset;
+
+ uint32 fOpcodeList3Count;
+ uint64 fOpcodeList3Offset;
+
+ bool fLosslessJPEGBug16;
+
+ uint32 fSampleBitShift;
+
+ uint64 fThisIFD;
+ uint64 fNextIFD;
+
+ int32 fCompressionQuality;
+
+ bool fPatchFirstJPEGByte;
+
+ public:
+
+ dng_ifd ();
+
+ virtual ~dng_ifd ();
+
+ virtual bool ParseTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ virtual void PostParse ();
+
+ virtual bool IsValidDNG (dng_shared &shared,
+ uint32 parentCode);
+
+ dng_rect Bounds () const
+ {
+ return dng_rect (0,
+ 0,
+ fImageLength,
+ fImageWidth);
+ }
+
+ uint32 TilesAcross () const;
+
+ uint32 TilesDown () const;
+
+ uint32 TilesPerImage () const;
+
+ dng_rect TileArea (uint32 rowIndex,
+ uint32 colIndex) const;
+
+ virtual uint32 TileByteCount (const dng_rect &tile) const;
+
+ void SetSingleStrip ();
+
+ void FindTileSize (uint32 bytesPerTile = 128 * 1024,
+ uint32 cellH = 16,
+ uint32 cellV = 16);
+
+ void FindStripSize (uint32 bytesPerStrip = 128 * 1024,
+ uint32 cellV = 16);
+
+ virtual uint32 PixelType () const;
+
+ virtual bool IsBaselineJPEG () const;
+
+ virtual bool CanRead () const;
+
+ virtual void ReadImage (dng_host &host,
+ dng_stream &stream,
+ dng_image &image,
+ dng_jpeg_image *jpegImage = NULL,
+ dng_fingerprint *jpegDigest = NULL) const;
+
+ protected:
+
+ virtual bool IsValidCFA (dng_shared &shared,
+ uint32 parentCode);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_image.cpp b/source/dng_image.cpp
index 50fd085..41b54f0 100644
--- a/source/dng_image.cpp
+++ b/source/dng_image.cpp
@@ -1,848 +1,848 @@
-/*****************************************************************************/
-// Copyright 2006-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_image.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_image.h"
-
-#include "dng_assertions.h"
-#include "dng_exceptions.h"
-#include "dng_orientation.h"
-#include "dng_pixel_buffer.h"
-#include "dng_tag_types.h"
-#include "dng_tile_iterator.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_tile_buffer::dng_tile_buffer (const dng_image &image,
- const dng_rect &tile,
- bool dirty)
-
- : fImage (image)
- , fRefData (NULL)
-
- {
-
- fImage.AcquireTileBuffer (*this,
- tile,
- dirty);
-
- }
-
-/*****************************************************************************/
-
-dng_tile_buffer::~dng_tile_buffer ()
- {
-
- fImage.ReleaseTileBuffer (*this);
-
- }
-
-/*****************************************************************************/
-
-dng_const_tile_buffer::dng_const_tile_buffer (const dng_image &image,
- const dng_rect &tile)
-
- : dng_tile_buffer (image, tile, false)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_const_tile_buffer::~dng_const_tile_buffer ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_dirty_tile_buffer::dng_dirty_tile_buffer (dng_image &image,
- const dng_rect &tile)
-
- : dng_tile_buffer (image, tile, true)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_dirty_tile_buffer::~dng_dirty_tile_buffer ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_image::dng_image (const dng_rect &bounds,
- uint32 planes,
- uint32 pixelType)
-
- : fBounds (bounds)
- , fPlanes (planes)
- , fPixelType (pixelType)
-
- {
-
- if (bounds.IsEmpty () || planes == 0 || PixelSize () == 0)
- {
-
- #if qDNGValidate
-
- ReportError ("Fuzz: Attempt to create zero size image");
-
- #endif
-
- ThrowBadFormat ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_image::~dng_image ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_image * dng_image::Clone () const
- {
-
- ThrowProgramError ("Clone is not supported by this dng_image subclass");
-
- return NULL;
-
- }
-
-/*****************************************************************************/
-
-void dng_image::SetPixelType (uint32 pixelType)
- {
-
- if (TagTypeSize (pixelType) != PixelSize ())
- {
-
- ThrowProgramError ("Cannot change pixel size for existing image");
-
- }
-
- fPixelType = pixelType;
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_image::PixelSize () const
- {
-
- return TagTypeSize (PixelType ());
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_image::PixelRange () const
- {
-
- switch (fPixelType)
- {
-
- case ttByte:
- case ttSByte:
- {
- return 0x0FF;
- }
-
- case ttShort:
- case ttSShort:
- {
- return 0x0FFFF;
- }
-
- case ttLong:
- case ttSLong:
- {
- return 0xFFFFFFFF;
- }
-
- default:
- break;
-
- }
-
- return 0;
-
- }
-
-/*****************************************************************************/
-
-dng_rect dng_image::RepeatingTile () const
- {
-
- return fBounds;
-
- }
-
-/*****************************************************************************/
-
-void dng_image::AcquireTileBuffer (dng_tile_buffer & /* buffer */,
- const dng_rect & /* area */,
- bool /* dirty */) const
- {
-
- ThrowProgramError ();
-
- }
-
-/*****************************************************************************/
-
-void dng_image::ReleaseTileBuffer (dng_tile_buffer & /* buffer */) const
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_image::DoGet (dng_pixel_buffer &buffer) const
- {
-
- dng_rect tile;
-
- dng_tile_iterator iter (*this, buffer.fArea);
-
- while (iter.GetOneTile (tile))
- {
-
- dng_const_tile_buffer tileBuffer (*this, tile);
-
- buffer.CopyArea (tileBuffer,
- tile,
- buffer.fPlane,
- buffer.fPlanes);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_image::DoPut (const dng_pixel_buffer &buffer)
- {
-
- dng_rect tile;
-
- dng_tile_iterator iter (*this, buffer.fArea);
-
- while (iter.GetOneTile (tile))
- {
-
- dng_dirty_tile_buffer tileBuffer (*this, tile);
-
- tileBuffer.CopyArea (buffer,
- tile,
- buffer.fPlane,
- buffer.fPlanes);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_image::GetRepeat (dng_pixel_buffer &buffer,
- const dng_rect &srcArea,
- const dng_rect &dstArea) const
- {
-
- // If we already have the entire srcArea in the
- // buffer, we can just repeat that.
-
- if ((srcArea & buffer.fArea) == srcArea)
- {
-
- buffer.RepeatArea (srcArea,
- dstArea);
-
- }
-
- // Else we first need to get the srcArea into the buffer area.
-
- else
- {
-
- // Find repeating pattern size.
-
- dng_point repeat = srcArea.Size ();
-
- // Find pattern phase at top-left corner of destination area.
-
- dng_point phase = dng_pixel_buffer::RepeatPhase (srcArea,
- dstArea);
-
- // Find new source area at top-left of dstArea.
-
- dng_rect newArea = srcArea + (dstArea.TL () -
- srcArea.TL ());
-
- // Find quadrant split coordinates.
-
- int32 splitV = newArea.t + repeat.v - phase.v;
- int32 splitH = newArea.l + repeat.h - phase.h;
-
- // Top-left quadrant.
-
- dng_rect dst1 (dng_rect (newArea.t,
- newArea.l,
- splitV,
- splitH) & dstArea);
-
- if (dst1.NotEmpty ())
- {
-
- dng_pixel_buffer temp (buffer);
-
- temp.fArea = dst1 + (srcArea.TL () -
- dstArea.TL () +
- dng_point (phase.v, phase.h));
-
- temp.fData = buffer.DirtyPixel (dst1.t,
- dst1.l,
- buffer.fPlane);
-
- DoGet (temp);
-
- }
-
- // Top-right quadrant.
-
- dng_rect dst2 (dng_rect (newArea.t,
- splitH,
- splitV,
- newArea.r) & dstArea);
-
- if (dst2.NotEmpty ())
- {
-
- dng_pixel_buffer temp (buffer);
-
- temp.fArea = dst2 + (srcArea.TL () -
- dstArea.TL () +
- dng_point (phase.v, -phase.h));
-
- temp.fData = buffer.DirtyPixel (dst2.t,
- dst2.l,
- buffer.fPlane);
-
- DoGet (temp);
-
- }
-
- // Bottom-left quadrant.
-
- dng_rect dst3 (dng_rect (splitV,
- newArea.l,
- newArea.b,
- splitH) & dstArea);
-
- if (dst3.NotEmpty ())
- {
-
- dng_pixel_buffer temp (buffer);
-
- temp.fArea = dst3 + (srcArea.TL () -
- dstArea.TL () +
- dng_point (-phase.v, phase.h));
-
- temp.fData = buffer.DirtyPixel (dst3.t,
- dst3.l,
- buffer.fPlane);
-
- DoGet (temp);
-
- }
-
- // Bottom-right quadrant.
-
- dng_rect dst4 (dng_rect (splitV,
- splitH,
- newArea.b,
- newArea.r) & dstArea);
-
- if (dst4.NotEmpty ())
- {
-
- dng_pixel_buffer temp (buffer);
-
- temp.fArea = dst4 + (srcArea.TL () -
- dstArea.TL () +
- dng_point (-phase.v, -phase.h));
-
- temp.fData = buffer.DirtyPixel (dst4.t,
- dst4.l,
- buffer.fPlane);
-
- DoGet (temp);
-
- }
-
- // Replicate this new source area.
-
- buffer.RepeatArea (newArea,
- dstArea);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_image::GetEdge (dng_pixel_buffer &buffer,
- edge_option edgeOption,
- const dng_rect &srcArea,
- const dng_rect &dstArea) const
- {
-
- switch (edgeOption)
- {
-
- case edge_zero:
- {
-
- buffer.SetZero (dstArea,
- buffer.fPlane,
- buffer.fPlanes);
-
- break;
-
- }
-
- case edge_repeat:
- {
-
- GetRepeat (buffer,
- srcArea,
- dstArea);
-
- break;
-
- }
-
- case edge_repeat_zero_last:
- {
-
- if (buffer.fPlanes > 1)
- {
-
- dng_pixel_buffer buffer1 (buffer);
-
- buffer1.fPlanes--;
-
- GetEdge (buffer1,
- edge_repeat,
- srcArea,
- dstArea);
-
- }
-
- dng_pixel_buffer buffer2 (buffer);
-
- buffer2.fPlane = buffer.fPlanes - 1;
- buffer2.fPlanes = 1;
-
- buffer2.fData = buffer.DirtyPixel (buffer2.fArea.t,
- buffer2.fArea.l,
- buffer2.fPlane);
-
- GetEdge (buffer2,
- edge_zero,
- srcArea,
- dstArea);
-
- break;
-
- }
-
- default:
- {
-
- ThrowProgramError ();
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_image::Get (dng_pixel_buffer &buffer,
- edge_option edgeOption,
- uint32 repeatV,
- uint32 repeatH) const
- {
-
- // Find the overlap with the image bounds.
-
- dng_rect overlap = buffer.fArea & fBounds;
-
- // Move the overlapping pixels.
-
- if (overlap.NotEmpty ())
- {
-
- dng_pixel_buffer temp (buffer);
-
- temp.fArea = overlap;
-
- temp.fData = buffer.DirtyPixel (overlap.t,
- overlap.l,
- buffer.fPlane);
-
- DoGet (temp);
-
- }
-
- // See if we need to pad the edge values.
-
- if ((edgeOption != edge_none) && (overlap != buffer.fArea))
- {
-
- dng_rect areaT (buffer.fArea);
- dng_rect areaL (buffer.fArea);
- dng_rect areaB (buffer.fArea);
- dng_rect areaR (buffer.fArea);
-
- areaT.b = Min_int32 (areaT.b, fBounds.t);
- areaL.r = Min_int32 (areaL.r, fBounds.l);
- areaB.t = Max_int32 (areaB.t, fBounds.b);
- areaR.l = Max_int32 (areaR.l, fBounds.r);
-
- dng_rect areaH (buffer.fArea);
- dng_rect areaV (buffer.fArea);
-
- areaH.l = Max_int32 (areaH.l, fBounds.l);
- areaH.r = Min_int32 (areaH.r, fBounds.r);
-
- areaV.t = Max_int32 (areaV.t, fBounds.t);
- areaV.b = Min_int32 (areaV.b, fBounds.b);
-
- // Top left.
-
- dng_rect areaTL = areaT & areaL;
-
- if (areaTL.NotEmpty ())
- {
-
- GetEdge (buffer,
- edgeOption,
- dng_rect (fBounds.t,
- fBounds.l,
- fBounds.t + repeatV,
- fBounds.l + repeatH),
- areaTL);
-
- }
-
- // Top middle.
-
- dng_rect areaTM = areaT & areaH;
-
- if (areaTM.NotEmpty ())
- {
-
- GetEdge (buffer,
- edgeOption,
- dng_rect (fBounds.t,
- areaTM.l,
- fBounds.t + repeatV,
- areaTM.r),
- areaTM);
-
- }
-
- // Top right.
-
- dng_rect areaTR = areaT & areaR;
-
- if (areaTR.NotEmpty ())
- {
-
- GetEdge (buffer,
- edgeOption,
- dng_rect (fBounds.t,
- fBounds.r - repeatH,
- fBounds.t + repeatV,
- fBounds.r),
- areaTR);
-
- }
-
- // Left middle.
-
- dng_rect areaLM = areaL & areaV;
-
- if (areaLM.NotEmpty ())
- {
-
- GetEdge (buffer,
- edgeOption,
- dng_rect (areaLM.t,
- fBounds.l,
- areaLM.b,
- fBounds.l + repeatH),
- areaLM);
-
- }
-
- // Right middle.
-
- dng_rect areaRM = areaR & areaV;
-
- if (areaRM.NotEmpty ())
- {
-
- GetEdge (buffer,
- edgeOption,
- dng_rect (areaRM.t,
- fBounds.r - repeatH,
- areaRM.b,
- fBounds.r),
- areaRM);
-
- }
-
- // Bottom left.
-
- dng_rect areaBL = areaB & areaL;
-
- if (areaBL.NotEmpty ())
- {
-
- GetEdge (buffer,
- edgeOption,
- dng_rect (fBounds.b - repeatV,
- fBounds.l,
- fBounds.b,
- fBounds.l + repeatH),
- areaBL);
-
- }
-
- // Bottom middle.
-
- dng_rect areaBM = areaB & areaH;
-
- if (areaBM.NotEmpty ())
- {
-
- GetEdge (buffer,
- edgeOption,
- dng_rect (fBounds.b - repeatV,
- areaBM.l,
- fBounds.b,
- areaBM.r),
- areaBM);
-
- }
-
- // Bottom right.
-
- dng_rect areaBR = areaB & areaR;
-
- if (areaBR.NotEmpty ())
- {
-
- GetEdge (buffer,
- edgeOption,
- dng_rect (fBounds.b - repeatV,
- fBounds.r - repeatH,
- fBounds.b,
- fBounds.r),
- areaBR);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_image::Put (const dng_pixel_buffer &buffer)
- {
-
- // Move the overlapping pixels.
-
- dng_rect overlap = buffer.fArea & fBounds;
-
- if (overlap.NotEmpty ())
- {
-
- dng_pixel_buffer temp (buffer);
-
- temp.fArea = overlap;
-
- temp.fData = (void *) buffer.ConstPixel (overlap.t,
- overlap.l,
- buffer.fPlane);
-
- // Move the overlapping planes.
-
- if (temp.fPlane < Planes ())
- {
-
- temp.fPlanes = Min_uint32 (temp.fPlanes,
- Planes () - temp.fPlane);
-
- DoPut (temp);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_image::Trim (const dng_rect &r)
- {
-
- if (r != Bounds ())
- {
-
- ThrowProgramError ("Trim is not support by this dng_image subclass");
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_image::Rotate (const dng_orientation &orientation)
- {
-
- if (orientation != dng_orientation::Normal ())
- {
-
- ThrowProgramError ("Rotate is not support by this dng_image subclass");
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_image::CopyArea (const dng_image &src,
- const dng_rect &area,
- uint32 srcPlane,
- uint32 dstPlane,
- uint32 planes)
- {
-
- if (&src == this)
- return;
-
- dng_tile_iterator destIter(*this, area);
- dng_rect destTileArea;
-
- while (destIter.GetOneTile(destTileArea))
- {
- dng_tile_iterator srcIter(src, destTileArea);
- dng_rect srcTileArea;
-
- while (srcIter.GetOneTile(srcTileArea))
- {
-
- dng_dirty_tile_buffer destTile(*this, srcTileArea);
- dng_const_tile_buffer srcTile(src, srcTileArea);
-
- destTile.CopyArea (srcTile, srcTileArea, srcPlane, dstPlane, planes);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_image::EqualArea (const dng_image &src,
- const dng_rect &area,
- uint32 plane,
- uint32 planes) const
- {
-
- if (&src == this)
- return true;
-
- dng_tile_iterator destIter (*this, area);
-
- dng_rect destTileArea;
-
- while (destIter.GetOneTile (destTileArea))
- {
-
- dng_tile_iterator srcIter (src, destTileArea);
-
- dng_rect srcTileArea;
-
- while (srcIter.GetOneTile (srcTileArea))
- {
-
- dng_const_tile_buffer destTile (*this, srcTileArea);
- dng_const_tile_buffer srcTile (src , srcTileArea);
-
- if (!destTile.EqualArea (srcTile, srcTileArea, plane, planes))
- {
- return false;
- }
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-void dng_image::SetConstant (uint32 value,
- const dng_rect &area)
- {
-
- dng_tile_iterator iter (*this, area);
-
- dng_rect tileArea;
-
- while (iter.GetOneTile (tileArea))
- {
-
- dng_dirty_tile_buffer buffer (*this, tileArea);
-
- buffer.SetConstant (tileArea,
- 0,
- fPlanes,
- value);
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_image.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_image.h"
+
+#include "dng_assertions.h"
+#include "dng_exceptions.h"
+#include "dng_orientation.h"
+#include "dng_pixel_buffer.h"
+#include "dng_tag_types.h"
+#include "dng_tile_iterator.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_tile_buffer::dng_tile_buffer (const dng_image &image,
+ const dng_rect &tile,
+ bool dirty)
+
+ : fImage (image)
+ , fRefData (NULL)
+
+ {
+
+ fImage.AcquireTileBuffer (*this,
+ tile,
+ dirty);
+
+ }
+
+/*****************************************************************************/
+
+dng_tile_buffer::~dng_tile_buffer ()
+ {
+
+ fImage.ReleaseTileBuffer (*this);
+
+ }
+
+/*****************************************************************************/
+
+dng_const_tile_buffer::dng_const_tile_buffer (const dng_image &image,
+ const dng_rect &tile)
+
+ : dng_tile_buffer (image, tile, false)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_const_tile_buffer::~dng_const_tile_buffer ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_dirty_tile_buffer::dng_dirty_tile_buffer (dng_image &image,
+ const dng_rect &tile)
+
+ : dng_tile_buffer (image, tile, true)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_dirty_tile_buffer::~dng_dirty_tile_buffer ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_image::dng_image (const dng_rect &bounds,
+ uint32 planes,
+ uint32 pixelType)
+
+ : fBounds (bounds)
+ , fPlanes (planes)
+ , fPixelType (pixelType)
+
+ {
+
+ if (bounds.IsEmpty () || planes == 0 || PixelSize () == 0)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Fuzz: Attempt to create zero size image");
+
+ #endif
+
+ ThrowBadFormat ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_image::~dng_image ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_image * dng_image::Clone () const
+ {
+
+ ThrowProgramError ("Clone is not supported by this dng_image subclass");
+
+ return NULL;
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::SetPixelType (uint32 pixelType)
+ {
+
+ if (TagTypeSize (pixelType) != PixelSize ())
+ {
+
+ ThrowProgramError ("Cannot change pixel size for existing image");
+
+ }
+
+ fPixelType = pixelType;
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_image::PixelSize () const
+ {
+
+ return TagTypeSize (PixelType ());
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_image::PixelRange () const
+ {
+
+ switch (fPixelType)
+ {
+
+ case ttByte:
+ case ttSByte:
+ {
+ return 0x0FF;
+ }
+
+ case ttShort:
+ case ttSShort:
+ {
+ return 0x0FFFF;
+ }
+
+ case ttLong:
+ case ttSLong:
+ {
+ return 0xFFFFFFFF;
+ }
+
+ default:
+ break;
+
+ }
+
+ return 0;
+
+ }
+
+/*****************************************************************************/
+
+dng_rect dng_image::RepeatingTile () const
+ {
+
+ return fBounds;
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::AcquireTileBuffer (dng_tile_buffer & /* buffer */,
+ const dng_rect & /* area */,
+ bool /* dirty */) const
+ {
+
+ ThrowProgramError ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::ReleaseTileBuffer (dng_tile_buffer & /* buffer */) const
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::DoGet (dng_pixel_buffer &buffer) const
+ {
+
+ dng_rect tile;
+
+ dng_tile_iterator iter (*this, buffer.fArea);
+
+ while (iter.GetOneTile (tile))
+ {
+
+ dng_const_tile_buffer tileBuffer (*this, tile);
+
+ buffer.CopyArea (tileBuffer,
+ tile,
+ buffer.fPlane,
+ buffer.fPlanes);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::DoPut (const dng_pixel_buffer &buffer)
+ {
+
+ dng_rect tile;
+
+ dng_tile_iterator iter (*this, buffer.fArea);
+
+ while (iter.GetOneTile (tile))
+ {
+
+ dng_dirty_tile_buffer tileBuffer (*this, tile);
+
+ tileBuffer.CopyArea (buffer,
+ tile,
+ buffer.fPlane,
+ buffer.fPlanes);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::GetRepeat (dng_pixel_buffer &buffer,
+ const dng_rect &srcArea,
+ const dng_rect &dstArea) const
+ {
+
+ // If we already have the entire srcArea in the
+ // buffer, we can just repeat that.
+
+ if ((srcArea & buffer.fArea) == srcArea)
+ {
+
+ buffer.RepeatArea (srcArea,
+ dstArea);
+
+ }
+
+ // Else we first need to get the srcArea into the buffer area.
+
+ else
+ {
+
+ // Find repeating pattern size.
+
+ dng_point repeat = srcArea.Size ();
+
+ // Find pattern phase at top-left corner of destination area.
+
+ dng_point phase = dng_pixel_buffer::RepeatPhase (srcArea,
+ dstArea);
+
+ // Find new source area at top-left of dstArea.
+
+ dng_rect newArea = srcArea + (dstArea.TL () -
+ srcArea.TL ());
+
+ // Find quadrant split coordinates.
+
+ int32 splitV = newArea.t + repeat.v - phase.v;
+ int32 splitH = newArea.l + repeat.h - phase.h;
+
+ // Top-left quadrant.
+
+ dng_rect dst1 (dng_rect (newArea.t,
+ newArea.l,
+ splitV,
+ splitH) & dstArea);
+
+ if (dst1.NotEmpty ())
+ {
+
+ dng_pixel_buffer temp (buffer);
+
+ temp.fArea = dst1 + (srcArea.TL () -
+ dstArea.TL () +
+ dng_point (phase.v, phase.h));
+
+ temp.fData = buffer.DirtyPixel (dst1.t,
+ dst1.l,
+ buffer.fPlane);
+
+ DoGet (temp);
+
+ }
+
+ // Top-right quadrant.
+
+ dng_rect dst2 (dng_rect (newArea.t,
+ splitH,
+ splitV,
+ newArea.r) & dstArea);
+
+ if (dst2.NotEmpty ())
+ {
+
+ dng_pixel_buffer temp (buffer);
+
+ temp.fArea = dst2 + (srcArea.TL () -
+ dstArea.TL () +
+ dng_point (phase.v, -phase.h));
+
+ temp.fData = buffer.DirtyPixel (dst2.t,
+ dst2.l,
+ buffer.fPlane);
+
+ DoGet (temp);
+
+ }
+
+ // Bottom-left quadrant.
+
+ dng_rect dst3 (dng_rect (splitV,
+ newArea.l,
+ newArea.b,
+ splitH) & dstArea);
+
+ if (dst3.NotEmpty ())
+ {
+
+ dng_pixel_buffer temp (buffer);
+
+ temp.fArea = dst3 + (srcArea.TL () -
+ dstArea.TL () +
+ dng_point (-phase.v, phase.h));
+
+ temp.fData = buffer.DirtyPixel (dst3.t,
+ dst3.l,
+ buffer.fPlane);
+
+ DoGet (temp);
+
+ }
+
+ // Bottom-right quadrant.
+
+ dng_rect dst4 (dng_rect (splitV,
+ splitH,
+ newArea.b,
+ newArea.r) & dstArea);
+
+ if (dst4.NotEmpty ())
+ {
+
+ dng_pixel_buffer temp (buffer);
+
+ temp.fArea = dst4 + (srcArea.TL () -
+ dstArea.TL () +
+ dng_point (-phase.v, -phase.h));
+
+ temp.fData = buffer.DirtyPixel (dst4.t,
+ dst4.l,
+ buffer.fPlane);
+
+ DoGet (temp);
+
+ }
+
+ // Replicate this new source area.
+
+ buffer.RepeatArea (newArea,
+ dstArea);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::GetEdge (dng_pixel_buffer &buffer,
+ edge_option edgeOption,
+ const dng_rect &srcArea,
+ const dng_rect &dstArea) const
+ {
+
+ switch (edgeOption)
+ {
+
+ case edge_zero:
+ {
+
+ buffer.SetZero (dstArea,
+ buffer.fPlane,
+ buffer.fPlanes);
+
+ break;
+
+ }
+
+ case edge_repeat:
+ {
+
+ GetRepeat (buffer,
+ srcArea,
+ dstArea);
+
+ break;
+
+ }
+
+ case edge_repeat_zero_last:
+ {
+
+ if (buffer.fPlanes > 1)
+ {
+
+ dng_pixel_buffer buffer1 (buffer);
+
+ buffer1.fPlanes--;
+
+ GetEdge (buffer1,
+ edge_repeat,
+ srcArea,
+ dstArea);
+
+ }
+
+ dng_pixel_buffer buffer2 (buffer);
+
+ buffer2.fPlane = buffer.fPlanes - 1;
+ buffer2.fPlanes = 1;
+
+ buffer2.fData = buffer.DirtyPixel (buffer2.fArea.t,
+ buffer2.fArea.l,
+ buffer2.fPlane);
+
+ GetEdge (buffer2,
+ edge_zero,
+ srcArea,
+ dstArea);
+
+ break;
+
+ }
+
+ default:
+ {
+
+ ThrowProgramError ();
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::Get (dng_pixel_buffer &buffer,
+ edge_option edgeOption,
+ uint32 repeatV,
+ uint32 repeatH) const
+ {
+
+ // Find the overlap with the image bounds.
+
+ dng_rect overlap = buffer.fArea & fBounds;
+
+ // Move the overlapping pixels.
+
+ if (overlap.NotEmpty ())
+ {
+
+ dng_pixel_buffer temp (buffer);
+
+ temp.fArea = overlap;
+
+ temp.fData = buffer.DirtyPixel (overlap.t,
+ overlap.l,
+ buffer.fPlane);
+
+ DoGet (temp);
+
+ }
+
+ // See if we need to pad the edge values.
+
+ if ((edgeOption != edge_none) && (overlap != buffer.fArea))
+ {
+
+ dng_rect areaT (buffer.fArea);
+ dng_rect areaL (buffer.fArea);
+ dng_rect areaB (buffer.fArea);
+ dng_rect areaR (buffer.fArea);
+
+ areaT.b = Min_int32 (areaT.b, fBounds.t);
+ areaL.r = Min_int32 (areaL.r, fBounds.l);
+ areaB.t = Max_int32 (areaB.t, fBounds.b);
+ areaR.l = Max_int32 (areaR.l, fBounds.r);
+
+ dng_rect areaH (buffer.fArea);
+ dng_rect areaV (buffer.fArea);
+
+ areaH.l = Max_int32 (areaH.l, fBounds.l);
+ areaH.r = Min_int32 (areaH.r, fBounds.r);
+
+ areaV.t = Max_int32 (areaV.t, fBounds.t);
+ areaV.b = Min_int32 (areaV.b, fBounds.b);
+
+ // Top left.
+
+ dng_rect areaTL = areaT & areaL;
+
+ if (areaTL.NotEmpty ())
+ {
+
+ GetEdge (buffer,
+ edgeOption,
+ dng_rect (fBounds.t,
+ fBounds.l,
+ fBounds.t + repeatV,
+ fBounds.l + repeatH),
+ areaTL);
+
+ }
+
+ // Top middle.
+
+ dng_rect areaTM = areaT & areaH;
+
+ if (areaTM.NotEmpty ())
+ {
+
+ GetEdge (buffer,
+ edgeOption,
+ dng_rect (fBounds.t,
+ areaTM.l,
+ fBounds.t + repeatV,
+ areaTM.r),
+ areaTM);
+
+ }
+
+ // Top right.
+
+ dng_rect areaTR = areaT & areaR;
+
+ if (areaTR.NotEmpty ())
+ {
+
+ GetEdge (buffer,
+ edgeOption,
+ dng_rect (fBounds.t,
+ fBounds.r - repeatH,
+ fBounds.t + repeatV,
+ fBounds.r),
+ areaTR);
+
+ }
+
+ // Left middle.
+
+ dng_rect areaLM = areaL & areaV;
+
+ if (areaLM.NotEmpty ())
+ {
+
+ GetEdge (buffer,
+ edgeOption,
+ dng_rect (areaLM.t,
+ fBounds.l,
+ areaLM.b,
+ fBounds.l + repeatH),
+ areaLM);
+
+ }
+
+ // Right middle.
+
+ dng_rect areaRM = areaR & areaV;
+
+ if (areaRM.NotEmpty ())
+ {
+
+ GetEdge (buffer,
+ edgeOption,
+ dng_rect (areaRM.t,
+ fBounds.r - repeatH,
+ areaRM.b,
+ fBounds.r),
+ areaRM);
+
+ }
+
+ // Bottom left.
+
+ dng_rect areaBL = areaB & areaL;
+
+ if (areaBL.NotEmpty ())
+ {
+
+ GetEdge (buffer,
+ edgeOption,
+ dng_rect (fBounds.b - repeatV,
+ fBounds.l,
+ fBounds.b,
+ fBounds.l + repeatH),
+ areaBL);
+
+ }
+
+ // Bottom middle.
+
+ dng_rect areaBM = areaB & areaH;
+
+ if (areaBM.NotEmpty ())
+ {
+
+ GetEdge (buffer,
+ edgeOption,
+ dng_rect (fBounds.b - repeatV,
+ areaBM.l,
+ fBounds.b,
+ areaBM.r),
+ areaBM);
+
+ }
+
+ // Bottom right.
+
+ dng_rect areaBR = areaB & areaR;
+
+ if (areaBR.NotEmpty ())
+ {
+
+ GetEdge (buffer,
+ edgeOption,
+ dng_rect (fBounds.b - repeatV,
+ fBounds.r - repeatH,
+ fBounds.b,
+ fBounds.r),
+ areaBR);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::Put (const dng_pixel_buffer &buffer)
+ {
+
+ // Move the overlapping pixels.
+
+ dng_rect overlap = buffer.fArea & fBounds;
+
+ if (overlap.NotEmpty ())
+ {
+
+ dng_pixel_buffer temp (buffer);
+
+ temp.fArea = overlap;
+
+ temp.fData = (void *) buffer.ConstPixel (overlap.t,
+ overlap.l,
+ buffer.fPlane);
+
+ // Move the overlapping planes.
+
+ if (temp.fPlane < Planes ())
+ {
+
+ temp.fPlanes = Min_uint32 (temp.fPlanes,
+ Planes () - temp.fPlane);
+
+ DoPut (temp);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::Trim (const dng_rect &r)
+ {
+
+ if (r != Bounds ())
+ {
+
+ ThrowProgramError ("Trim is not support by this dng_image subclass");
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::Rotate (const dng_orientation &orientation)
+ {
+
+ if (orientation != dng_orientation::Normal ())
+ {
+
+ ThrowProgramError ("Rotate is not support by this dng_image subclass");
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::CopyArea (const dng_image &src,
+ const dng_rect &area,
+ uint32 srcPlane,
+ uint32 dstPlane,
+ uint32 planes)
+ {
+
+ if (&src == this)
+ return;
+
+ dng_tile_iterator destIter(*this, area);
+ dng_rect destTileArea;
+
+ while (destIter.GetOneTile(destTileArea))
+ {
+ dng_tile_iterator srcIter(src, destTileArea);
+ dng_rect srcTileArea;
+
+ while (srcIter.GetOneTile(srcTileArea))
+ {
+
+ dng_dirty_tile_buffer destTile(*this, srcTileArea);
+ dng_const_tile_buffer srcTile(src, srcTileArea);
+
+ destTile.CopyArea (srcTile, srcTileArea, srcPlane, dstPlane, planes);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_image::EqualArea (const dng_image &src,
+ const dng_rect &area,
+ uint32 plane,
+ uint32 planes) const
+ {
+
+ if (&src == this)
+ return true;
+
+ dng_tile_iterator destIter (*this, area);
+
+ dng_rect destTileArea;
+
+ while (destIter.GetOneTile (destTileArea))
+ {
+
+ dng_tile_iterator srcIter (src, destTileArea);
+
+ dng_rect srcTileArea;
+
+ while (srcIter.GetOneTile (srcTileArea))
+ {
+
+ dng_const_tile_buffer destTile (*this, srcTileArea);
+ dng_const_tile_buffer srcTile (src , srcTileArea);
+
+ if (!destTile.EqualArea (srcTile, srcTileArea, plane, planes))
+ {
+ return false;
+ }
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+void dng_image::SetConstant (uint32 value,
+ const dng_rect &area)
+ {
+
+ dng_tile_iterator iter (*this, area);
+
+ dng_rect tileArea;
+
+ while (iter.GetOneTile (tileArea))
+ {
+
+ dng_dirty_tile_buffer buffer (*this, tileArea);
+
+ buffer.SetConstant (tileArea,
+ 0,
+ fPlanes,
+ value);
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_image.h b/source/dng_image.h
index 013182d..c19b329 100644
--- a/source/dng_image.h
+++ b/source/dng_image.h
@@ -1,433 +1,433 @@
-/*****************************************************************************/
-// Copyright 2006-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_image.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Support for working with image data in DNG SDK.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_image__
-#define __dng_image__
-
-/*****************************************************************************/
-
-#include "dng_assertions.h"
-#include "dng_classes.h"
-#include "dng_pixel_buffer.h"
-#include "dng_point.h"
-#include "dng_rect.h"
-#include "dng_tag_types.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief Class to get resource acquisition is instantiation behavior for tile
-/// buffers. Can be dirty or constant tile access.
-
-class dng_tile_buffer: public dng_pixel_buffer
- {
-
- protected:
-
- const dng_image &fImage;
-
- void *fRefData;
-
- protected:
-
- /// Obtain a tile from an image.
- /// \param image Image tile will come from.
- /// \param tile Rectangle denoting extent of tile.
- /// \param dirty Flag indicating whether this is read-only or read-write acesss.
-
- dng_tile_buffer (const dng_image &image,
- const dng_rect &tile,
- bool dirty);
-
- virtual ~dng_tile_buffer ();
-
- public:
-
- void SetRefData (void *refData)
- {
- fRefData = refData;
- }
-
- void * GetRefData () const
- {
- return fRefData;
- }
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_tile_buffer (const dng_tile_buffer &buffer);
-
- dng_tile_buffer & operator= (const dng_tile_buffer &buffer);
-
- };
-
-/*****************************************************************************/
-
-/// \brief Class to get resource acquisition is instantiation behavior for
-/// constant (read-only) tile buffers.
-
-class dng_const_tile_buffer: public dng_tile_buffer
- {
-
- public:
-
- /// Obtain a read-only tile from an image.
- /// \param image Image tile will come from.
- /// \param tile Rectangle denoting extent of tile.
-
- dng_const_tile_buffer (const dng_image &image,
- const dng_rect &tile);
-
- virtual ~dng_const_tile_buffer ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief Class to get resource acquisition is instantiation behavior for
-/// dirty (writable) tile buffers.
-
-class dng_dirty_tile_buffer: public dng_tile_buffer
- {
-
- public:
-
- /// Obtain a writable tile from an image.
- /// \param image Image tile will come from.
- /// \param tile Rectangle denoting extent of tile.
-
- dng_dirty_tile_buffer (dng_image &image,
- const dng_rect &tile);
-
- virtual ~dng_dirty_tile_buffer ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief Base class for holding image data in DNG SDK. See dng_simple_image
-/// for derived class most often used in DNG SDK.
-
-class dng_image
- {
-
- friend class dng_tile_buffer;
-
- protected:
-
- // Bounds for this image.
-
- dng_rect fBounds;
-
- // Number of image planes.
-
- uint32 fPlanes;
-
- // Basic pixel type (TIFF tag type code).
-
- uint32 fPixelType;
-
- public:
-
- /// How to handle requests to get image areas outside the image bounds.
-
- enum edge_option
- {
-
- /// Leave edge pixels unchanged.
-
- edge_none,
-
- /// Pad with zeros.
-
- edge_zero,
-
- /// Repeat edge pixels.
-
- edge_repeat,
-
- /// Repeat edge pixels, except for last plane which is zero padded.
-
- edge_repeat_zero_last
-
- };
-
- protected:
-
- dng_image (const dng_rect &bounds,
- uint32 planes,
- uint32 pixelType);
-
- public:
-
- virtual ~dng_image ();
-
- virtual dng_image * Clone () const;
-
- /// Getter method for bounds of an image.
-
- const dng_rect & Bounds () const
- {
- return fBounds;
- }
-
- /// Getter method for size of an image.
-
- dng_point Size () const
- {
- return Bounds ().Size ();
- }
-
- /// Getter method for width of an image.
-
- uint32 Width () const
- {
- return Bounds ().W ();
- }
-
- /// Getter method for height of an image.
-
- uint32 Height () const
- {
- return Bounds ().H ();
- }
-
- /// Getter method for number of planes in an image.
-
- uint32 Planes () const
- {
- return fPlanes;
- }
-
- /// Getter for pixel type.
- /// \retval See dng_tagtypes.h . Valid values are ttByte, ttShort, ttSShort,
- /// ttLong, ttFloat .
-
- uint32 PixelType () const
- {
- return fPixelType;
- }
-
- /// Setter for pixel type.
- /// \param pixelType The new pixel type .
-
- virtual void SetPixelType (uint32 pixelType);
-
- /// Getter for pixel size.
- /// \retval Size, in bytes, of pixel type for this image .
-
- uint32 PixelSize () const;
-
- /// Getter for pixel range.
- /// For unsigned types, range is 0 to return value.
- /// For signed types, range is return value - 0x8000U.
- /// For ttFloat type, pixel range is 0.0 to 1.0 and this routine returns 1.
-
- uint32 PixelRange () const;
-
- /// Getter for best "tile stride" for accessing image.
-
- virtual dng_rect RepeatingTile () const;
-
- /// Get a pixel buffer of data on image with proper edge padding.
- /// \param buffer Receives resulting pixel buffer.
- /// \param edgeOption edge_option describing how to pad edges.
- /// \param repeatV Amount of repeated padding needed in vertical for
- /// edge_repeat and edge_repeat_zero_last edgeOption cases.
- /// \param repeatH Amount of repeated padding needed in horizontal for
- /// edge_repeat and edge_repeat_zero_last edgeOption cases.
-
- void Get (dng_pixel_buffer &buffer,
- edge_option edgeOption = edge_none,
- uint32 repeatV = 1,
- uint32 repeatH = 1) const;
-
- /// Put a pixel buffer into image.
- /// \param buffer Pixel buffer to copy from.
-
- void Put (const dng_pixel_buffer &buffer);
-
- /// Shrink bounds of image to given rectangle.
- /// \param r Rectangle to crop to.
-
- virtual void Trim (const dng_rect &r);
-
- /// Rotate image to reflect given orientation change.
- /// \param orientation Directive to rotate image in a certain way.
-
- virtual void Rotate (const dng_orientation &orientation);
-
- /// Copy image data from an area of one image to same area of another.
- /// \param src Image to copy from.
- /// \param area Rectangle of images to copy.
- /// \param srcPlane Plane to start copying in src.
- /// \param dstPlane Plane to start copying in this.
- /// \param planes Number of planes to copy.
-
- void CopyArea (const dng_image &src,
- const dng_rect &area,
- uint32 srcPlane,
- uint32 dstPlane,
- uint32 planes);
-
- /// Copy image data from an area of one image to same area of another.
- /// \param src Image to copy from.
- /// \param area Rectangle of images to copy.
- /// \param plane Plane to start copying in src and this.
- /// \param planes Number of planes to copy.
-
- void CopyArea (const dng_image &src,
- const dng_rect &area,
- uint32 plane,
- uint32 planes)
- {
-
- CopyArea (src, area, plane, plane, planes);
-
- }
-
- /// Return true if the contents of an area of the image are the same as those of another.
- /// \param rhs Image to compare against.
- /// \param area Rectangle of image to test.
- /// \param plane Plane to start comparing.
- /// \param planes Number of planes to compare.
-
- bool EqualArea (const dng_image &rhs,
- const dng_rect &area,
- uint32 plane,
- uint32 planes) const;
-
- // Routines to set the entire image to a constant value.
-
- void SetConstant_uint8 (uint8 value,
- const dng_rect &area)
- {
-
- DNG_ASSERT (fPixelType == ttByte, "Mismatched pixel type");
-
- SetConstant ((uint32) value, area);
-
- }
-
- void SetConstant_uint8 (uint8 value)
- {
- SetConstant (value, Bounds ());
- }
-
- void SetConstant_uint16 (uint16 value,
- const dng_rect &area)
- {
-
- DNG_ASSERT (fPixelType == ttShort, "Mismatched pixel type");
-
- SetConstant ((uint32) value, area);
-
- }
-
- void SetConstant_uint16 (uint16 value)
- {
- SetConstant_uint16 (value, Bounds ());
- }
-
- void SetConstant_int16 (int16 value,
- const dng_rect &area)
- {
-
- DNG_ASSERT (fPixelType == ttSShort, "Mismatched pixel type");
-
- SetConstant ((uint32) (uint16) value, area);
-
- }
-
- void SetConstant_int16 (int16 value)
- {
- SetConstant_int16 (value, Bounds ());
- }
-
- void SetConstant_uint32 (uint32 value,
- const dng_rect &area)
- {
-
- DNG_ASSERT (fPixelType == ttLong, "Mismatched pixel type");
-
- SetConstant (value, area);
-
- }
-
- void SetConstant_uint32 (uint32 value)
- {
- SetConstant_uint32 (value, Bounds ());
- }
-
- void SetConstant_real32 (real32 value,
- const dng_rect &area)
- {
-
- DNG_ASSERT (fPixelType == ttFloat, "Mismatched pixel type");
-
- union
- {
- uint32 i;
- real32 f;
- } x;
-
- x.f = value;
-
- SetConstant (x.i, area);
-
- }
-
- void SetConstant_real32 (real32 value)
- {
- SetConstant_real32 (value, Bounds ());
- }
-
- virtual void GetRepeat (dng_pixel_buffer &buffer,
- const dng_rect &srcArea,
- const dng_rect &dstArea) const;
-
- protected:
-
- virtual void AcquireTileBuffer (dng_tile_buffer &buffer,
- const dng_rect &area,
- bool dirty) const;
-
- virtual void ReleaseTileBuffer (dng_tile_buffer &buffer) const;
-
- virtual void DoGet (dng_pixel_buffer &buffer) const;
-
- virtual void DoPut (const dng_pixel_buffer &buffer);
-
- void GetEdge (dng_pixel_buffer &buffer,
- edge_option edgeOption,
- const dng_rect &srcArea,
- const dng_rect &dstArea) const;
-
- virtual void SetConstant (uint32 value,
- const dng_rect &area);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_image.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Support for working with image data in DNG SDK.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_image__
+#define __dng_image__
+
+/*****************************************************************************/
+
+#include "dng_assertions.h"
+#include "dng_classes.h"
+#include "dng_pixel_buffer.h"
+#include "dng_point.h"
+#include "dng_rect.h"
+#include "dng_tag_types.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief Class to get resource acquisition is instantiation behavior for tile
+/// buffers. Can be dirty or constant tile access.
+
+class dng_tile_buffer: public dng_pixel_buffer
+ {
+
+ protected:
+
+ const dng_image &fImage;
+
+ void *fRefData;
+
+ protected:
+
+ /// Obtain a tile from an image.
+ /// \param image Image tile will come from.
+ /// \param tile Rectangle denoting extent of tile.
+ /// \param dirty Flag indicating whether this is read-only or read-write acesss.
+
+ dng_tile_buffer (const dng_image &image,
+ const dng_rect &tile,
+ bool dirty);
+
+ virtual ~dng_tile_buffer ();
+
+ public:
+
+ void SetRefData (void *refData)
+ {
+ fRefData = refData;
+ }
+
+ void * GetRefData () const
+ {
+ return fRefData;
+ }
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_tile_buffer (const dng_tile_buffer &buffer);
+
+ dng_tile_buffer & operator= (const dng_tile_buffer &buffer);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Class to get resource acquisition is instantiation behavior for
+/// constant (read-only) tile buffers.
+
+class dng_const_tile_buffer: public dng_tile_buffer
+ {
+
+ public:
+
+ /// Obtain a read-only tile from an image.
+ /// \param image Image tile will come from.
+ /// \param tile Rectangle denoting extent of tile.
+
+ dng_const_tile_buffer (const dng_image &image,
+ const dng_rect &tile);
+
+ virtual ~dng_const_tile_buffer ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Class to get resource acquisition is instantiation behavior for
+/// dirty (writable) tile buffers.
+
+class dng_dirty_tile_buffer: public dng_tile_buffer
+ {
+
+ public:
+
+ /// Obtain a writable tile from an image.
+ /// \param image Image tile will come from.
+ /// \param tile Rectangle denoting extent of tile.
+
+ dng_dirty_tile_buffer (dng_image &image,
+ const dng_rect &tile);
+
+ virtual ~dng_dirty_tile_buffer ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Base class for holding image data in DNG SDK. See dng_simple_image
+/// for derived class most often used in DNG SDK.
+
+class dng_image
+ {
+
+ friend class dng_tile_buffer;
+
+ protected:
+
+ // Bounds for this image.
+
+ dng_rect fBounds;
+
+ // Number of image planes.
+
+ uint32 fPlanes;
+
+ // Basic pixel type (TIFF tag type code).
+
+ uint32 fPixelType;
+
+ public:
+
+ /// How to handle requests to get image areas outside the image bounds.
+
+ enum edge_option
+ {
+
+ /// Leave edge pixels unchanged.
+
+ edge_none,
+
+ /// Pad with zeros.
+
+ edge_zero,
+
+ /// Repeat edge pixels.
+
+ edge_repeat,
+
+ /// Repeat edge pixels, except for last plane which is zero padded.
+
+ edge_repeat_zero_last
+
+ };
+
+ protected:
+
+ dng_image (const dng_rect &bounds,
+ uint32 planes,
+ uint32 pixelType);
+
+ public:
+
+ virtual ~dng_image ();
+
+ virtual dng_image * Clone () const;
+
+ /// Getter method for bounds of an image.
+
+ const dng_rect & Bounds () const
+ {
+ return fBounds;
+ }
+
+ /// Getter method for size of an image.
+
+ dng_point Size () const
+ {
+ return Bounds ().Size ();
+ }
+
+ /// Getter method for width of an image.
+
+ uint32 Width () const
+ {
+ return Bounds ().W ();
+ }
+
+ /// Getter method for height of an image.
+
+ uint32 Height () const
+ {
+ return Bounds ().H ();
+ }
+
+ /// Getter method for number of planes in an image.
+
+ uint32 Planes () const
+ {
+ return fPlanes;
+ }
+
+ /// Getter for pixel type.
+ /// \retval See dng_tagtypes.h . Valid values are ttByte, ttShort, ttSShort,
+ /// ttLong, ttFloat .
+
+ uint32 PixelType () const
+ {
+ return fPixelType;
+ }
+
+ /// Setter for pixel type.
+ /// \param pixelType The new pixel type .
+
+ virtual void SetPixelType (uint32 pixelType);
+
+ /// Getter for pixel size.
+ /// \retval Size, in bytes, of pixel type for this image .
+
+ uint32 PixelSize () const;
+
+ /// Getter for pixel range.
+ /// For unsigned types, range is 0 to return value.
+ /// For signed types, range is return value - 0x8000U.
+ /// For ttFloat type, pixel range is 0.0 to 1.0 and this routine returns 1.
+
+ uint32 PixelRange () const;
+
+ /// Getter for best "tile stride" for accessing image.
+
+ virtual dng_rect RepeatingTile () const;
+
+ /// Get a pixel buffer of data on image with proper edge padding.
+ /// \param buffer Receives resulting pixel buffer.
+ /// \param edgeOption edge_option describing how to pad edges.
+ /// \param repeatV Amount of repeated padding needed in vertical for
+ /// edge_repeat and edge_repeat_zero_last edgeOption cases.
+ /// \param repeatH Amount of repeated padding needed in horizontal for
+ /// edge_repeat and edge_repeat_zero_last edgeOption cases.
+
+ void Get (dng_pixel_buffer &buffer,
+ edge_option edgeOption = edge_none,
+ uint32 repeatV = 1,
+ uint32 repeatH = 1) const;
+
+ /// Put a pixel buffer into image.
+ /// \param buffer Pixel buffer to copy from.
+
+ void Put (const dng_pixel_buffer &buffer);
+
+ /// Shrink bounds of image to given rectangle.
+ /// \param r Rectangle to crop to.
+
+ virtual void Trim (const dng_rect &r);
+
+ /// Rotate image to reflect given orientation change.
+ /// \param orientation Directive to rotate image in a certain way.
+
+ virtual void Rotate (const dng_orientation &orientation);
+
+ /// Copy image data from an area of one image to same area of another.
+ /// \param src Image to copy from.
+ /// \param area Rectangle of images to copy.
+ /// \param srcPlane Plane to start copying in src.
+ /// \param dstPlane Plane to start copying in this.
+ /// \param planes Number of planes to copy.
+
+ void CopyArea (const dng_image &src,
+ const dng_rect &area,
+ uint32 srcPlane,
+ uint32 dstPlane,
+ uint32 planes);
+
+ /// Copy image data from an area of one image to same area of another.
+ /// \param src Image to copy from.
+ /// \param area Rectangle of images to copy.
+ /// \param plane Plane to start copying in src and this.
+ /// \param planes Number of planes to copy.
+
+ void CopyArea (const dng_image &src,
+ const dng_rect &area,
+ uint32 plane,
+ uint32 planes)
+ {
+
+ CopyArea (src, area, plane, plane, planes);
+
+ }
+
+ /// Return true if the contents of an area of the image are the same as those of another.
+ /// \param rhs Image to compare against.
+ /// \param area Rectangle of image to test.
+ /// \param plane Plane to start comparing.
+ /// \param planes Number of planes to compare.
+
+ bool EqualArea (const dng_image &rhs,
+ const dng_rect &area,
+ uint32 plane,
+ uint32 planes) const;
+
+ // Routines to set the entire image to a constant value.
+
+ void SetConstant_uint8 (uint8 value,
+ const dng_rect &area)
+ {
+
+ DNG_ASSERT (fPixelType == ttByte, "Mismatched pixel type");
+
+ SetConstant ((uint32) value, area);
+
+ }
+
+ void SetConstant_uint8 (uint8 value)
+ {
+ SetConstant (value, Bounds ());
+ }
+
+ void SetConstant_uint16 (uint16 value,
+ const dng_rect &area)
+ {
+
+ DNG_ASSERT (fPixelType == ttShort, "Mismatched pixel type");
+
+ SetConstant ((uint32) value, area);
+
+ }
+
+ void SetConstant_uint16 (uint16 value)
+ {
+ SetConstant_uint16 (value, Bounds ());
+ }
+
+ void SetConstant_int16 (int16 value,
+ const dng_rect &area)
+ {
+
+ DNG_ASSERT (fPixelType == ttSShort, "Mismatched pixel type");
+
+ SetConstant ((uint32) (uint16) value, area);
+
+ }
+
+ void SetConstant_int16 (int16 value)
+ {
+ SetConstant_int16 (value, Bounds ());
+ }
+
+ void SetConstant_uint32 (uint32 value,
+ const dng_rect &area)
+ {
+
+ DNG_ASSERT (fPixelType == ttLong, "Mismatched pixel type");
+
+ SetConstant (value, area);
+
+ }
+
+ void SetConstant_uint32 (uint32 value)
+ {
+ SetConstant_uint32 (value, Bounds ());
+ }
+
+ void SetConstant_real32 (real32 value,
+ const dng_rect &area)
+ {
+
+ DNG_ASSERT (fPixelType == ttFloat, "Mismatched pixel type");
+
+ union
+ {
+ uint32 i;
+ real32 f;
+ } x;
+
+ x.f = value;
+
+ SetConstant (x.i, area);
+
+ }
+
+ void SetConstant_real32 (real32 value)
+ {
+ SetConstant_real32 (value, Bounds ());
+ }
+
+ virtual void GetRepeat (dng_pixel_buffer &buffer,
+ const dng_rect &srcArea,
+ const dng_rect &dstArea) const;
+
+ protected:
+
+ virtual void AcquireTileBuffer (dng_tile_buffer &buffer,
+ const dng_rect &area,
+ bool dirty) const;
+
+ virtual void ReleaseTileBuffer (dng_tile_buffer &buffer) const;
+
+ virtual void DoGet (dng_pixel_buffer &buffer) const;
+
+ virtual void DoPut (const dng_pixel_buffer &buffer);
+
+ void GetEdge (dng_pixel_buffer &buffer,
+ edge_option edgeOption,
+ const dng_rect &srcArea,
+ const dng_rect &dstArea) const;
+
+ virtual void SetConstant (uint32 value,
+ const dng_rect &area);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_image_writer.h b/source/dng_image_writer.h
index 0b90c23..0690543 100644
--- a/source/dng_image_writer.h
+++ b/source/dng_image_writer.h
@@ -1,1245 +1,1245 @@
-/*****************************************************************************/
-// Copyright 2006-2012 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_image_writer.h#3 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Support for writing DNG images to files.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_image_writer__
-#define __dng_image_writer__
-
-/*****************************************************************************/
-
-#include "dng_auto_ptr.h"
-#include "dng_classes.h"
-#include "dng_fingerprint.h"
-#include "dng_memory.h"
-#include "dng_point.h"
-#include "dng_rational.h"
-#include "dng_sdk_limits.h"
-#include "dng_string.h"
-#include "dng_tag_types.h"
-#include "dng_tag_values.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief Image resolution.
-
-class dng_resolution
- {
-
- public:
-
- dng_urational fXResolution;
- dng_urational fYResolution;
-
- uint16 fResolutionUnit;
-
- public:
-
- dng_resolution ();
-
- };
-
-/*****************************************************************************/
-
-class tiff_tag
- {
-
- protected:
-
- uint16 fCode;
-
- uint16 fType;
-
- uint32 fCount;
-
- protected:
-
- tiff_tag (uint16 code,
- uint16 type,
- uint32 count)
-
- : fCode (code)
- , fType (type)
- , fCount (count)
-
- {
- }
-
- public:
-
- virtual ~tiff_tag ()
- {
- }
-
- uint16 Code () const
- {
- return fCode;
- }
-
- uint16 Type () const
- {
- return fType;
- }
-
- uint32 Count () const
- {
- return fCount;
- }
-
- void SetCount (uint32 count)
- {
- fCount = count;
- }
-
- uint32 Size () const
- {
- return TagTypeSize (Type ()) * Count ();
- }
-
- virtual void Put (dng_stream &stream) const = 0;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- tiff_tag (const tiff_tag &tag);
-
- tiff_tag & operator= (const tiff_tag &tag);
-
- };
-
-/******************************************************************************/
-
-class tag_data_ptr: public tiff_tag
- {
-
- protected:
-
- const void *fData;
-
- public:
-
- tag_data_ptr (uint16 code,
- uint16 type,
- uint32 count,
- const void *data)
-
- : tiff_tag (code, type, count)
-
- , fData (data)
-
- {
- }
-
- void SetData (const void *data)
- {
- fData = data;
- }
-
- virtual void Put (dng_stream &stream) const;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- tag_data_ptr (const tag_data_ptr &tag);
-
- tag_data_ptr & operator= (const tag_data_ptr &tag);
-
- };
-
-/******************************************************************************/
-
-class tag_string: public tiff_tag
- {
-
- protected:
-
- dng_string fString;
-
- public:
-
- tag_string (uint16 code,
- const dng_string &s,
- bool forceASCII = true);
-
- virtual void Put (dng_stream &stream) const;
-
- };
-
-/******************************************************************************/
-
-class tag_encoded_text: public tiff_tag
- {
-
- private:
-
- dng_string fText;
-
- dng_memory_data fUTF16;
-
- public:
-
- tag_encoded_text (uint16 code,
- const dng_string &text);
-
- virtual void Put (dng_stream &stream) const;
-
- };
-
-/******************************************************************************/
-
-class tag_uint8: public tag_data_ptr
- {
-
- private:
-
- uint8 fValue;
-
- public:
-
- tag_uint8 (uint16 code,
- uint8 value = 0)
-
- : tag_data_ptr (code, ttByte, 1, &fValue)
-
- , fValue (value)
-
- {
- }
-
- void Set (uint8 value)
- {
- fValue = value;
- }
-
- };
-
-/******************************************************************************/
-
-class tag_uint8_ptr: public tag_data_ptr
- {
-
- public:
-
- tag_uint8_ptr (uint16 code,
- const uint8 *data,
- uint32 count = 1)
-
- : tag_data_ptr (code, ttByte, count, data)
-
- {
- }
-
- };
-
-/******************************************************************************/
-
-class tag_uint16: public tag_data_ptr
- {
-
- private:
-
- uint16 fValue;
-
- public:
-
- tag_uint16 (uint16 code,
- uint16 value = 0)
-
- : tag_data_ptr (code, ttShort, 1, &fValue)
-
- , fValue (value)
-
- {
- }
-
- void Set (uint16 value)
- {
- fValue = value;
- }
-
- };
-
-/******************************************************************************/
-
-class tag_int16_ptr: public tag_data_ptr
- {
-
- public:
-
- tag_int16_ptr (uint16 code,
- const int16 *data,
- uint32 count = 1)
-
- : tag_data_ptr (code, ttSShort, count, data)
-
- {
- }
-
- };
-
-/******************************************************************************/
-
-class tag_uint16_ptr: public tag_data_ptr
- {
-
- public:
-
- tag_uint16_ptr (uint16 code,
- const uint16 *data,
- uint32 count = 1)
-
- : tag_data_ptr (code, ttShort, count, data)
-
- {
- }
-
- };
-
-/******************************************************************************/
-
-class tag_uint32: public tag_data_ptr
- {
-
- private:
-
- uint32 fValue;
-
- public:
-
- tag_uint32 (uint16 code,
- uint32 value = 0)
-
- : tag_data_ptr (code, ttLong, 1, &fValue)
-
- , fValue (value)
-
- {
- }
-
- void Set (uint32 value)
- {
- fValue = value;
- }
-
- };
-
-/******************************************************************************/
-
-class tag_uint32_ptr: public tag_data_ptr
- {
-
- public:
-
- tag_uint32_ptr (uint16 code,
- const uint32 *data,
- uint32 count = 1)
-
- : tag_data_ptr (code, ttLong, count, data)
-
- {
- }
-
- };
-
-/******************************************************************************/
-
-class tag_urational: public tag_data_ptr
- {
-
- private:
-
- const dng_urational fValue;
-
- public:
-
- tag_urational (uint16 code,
- const dng_urational &value)
-
- : tag_data_ptr (code, ttRational, 1, &fValue)
-
- , fValue (value)
-
- {
- }
-
- };
-
-/******************************************************************************/
-
-class tag_urational_ptr: public tag_data_ptr
- {
-
- public:
-
- tag_urational_ptr (uint16 code,
- const dng_urational *data = NULL,
- uint32 count = 1)
-
- : tag_data_ptr (code, ttRational, count, data)
-
- {
- }
-
- };
-
-/******************************************************************************/
-
-class tag_srational: public tag_data_ptr
- {
-
- private:
-
- const dng_srational fValue;
-
- public:
-
- tag_srational (uint16 code,
- const dng_srational &value)
-
- : tag_data_ptr (code, ttSRational, 1, &fValue)
-
- , fValue (value)
-
- {
- }
-
- };
-
-/******************************************************************************/
-
-class tag_srational_ptr: public tag_data_ptr
- {
-
- public:
-
- tag_srational_ptr (uint16 code,
- const dng_srational *data = NULL,
- uint32 count = 1)
-
- : tag_data_ptr (code, ttSRational, count, data)
-
- {
- }
-
- };
-
-/******************************************************************************/
-
-class tag_real64: public tag_data_ptr
- {
-
- private:
-
- real64 fValue;
-
- public:
-
- tag_real64 (uint16 code,
- real64 value = 0.0)
-
- : tag_data_ptr (code, ttDouble, 1, &fValue)
-
- , fValue (value)
-
- {
- }
-
- void Set (real64 value)
- {
- fValue = value;
- }
-
- };
-
-/******************************************************************************/
-
-class tag_matrix: public tag_srational_ptr
- {
-
- private:
-
- dng_srational fEntry [kMaxColorPlanes *
- kMaxColorPlanes];
-
- public:
-
- tag_matrix (uint16 code,
- const dng_matrix &m);
-
- };
-
-/******************************************************************************/
-
-class tag_icc_profile: public tag_data_ptr
- {
-
- public:
-
- tag_icc_profile (const void *profileData, uint32 profileSize);
-
- };
-
-/******************************************************************************/
-
-class tag_cfa_pattern: public tiff_tag
- {
-
- private:
-
- uint32 fRows;
- uint32 fCols;
-
- const uint8 *fPattern;
-
- public:
-
- tag_cfa_pattern (uint16 code,
- uint32 rows,
- uint32 cols,
- const uint8 *pattern)
-
- : tiff_tag (code, ttUndefined, 4 + rows * cols)
-
- , fRows (rows )
- , fCols (cols )
- , fPattern (pattern)
-
- {
- }
-
- virtual void Put (dng_stream &stream) const;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- tag_cfa_pattern (const tag_cfa_pattern &tag);
-
- tag_cfa_pattern & operator= (const tag_cfa_pattern &tag);
-
- };
-
-/******************************************************************************/
-
-class tag_exif_date_time: public tag_data_ptr
- {
-
- private:
-
- char fData [20];
-
- public:
-
- tag_exif_date_time (uint16 code,
- const dng_date_time &dt);
-
- };
-
-/******************************************************************************/
-
-class tag_iptc: public tiff_tag
- {
-
- private:
-
- const void *fData;
-
- uint32 fLength;
-
- public:
-
- tag_iptc (const void *data,
- uint32 length);
-
- virtual void Put (dng_stream &stream) const;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- tag_iptc (const tag_iptc &tag);
-
- tag_iptc & operator= (const tag_iptc &tag);
-
- };
-
-/******************************************************************************/
-
-class tag_xmp: public tag_uint8_ptr
- {
-
- private:
-
- AutoPtr<dng_memory_block> fBuffer;
-
- public:
-
- tag_xmp (const dng_xmp *xmp);
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- tag_xmp (const tag_xmp &tag);
-
- tag_xmp & operator= (const tag_xmp &tag);
-
- };
-
-/******************************************************************************/
-
-class dng_tiff_directory
- {
-
- private:
-
- enum
- {
- kMaxEntries = 100
- };
-
- uint32 fEntries;
-
- const tiff_tag *fTag [kMaxEntries];
-
- uint32 fChained;
-
- public:
-
- dng_tiff_directory ()
-
- : fEntries (0)
- , fChained (0)
-
- {
- }
-
- virtual ~dng_tiff_directory ()
- {
- }
-
- void Add (const tiff_tag *tag);
-
- void SetChained (uint32 offset)
- {
- fChained = offset;
- }
-
- uint32 Size () const;
-
- enum OffsetsBase
- {
- offsetsRelativeToStream = 0,
- offsetsRelativeToExplicitBase = 1,
- offsetsRelativeToIFD = 2
- };
-
- void Put (dng_stream &stream,
- OffsetsBase offsetsBase = offsetsRelativeToStream,
- uint32 explicitBase = 0) const;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_tiff_directory (const dng_tiff_directory &dir);
-
- dng_tiff_directory & operator= (const dng_tiff_directory &dir);
-
- };
-
-/******************************************************************************/
-
-class dng_basic_tag_set
- {
-
- private:
-
- tag_uint32 fNewSubFileType;
-
- tag_uint32 fImageWidth;
- tag_uint32 fImageLength;
-
- tag_uint16 fPhotoInterpretation;
-
- tag_uint16 fFillOrder;
-
- tag_uint16 fSamplesPerPixel;
-
- uint16 fBitsPerSampleData [kMaxSamplesPerPixel];
-
- tag_uint16_ptr fBitsPerSample;
-
- bool fStrips;
-
- tag_uint32 fTileWidth;
- tag_uint32 fTileLength;
-
- dng_memory_data fTileInfoBuffer;
-
- uint32 *fTileOffsetData;
-
- tag_uint32_ptr fTileOffsets;
-
- uint32 *fTileByteCountData;
-
- tag_uint32_ptr fTileByteCounts;
-
- tag_uint16 fPlanarConfiguration;
-
- tag_uint16 fCompression;
-
- tag_uint16 fPredictor;
-
- uint16 fExtraSamplesData [kMaxSamplesPerPixel];
-
- tag_uint16_ptr fExtraSamples;
-
- uint16 fSampleFormatData [kMaxSamplesPerPixel];
-
- tag_uint16_ptr fSampleFormat;
-
- tag_uint16 fRowInterleaveFactor;
-
- uint16 fSubTileBlockSizeData [2];
-
- tag_uint16_ptr fSubTileBlockSize;
-
- public:
-
- dng_basic_tag_set (dng_tiff_directory &directory,
- const dng_ifd &info);
-
- virtual ~dng_basic_tag_set ()
- {
- }
-
- void SetTileOffset (uint32 index,
- uint32 offset)
- {
- fTileOffsetData [index] = offset;
- }
-
- void SetTileByteCount (uint32 index,
- uint32 count)
- {
- fTileByteCountData [index] = count;
- }
-
- bool WritingStrips () const
- {
- return fStrips;
- }
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_basic_tag_set (const dng_basic_tag_set &set);
-
- dng_basic_tag_set & operator= (const dng_basic_tag_set &set);
-
- };
-
-/******************************************************************************/
-
-class exif_tag_set
- {
-
- protected:
-
- dng_tiff_directory fExifIFD;
- dng_tiff_directory fGPSIFD;
-
- private:
-
- tag_uint32 fExifLink;
- tag_uint32 fGPSLink;
-
- bool fAddedExifLink;
- bool fAddedGPSLink;
-
- uint8 fExifVersionData [4];
-
- tag_data_ptr fExifVersion;
-
- tag_urational fExposureTime;
- tag_srational fShutterSpeedValue;
-
- tag_urational fFNumber;
- tag_urational fApertureValue;
-
- tag_srational fBrightnessValue;
-
- tag_srational fExposureBiasValue;
-
- tag_urational fMaxApertureValue;
-
- tag_urational fSubjectDistance;
-
- tag_urational fFocalLength;
-
- tag_uint16 fISOSpeedRatings;
-
- tag_uint16 fSensitivityType;
- tag_uint32 fStandardOutputSensitivity;
- tag_uint32 fRecommendedExposureIndex;
- tag_uint32 fISOSpeed;
- tag_uint32 fISOSpeedLatitudeyyy;
- tag_uint32 fISOSpeedLatitudezzz;
-
- tag_uint16 fFlash;
-
- tag_uint16 fExposureProgram;
-
- tag_uint16 fMeteringMode;
-
- tag_uint16 fLightSource;
-
- tag_uint16 fSensingMethod;
-
- tag_uint16 fFocalLength35mm;
-
- uint8 fFileSourceData;
- tag_data_ptr fFileSource;
-
- uint8 fSceneTypeData;
- tag_data_ptr fSceneType;
-
- tag_cfa_pattern fCFAPattern;
-
- tag_uint16 fCustomRendered;
- tag_uint16 fExposureMode;
- tag_uint16 fWhiteBalance;
- tag_uint16 fSceneCaptureType;
- tag_uint16 fGainControl;
- tag_uint16 fContrast;
- tag_uint16 fSaturation;
- tag_uint16 fSharpness;
- tag_uint16 fSubjectDistanceRange;
-
- tag_urational fDigitalZoomRatio;
-
- tag_urational fExposureIndex;
-
- tag_uint32 fImageNumber;
-
- tag_uint16 fSelfTimerMode;
-
- tag_string fBatteryLevelA;
- tag_urational fBatteryLevelR;
-
- tag_urational fFocalPlaneXResolution;
- tag_urational fFocalPlaneYResolution;
-
- tag_uint16 fFocalPlaneResolutionUnit;
-
- uint16 fSubjectAreaData [4];
-
- tag_uint16_ptr fSubjectArea;
-
- dng_urational fLensInfoData [4];
-
- tag_urational_ptr fLensInfo;
-
- tag_exif_date_time fDateTime;
- tag_exif_date_time fDateTimeOriginal;
- tag_exif_date_time fDateTimeDigitized;
-
- tag_string fSubsecTime;
- tag_string fSubsecTimeOriginal;
- tag_string fSubsecTimeDigitized;
-
- tag_string fMake;
- tag_string fModel;
- tag_string fArtist;
- tag_string fSoftware;
- tag_string fCopyright;
- tag_string fImageDescription;
-
- tag_string fSerialNumber;
-
- tag_uint16 fMakerNoteSafety;
-
- tag_data_ptr fMakerNote;
-
- tag_encoded_text fUserComment;
-
- char fImageUniqueIDData [33];
-
- tag_data_ptr fImageUniqueID;
-
- // EXIF 2.3 tags.
-
- tag_string fCameraOwnerName;
- tag_string fBodySerialNumber;
- tag_urational_ptr fLensSpecification;
- tag_string fLensMake;
- tag_string fLensModel;
- tag_string fLensSerialNumber;
-
- uint8 fGPSVersionData [4];
-
- tag_uint8_ptr fGPSVersionID;
-
- tag_string fGPSLatitudeRef;
- tag_urational_ptr fGPSLatitude;
-
- tag_string fGPSLongitudeRef;
- tag_urational_ptr fGPSLongitude;
-
- tag_uint8 fGPSAltitudeRef;
- tag_urational fGPSAltitude;
-
- tag_urational_ptr fGPSTimeStamp;
-
- tag_string fGPSSatellites;
- tag_string fGPSStatus;
- tag_string fGPSMeasureMode;
-
- tag_urational fGPSDOP;
-
- tag_string fGPSSpeedRef;
- tag_urational fGPSSpeed;
-
- tag_string fGPSTrackRef;
- tag_urational fGPSTrack;
-
- tag_string fGPSImgDirectionRef;
- tag_urational fGPSImgDirection;
-
- tag_string fGPSMapDatum;
-
- tag_string fGPSDestLatitudeRef;
- tag_urational_ptr fGPSDestLatitude;
-
- tag_string fGPSDestLongitudeRef;
- tag_urational_ptr fGPSDestLongitude;
-
- tag_string fGPSDestBearingRef;
- tag_urational fGPSDestBearing;
-
- tag_string fGPSDestDistanceRef;
- tag_urational fGPSDestDistance;
-
- tag_encoded_text fGPSProcessingMethod;
- tag_encoded_text fGPSAreaInformation;
-
- tag_string fGPSDateStamp;
-
- tag_uint16 fGPSDifferential;
-
- tag_urational fGPSHPositioningError;
-
- public:
-
- exif_tag_set (dng_tiff_directory &directory,
- const dng_exif &exif,
- bool makerNoteSafe = false,
- const void *makerNoteData = NULL,
- uint32 makerNoteLength = 0,
- bool insideDNG = false);
-
- void Locate (uint32 offset)
- {
- fExifLink.Set (offset);
- fGPSLink .Set (offset + fExifIFD.Size ());
- }
-
- uint32 Size () const
- {
- return fExifIFD.Size () +
- fGPSIFD .Size ();
- }
-
- void Put (dng_stream &stream) const
- {
- fExifIFD.Put (stream);
- fGPSIFD .Put (stream);
- }
-
- protected:
-
- void AddLinks (dng_tiff_directory &directory);
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- exif_tag_set (const exif_tag_set &set);
-
- exif_tag_set & operator= (const exif_tag_set &set);
-
- };
-
-/******************************************************************************/
-
-class tiff_dng_extended_color_profile: private dng_tiff_directory
- {
-
- protected:
-
- const dng_camera_profile &fProfile;
-
- public:
-
- tiff_dng_extended_color_profile (const dng_camera_profile &profile);
-
- void Put (dng_stream &stream,
- bool includeModelRestriction = true);
-
- };
-
-/*****************************************************************************/
-
-class tag_dng_noise_profile: public tag_data_ptr
- {
-
- protected:
-
- real64 fValues [2 * kMaxColorPlanes];
-
- public:
-
- explicit tag_dng_noise_profile (const dng_noise_profile &profile);
-
- };
-
-/*****************************************************************************/
-
-// Enum to control the subset of metadata to save to a file.
-
-enum dng_metadata_subset
- {
-
- kMetadataSubset_CopyrightOnly = 0,
- kMetadataSubset_CopyrightAndContact,
- kMetadataSubset_AllExceptCameraInfo,
- kMetadataSubset_All,
- kMetadataSubset_AllExceptLocationInfo,
- kMetadataSubset_AllExceptCameraAndLocation,
-
- kMetadataSubset_Last = kMetadataSubset_AllExceptCameraAndLocation
-
- };
-
-/*****************************************************************************/
-
-/// \brief Support for writing dng_image or dng_negative instances to a
-/// dng_stream in TIFF or DNG format.
-
-class dng_image_writer
- {
-
- friend class dng_jpeg_image;
- friend class dng_jpeg_image_encode_task;
- friend class dng_write_tiles_task;
-
- protected:
-
- enum
- {
-
- // Target size for buffer used to copy data to the image.
-
- kImageBufferSize = 128 * 1024
-
- };
-
- public:
-
- dng_image_writer ();
-
- virtual ~dng_image_writer ();
-
- virtual void EncodeJPEGPreview (dng_host &host,
- const dng_image &image,
- dng_jpeg_preview &preview,
- int32 quality = -1);
-
- virtual void WriteImage (dng_host &host,
- const dng_ifd &ifd,
- dng_basic_tag_set &basic,
- dng_stream &stream,
- const dng_image &image,
- uint32 fakeChannels = 1);
-
- /// Write a dng_image to a dng_stream in TIFF format.
- /// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
- /// \param stream The dng_stream on which to write the TIFF.
- /// \param image The actual image data to be written.
- /// \param photometricInterpretation Either piBlackIsZero for monochrome or piRGB for RGB images.
- /// \param compression Must be ccUncompressed.
- /// \param negative or metadata If non-NULL, EXIF, IPTC, and XMP metadata from this negative is written to TIFF.
- /// \param space If non-null and color space has an ICC profile, TIFF will be tagged with this
- /// profile. No color space conversion of image data occurs.
- /// \param resolution If non-NULL, TIFF will be tagged with this resolution.
- /// \param thumbnail If non-NULL, will be stored in TIFF as preview image.
- /// \param imageResources If non-NULL, will image resources be stored in TIFF as well.
- /// \param metadataSubset The subset of metadata (e.g., copyright only) to include in the TIFF.
-
- void WriteTIFF (dng_host &host,
- dng_stream &stream,
- const dng_image &image,
- uint32 photometricInterpretation,
- uint32 compression,
- dng_negative *negative,
- const dng_color_space *space = NULL,
- const dng_resolution *resolution = NULL,
- const dng_jpeg_preview *thumbnail = NULL,
- const dng_memory_block *imageResources = NULL,
- dng_metadata_subset metadataSubset = kMetadataSubset_All);
-
- void WriteTIFF (dng_host &host,
- dng_stream &stream,
- const dng_image &image,
- uint32 photometricInterpretation = piBlackIsZero,
- uint32 compression = ccUncompressed,
- const dng_metadata *metadata = NULL,
- const dng_color_space *space = NULL,
- const dng_resolution *resolution = NULL,
- const dng_jpeg_preview *thumbnail = NULL,
- const dng_memory_block *imageResources = NULL,
- dng_metadata_subset metadataSubset = kMetadataSubset_All);
-
- /// Write a dng_image to a dng_stream in TIFF format.
- /// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
- /// \param stream The dng_stream on which to write the TIFF.
- /// \param image The actual image data to be written.
- /// \param photometricInterpretation Either piBlackIsZero for monochrome or piRGB for RGB images.
- /// \param compression Must be ccUncompressed.
- /// \param negative or metadata If non-NULL, EXIF, IPTC, and XMP metadata from this negative is written to TIFF.
- /// \param profileData If non-null, TIFF will be tagged with this profile. No color space conversion
- /// of image data occurs.
- /// \param profileSize The size for the profile data.
- /// \param resolution If non-NULL, TIFF will be tagged with this resolution.
- /// \param thumbnail If non-NULL, will be stored in TIFF as preview image.
- /// \param imageResources If non-NULL, will image resources be stored in TIFF as well.
- /// \param metadataSubset The subset of metadata (e.g., copyright only) to include in the TIFF.
-
- void WriteTIFFWithProfile (dng_host &host,
- dng_stream &stream,
- const dng_image &image,
- uint32 photometricInterpretation,
- uint32 compression,
- dng_negative *negative,
- const void *profileData = NULL,
- uint32 profileSize = 0,
- const dng_resolution *resolution = NULL,
- const dng_jpeg_preview *thumbnail = NULL,
- const dng_memory_block *imageResources = NULL,
- dng_metadata_subset metadataSubset = kMetadataSubset_All);
-
- virtual void WriteTIFFWithProfile (dng_host &host,
- dng_stream &stream,
- const dng_image &image,
- uint32 photometricInterpretation = piBlackIsZero,
- uint32 compression = ccUncompressed,
- const dng_metadata *metadata = NULL,
- const void *profileData = NULL,
- uint32 profileSize = 0,
- const dng_resolution *resolution = NULL,
- const dng_jpeg_preview *thumbnail = NULL,
- const dng_memory_block *imageResources = NULL,
- dng_metadata_subset metadataSubset = kMetadataSubset_All);
-
- /// Write a dng_image to a dng_stream in DNG format.
- /// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
- /// \param stream The dng_stream on which to write the TIFF.
- /// \param negative The image data and metadata (EXIF, IPTC, XMP) to be written.
- /// \param previewList List of previews (not counting thumbnail) to write to the file. Defaults to empty.
- /// \param maxBackwardVersion The DNG file should be readable by readers at least back to this version.
- /// \param uncompressed True to force uncompressed images. Otherwise use normal compression.
-
- void WriteDNG (dng_host &host,
- dng_stream &stream,
- dng_negative &negative,
- const dng_preview_list *previewList = NULL,
- uint32 maxBackwardVersion = dngVersion_SaveDefault,
- bool uncompressed = false);
-
- /// Write a dng_image to a dng_stream in DNG format.
- /// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
- /// \param stream The dng_stream on which to write the TIFF.
- /// \param negative The image data to be written.
- /// \param metadata The metadata (EXIF, IPTC, XMP) to be written.
- /// \param previewList List of previews (not counting thumbnail) to write to the file. Defaults to empty.
- /// \param maxBackwardVersion The DNG file should be readable by readers at least back to this version.
- /// \param uncompressed True to force uncompressed images. Otherwise use normal compression.
-
- virtual void WriteDNG (dng_host &host,
- dng_stream &stream,
- const dng_negative &negative,
- const dng_metadata &metadata,
- const dng_preview_list *previewList = NULL,
- uint32 maxBackwardVersion = dngVersion_SaveDefault,
- bool uncompressed = false);
-
- /// Resolve metadata conflicts and apply metadata policies in keeping
- /// with Metadata Working Group (MWG) guidelines.
-
- virtual void CleanUpMetadata (dng_host &host,
- dng_metadata &metadata,
- dng_metadata_subset metadataSubset,
- const char *dstMIMI,
- const char *software = NULL);
-
- protected:
-
- virtual uint32 CompressedBufferSize (const dng_ifd &ifd,
- uint32 uncompressedSize);
-
- virtual void EncodePredictor (dng_host &host,
- const dng_ifd &ifd,
- dng_pixel_buffer &buffer,
- AutoPtr<dng_memory_block> &tempBuffer);
-
- virtual void ByteSwapBuffer (dng_host &host,
- dng_pixel_buffer &buffer);
-
- void ReorderSubTileBlocks (const dng_ifd &ifd,
- dng_pixel_buffer &buffer,
- AutoPtr<dng_memory_block> &uncompressedBuffer,
- AutoPtr<dng_memory_block> &subTileBlockBuffer);
-
- virtual void WriteData (dng_host &host,
- const dng_ifd &ifd,
- dng_stream &stream,
- dng_pixel_buffer &buffer,
- AutoPtr<dng_memory_block> &compressedBuffer);
-
- virtual void WriteTile (dng_host &host,
- const dng_ifd &ifd,
- dng_stream &stream,
- const dng_image &image,
- const dng_rect &tileArea,
- uint32 fakeChannels,
- AutoPtr<dng_memory_block> &compressedBuffer,
- AutoPtr<dng_memory_block> &uncompressedBuffer,
- AutoPtr<dng_memory_block> &subTileBlockBuffer,
- AutoPtr<dng_memory_block> &tempBuffer);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2012 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_image_writer.h#3 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Support for writing DNG images to files.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_image_writer__
+#define __dng_image_writer__
+
+/*****************************************************************************/
+
+#include "dng_auto_ptr.h"
+#include "dng_classes.h"
+#include "dng_fingerprint.h"
+#include "dng_memory.h"
+#include "dng_point.h"
+#include "dng_rational.h"
+#include "dng_sdk_limits.h"
+#include "dng_string.h"
+#include "dng_tag_types.h"
+#include "dng_tag_values.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief Image resolution.
+
+class dng_resolution
+ {
+
+ public:
+
+ dng_urational fXResolution;
+ dng_urational fYResolution;
+
+ uint16 fResolutionUnit;
+
+ public:
+
+ dng_resolution ();
+
+ };
+
+/*****************************************************************************/
+
+class tiff_tag
+ {
+
+ protected:
+
+ uint16 fCode;
+
+ uint16 fType;
+
+ uint32 fCount;
+
+ protected:
+
+ tiff_tag (uint16 code,
+ uint16 type,
+ uint32 count)
+
+ : fCode (code)
+ , fType (type)
+ , fCount (count)
+
+ {
+ }
+
+ public:
+
+ virtual ~tiff_tag ()
+ {
+ }
+
+ uint16 Code () const
+ {
+ return fCode;
+ }
+
+ uint16 Type () const
+ {
+ return fType;
+ }
+
+ uint32 Count () const
+ {
+ return fCount;
+ }
+
+ void SetCount (uint32 count)
+ {
+ fCount = count;
+ }
+
+ uint32 Size () const
+ {
+ return TagTypeSize (Type ()) * Count ();
+ }
+
+ virtual void Put (dng_stream &stream) const = 0;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ tiff_tag (const tiff_tag &tag);
+
+ tiff_tag & operator= (const tiff_tag &tag);
+
+ };
+
+/******************************************************************************/
+
+class tag_data_ptr: public tiff_tag
+ {
+
+ protected:
+
+ const void *fData;
+
+ public:
+
+ tag_data_ptr (uint16 code,
+ uint16 type,
+ uint32 count,
+ const void *data)
+
+ : tiff_tag (code, type, count)
+
+ , fData (data)
+
+ {
+ }
+
+ void SetData (const void *data)
+ {
+ fData = data;
+ }
+
+ virtual void Put (dng_stream &stream) const;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ tag_data_ptr (const tag_data_ptr &tag);
+
+ tag_data_ptr & operator= (const tag_data_ptr &tag);
+
+ };
+
+/******************************************************************************/
+
+class tag_string: public tiff_tag
+ {
+
+ protected:
+
+ dng_string fString;
+
+ public:
+
+ tag_string (uint16 code,
+ const dng_string &s,
+ bool forceASCII = true);
+
+ virtual void Put (dng_stream &stream) const;
+
+ };
+
+/******************************************************************************/
+
+class tag_encoded_text: public tiff_tag
+ {
+
+ private:
+
+ dng_string fText;
+
+ dng_memory_data fUTF16;
+
+ public:
+
+ tag_encoded_text (uint16 code,
+ const dng_string &text);
+
+ virtual void Put (dng_stream &stream) const;
+
+ };
+
+/******************************************************************************/
+
+class tag_uint8: public tag_data_ptr
+ {
+
+ private:
+
+ uint8 fValue;
+
+ public:
+
+ tag_uint8 (uint16 code,
+ uint8 value = 0)
+
+ : tag_data_ptr (code, ttByte, 1, &fValue)
+
+ , fValue (value)
+
+ {
+ }
+
+ void Set (uint8 value)
+ {
+ fValue = value;
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_uint8_ptr: public tag_data_ptr
+ {
+
+ public:
+
+ tag_uint8_ptr (uint16 code,
+ const uint8 *data,
+ uint32 count = 1)
+
+ : tag_data_ptr (code, ttByte, count, data)
+
+ {
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_uint16: public tag_data_ptr
+ {
+
+ private:
+
+ uint16 fValue;
+
+ public:
+
+ tag_uint16 (uint16 code,
+ uint16 value = 0)
+
+ : tag_data_ptr (code, ttShort, 1, &fValue)
+
+ , fValue (value)
+
+ {
+ }
+
+ void Set (uint16 value)
+ {
+ fValue = value;
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_int16_ptr: public tag_data_ptr
+ {
+
+ public:
+
+ tag_int16_ptr (uint16 code,
+ const int16 *data,
+ uint32 count = 1)
+
+ : tag_data_ptr (code, ttSShort, count, data)
+
+ {
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_uint16_ptr: public tag_data_ptr
+ {
+
+ public:
+
+ tag_uint16_ptr (uint16 code,
+ const uint16 *data,
+ uint32 count = 1)
+
+ : tag_data_ptr (code, ttShort, count, data)
+
+ {
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_uint32: public tag_data_ptr
+ {
+
+ private:
+
+ uint32 fValue;
+
+ public:
+
+ tag_uint32 (uint16 code,
+ uint32 value = 0)
+
+ : tag_data_ptr (code, ttLong, 1, &fValue)
+
+ , fValue (value)
+
+ {
+ }
+
+ void Set (uint32 value)
+ {
+ fValue = value;
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_uint32_ptr: public tag_data_ptr
+ {
+
+ public:
+
+ tag_uint32_ptr (uint16 code,
+ const uint32 *data,
+ uint32 count = 1)
+
+ : tag_data_ptr (code, ttLong, count, data)
+
+ {
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_urational: public tag_data_ptr
+ {
+
+ private:
+
+ const dng_urational fValue;
+
+ public:
+
+ tag_urational (uint16 code,
+ const dng_urational &value)
+
+ : tag_data_ptr (code, ttRational, 1, &fValue)
+
+ , fValue (value)
+
+ {
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_urational_ptr: public tag_data_ptr
+ {
+
+ public:
+
+ tag_urational_ptr (uint16 code,
+ const dng_urational *data = NULL,
+ uint32 count = 1)
+
+ : tag_data_ptr (code, ttRational, count, data)
+
+ {
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_srational: public tag_data_ptr
+ {
+
+ private:
+
+ const dng_srational fValue;
+
+ public:
+
+ tag_srational (uint16 code,
+ const dng_srational &value)
+
+ : tag_data_ptr (code, ttSRational, 1, &fValue)
+
+ , fValue (value)
+
+ {
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_srational_ptr: public tag_data_ptr
+ {
+
+ public:
+
+ tag_srational_ptr (uint16 code,
+ const dng_srational *data = NULL,
+ uint32 count = 1)
+
+ : tag_data_ptr (code, ttSRational, count, data)
+
+ {
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_real64: public tag_data_ptr
+ {
+
+ private:
+
+ real64 fValue;
+
+ public:
+
+ tag_real64 (uint16 code,
+ real64 value = 0.0)
+
+ : tag_data_ptr (code, ttDouble, 1, &fValue)
+
+ , fValue (value)
+
+ {
+ }
+
+ void Set (real64 value)
+ {
+ fValue = value;
+ }
+
+ };
+
+/******************************************************************************/
+
+class tag_matrix: public tag_srational_ptr
+ {
+
+ private:
+
+ dng_srational fEntry [kMaxColorPlanes *
+ kMaxColorPlanes];
+
+ public:
+
+ tag_matrix (uint16 code,
+ const dng_matrix &m);
+
+ };
+
+/******************************************************************************/
+
+class tag_icc_profile: public tag_data_ptr
+ {
+
+ public:
+
+ tag_icc_profile (const void *profileData, uint32 profileSize);
+
+ };
+
+/******************************************************************************/
+
+class tag_cfa_pattern: public tiff_tag
+ {
+
+ private:
+
+ uint32 fRows;
+ uint32 fCols;
+
+ const uint8 *fPattern;
+
+ public:
+
+ tag_cfa_pattern (uint16 code,
+ uint32 rows,
+ uint32 cols,
+ const uint8 *pattern)
+
+ : tiff_tag (code, ttUndefined, 4 + rows * cols)
+
+ , fRows (rows )
+ , fCols (cols )
+ , fPattern (pattern)
+
+ {
+ }
+
+ virtual void Put (dng_stream &stream) const;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ tag_cfa_pattern (const tag_cfa_pattern &tag);
+
+ tag_cfa_pattern & operator= (const tag_cfa_pattern &tag);
+
+ };
+
+/******************************************************************************/
+
+class tag_exif_date_time: public tag_data_ptr
+ {
+
+ private:
+
+ char fData [20];
+
+ public:
+
+ tag_exif_date_time (uint16 code,
+ const dng_date_time &dt);
+
+ };
+
+/******************************************************************************/
+
+class tag_iptc: public tiff_tag
+ {
+
+ private:
+
+ const void *fData;
+
+ uint32 fLength;
+
+ public:
+
+ tag_iptc (const void *data,
+ uint32 length);
+
+ virtual void Put (dng_stream &stream) const;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ tag_iptc (const tag_iptc &tag);
+
+ tag_iptc & operator= (const tag_iptc &tag);
+
+ };
+
+/******************************************************************************/
+
+class tag_xmp: public tag_uint8_ptr
+ {
+
+ private:
+
+ AutoPtr<dng_memory_block> fBuffer;
+
+ public:
+
+ tag_xmp (const dng_xmp *xmp);
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ tag_xmp (const tag_xmp &tag);
+
+ tag_xmp & operator= (const tag_xmp &tag);
+
+ };
+
+/******************************************************************************/
+
+class dng_tiff_directory
+ {
+
+ private:
+
+ enum
+ {
+ kMaxEntries = 100
+ };
+
+ uint32 fEntries;
+
+ const tiff_tag *fTag [kMaxEntries];
+
+ uint32 fChained;
+
+ public:
+
+ dng_tiff_directory ()
+
+ : fEntries (0)
+ , fChained (0)
+
+ {
+ }
+
+ virtual ~dng_tiff_directory ()
+ {
+ }
+
+ void Add (const tiff_tag *tag);
+
+ void SetChained (uint32 offset)
+ {
+ fChained = offset;
+ }
+
+ uint32 Size () const;
+
+ enum OffsetsBase
+ {
+ offsetsRelativeToStream = 0,
+ offsetsRelativeToExplicitBase = 1,
+ offsetsRelativeToIFD = 2
+ };
+
+ void Put (dng_stream &stream,
+ OffsetsBase offsetsBase = offsetsRelativeToStream,
+ uint32 explicitBase = 0) const;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_tiff_directory (const dng_tiff_directory &dir);
+
+ dng_tiff_directory & operator= (const dng_tiff_directory &dir);
+
+ };
+
+/******************************************************************************/
+
+class dng_basic_tag_set
+ {
+
+ private:
+
+ tag_uint32 fNewSubFileType;
+
+ tag_uint32 fImageWidth;
+ tag_uint32 fImageLength;
+
+ tag_uint16 fPhotoInterpretation;
+
+ tag_uint16 fFillOrder;
+
+ tag_uint16 fSamplesPerPixel;
+
+ uint16 fBitsPerSampleData [kMaxSamplesPerPixel];
+
+ tag_uint16_ptr fBitsPerSample;
+
+ bool fStrips;
+
+ tag_uint32 fTileWidth;
+ tag_uint32 fTileLength;
+
+ dng_memory_data fTileInfoBuffer;
+
+ uint32 *fTileOffsetData;
+
+ tag_uint32_ptr fTileOffsets;
+
+ uint32 *fTileByteCountData;
+
+ tag_uint32_ptr fTileByteCounts;
+
+ tag_uint16 fPlanarConfiguration;
+
+ tag_uint16 fCompression;
+
+ tag_uint16 fPredictor;
+
+ uint16 fExtraSamplesData [kMaxSamplesPerPixel];
+
+ tag_uint16_ptr fExtraSamples;
+
+ uint16 fSampleFormatData [kMaxSamplesPerPixel];
+
+ tag_uint16_ptr fSampleFormat;
+
+ tag_uint16 fRowInterleaveFactor;
+
+ uint16 fSubTileBlockSizeData [2];
+
+ tag_uint16_ptr fSubTileBlockSize;
+
+ public:
+
+ dng_basic_tag_set (dng_tiff_directory &directory,
+ const dng_ifd &info);
+
+ virtual ~dng_basic_tag_set ()
+ {
+ }
+
+ void SetTileOffset (uint32 index,
+ uint32 offset)
+ {
+ fTileOffsetData [index] = offset;
+ }
+
+ void SetTileByteCount (uint32 index,
+ uint32 count)
+ {
+ fTileByteCountData [index] = count;
+ }
+
+ bool WritingStrips () const
+ {
+ return fStrips;
+ }
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_basic_tag_set (const dng_basic_tag_set &set);
+
+ dng_basic_tag_set & operator= (const dng_basic_tag_set &set);
+
+ };
+
+/******************************************************************************/
+
+class exif_tag_set
+ {
+
+ protected:
+
+ dng_tiff_directory fExifIFD;
+ dng_tiff_directory fGPSIFD;
+
+ private:
+
+ tag_uint32 fExifLink;
+ tag_uint32 fGPSLink;
+
+ bool fAddedExifLink;
+ bool fAddedGPSLink;
+
+ uint8 fExifVersionData [4];
+
+ tag_data_ptr fExifVersion;
+
+ tag_urational fExposureTime;
+ tag_srational fShutterSpeedValue;
+
+ tag_urational fFNumber;
+ tag_urational fApertureValue;
+
+ tag_srational fBrightnessValue;
+
+ tag_srational fExposureBiasValue;
+
+ tag_urational fMaxApertureValue;
+
+ tag_urational fSubjectDistance;
+
+ tag_urational fFocalLength;
+
+ tag_uint16 fISOSpeedRatings;
+
+ tag_uint16 fSensitivityType;
+ tag_uint32 fStandardOutputSensitivity;
+ tag_uint32 fRecommendedExposureIndex;
+ tag_uint32 fISOSpeed;
+ tag_uint32 fISOSpeedLatitudeyyy;
+ tag_uint32 fISOSpeedLatitudezzz;
+
+ tag_uint16 fFlash;
+
+ tag_uint16 fExposureProgram;
+
+ tag_uint16 fMeteringMode;
+
+ tag_uint16 fLightSource;
+
+ tag_uint16 fSensingMethod;
+
+ tag_uint16 fFocalLength35mm;
+
+ uint8 fFileSourceData;
+ tag_data_ptr fFileSource;
+
+ uint8 fSceneTypeData;
+ tag_data_ptr fSceneType;
+
+ tag_cfa_pattern fCFAPattern;
+
+ tag_uint16 fCustomRendered;
+ tag_uint16 fExposureMode;
+ tag_uint16 fWhiteBalance;
+ tag_uint16 fSceneCaptureType;
+ tag_uint16 fGainControl;
+ tag_uint16 fContrast;
+ tag_uint16 fSaturation;
+ tag_uint16 fSharpness;
+ tag_uint16 fSubjectDistanceRange;
+
+ tag_urational fDigitalZoomRatio;
+
+ tag_urational fExposureIndex;
+
+ tag_uint32 fImageNumber;
+
+ tag_uint16 fSelfTimerMode;
+
+ tag_string fBatteryLevelA;
+ tag_urational fBatteryLevelR;
+
+ tag_urational fFocalPlaneXResolution;
+ tag_urational fFocalPlaneYResolution;
+
+ tag_uint16 fFocalPlaneResolutionUnit;
+
+ uint16 fSubjectAreaData [4];
+
+ tag_uint16_ptr fSubjectArea;
+
+ dng_urational fLensInfoData [4];
+
+ tag_urational_ptr fLensInfo;
+
+ tag_exif_date_time fDateTime;
+ tag_exif_date_time fDateTimeOriginal;
+ tag_exif_date_time fDateTimeDigitized;
+
+ tag_string fSubsecTime;
+ tag_string fSubsecTimeOriginal;
+ tag_string fSubsecTimeDigitized;
+
+ tag_string fMake;
+ tag_string fModel;
+ tag_string fArtist;
+ tag_string fSoftware;
+ tag_string fCopyright;
+ tag_string fImageDescription;
+
+ tag_string fSerialNumber;
+
+ tag_uint16 fMakerNoteSafety;
+
+ tag_data_ptr fMakerNote;
+
+ tag_encoded_text fUserComment;
+
+ char fImageUniqueIDData [33];
+
+ tag_data_ptr fImageUniqueID;
+
+ // EXIF 2.3 tags.
+
+ tag_string fCameraOwnerName;
+ tag_string fBodySerialNumber;
+ tag_urational_ptr fLensSpecification;
+ tag_string fLensMake;
+ tag_string fLensModel;
+ tag_string fLensSerialNumber;
+
+ uint8 fGPSVersionData [4];
+
+ tag_uint8_ptr fGPSVersionID;
+
+ tag_string fGPSLatitudeRef;
+ tag_urational_ptr fGPSLatitude;
+
+ tag_string fGPSLongitudeRef;
+ tag_urational_ptr fGPSLongitude;
+
+ tag_uint8 fGPSAltitudeRef;
+ tag_urational fGPSAltitude;
+
+ tag_urational_ptr fGPSTimeStamp;
+
+ tag_string fGPSSatellites;
+ tag_string fGPSStatus;
+ tag_string fGPSMeasureMode;
+
+ tag_urational fGPSDOP;
+
+ tag_string fGPSSpeedRef;
+ tag_urational fGPSSpeed;
+
+ tag_string fGPSTrackRef;
+ tag_urational fGPSTrack;
+
+ tag_string fGPSImgDirectionRef;
+ tag_urational fGPSImgDirection;
+
+ tag_string fGPSMapDatum;
+
+ tag_string fGPSDestLatitudeRef;
+ tag_urational_ptr fGPSDestLatitude;
+
+ tag_string fGPSDestLongitudeRef;
+ tag_urational_ptr fGPSDestLongitude;
+
+ tag_string fGPSDestBearingRef;
+ tag_urational fGPSDestBearing;
+
+ tag_string fGPSDestDistanceRef;
+ tag_urational fGPSDestDistance;
+
+ tag_encoded_text fGPSProcessingMethod;
+ tag_encoded_text fGPSAreaInformation;
+
+ tag_string fGPSDateStamp;
+
+ tag_uint16 fGPSDifferential;
+
+ tag_urational fGPSHPositioningError;
+
+ public:
+
+ exif_tag_set (dng_tiff_directory &directory,
+ const dng_exif &exif,
+ bool makerNoteSafe = false,
+ const void *makerNoteData = NULL,
+ uint32 makerNoteLength = 0,
+ bool insideDNG = false);
+
+ void Locate (uint32 offset)
+ {
+ fExifLink.Set (offset);
+ fGPSLink .Set (offset + fExifIFD.Size ());
+ }
+
+ uint32 Size () const
+ {
+ return fExifIFD.Size () +
+ fGPSIFD .Size ();
+ }
+
+ void Put (dng_stream &stream) const
+ {
+ fExifIFD.Put (stream);
+ fGPSIFD .Put (stream);
+ }
+
+ protected:
+
+ void AddLinks (dng_tiff_directory &directory);
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ exif_tag_set (const exif_tag_set &set);
+
+ exif_tag_set & operator= (const exif_tag_set &set);
+
+ };
+
+/******************************************************************************/
+
+class tiff_dng_extended_color_profile: private dng_tiff_directory
+ {
+
+ protected:
+
+ const dng_camera_profile &fProfile;
+
+ public:
+
+ tiff_dng_extended_color_profile (const dng_camera_profile &profile);
+
+ void Put (dng_stream &stream,
+ bool includeModelRestriction = true);
+
+ };
+
+/*****************************************************************************/
+
+class tag_dng_noise_profile: public tag_data_ptr
+ {
+
+ protected:
+
+ real64 fValues [2 * kMaxColorPlanes];
+
+ public:
+
+ explicit tag_dng_noise_profile (const dng_noise_profile &profile);
+
+ };
+
+/*****************************************************************************/
+
+// Enum to control the subset of metadata to save to a file.
+
+enum dng_metadata_subset
+ {
+
+ kMetadataSubset_CopyrightOnly = 0,
+ kMetadataSubset_CopyrightAndContact,
+ kMetadataSubset_AllExceptCameraInfo,
+ kMetadataSubset_All,
+ kMetadataSubset_AllExceptLocationInfo,
+ kMetadataSubset_AllExceptCameraAndLocation,
+
+ kMetadataSubset_Last = kMetadataSubset_AllExceptCameraAndLocation
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Support for writing dng_image or dng_negative instances to a
+/// dng_stream in TIFF or DNG format.
+
+class dng_image_writer
+ {
+
+ friend class dng_jpeg_image;
+ friend class dng_jpeg_image_encode_task;
+ friend class dng_write_tiles_task;
+
+ protected:
+
+ enum
+ {
+
+ // Target size for buffer used to copy data to the image.
+
+ kImageBufferSize = 128 * 1024
+
+ };
+
+ public:
+
+ dng_image_writer ();
+
+ virtual ~dng_image_writer ();
+
+ virtual void EncodeJPEGPreview (dng_host &host,
+ const dng_image &image,
+ dng_jpeg_preview &preview,
+ int32 quality = -1);
+
+ virtual void WriteImage (dng_host &host,
+ const dng_ifd &ifd,
+ dng_basic_tag_set &basic,
+ dng_stream &stream,
+ const dng_image &image,
+ uint32 fakeChannels = 1);
+
+ /// Write a dng_image to a dng_stream in TIFF format.
+ /// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
+ /// \param stream The dng_stream on which to write the TIFF.
+ /// \param image The actual image data to be written.
+ /// \param photometricInterpretation Either piBlackIsZero for monochrome or piRGB for RGB images.
+ /// \param compression Must be ccUncompressed.
+ /// \param negative or metadata If non-NULL, EXIF, IPTC, and XMP metadata from this negative is written to TIFF.
+ /// \param space If non-null and color space has an ICC profile, TIFF will be tagged with this
+ /// profile. No color space conversion of image data occurs.
+ /// \param resolution If non-NULL, TIFF will be tagged with this resolution.
+ /// \param thumbnail If non-NULL, will be stored in TIFF as preview image.
+ /// \param imageResources If non-NULL, will image resources be stored in TIFF as well.
+ /// \param metadataSubset The subset of metadata (e.g., copyright only) to include in the TIFF.
+
+ void WriteTIFF (dng_host &host,
+ dng_stream &stream,
+ const dng_image &image,
+ uint32 photometricInterpretation,
+ uint32 compression,
+ dng_negative *negative,
+ const dng_color_space *space = NULL,
+ const dng_resolution *resolution = NULL,
+ const dng_jpeg_preview *thumbnail = NULL,
+ const dng_memory_block *imageResources = NULL,
+ dng_metadata_subset metadataSubset = kMetadataSubset_All);
+
+ void WriteTIFF (dng_host &host,
+ dng_stream &stream,
+ const dng_image &image,
+ uint32 photometricInterpretation = piBlackIsZero,
+ uint32 compression = ccUncompressed,
+ const dng_metadata *metadata = NULL,
+ const dng_color_space *space = NULL,
+ const dng_resolution *resolution = NULL,
+ const dng_jpeg_preview *thumbnail = NULL,
+ const dng_memory_block *imageResources = NULL,
+ dng_metadata_subset metadataSubset = kMetadataSubset_All);
+
+ /// Write a dng_image to a dng_stream in TIFF format.
+ /// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
+ /// \param stream The dng_stream on which to write the TIFF.
+ /// \param image The actual image data to be written.
+ /// \param photometricInterpretation Either piBlackIsZero for monochrome or piRGB for RGB images.
+ /// \param compression Must be ccUncompressed.
+ /// \param negative or metadata If non-NULL, EXIF, IPTC, and XMP metadata from this negative is written to TIFF.
+ /// \param profileData If non-null, TIFF will be tagged with this profile. No color space conversion
+ /// of image data occurs.
+ /// \param profileSize The size for the profile data.
+ /// \param resolution If non-NULL, TIFF will be tagged with this resolution.
+ /// \param thumbnail If non-NULL, will be stored in TIFF as preview image.
+ /// \param imageResources If non-NULL, will image resources be stored in TIFF as well.
+ /// \param metadataSubset The subset of metadata (e.g., copyright only) to include in the TIFF.
+
+ void WriteTIFFWithProfile (dng_host &host,
+ dng_stream &stream,
+ const dng_image &image,
+ uint32 photometricInterpretation,
+ uint32 compression,
+ dng_negative *negative,
+ const void *profileData = NULL,
+ uint32 profileSize = 0,
+ const dng_resolution *resolution = NULL,
+ const dng_jpeg_preview *thumbnail = NULL,
+ const dng_memory_block *imageResources = NULL,
+ dng_metadata_subset metadataSubset = kMetadataSubset_All);
+
+ virtual void WriteTIFFWithProfile (dng_host &host,
+ dng_stream &stream,
+ const dng_image &image,
+ uint32 photometricInterpretation = piBlackIsZero,
+ uint32 compression = ccUncompressed,
+ const dng_metadata *metadata = NULL,
+ const void *profileData = NULL,
+ uint32 profileSize = 0,
+ const dng_resolution *resolution = NULL,
+ const dng_jpeg_preview *thumbnail = NULL,
+ const dng_memory_block *imageResources = NULL,
+ dng_metadata_subset metadataSubset = kMetadataSubset_All);
+
+ /// Write a dng_image to a dng_stream in DNG format.
+ /// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
+ /// \param stream The dng_stream on which to write the TIFF.
+ /// \param negative The image data and metadata (EXIF, IPTC, XMP) to be written.
+ /// \param previewList List of previews (not counting thumbnail) to write to the file. Defaults to empty.
+ /// \param maxBackwardVersion The DNG file should be readable by readers at least back to this version.
+ /// \param uncompressed True to force uncompressed images. Otherwise use normal compression.
+
+ void WriteDNG (dng_host &host,
+ dng_stream &stream,
+ dng_negative &negative,
+ const dng_preview_list *previewList = NULL,
+ uint32 maxBackwardVersion = dngVersion_SaveDefault,
+ bool uncompressed = false);
+
+ /// Write a dng_image to a dng_stream in DNG format.
+ /// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
+ /// \param stream The dng_stream on which to write the TIFF.
+ /// \param negative The image data to be written.
+ /// \param metadata The metadata (EXIF, IPTC, XMP) to be written.
+ /// \param previewList List of previews (not counting thumbnail) to write to the file. Defaults to empty.
+ /// \param maxBackwardVersion The DNG file should be readable by readers at least back to this version.
+ /// \param uncompressed True to force uncompressed images. Otherwise use normal compression.
+
+ virtual void WriteDNG (dng_host &host,
+ dng_stream &stream,
+ const dng_negative &negative,
+ const dng_metadata &metadata,
+ const dng_preview_list *previewList = NULL,
+ uint32 maxBackwardVersion = dngVersion_SaveDefault,
+ bool uncompressed = false);
+
+ /// Resolve metadata conflicts and apply metadata policies in keeping
+ /// with Metadata Working Group (MWG) guidelines.
+
+ virtual void CleanUpMetadata (dng_host &host,
+ dng_metadata &metadata,
+ dng_metadata_subset metadataSubset,
+ const char *dstMIMI,
+ const char *software = NULL);
+
+ protected:
+
+ virtual uint32 CompressedBufferSize (const dng_ifd &ifd,
+ uint32 uncompressedSize);
+
+ virtual void EncodePredictor (dng_host &host,
+ const dng_ifd &ifd,
+ dng_pixel_buffer &buffer,
+ AutoPtr<dng_memory_block> &tempBuffer);
+
+ virtual void ByteSwapBuffer (dng_host &host,
+ dng_pixel_buffer &buffer);
+
+ void ReorderSubTileBlocks (const dng_ifd &ifd,
+ dng_pixel_buffer &buffer,
+ AutoPtr<dng_memory_block> &uncompressedBuffer,
+ AutoPtr<dng_memory_block> &subTileBlockBuffer);
+
+ virtual void WriteData (dng_host &host,
+ const dng_ifd &ifd,
+ dng_stream &stream,
+ dng_pixel_buffer &buffer,
+ AutoPtr<dng_memory_block> &compressedBuffer);
+
+ virtual void WriteTile (dng_host &host,
+ const dng_ifd &ifd,
+ dng_stream &stream,
+ const dng_image &image,
+ const dng_rect &tileArea,
+ uint32 fakeChannels,
+ AutoPtr<dng_memory_block> &compressedBuffer,
+ AutoPtr<dng_memory_block> &uncompressedBuffer,
+ AutoPtr<dng_memory_block> &subTileBlockBuffer,
+ AutoPtr<dng_memory_block> &tempBuffer);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_info.cpp b/source/dng_info.cpp
index d6bd360..65f3a4b 100644
--- a/source/dng_info.cpp
+++ b/source/dng_info.cpp
@@ -1,2525 +1,2525 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_info.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_info.h"
-
-#include "dng_camera_profile.h"
-#include "dng_exceptions.h"
-#include "dng_globals.h"
-#include "dng_host.h"
-#include "dng_tag_codes.h"
-#include "dng_parse_utils.h"
-#include "dng_tag_types.h"
-#include "dng_tag_values.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_info::dng_info ()
-
- : fTIFFBlockOffset (0)
- , fTIFFBlockOriginalOffset (kDNGStreamInvalidOffset)
- , fBigEndian (false)
- , fMagic (0)
- , fExif ()
- , fShared ()
- , fMainIndex (-1)
- , fMaskIndex (-1)
- , fIFDCount (0)
- , fChainedIFDCount (0)
- , fMakerNoteNextIFD (0)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_info::~dng_info ()
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_info::ValidateMagic ()
- {
-
- switch (fMagic)
- {
-
- case magicTIFF:
- case magicExtendedProfile:
- case magicRawCache:
- case magicPanasonic:
- case magicOlympusA:
- case magicOlympusB:
- {
-
- return;
-
- }
-
- default:
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid TIFF magic number");
-
- #endif
-
- ThrowBadFormat ();
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_info::ParseTag (dng_host &host,
- dng_stream &stream,
- dng_exif *exif,
- dng_shared *shared,
- dng_ifd *ifd,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset,
- int64 offsetDelta)
- {
-
- bool isSubIFD = parentCode >= tcFirstSubIFD &&
- parentCode <= tcLastSubIFD;
-
- bool isMainIFD = (parentCode == 0 || isSubIFD) &&
- ifd &&
- ifd->fUsesNewSubFileType &&
- ifd->fNewSubFileType == sfMainImage;
-
- // Panasonic RAW format stores private tags using tag codes < 254 in
- // IFD 0. Redirect the parsing of these tags into a logical
- // "PanasonicRAW" IFD.
-
- // Panasonic is starting to use some higher numbers also (280..283).
-
- if (fMagic == 85 && parentCode == 0 && (tagCode < tcNewSubFileType ||
- (tagCode >= 280 && tagCode <= 283)))
- {
-
- parentCode = tcPanasonicRAW;
-
- ifd = NULL;
-
- }
-
- stream.SetReadPosition (tagOffset);
-
- if (ifd && ifd->ParseTag (stream,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- tagOffset))
- {
-
- return;
-
- }
-
- stream.SetReadPosition (tagOffset);
-
- if (exif && shared && exif->ParseTag (stream,
- *shared,
- parentCode,
- isMainIFD,
- tagCode,
- tagType,
- tagCount,
- tagOffset))
- {
-
- return;
-
- }
-
- stream.SetReadPosition (tagOffset);
-
- if (shared && exif && shared->ParseTag (stream,
- *exif,
- parentCode,
- isMainIFD,
- tagCode,
- tagType,
- tagCount,
- tagOffset,
- offsetDelta))
- {
-
- return;
-
- }
-
- if (parentCode == tcLeicaMakerNote &&
- tagType == ttUndefined &&
- tagCount >= 14)
- {
-
- if (ParseMakerNoteIFD (host,
- stream,
- tagCount,
- tagOffset,
- offsetDelta,
- tagOffset,
- stream.Length (),
- tcLeicaMakerNote))
- {
-
- return;
-
- }
-
- }
-
- if (parentCode == tcOlympusMakerNote &&
- tagType == ttUndefined &&
- tagCount >= 14)
- {
-
- uint32 olympusMakerParent = 0;
-
- switch (tagCode)
- {
-
- case 8208:
- olympusMakerParent = tcOlympusMakerNote8208;
- break;
-
- case 8224:
- olympusMakerParent = tcOlympusMakerNote8224;
- break;
-
- case 8240:
- olympusMakerParent = tcOlympusMakerNote8240;
- break;
-
- case 8256:
- olympusMakerParent = tcOlympusMakerNote8256;
- break;
-
- case 8272:
- olympusMakerParent = tcOlympusMakerNote8272;
- break;
-
- case 12288:
- olympusMakerParent = tcOlympusMakerNote12288;
- break;
-
- default:
- break;
-
- }
-
- if (olympusMakerParent)
- {
-
- // Olympus made a mistake in some camera models in computing
- // the size of these sub-tags, so we fudge the count.
-
- if (ParseMakerNoteIFD (host,
- stream,
- stream.Length () - tagOffset,
- tagOffset,
- offsetDelta,
- tagOffset,
- stream.Length (),
- olympusMakerParent))
- {
-
- return;
-
- }
-
- }
-
- }
-
- if (parentCode == tcRicohMakerNote &&
- tagCode == 0x2001 &&
- tagType == ttUndefined &&
- tagCount > 22)
- {
-
- char header [20];
-
- stream.SetReadPosition (tagOffset);
-
- stream.Get (header, sizeof (header));
-
- if (memcmp (header, "[Ricoh Camera Info]", 19) == 0)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- tagCount - 20,
- tagOffset + 20,
- offsetDelta,
- tagOffset + 20,
- tagOffset + tagCount,
- tcRicohMakerNoteCameraInfo);
-
- return;
-
- }
-
- }
-
- #if qDNGValidate
-
- {
-
- stream.SetReadPosition (tagOffset);
-
- if (gVerbose)
- {
-
- printf ("*");
-
- DumpTagValues (stream,
- LookupTagType (tagType),
- parentCode,
- tagCode,
- tagType,
- tagCount);
-
- }
-
- // If type is ASCII, then parse anyway so we report any ASCII
- // NULL termination or character set errors.
-
- else if (tagType == ttAscii)
- {
-
- dng_string s;
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- s,
- false);
-
- }
-
- }
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-bool dng_info::ValidateIFD (dng_stream &stream,
- uint64 ifdOffset,
- int64 offsetDelta)
- {
-
- // Make sure we have a count.
-
- if (ifdOffset + 2 > stream.Length ())
- {
- return false;
- }
-
- // Get entry count.
-
- stream.SetReadPosition (ifdOffset);
-
- uint32 ifdEntries = stream.Get_uint16 ();
-
- if (ifdEntries < 1)
- {
- return false;
- }
-
- // Make sure we have room for all entries and next IFD link.
-
- if (ifdOffset + 2 + ifdEntries * 12 + 4 > stream.Length ())
- {
- return false;
- }
-
- // Check each entry.
-
- for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++)
- {
-
- stream.SetReadPosition (ifdOffset + 2 + tag_index * 12);
-
- stream.Skip (2); // Ignore tag code.
-
- uint32 tagType = stream.Get_uint16 ();
- uint32 tagCount = stream.Get_uint32 ();
-
- uint32 tag_type_size = TagTypeSize (tagType);
-
- if (tag_type_size == 0)
- {
- return false;
- }
-
- uint32 tag_data_size = tagCount * tag_type_size;
-
- if (tag_data_size > 4)
- {
-
- uint64 tagOffset = stream.Get_uint32 ();
-
- tagOffset += offsetDelta;
-
- if (tagOffset + tag_data_size > stream.Length ())
- {
- return false;
- }
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-void dng_info::ParseIFD (dng_host &host,
- dng_stream &stream,
- dng_exif *exif,
- dng_shared *shared,
- dng_ifd *ifd,
- uint64 ifdOffset,
- int64 offsetDelta,
- uint32 parentCode)
- {
-
- #if qDNGValidate
-
- bool isMakerNote = (parentCode >= tcFirstMakerNoteIFD &&
- parentCode <= tcLastMakerNoteIFD);
-
- #endif
-
- stream.SetReadPosition (ifdOffset);
-
- if (ifd)
- {
- ifd->fThisIFD = ifdOffset;
- }
-
- uint32 ifdEntries = stream.Get_uint16 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: Offset = %u, Entries = %u\n\n",
- LookupParentCode (parentCode),
- (unsigned) ifdOffset,
- (unsigned) ifdEntries);
-
- }
-
- if ((ifdOffset & 1) && !isMakerNote)
- {
-
- char message [256];
-
- sprintf (message,
- "%s has odd offset (%u)",
- LookupParentCode (parentCode),
- (unsigned) ifdOffset);
-
- ReportWarning (message);
-
- }
-
- #endif
-
- uint32 prev_tag_code = 0;
-
- for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++)
- {
-
- stream.SetReadPosition (ifdOffset + 2 + tag_index * 12);
-
- uint32 tagCode = stream.Get_uint16 ();
- uint32 tagType = stream.Get_uint16 ();
-
- // Minolta 7D files have a bug in the EXIF block where the count
- // is wrong, and we run off into next IFD link. So if abort parsing
- // if we get a zero code/type combinations.
-
- if (tagCode == 0 && tagType == 0)
- {
-
- #if qDNGValidate
-
- char message [256];
-
- sprintf (message,
- "%s had zero/zero tag code/type entry",
- LookupParentCode (parentCode));
-
- ReportWarning (message);
-
- #endif
-
- return;
-
- }
-
- uint32 tagCount = stream.Get_uint32 ();
-
- #if qDNGValidate
-
- {
-
- if (tag_index > 0 && tagCode <= prev_tag_code && !isMakerNote)
- {
-
- char message [256];
-
- sprintf (message,
- "%s tags are not sorted in ascending numerical order",
- LookupParentCode (parentCode));
-
- ReportWarning (message);
-
- }
-
- }
-
- #endif
-
- prev_tag_code = tagCode;
-
- uint32 tag_type_size = TagTypeSize (tagType);
-
- if (tag_type_size == 0)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s has unknown type (%u)",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode),
- (unsigned) tagType);
-
- ReportWarning (message);
-
- }
-
- #endif
-
- continue;
-
- }
-
- uint64 tagOffset = ifdOffset + 2 + tag_index * 12 + 8;
-
- if (tagCount * tag_type_size > 4)
- {
-
- tagOffset = stream.Get_uint32 ();
-
- #if qDNGValidate
-
- {
-
- if (!(ifdOffset & 1) &&
- (tagOffset & 1) &&
- !isMakerNote &&
- parentCode != tcKodakDCRPrivateIFD &&
- parentCode != tcKodakKDCPrivateIFD)
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s has odd data offset (%u)",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode),
- (unsigned) tagOffset);
-
- ReportWarning (message);
-
- }
-
- }
-
- #endif
-
- tagOffset += offsetDelta;
-
- stream.SetReadPosition (tagOffset);
-
- }
-
- ParseTag (host,
- stream,
- exif,
- shared,
- ifd,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- tagOffset,
- offsetDelta);
-
- }
-
- stream.SetReadPosition (ifdOffset + 2 + ifdEntries * 12);
-
- uint32 nextIFD = stream.Get_uint32 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("NextIFD = %u\n", (unsigned) nextIFD);
- }
-
- #endif
-
- if (ifd)
- {
- ifd->fNextIFD = nextIFD;
- }
-
- #if qDNGValidate
-
- if (nextIFD)
- {
-
- if (parentCode != 0 &&
- (parentCode < tcFirstChainedIFD ||
- parentCode > tcLastChainedIFD ))
- {
-
- char message [256];
-
- sprintf (message,
- "%s has an unexpected non-zero NextIFD (%u)",
- LookupParentCode (parentCode),
- (unsigned) nextIFD);
-
- ReportWarning (message);
-
- }
-
- }
-
- if (gVerbose)
- {
- printf ("\n");
- }
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-bool dng_info::ParseMakerNoteIFD (dng_host &host,
- dng_stream &stream,
- uint64 ifdSize,
- uint64 ifdOffset,
- int64 offsetDelta,
- uint64 minOffset,
- uint64 maxOffset,
- uint32 parentCode)
- {
-
- uint32 tagIndex;
- uint32 tagCode;
- uint32 tagType;
- uint32 tagCount;
-
- // Assume there is no next IFD pointer.
-
- fMakerNoteNextIFD = 0;
-
- // If size is too small to hold a single entry IFD, abort.
-
- if (ifdSize < 14)
- {
- return false;
- }
-
- // Get entry count.
-
- stream.SetReadPosition (ifdOffset);
-
- uint32 ifdEntries = stream.Get_uint16 ();
-
- // Make the entry count if reasonable for the MakerNote size.
-
- if (ifdEntries < 1 || 2 + ifdEntries * 12 > ifdSize)
- {
- return false;
- }
-
- // Scan IFD to verify all the tag types are all valid.
-
- for (tagIndex = 0; tagIndex < ifdEntries; tagIndex++)
- {
-
- stream.SetReadPosition (ifdOffset + 2 + tagIndex * 12 + 2);
-
- tagType = stream.Get_uint16 ();
-
- // Kludge: Some Canon MakerNotes contain tagType = 0 tags, so we
- // need to ignore them. This was a "firmware 1.0.4" Canon 40D raw file.
-
- if (parentCode == tcCanonMakerNote && tagType == 0)
- {
- continue;
- }
-
- if (TagTypeSize (tagType) == 0)
- {
- return false;
- }
-
- }
-
- // OK, the IFD looks reasonable enough to parse.
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("%s: Offset = %u, Entries = %u\n\n",
- LookupParentCode (parentCode),
- (unsigned) ifdOffset,
- (unsigned) ifdEntries);
-
- }
-
- #endif
-
- for (tagIndex = 0; tagIndex < ifdEntries; tagIndex++)
- {
-
- stream.SetReadPosition (ifdOffset + 2 + tagIndex * 12);
-
- tagCode = stream.Get_uint16 ();
- tagType = stream.Get_uint16 ();
- tagCount = stream.Get_uint32 ();
-
- if (tagType == 0)
- {
- continue;
- }
-
- uint32 tagSize = tagCount * TagTypeSize (tagType);
-
- uint64 tagOffset = ifdOffset + 2 + tagIndex * 12 + 8;
-
- if (tagSize > 4)
- {
-
- tagOffset = stream.Get_uint32 () + offsetDelta;
-
- if (tagOffset < minOffset ||
- tagOffset + tagSize > maxOffset)
- {
-
- // Tag data is outside the valid offset range,
- // so ignore this tag.
-
- continue;
-
- }
-
- stream.SetReadPosition (tagOffset);
-
- }
-
- // Olympus switched to using IFDs in version 3 makernotes.
-
- if (parentCode == tcOlympusMakerNote &&
- tagType == ttIFD &&
- tagCount == 1)
- {
-
- uint32 olympusMakerParent = 0;
-
- switch (tagCode)
- {
-
- case 8208:
- olympusMakerParent = tcOlympusMakerNote8208;
- break;
-
- case 8224:
- olympusMakerParent = tcOlympusMakerNote8224;
- break;
-
- case 8240:
- olympusMakerParent = tcOlympusMakerNote8240;
- break;
-
- case 8256:
- olympusMakerParent = tcOlympusMakerNote8256;
- break;
-
- case 8272:
- olympusMakerParent = tcOlympusMakerNote8272;
- break;
-
- case 12288:
- olympusMakerParent = tcOlympusMakerNote12288;
- break;
-
- default:
- break;
-
- }
-
- if (olympusMakerParent)
- {
-
- stream.SetReadPosition (tagOffset);
-
- uint64 subMakerNoteOffset = stream.Get_uint32 () + offsetDelta;
-
- if (subMakerNoteOffset >= minOffset &&
- subMakerNoteOffset < maxOffset)
- {
-
- if (ParseMakerNoteIFD (host,
- stream,
- maxOffset - subMakerNoteOffset,
- subMakerNoteOffset,
- offsetDelta,
- minOffset,
- maxOffset,
- olympusMakerParent))
- {
-
- continue;
-
- }
-
- }
-
- }
-
- stream.SetReadPosition (tagOffset);
-
- }
-
- ParseTag (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- tagOffset,
- offsetDelta);
-
- }
-
- // Grab next IFD pointer, for possible use.
-
- if (ifdSize >= 2 + ifdEntries * 12 + 4)
- {
-
- stream.SetReadPosition (ifdOffset + 2 + ifdEntries * 12);
-
- fMakerNoteNextIFD = stream.Get_uint32 ();
-
- }
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("\n");
- }
-
- #endif
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-void dng_info::ParseMakerNote (dng_host &host,
- dng_stream &stream,
- uint32 makerNoteCount,
- uint64 makerNoteOffset,
- int64 offsetDelta,
- uint64 minOffset,
- uint64 maxOffset)
- {
-
- uint8 firstBytes [16];
-
- memset (firstBytes, 0, sizeof (firstBytes));
-
- stream.SetReadPosition (makerNoteOffset);
-
- stream.Get (firstBytes, (uint32) Min_uint64 (sizeof (firstBytes),
- makerNoteCount));
-
- // Epson MakerNote with header.
-
- if (memcmp (firstBytes, "EPSON\000\001\000", 8) == 0)
- {
-
- if (makerNoteCount > 8)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 8,
- makerNoteOffset + 8,
- offsetDelta,
- minOffset,
- maxOffset,
- tcEpsonMakerNote);
-
- }
-
- return;
-
- }
-
- // Fujifilm MakerNote.
-
- if (memcmp (firstBytes, "FUJIFILM", 8) == 0)
- {
-
- stream.SetReadPosition (makerNoteOffset + 8);
-
- TempLittleEndian tempEndian (stream);
-
- uint32 ifd_offset = stream.Get_uint32 ();
-
- if (ifd_offset >= 12 && ifd_offset < makerNoteCount)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - ifd_offset,
- makerNoteOffset + ifd_offset,
- makerNoteOffset,
- minOffset,
- maxOffset,
- tcFujiMakerNote);
-
- }
-
- return;
-
- }
-
- // Leica MakerNote for models that store entry offsets relative to the start of
- // the MakerNote (e.g., M9).
-
- if ((memcmp (firstBytes, "LEICA\000\000\000", 8) == 0) ||
- (memcmp (firstBytes, "LEICA0\003\000", 8) == 0) ||
- (memcmp (firstBytes, "LEICA\000\001\000", 8) == 0) ||
- (memcmp (firstBytes, "LEICA\000\005\000", 8) == 0))
- {
-
- if (makerNoteCount > 8)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 8,
- makerNoteOffset + 8,
- makerNoteOffset,
- minOffset,
- maxOffset,
- tcLeicaMakerNote);
-
- }
-
- return;
-
- }
-
- // Leica MakerNote for models that store absolute entry offsets (i.e., relative
- // to the start of the file, e.g., S2).
-
- if (memcmp (firstBytes, "LEICA\000\002\377", 8) == 0)
- {
-
- if (makerNoteCount > 8)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 8,
- makerNoteOffset + 8,
- offsetDelta,
- minOffset,
- maxOffset,
- tcLeicaMakerNote);
-
- }
-
- return;
-
- }
-
- // Nikon version 2 MakerNote with header.
-
- if (memcmp (firstBytes, "Nikon\000\002", 7) == 0)
- {
-
- stream.SetReadPosition (makerNoteOffset + 10);
-
- bool bigEndian = false;
-
- uint16 endianMark = stream.Get_uint16 ();
-
- if (endianMark == byteOrderMM)
- {
- bigEndian = true;
- }
-
- else if (endianMark != byteOrderII)
- {
- return;
- }
-
- TempBigEndian temp_endian (stream, bigEndian);
-
- uint16 magic = stream.Get_uint16 ();
-
- if (magic != 42)
- {
- return;
- }
-
- uint32 ifd_offset = stream.Get_uint32 ();
-
- if (ifd_offset >= 8 && ifd_offset < makerNoteCount - 10)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 10 - ifd_offset,
- makerNoteOffset + 10 + ifd_offset,
- makerNoteOffset + 10,
- minOffset,
- maxOffset,
- tcNikonMakerNote);
-
- }
-
- return;
-
- }
-
- // Newer version of Olympus MakerNote with byte order mark.
-
- if (memcmp (firstBytes, "OLYMPUS\000", 8) == 0)
- {
-
- stream.SetReadPosition (makerNoteOffset + 8);
-
- bool bigEndian = false;
-
- uint16 endianMark = stream.Get_uint16 ();
-
- if (endianMark == byteOrderMM)
- {
- bigEndian = true;
- }
-
- else if (endianMark != byteOrderII)
- {
- return;
- }
-
- TempBigEndian temp_endian (stream, bigEndian);
-
- uint16 version = stream.Get_uint16 ();
-
- if (version != 3)
- {
- return;
- }
-
- if (makerNoteCount > 12)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 12,
- makerNoteOffset + 12,
- makerNoteOffset,
- minOffset,
- maxOffset,
- tcOlympusMakerNote);
-
- }
-
- return;
-
- }
-
- // Olympus MakerNote with header.
-
- if (memcmp (firstBytes, "OLYMP", 5) == 0)
- {
-
- if (makerNoteCount > 8)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 8,
- makerNoteOffset + 8,
- offsetDelta,
- minOffset,
- maxOffset,
- tcOlympusMakerNote);
-
- }
-
- return;
-
- }
-
- // Panasonic MakerNote.
-
- if (memcmp (firstBytes, "Panasonic\000\000\000", 12) == 0)
- {
-
- if (makerNoteCount > 12)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 12,
- makerNoteOffset + 12,
- offsetDelta,
- minOffset,
- maxOffset,
- tcPanasonicMakerNote);
-
- }
-
- return;
-
- }
-
- // Pentax MakerNote.
-
- if (memcmp (firstBytes, "AOC", 4) == 0)
- {
-
- if (makerNoteCount > 6)
- {
-
- stream.SetReadPosition (makerNoteOffset + 4);
-
- bool bigEndian = stream.BigEndian ();
-
- uint16 endianMark = stream.Get_uint16 ();
-
- if (endianMark == byteOrderMM)
- {
- bigEndian = true;
- }
-
- else if (endianMark == byteOrderII)
- {
- bigEndian = false;
- }
-
- TempBigEndian temp_endian (stream, bigEndian);
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 6,
- makerNoteOffset + 6,
- offsetDelta,
- minOffset,
- maxOffset,
- tcPentaxMakerNote);
-
- }
-
- return;
-
- }
-
- // Ricoh MakerNote.
-
- if (memcmp (firstBytes, "RICOH", 5) == 0 ||
- memcmp (firstBytes, "Ricoh", 5) == 0)
- {
-
- if (makerNoteCount > 8)
- {
-
- TempBigEndian tempEndian (stream);
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 8,
- makerNoteOffset + 8,
- offsetDelta,
- minOffset,
- maxOffset,
- tcRicohMakerNote);
-
- }
-
- return;
-
- }
-
- // Nikon MakerNote without header.
-
- if (fExif->fMake.StartsWith ("NIKON"))
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount,
- makerNoteOffset,
- offsetDelta,
- minOffset,
- maxOffset,
- tcNikonMakerNote);
-
- return;
-
- }
-
- // Canon MakerNote.
-
- if (fExif->fMake.StartsWith ("CANON"))
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount,
- makerNoteOffset,
- offsetDelta,
- minOffset,
- maxOffset,
- tcCanonMakerNote);
-
- return;
-
- }
-
- // Minolta MakerNote.
-
- if (fExif->fMake.StartsWith ("MINOLTA" ) ||
- fExif->fMake.StartsWith ("KONICA MINOLTA"))
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount,
- makerNoteOffset,
- offsetDelta,
- minOffset,
- maxOffset,
- tcMinoltaMakerNote);
-
- return;
-
- }
-
- // Sony MakerNote.
-
- if (fExif->fMake.StartsWith ("SONY"))
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount,
- makerNoteOffset,
- offsetDelta,
- minOffset,
- maxOffset,
- tcSonyMakerNote);
-
- return;
-
- }
-
- // Kodak MakerNote.
-
- if (fExif->fMake.StartsWith ("EASTMAN KODAK"))
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount,
- makerNoteOffset,
- offsetDelta,
- minOffset,
- maxOffset,
- tcKodakMakerNote);
-
- return;
-
- }
-
- // Mamiya MakerNote.
-
- if (fExif->fMake.StartsWith ("Mamiya"))
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount,
- makerNoteOffset,
- offsetDelta,
- minOffset,
- maxOffset,
- tcMamiyaMakerNote);
-
- // Mamiya uses a MakerNote chain.
-
- while (fMakerNoteNextIFD)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount,
- offsetDelta + fMakerNoteNextIFD,
- offsetDelta,
- minOffset,
- maxOffset,
- tcMamiyaMakerNote);
-
- }
-
- return;
-
- }
-
- // Nikon MakerNote without header.
-
- if (fExif->fMake.StartsWith ("Hasselblad"))
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount,
- makerNoteOffset,
- offsetDelta,
- minOffset,
- maxOffset,
- tcHasselbladMakerNote);
-
- return;
-
- }
-
- // Samsung MakerNote.
-
- if (fExif->fMake.StartsWith ("Samsung"))
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount,
- makerNoteOffset,
- makerNoteOffset,
- minOffset,
- maxOffset,
- tcSamsungMakerNote);
-
- return;
-
- }
-
- // Casio MakerNote.
-
- if (fExif->fMake.StartsWith ("CASIO COMPUTER") &&
- memcmp (firstBytes, "QVC\000\000\000", 6) == 0)
- {
-
- ParseMakerNoteIFD (host,
- stream,
- makerNoteCount - 6,
- makerNoteOffset + 6,
- makerNoteOffset,
- minOffset,
- maxOffset,
- tcCasioMakerNote);
-
- return;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_info::ParseSonyPrivateData (dng_host & /* host */,
- dng_stream & /* stream */,
- uint64 /* count */,
- uint64 /* oldOffset */,
- uint64 /* newOffset */)
- {
-
- // Sony private data is encrypted, sorry.
-
- }
-
-/*****************************************************************************/
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
-void dng_info::ParseDNGPrivateData (dng_host &host,
- dng_stream &stream)
- {
-
- if (fShared->fDNGPrivateDataCount < 2)
- {
- return;
- }
-
- // DNG private data should always start with a null-terminated
- // company name, to define the format of the private data.
-
- dng_string privateName;
-
- {
-
- char buffer [64];
-
- stream.SetReadPosition (fShared->fDNGPrivateDataOffset);
-
- uint32 readLength = Min_uint32 (fShared->fDNGPrivateDataCount,
- sizeof (buffer) - 1);
-
- stream.Get (buffer, readLength);
-
- buffer [readLength] = 0;
-
- privateName.Set (buffer);
-
- }
-
- // Pentax is storing their MakerNote in the DNGPrivateData data.
-
- if (privateName.StartsWith ("PENTAX" ) ||
- privateName.StartsWith ("SAMSUNG"))
- {
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("Parsing Pentax/Samsung DNGPrivateData\n\n");
- }
-
- #endif
-
- stream.SetReadPosition (fShared->fDNGPrivateDataOffset + 8);
-
- bool bigEndian = stream.BigEndian ();
-
- uint16 endianMark = stream.Get_uint16 ();
-
- if (endianMark == byteOrderMM)
- {
- bigEndian = true;
- }
-
- else if (endianMark == byteOrderII)
- {
- bigEndian = false;
- }
-
- TempBigEndian temp_endian (stream, bigEndian);
-
- ParseMakerNoteIFD (host,
- stream,
- fShared->fDNGPrivateDataCount - 10,
- fShared->fDNGPrivateDataOffset + 10,
- fShared->fDNGPrivateDataOffset,
- fShared->fDNGPrivateDataOffset,
- fShared->fDNGPrivateDataOffset + fShared->fDNGPrivateDataCount,
- tcPentaxMakerNote);
-
- return;
-
- }
-
- // Stop parsing if this is not an Adobe format block.
-
- if (!privateName.Matches ("Adobe"))
- {
- return;
- }
-
- TempBigEndian temp_order (stream);
-
- uint32 section_offset = 6;
-
- while (section_offset + 8 < fShared->fDNGPrivateDataCount)
- {
-
- stream.SetReadPosition (fShared->fDNGPrivateDataOffset + section_offset);
-
- uint32 section_key = stream.Get_uint32 ();
- uint32 section_count = stream.Get_uint32 ();
-
- if (section_key == DNG_CHAR4 ('M','a','k','N') && section_count > 6)
- {
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("Found MakerNote inside DNGPrivateData\n\n");
- }
-
- #endif
-
- uint16 order_mark = stream.Get_uint16 ();
- int64 old_offset = stream.Get_uint32 ();
-
- uint32 tempSize = section_count - 6;
-
- AutoPtr<dng_memory_block> tempBlock (host.Allocate (tempSize));
-
- uint64 positionInOriginalFile = stream.PositionInOriginalFile();
-
- stream.Get (tempBlock->Buffer (), tempSize);
-
- dng_stream tempStream (tempBlock->Buffer (),
- tempSize,
- positionInOriginalFile);
-
- tempStream.SetBigEndian (order_mark == byteOrderMM);
-
- ParseMakerNote (host,
- tempStream,
- tempSize,
- 0,
- 0 - old_offset,
- 0,
- tempSize);
-
- }
-
- else if (section_key == DNG_CHAR4 ('S','R','2',' ') && section_count > 6)
- {
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("Found Sony private data inside DNGPrivateData\n\n");
- }
-
- #endif
-
- uint16 order_mark = stream.Get_uint16 ();
- uint64 old_offset = stream.Get_uint32 ();
-
- uint64 new_offset = fShared->fDNGPrivateDataOffset + section_offset + 14;
-
- TempBigEndian sr2_order (stream, order_mark == byteOrderMM);
-
- ParseSonyPrivateData (host,
- stream,
- section_count - 6,
- old_offset,
- new_offset);
-
- }
-
- else if (section_key == DNG_CHAR4 ('R','A','F',' ') && section_count > 4)
- {
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("Found Fuji RAF tags inside DNGPrivateData\n\n");
- }
-
- #endif
-
- uint16 order_mark = stream.Get_uint16 ();
-
- uint32 tagCount = stream.Get_uint32 ();
-
- uint64 tagOffset = stream.Position ();
-
- if (tagCount)
- {
-
- TempBigEndian raf_order (stream, order_mark == byteOrderMM);
-
- ParseTag (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- tcFujiRAF,
- tcFujiHeader,
- ttUndefined,
- tagCount,
- tagOffset,
- 0);
-
- stream.SetReadPosition (tagOffset + tagCount);
-
- }
-
- tagCount = stream.Get_uint32 ();
-
- tagOffset = stream.Position ();
-
- if (tagCount)
- {
-
- TempBigEndian raf_order (stream, order_mark == byteOrderMM);
-
- ParseTag (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- tcFujiRAF,
- tcFujiRawInfo1,
- ttUndefined,
- tagCount,
- tagOffset,
- 0);
-
- stream.SetReadPosition (tagOffset + tagCount);
-
- }
-
- tagCount = stream.Get_uint32 ();
-
- tagOffset = stream.Position ();
-
- if (tagCount)
- {
-
- TempBigEndian raf_order (stream, order_mark == byteOrderMM);
-
- ParseTag (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- tcFujiRAF,
- tcFujiRawInfo2,
- ttUndefined,
- tagCount,
- tagOffset,
- 0);
-
- stream.SetReadPosition (tagOffset + tagCount);
-
- }
-
- }
-
- else if (section_key == DNG_CHAR4 ('C','n','t','x') && section_count > 4)
- {
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("Found Contax Raw header inside DNGPrivateData\n\n");
- }
-
- #endif
-
- uint16 order_mark = stream.Get_uint16 ();
-
- uint32 tagCount = stream.Get_uint32 ();
-
- uint64 tagOffset = stream.Position ();
-
- if (tagCount)
- {
-
- TempBigEndian contax_order (stream, order_mark == byteOrderMM);
-
- ParseTag (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- tcContaxRAW,
- tcContaxHeader,
- ttUndefined,
- tagCount,
- tagOffset,
- 0);
-
- }
-
- }
-
- else if (section_key == DNG_CHAR4 ('C','R','W',' ') && section_count > 4)
- {
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("Found Canon CRW tags inside DNGPrivateData\n\n");
- }
-
- #endif
-
- uint16 order_mark = stream.Get_uint16 ();
- uint32 entries = stream.Get_uint16 ();
-
- uint64 crwTagStart = stream.Position ();
-
- for (uint32 parsePass = 1; parsePass <= 2; parsePass++)
- {
-
- stream.SetReadPosition (crwTagStart);
-
- for (uint32 index = 0; index < entries; index++)
- {
-
- uint32 tagCode = stream.Get_uint16 ();
-
- uint32 tagCount = stream.Get_uint32 ();
-
- uint64 tagOffset = stream.Position ();
-
- // We need to grab the model id tag first, and then all the
- // other tags.
-
- if ((parsePass == 1) == (tagCode == 0x5834))
- {
-
- TempBigEndian tag_order (stream, order_mark == byteOrderMM);
-
- ParseTag (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- tcCanonCRW,
- tagCode,
- ttUndefined,
- tagCount,
- tagOffset,
- 0);
-
- }
-
- stream.SetReadPosition (tagOffset + tagCount);
-
- }
-
- }
-
- }
-
- else if (section_count > 4)
- {
-
- uint32 parentCode = 0;
-
- bool code32 = false;
- bool hasType = true;
-
- switch (section_key)
- {
-
- case DNG_CHAR4 ('M','R','W',' '):
- {
- parentCode = tcMinoltaMRW;
- code32 = true;
- hasType = false;
- break;
- }
-
- case DNG_CHAR4 ('P','a','n','o'):
- {
- parentCode = tcPanasonicRAW;
- break;
- }
-
- case DNG_CHAR4 ('L','e','a','f'):
- {
- parentCode = tcLeafMOS;
- break;
- }
-
- case DNG_CHAR4 ('K','o','d','a'):
- {
- parentCode = tcKodakDCRPrivateIFD;
- break;
- }
-
- case DNG_CHAR4 ('K','D','C',' '):
- {
- parentCode = tcKodakKDCPrivateIFD;
- break;
- }
-
- default:
- break;
-
- }
-
- if (parentCode)
- {
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("Found %s tags inside DNGPrivateData\n\n",
- LookupParentCode (parentCode));
- }
-
- #endif
-
- uint16 order_mark = stream.Get_uint16 ();
- uint32 entries = stream.Get_uint16 ();
-
- for (uint32 index = 0; index < entries; index++)
- {
-
- uint32 tagCode = code32 ? stream.Get_uint32 ()
- : stream.Get_uint16 ();
-
- uint32 tagType = hasType ? stream.Get_uint16 ()
- : ttUndefined;
-
- uint32 tagCount = stream.Get_uint32 ();
-
- uint32 tagSize = tagCount * TagTypeSize (tagType);
-
- uint64 tagOffset = stream.Position ();
-
- TempBigEndian tag_order (stream, order_mark == byteOrderMM);
-
- ParseTag (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- parentCode,
- tagCode,
- tagType,
- tagCount,
- tagOffset,
- 0);
-
- stream.SetReadPosition (tagOffset + tagSize);
-
- }
-
- }
-
- }
-
- section_offset += 8 + section_count;
-
- if (section_offset & 1)
- {
- section_offset++;
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_info::Parse (dng_host &host,
- dng_stream &stream)
- {
-
- fTIFFBlockOffset = stream.Position ();
-
- fTIFFBlockOriginalOffset = stream.PositionInOriginalFile ();
-
- // Check byte order indicator.
-
- uint16 byteOrder = stream.Get_uint16 ();
-
- if (byteOrder == byteOrderII)
- {
-
- fBigEndian = false;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("\nUses little-endian byte order\n");
- }
-
- #endif
-
- stream.SetLittleEndian ();
-
- }
-
- else if (byteOrder == byteOrderMM)
- {
-
- fBigEndian = true;
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("\nUses big-endian byte order\n");
- }
-
- #endif
-
- stream.SetBigEndian ();
-
- }
-
- else
- {
-
- #if qDNGValidate
-
- ReportError ("Unknown byte order");
-
- #endif
-
- ThrowBadFormat ();
-
- }
-
- // Check "magic number" indicator.
-
- fMagic = stream.Get_uint16 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
- printf ("Magic number = %u\n\n", (unsigned) fMagic);
- }
-
- #endif
-
- ValidateMagic ();
-
- // Parse IFD 0.
-
- uint64 next_offset = stream.Get_uint32 ();
-
- fExif.Reset (host.Make_dng_exif ());
-
- fShared.Reset (host.Make_dng_shared ());
-
- fIFD [0].Reset (host.Make_dng_ifd ());
-
- ParseIFD (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- fIFD [0].Get (),
- fTIFFBlockOffset + next_offset,
- fTIFFBlockOffset,
- 0);
-
- next_offset = fIFD [0]->fNextIFD;
-
- fIFDCount = 1;
-
- // Parse chained IFDs.
-
- while (next_offset)
- {
-
- if (next_offset >= stream.Length ())
- {
-
- #if qDNGValidate
-
- {
-
- ReportWarning ("Chained IFD offset past end of stream");
-
- }
-
- #endif
-
- break;
-
- }
-
- // Some TIFF file writers forget about the next IFD offset, so
- // validate the IFD at that offset before parsing it.
-
- if (!ValidateIFD (stream,
- fTIFFBlockOffset + next_offset,
- fTIFFBlockOffset))
- {
-
- #if qDNGValidate
-
- {
-
- ReportWarning ("Chained IFD is not valid");
-
- }
-
- #endif
-
- break;
-
- }
-
- if (fChainedIFDCount == kMaxChainedIFDs)
- {
-
- #if qDNGValidate
-
- {
-
- ReportWarning ("Chained IFD count exceeds DNG SDK parsing limit");
-
- }
-
- #endif
-
- break;
-
- }
-
- fChainedIFD [fChainedIFDCount].Reset (host.Make_dng_ifd ());
-
- ParseIFD (host,
- stream,
- NULL,
- NULL,
- fChainedIFD [fChainedIFDCount].Get (),
- fTIFFBlockOffset + next_offset,
- fTIFFBlockOffset,
- tcFirstChainedIFD + fChainedIFDCount);
-
- next_offset = fChainedIFD [fChainedIFDCount]->fNextIFD;
-
- fChainedIFDCount++;
-
- }
-
- // Parse SubIFDs.
-
- uint32 searchedIFDs = 0;
-
- bool tooManySubIFDs = false;
-
- while (searchedIFDs < fIFDCount && !tooManySubIFDs)
- {
-
- uint32 searchLimit = fIFDCount;
-
- for (uint32 searchIndex = searchedIFDs;
- searchIndex < searchLimit && !tooManySubIFDs;
- searchIndex++)
- {
-
- for (uint32 subIndex = 0;
- subIndex < fIFD [searchIndex]->fSubIFDsCount;
- subIndex++)
- {
-
- if (fIFDCount == kMaxSubIFDs + 1)
- {
-
- tooManySubIFDs = true;
-
- break;
-
- }
-
- stream.SetReadPosition (fIFD [searchIndex]->fSubIFDsOffset +
- subIndex * 4);
-
- uint32 sub_ifd_offset = stream.Get_uint32 ();
-
- fIFD [fIFDCount].Reset (host.Make_dng_ifd ());
-
- ParseIFD (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- fIFD [fIFDCount].Get (),
- fTIFFBlockOffset + sub_ifd_offset,
- fTIFFBlockOffset,
- tcFirstSubIFD + fIFDCount - 1);
-
- fIFDCount++;
-
- }
-
- searchedIFDs = searchLimit;
-
- }
-
- }
-
- #if qDNGValidate
-
- {
-
- if (tooManySubIFDs)
- {
-
- ReportWarning ("SubIFD count exceeds DNG SDK parsing limit");
-
- }
-
- }
-
- #endif
-
- // Parse EXIF IFD.
-
- if (fShared->fExifIFD)
- {
-
- ParseIFD (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- fTIFFBlockOffset + fShared->fExifIFD,
- fTIFFBlockOffset,
- tcExifIFD);
-
- }
-
- // Parse GPS IFD.
-
- if (fShared->fGPSInfo)
- {
-
- ParseIFD (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- fTIFFBlockOffset + fShared->fGPSInfo,
- fTIFFBlockOffset,
- tcGPSInfo);
-
- }
-
- // Parse Interoperability IFD.
-
- if (fShared->fInteroperabilityIFD)
- {
-
- // Some Kodak KDC files have bogus Interoperability IFDs, so
- // validate the IFD before trying to parse it.
-
- if (ValidateIFD (stream,
- fTIFFBlockOffset + fShared->fInteroperabilityIFD,
- fTIFFBlockOffset))
- {
-
- ParseIFD (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- fTIFFBlockOffset + fShared->fInteroperabilityIFD,
- fTIFFBlockOffset,
- tcInteroperabilityIFD);
-
- }
-
- #if qDNGValidate
-
- else
- {
-
- ReportWarning ("The Interoperability IFD is not a valid IFD");
-
- }
-
- #endif
-
- }
-
- // Parse Kodak DCR Private IFD.
-
- if (fShared->fKodakDCRPrivateIFD)
- {
-
- ParseIFD (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- fTIFFBlockOffset + fShared->fKodakDCRPrivateIFD,
- fTIFFBlockOffset,
- tcKodakDCRPrivateIFD);
-
- }
-
- // Parse Kodak KDC Private IFD.
-
- if (fShared->fKodakKDCPrivateIFD)
- {
-
- ParseIFD (host,
- stream,
- fExif.Get (),
- fShared.Get (),
- NULL,
- fTIFFBlockOffset + fShared->fKodakKDCPrivateIFD,
- fTIFFBlockOffset,
- tcKodakKDCPrivateIFD);
-
- }
-
- // Parse MakerNote tag.
-
- if (fShared->fMakerNoteCount)
- {
-
- ParseMakerNote (host,
- stream,
- (uint32) (fTIFFBlockOffset + fShared->fMakerNoteCount),
- fShared->fMakerNoteOffset,
- fTIFFBlockOffset,
- 0,
- stream.Length ());
-
- }
-
- // Parse DNGPrivateData tag.
-
- if (fShared->fDNGPrivateDataCount &&
- fShared->fDNGVersion)
- {
-
- ParseDNGPrivateData (host, stream);
-
- }
-
- #if qDNGValidate
-
- // If we are running dng_validate on stand-alone camera profile file,
- // complete the validation of the profile.
-
- if (fMagic == magicExtendedProfile)
- {
-
- dng_camera_profile_info &profileInfo = fShared->fCameraProfile;
-
- dng_camera_profile profile;
-
- profile.Parse (stream, profileInfo);
-
- if (profileInfo.fColorPlanes < 3 || !profile.IsValid (profileInfo.fColorPlanes))
- {
-
- ReportError ("Invalid camera profile file");
-
- }
-
- }
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-void dng_info::PostParse (dng_host &host)
- {
-
- uint32 index;
-
- fExif->PostParse (host, *fShared.Get ());
-
- fShared->PostParse (host, *fExif.Get ());
-
- for (index = 0; index < fIFDCount; index++)
- {
-
- fIFD [index]->PostParse ();
-
- }
-
- for (index = 0; index < fChainedIFDCount; index++)
- {
-
- fChainedIFD [index]->PostParse ();
-
- }
-
- if (fShared->fDNGVersion != 0)
- {
-
- // Find main IFD.
-
- fMainIndex = -1;
-
- for (index = 0; index < fIFDCount; index++)
- {
-
- if (fIFD [index]->fUsesNewSubFileType &&
- fIFD [index]->fNewSubFileType == sfMainImage)
- {
-
- if (fMainIndex == -1)
- {
-
- fMainIndex = index;
-
- }
-
- #if qDNGValidate
-
- else
- {
-
- ReportError ("Multiple IFDs marked as main image");
-
- }
-
- #endif
-
- }
-
- else if (fIFD [index]->fNewSubFileType == sfPreviewImage ||
- fIFD [index]->fNewSubFileType == sfAltPreviewImage)
- {
-
- // Fill in default color space for DNG previews if not included.
-
- if (fIFD [index]->fPreviewInfo.fColorSpace == previewColorSpace_MaxEnum)
- {
-
- if (fIFD [index]->fSamplesPerPixel == 1)
- {
-
- fIFD [index]->fPreviewInfo.fColorSpace = previewColorSpace_GrayGamma22;
-
- }
-
- else
- {
-
- fIFD [index]->fPreviewInfo.fColorSpace = previewColorSpace_sRGB;
-
- }
-
- }
-
- }
-
- }
-
- // Deal with lossless JPEG bug in early DNG versions.
-
- if (fShared->fDNGVersion < dngVersion_1_1_0_0)
- {
-
- if (fMainIndex != -1)
- {
-
- fIFD [fMainIndex]->fLosslessJPEGBug16 = true;
-
- }
-
- }
-
- // Find mask index.
-
- for (index = 0; index < fIFDCount; index++)
- {
-
- if (fIFD [index]->fNewSubFileType == sfTransparencyMask)
- {
-
- if (fMaskIndex == -1)
- {
-
- fMaskIndex = index;
-
- }
-
- #if qDNGValidate
-
- else
- {
-
- ReportError ("Multiple IFDs marked as transparency mask image");
-
- }
-
- #endif
-
- }
-
- }
-
- // Warn about Chained IFDs.
-
- #if qDNGValidate
-
- if (fChainedIFDCount > 0)
- {
-
- ReportWarning ("This file has Chained IFDs, which will be ignored by DNG readers");
-
- }
-
- #endif
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_info::IsValidDNG ()
- {
-
- // Check shared info.
-
- if (!fShared->IsValidDNG ())
- {
-
- return false;
-
- }
-
- // Check TIFF magic number.
-
- if (fMagic != 42)
- {
-
- #if qDNGValidate
-
- ReportError ("Invalid TIFF magic number");
-
- #endif
-
- return false;
-
- }
-
- // Make sure we have a main image IFD.
-
- if (fMainIndex == -1)
- {
-
- #if qDNGValidate
-
- ReportError ("Unable to find main image IFD");
-
- #endif
-
- return false;
-
- }
-
- // Make sure is each IFD is valid.
-
- for (uint32 index = 0; index < fIFDCount; index++)
- {
-
- uint32 parentCode = (index == 0 ? 0 : tcFirstSubIFD + index - 1);
-
- if (!fIFD [index]->IsValidDNG (*fShared.Get (),
- parentCode))
- {
-
- // Only errors in the main and transparency mask IFDs are fatal to parsing.
-
- if (index == (uint32) fMainIndex ||
- index == (uint32) fMaskIndex)
- {
-
- return false;
-
- }
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_info.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_info.h"
+
+#include "dng_camera_profile.h"
+#include "dng_exceptions.h"
+#include "dng_globals.h"
+#include "dng_host.h"
+#include "dng_tag_codes.h"
+#include "dng_parse_utils.h"
+#include "dng_tag_types.h"
+#include "dng_tag_values.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_info::dng_info ()
+
+ : fTIFFBlockOffset (0)
+ , fTIFFBlockOriginalOffset (kDNGStreamInvalidOffset)
+ , fBigEndian (false)
+ , fMagic (0)
+ , fExif ()
+ , fShared ()
+ , fMainIndex (-1)
+ , fMaskIndex (-1)
+ , fIFDCount (0)
+ , fChainedIFDCount (0)
+ , fMakerNoteNextIFD (0)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_info::~dng_info ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_info::ValidateMagic ()
+ {
+
+ switch (fMagic)
+ {
+
+ case magicTIFF:
+ case magicExtendedProfile:
+ case magicRawCache:
+ case magicPanasonic:
+ case magicOlympusA:
+ case magicOlympusB:
+ {
+
+ return;
+
+ }
+
+ default:
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid TIFF magic number");
+
+ #endif
+
+ ThrowBadFormat ();
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_info::ParseTag (dng_host &host,
+ dng_stream &stream,
+ dng_exif *exif,
+ dng_shared *shared,
+ dng_ifd *ifd,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset,
+ int64 offsetDelta)
+ {
+
+ bool isSubIFD = parentCode >= tcFirstSubIFD &&
+ parentCode <= tcLastSubIFD;
+
+ bool isMainIFD = (parentCode == 0 || isSubIFD) &&
+ ifd &&
+ ifd->fUsesNewSubFileType &&
+ ifd->fNewSubFileType == sfMainImage;
+
+ // Panasonic RAW format stores private tags using tag codes < 254 in
+ // IFD 0. Redirect the parsing of these tags into a logical
+ // "PanasonicRAW" IFD.
+
+ // Panasonic is starting to use some higher numbers also (280..283).
+
+ if (fMagic == 85 && parentCode == 0 && (tagCode < tcNewSubFileType ||
+ (tagCode >= 280 && tagCode <= 283)))
+ {
+
+ parentCode = tcPanasonicRAW;
+
+ ifd = NULL;
+
+ }
+
+ stream.SetReadPosition (tagOffset);
+
+ if (ifd && ifd->ParseTag (stream,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset))
+ {
+
+ return;
+
+ }
+
+ stream.SetReadPosition (tagOffset);
+
+ if (exif && shared && exif->ParseTag (stream,
+ *shared,
+ parentCode,
+ isMainIFD,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset))
+ {
+
+ return;
+
+ }
+
+ stream.SetReadPosition (tagOffset);
+
+ if (shared && exif && shared->ParseTag (stream,
+ *exif,
+ parentCode,
+ isMainIFD,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset,
+ offsetDelta))
+ {
+
+ return;
+
+ }
+
+ if (parentCode == tcLeicaMakerNote &&
+ tagType == ttUndefined &&
+ tagCount >= 14)
+ {
+
+ if (ParseMakerNoteIFD (host,
+ stream,
+ tagCount,
+ tagOffset,
+ offsetDelta,
+ tagOffset,
+ stream.Length (),
+ tcLeicaMakerNote))
+ {
+
+ return;
+
+ }
+
+ }
+
+ if (parentCode == tcOlympusMakerNote &&
+ tagType == ttUndefined &&
+ tagCount >= 14)
+ {
+
+ uint32 olympusMakerParent = 0;
+
+ switch (tagCode)
+ {
+
+ case 8208:
+ olympusMakerParent = tcOlympusMakerNote8208;
+ break;
+
+ case 8224:
+ olympusMakerParent = tcOlympusMakerNote8224;
+ break;
+
+ case 8240:
+ olympusMakerParent = tcOlympusMakerNote8240;
+ break;
+
+ case 8256:
+ olympusMakerParent = tcOlympusMakerNote8256;
+ break;
+
+ case 8272:
+ olympusMakerParent = tcOlympusMakerNote8272;
+ break;
+
+ case 12288:
+ olympusMakerParent = tcOlympusMakerNote12288;
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (olympusMakerParent)
+ {
+
+ // Olympus made a mistake in some camera models in computing
+ // the size of these sub-tags, so we fudge the count.
+
+ if (ParseMakerNoteIFD (host,
+ stream,
+ stream.Length () - tagOffset,
+ tagOffset,
+ offsetDelta,
+ tagOffset,
+ stream.Length (),
+ olympusMakerParent))
+ {
+
+ return;
+
+ }
+
+ }
+
+ }
+
+ if (parentCode == tcRicohMakerNote &&
+ tagCode == 0x2001 &&
+ tagType == ttUndefined &&
+ tagCount > 22)
+ {
+
+ char header [20];
+
+ stream.SetReadPosition (tagOffset);
+
+ stream.Get (header, sizeof (header));
+
+ if (memcmp (header, "[Ricoh Camera Info]", 19) == 0)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ tagCount - 20,
+ tagOffset + 20,
+ offsetDelta,
+ tagOffset + 20,
+ tagOffset + tagCount,
+ tcRicohMakerNoteCameraInfo);
+
+ return;
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ {
+
+ stream.SetReadPosition (tagOffset);
+
+ if (gVerbose)
+ {
+
+ printf ("*");
+
+ DumpTagValues (stream,
+ LookupTagType (tagType),
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount);
+
+ }
+
+ // If type is ASCII, then parse anyway so we report any ASCII
+ // NULL termination or character set errors.
+
+ else if (tagType == ttAscii)
+ {
+
+ dng_string s;
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ s,
+ false);
+
+ }
+
+ }
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+bool dng_info::ValidateIFD (dng_stream &stream,
+ uint64 ifdOffset,
+ int64 offsetDelta)
+ {
+
+ // Make sure we have a count.
+
+ if (ifdOffset + 2 > stream.Length ())
+ {
+ return false;
+ }
+
+ // Get entry count.
+
+ stream.SetReadPosition (ifdOffset);
+
+ uint32 ifdEntries = stream.Get_uint16 ();
+
+ if (ifdEntries < 1)
+ {
+ return false;
+ }
+
+ // Make sure we have room for all entries and next IFD link.
+
+ if (ifdOffset + 2 + ifdEntries * 12 + 4 > stream.Length ())
+ {
+ return false;
+ }
+
+ // Check each entry.
+
+ for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++)
+ {
+
+ stream.SetReadPosition (ifdOffset + 2 + tag_index * 12);
+
+ stream.Skip (2); // Ignore tag code.
+
+ uint32 tagType = stream.Get_uint16 ();
+ uint32 tagCount = stream.Get_uint32 ();
+
+ uint32 tag_type_size = TagTypeSize (tagType);
+
+ if (tag_type_size == 0)
+ {
+ return false;
+ }
+
+ uint32 tag_data_size = tagCount * tag_type_size;
+
+ if (tag_data_size > 4)
+ {
+
+ uint64 tagOffset = stream.Get_uint32 ();
+
+ tagOffset += offsetDelta;
+
+ if (tagOffset + tag_data_size > stream.Length ())
+ {
+ return false;
+ }
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+void dng_info::ParseIFD (dng_host &host,
+ dng_stream &stream,
+ dng_exif *exif,
+ dng_shared *shared,
+ dng_ifd *ifd,
+ uint64 ifdOffset,
+ int64 offsetDelta,
+ uint32 parentCode)
+ {
+
+ #if qDNGValidate
+
+ bool isMakerNote = (parentCode >= tcFirstMakerNoteIFD &&
+ parentCode <= tcLastMakerNoteIFD);
+
+ #endif
+
+ stream.SetReadPosition (ifdOffset);
+
+ if (ifd)
+ {
+ ifd->fThisIFD = ifdOffset;
+ }
+
+ uint32 ifdEntries = stream.Get_uint16 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: Offset = %u, Entries = %u\n\n",
+ LookupParentCode (parentCode),
+ (unsigned) ifdOffset,
+ (unsigned) ifdEntries);
+
+ }
+
+ if ((ifdOffset & 1) && !isMakerNote)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s has odd offset (%u)",
+ LookupParentCode (parentCode),
+ (unsigned) ifdOffset);
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ uint32 prev_tag_code = 0;
+
+ for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++)
+ {
+
+ stream.SetReadPosition (ifdOffset + 2 + tag_index * 12);
+
+ uint32 tagCode = stream.Get_uint16 ();
+ uint32 tagType = stream.Get_uint16 ();
+
+ // Minolta 7D files have a bug in the EXIF block where the count
+ // is wrong, and we run off into next IFD link. So if abort parsing
+ // if we get a zero code/type combinations.
+
+ if (tagCode == 0 && tagType == 0)
+ {
+
+ #if qDNGValidate
+
+ char message [256];
+
+ sprintf (message,
+ "%s had zero/zero tag code/type entry",
+ LookupParentCode (parentCode));
+
+ ReportWarning (message);
+
+ #endif
+
+ return;
+
+ }
+
+ uint32 tagCount = stream.Get_uint32 ();
+
+ #if qDNGValidate
+
+ {
+
+ if (tag_index > 0 && tagCode <= prev_tag_code && !isMakerNote)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s tags are not sorted in ascending numerical order",
+ LookupParentCode (parentCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #endif
+
+ prev_tag_code = tagCode;
+
+ uint32 tag_type_size = TagTypeSize (tagType);
+
+ if (tag_type_size == 0)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unknown type (%u)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode),
+ (unsigned) tagType);
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ continue;
+
+ }
+
+ uint64 tagOffset = ifdOffset + 2 + tag_index * 12 + 8;
+
+ if (tagCount * tag_type_size > 4)
+ {
+
+ tagOffset = stream.Get_uint32 ();
+
+ #if qDNGValidate
+
+ {
+
+ if (!(ifdOffset & 1) &&
+ (tagOffset & 1) &&
+ !isMakerNote &&
+ parentCode != tcKodakDCRPrivateIFD &&
+ parentCode != tcKodakKDCPrivateIFD)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has odd data offset (%u)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode),
+ (unsigned) tagOffset);
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #endif
+
+ tagOffset += offsetDelta;
+
+ stream.SetReadPosition (tagOffset);
+
+ }
+
+ ParseTag (host,
+ stream,
+ exif,
+ shared,
+ ifd,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset,
+ offsetDelta);
+
+ }
+
+ stream.SetReadPosition (ifdOffset + 2 + ifdEntries * 12);
+
+ uint32 nextIFD = stream.Get_uint32 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("NextIFD = %u\n", (unsigned) nextIFD);
+ }
+
+ #endif
+
+ if (ifd)
+ {
+ ifd->fNextIFD = nextIFD;
+ }
+
+ #if qDNGValidate
+
+ if (nextIFD)
+ {
+
+ if (parentCode != 0 &&
+ (parentCode < tcFirstChainedIFD ||
+ parentCode > tcLastChainedIFD ))
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s has an unexpected non-zero NextIFD (%u)",
+ LookupParentCode (parentCode),
+ (unsigned) nextIFD);
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ if (gVerbose)
+ {
+ printf ("\n");
+ }
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+bool dng_info::ParseMakerNoteIFD (dng_host &host,
+ dng_stream &stream,
+ uint64 ifdSize,
+ uint64 ifdOffset,
+ int64 offsetDelta,
+ uint64 minOffset,
+ uint64 maxOffset,
+ uint32 parentCode)
+ {
+
+ uint32 tagIndex;
+ uint32 tagCode;
+ uint32 tagType;
+ uint32 tagCount;
+
+ // Assume there is no next IFD pointer.
+
+ fMakerNoteNextIFD = 0;
+
+ // If size is too small to hold a single entry IFD, abort.
+
+ if (ifdSize < 14)
+ {
+ return false;
+ }
+
+ // Get entry count.
+
+ stream.SetReadPosition (ifdOffset);
+
+ uint32 ifdEntries = stream.Get_uint16 ();
+
+ // Make the entry count if reasonable for the MakerNote size.
+
+ if (ifdEntries < 1 || 2 + ifdEntries * 12 > ifdSize)
+ {
+ return false;
+ }
+
+ // Scan IFD to verify all the tag types are all valid.
+
+ for (tagIndex = 0; tagIndex < ifdEntries; tagIndex++)
+ {
+
+ stream.SetReadPosition (ifdOffset + 2 + tagIndex * 12 + 2);
+
+ tagType = stream.Get_uint16 ();
+
+ // Kludge: Some Canon MakerNotes contain tagType = 0 tags, so we
+ // need to ignore them. This was a "firmware 1.0.4" Canon 40D raw file.
+
+ if (parentCode == tcCanonMakerNote && tagType == 0)
+ {
+ continue;
+ }
+
+ if (TagTypeSize (tagType) == 0)
+ {
+ return false;
+ }
+
+ }
+
+ // OK, the IFD looks reasonable enough to parse.
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("%s: Offset = %u, Entries = %u\n\n",
+ LookupParentCode (parentCode),
+ (unsigned) ifdOffset,
+ (unsigned) ifdEntries);
+
+ }
+
+ #endif
+
+ for (tagIndex = 0; tagIndex < ifdEntries; tagIndex++)
+ {
+
+ stream.SetReadPosition (ifdOffset + 2 + tagIndex * 12);
+
+ tagCode = stream.Get_uint16 ();
+ tagType = stream.Get_uint16 ();
+ tagCount = stream.Get_uint32 ();
+
+ if (tagType == 0)
+ {
+ continue;
+ }
+
+ uint32 tagSize = tagCount * TagTypeSize (tagType);
+
+ uint64 tagOffset = ifdOffset + 2 + tagIndex * 12 + 8;
+
+ if (tagSize > 4)
+ {
+
+ tagOffset = stream.Get_uint32 () + offsetDelta;
+
+ if (tagOffset < minOffset ||
+ tagOffset + tagSize > maxOffset)
+ {
+
+ // Tag data is outside the valid offset range,
+ // so ignore this tag.
+
+ continue;
+
+ }
+
+ stream.SetReadPosition (tagOffset);
+
+ }
+
+ // Olympus switched to using IFDs in version 3 makernotes.
+
+ if (parentCode == tcOlympusMakerNote &&
+ tagType == ttIFD &&
+ tagCount == 1)
+ {
+
+ uint32 olympusMakerParent = 0;
+
+ switch (tagCode)
+ {
+
+ case 8208:
+ olympusMakerParent = tcOlympusMakerNote8208;
+ break;
+
+ case 8224:
+ olympusMakerParent = tcOlympusMakerNote8224;
+ break;
+
+ case 8240:
+ olympusMakerParent = tcOlympusMakerNote8240;
+ break;
+
+ case 8256:
+ olympusMakerParent = tcOlympusMakerNote8256;
+ break;
+
+ case 8272:
+ olympusMakerParent = tcOlympusMakerNote8272;
+ break;
+
+ case 12288:
+ olympusMakerParent = tcOlympusMakerNote12288;
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (olympusMakerParent)
+ {
+
+ stream.SetReadPosition (tagOffset);
+
+ uint64 subMakerNoteOffset = stream.Get_uint32 () + offsetDelta;
+
+ if (subMakerNoteOffset >= minOffset &&
+ subMakerNoteOffset < maxOffset)
+ {
+
+ if (ParseMakerNoteIFD (host,
+ stream,
+ maxOffset - subMakerNoteOffset,
+ subMakerNoteOffset,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ olympusMakerParent))
+ {
+
+ continue;
+
+ }
+
+ }
+
+ }
+
+ stream.SetReadPosition (tagOffset);
+
+ }
+
+ ParseTag (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset,
+ offsetDelta);
+
+ }
+
+ // Grab next IFD pointer, for possible use.
+
+ if (ifdSize >= 2 + ifdEntries * 12 + 4)
+ {
+
+ stream.SetReadPosition (ifdOffset + 2 + ifdEntries * 12);
+
+ fMakerNoteNextIFD = stream.Get_uint32 ();
+
+ }
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("\n");
+ }
+
+ #endif
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+void dng_info::ParseMakerNote (dng_host &host,
+ dng_stream &stream,
+ uint32 makerNoteCount,
+ uint64 makerNoteOffset,
+ int64 offsetDelta,
+ uint64 minOffset,
+ uint64 maxOffset)
+ {
+
+ uint8 firstBytes [16];
+
+ memset (firstBytes, 0, sizeof (firstBytes));
+
+ stream.SetReadPosition (makerNoteOffset);
+
+ stream.Get (firstBytes, (uint32) Min_uint64 (sizeof (firstBytes),
+ makerNoteCount));
+
+ // Epson MakerNote with header.
+
+ if (memcmp (firstBytes, "EPSON\000\001\000", 8) == 0)
+ {
+
+ if (makerNoteCount > 8)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 8,
+ makerNoteOffset + 8,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcEpsonMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Fujifilm MakerNote.
+
+ if (memcmp (firstBytes, "FUJIFILM", 8) == 0)
+ {
+
+ stream.SetReadPosition (makerNoteOffset + 8);
+
+ TempLittleEndian tempEndian (stream);
+
+ uint32 ifd_offset = stream.Get_uint32 ();
+
+ if (ifd_offset >= 12 && ifd_offset < makerNoteCount)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - ifd_offset,
+ makerNoteOffset + ifd_offset,
+ makerNoteOffset,
+ minOffset,
+ maxOffset,
+ tcFujiMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Leica MakerNote for models that store entry offsets relative to the start of
+ // the MakerNote (e.g., M9).
+
+ if ((memcmp (firstBytes, "LEICA\000\000\000", 8) == 0) ||
+ (memcmp (firstBytes, "LEICA0\003\000", 8) == 0) ||
+ (memcmp (firstBytes, "LEICA\000\001\000", 8) == 0) ||
+ (memcmp (firstBytes, "LEICA\000\005\000", 8) == 0))
+ {
+
+ if (makerNoteCount > 8)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 8,
+ makerNoteOffset + 8,
+ makerNoteOffset,
+ minOffset,
+ maxOffset,
+ tcLeicaMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Leica MakerNote for models that store absolute entry offsets (i.e., relative
+ // to the start of the file, e.g., S2).
+
+ if (memcmp (firstBytes, "LEICA\000\002\377", 8) == 0)
+ {
+
+ if (makerNoteCount > 8)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 8,
+ makerNoteOffset + 8,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcLeicaMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Nikon version 2 MakerNote with header.
+
+ if (memcmp (firstBytes, "Nikon\000\002", 7) == 0)
+ {
+
+ stream.SetReadPosition (makerNoteOffset + 10);
+
+ bool bigEndian = false;
+
+ uint16 endianMark = stream.Get_uint16 ();
+
+ if (endianMark == byteOrderMM)
+ {
+ bigEndian = true;
+ }
+
+ else if (endianMark != byteOrderII)
+ {
+ return;
+ }
+
+ TempBigEndian temp_endian (stream, bigEndian);
+
+ uint16 magic = stream.Get_uint16 ();
+
+ if (magic != 42)
+ {
+ return;
+ }
+
+ uint32 ifd_offset = stream.Get_uint32 ();
+
+ if (ifd_offset >= 8 && ifd_offset < makerNoteCount - 10)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 10 - ifd_offset,
+ makerNoteOffset + 10 + ifd_offset,
+ makerNoteOffset + 10,
+ minOffset,
+ maxOffset,
+ tcNikonMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Newer version of Olympus MakerNote with byte order mark.
+
+ if (memcmp (firstBytes, "OLYMPUS\000", 8) == 0)
+ {
+
+ stream.SetReadPosition (makerNoteOffset + 8);
+
+ bool bigEndian = false;
+
+ uint16 endianMark = stream.Get_uint16 ();
+
+ if (endianMark == byteOrderMM)
+ {
+ bigEndian = true;
+ }
+
+ else if (endianMark != byteOrderII)
+ {
+ return;
+ }
+
+ TempBigEndian temp_endian (stream, bigEndian);
+
+ uint16 version = stream.Get_uint16 ();
+
+ if (version != 3)
+ {
+ return;
+ }
+
+ if (makerNoteCount > 12)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 12,
+ makerNoteOffset + 12,
+ makerNoteOffset,
+ minOffset,
+ maxOffset,
+ tcOlympusMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Olympus MakerNote with header.
+
+ if (memcmp (firstBytes, "OLYMP", 5) == 0)
+ {
+
+ if (makerNoteCount > 8)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 8,
+ makerNoteOffset + 8,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcOlympusMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Panasonic MakerNote.
+
+ if (memcmp (firstBytes, "Panasonic\000\000\000", 12) == 0)
+ {
+
+ if (makerNoteCount > 12)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 12,
+ makerNoteOffset + 12,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcPanasonicMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Pentax MakerNote.
+
+ if (memcmp (firstBytes, "AOC", 4) == 0)
+ {
+
+ if (makerNoteCount > 6)
+ {
+
+ stream.SetReadPosition (makerNoteOffset + 4);
+
+ bool bigEndian = stream.BigEndian ();
+
+ uint16 endianMark = stream.Get_uint16 ();
+
+ if (endianMark == byteOrderMM)
+ {
+ bigEndian = true;
+ }
+
+ else if (endianMark == byteOrderII)
+ {
+ bigEndian = false;
+ }
+
+ TempBigEndian temp_endian (stream, bigEndian);
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 6,
+ makerNoteOffset + 6,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcPentaxMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Ricoh MakerNote.
+
+ if (memcmp (firstBytes, "RICOH", 5) == 0 ||
+ memcmp (firstBytes, "Ricoh", 5) == 0)
+ {
+
+ if (makerNoteCount > 8)
+ {
+
+ TempBigEndian tempEndian (stream);
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 8,
+ makerNoteOffset + 8,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcRicohMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Nikon MakerNote without header.
+
+ if (fExif->fMake.StartsWith ("NIKON"))
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount,
+ makerNoteOffset,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcNikonMakerNote);
+
+ return;
+
+ }
+
+ // Canon MakerNote.
+
+ if (fExif->fMake.StartsWith ("CANON"))
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount,
+ makerNoteOffset,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcCanonMakerNote);
+
+ return;
+
+ }
+
+ // Minolta MakerNote.
+
+ if (fExif->fMake.StartsWith ("MINOLTA" ) ||
+ fExif->fMake.StartsWith ("KONICA MINOLTA"))
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount,
+ makerNoteOffset,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcMinoltaMakerNote);
+
+ return;
+
+ }
+
+ // Sony MakerNote.
+
+ if (fExif->fMake.StartsWith ("SONY"))
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount,
+ makerNoteOffset,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcSonyMakerNote);
+
+ return;
+
+ }
+
+ // Kodak MakerNote.
+
+ if (fExif->fMake.StartsWith ("EASTMAN KODAK"))
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount,
+ makerNoteOffset,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcKodakMakerNote);
+
+ return;
+
+ }
+
+ // Mamiya MakerNote.
+
+ if (fExif->fMake.StartsWith ("Mamiya"))
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount,
+ makerNoteOffset,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcMamiyaMakerNote);
+
+ // Mamiya uses a MakerNote chain.
+
+ while (fMakerNoteNextIFD)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount,
+ offsetDelta + fMakerNoteNextIFD,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcMamiyaMakerNote);
+
+ }
+
+ return;
+
+ }
+
+ // Nikon MakerNote without header.
+
+ if (fExif->fMake.StartsWith ("Hasselblad"))
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount,
+ makerNoteOffset,
+ offsetDelta,
+ minOffset,
+ maxOffset,
+ tcHasselbladMakerNote);
+
+ return;
+
+ }
+
+ // Samsung MakerNote.
+
+ if (fExif->fMake.StartsWith ("Samsung"))
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount,
+ makerNoteOffset,
+ makerNoteOffset,
+ minOffset,
+ maxOffset,
+ tcSamsungMakerNote);
+
+ return;
+
+ }
+
+ // Casio MakerNote.
+
+ if (fExif->fMake.StartsWith ("CASIO COMPUTER") &&
+ memcmp (firstBytes, "QVC\000\000\000", 6) == 0)
+ {
+
+ ParseMakerNoteIFD (host,
+ stream,
+ makerNoteCount - 6,
+ makerNoteOffset + 6,
+ makerNoteOffset,
+ minOffset,
+ maxOffset,
+ tcCasioMakerNote);
+
+ return;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_info::ParseSonyPrivateData (dng_host & /* host */,
+ dng_stream & /* stream */,
+ uint64 /* count */,
+ uint64 /* oldOffset */,
+ uint64 /* newOffset */)
+ {
+
+ // Sony private data is encrypted, sorry.
+
+ }
+
+/*****************************************************************************/
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+void dng_info::ParseDNGPrivateData (dng_host &host,
+ dng_stream &stream)
+ {
+
+ if (fShared->fDNGPrivateDataCount < 2)
+ {
+ return;
+ }
+
+ // DNG private data should always start with a null-terminated
+ // company name, to define the format of the private data.
+
+ dng_string privateName;
+
+ {
+
+ char buffer [64];
+
+ stream.SetReadPosition (fShared->fDNGPrivateDataOffset);
+
+ uint32 readLength = Min_uint32 (fShared->fDNGPrivateDataCount,
+ sizeof (buffer) - 1);
+
+ stream.Get (buffer, readLength);
+
+ buffer [readLength] = 0;
+
+ privateName.Set (buffer);
+
+ }
+
+ // Pentax is storing their MakerNote in the DNGPrivateData data.
+
+ if (privateName.StartsWith ("PENTAX" ) ||
+ privateName.StartsWith ("SAMSUNG"))
+ {
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("Parsing Pentax/Samsung DNGPrivateData\n\n");
+ }
+
+ #endif
+
+ stream.SetReadPosition (fShared->fDNGPrivateDataOffset + 8);
+
+ bool bigEndian = stream.BigEndian ();
+
+ uint16 endianMark = stream.Get_uint16 ();
+
+ if (endianMark == byteOrderMM)
+ {
+ bigEndian = true;
+ }
+
+ else if (endianMark == byteOrderII)
+ {
+ bigEndian = false;
+ }
+
+ TempBigEndian temp_endian (stream, bigEndian);
+
+ ParseMakerNoteIFD (host,
+ stream,
+ fShared->fDNGPrivateDataCount - 10,
+ fShared->fDNGPrivateDataOffset + 10,
+ fShared->fDNGPrivateDataOffset,
+ fShared->fDNGPrivateDataOffset,
+ fShared->fDNGPrivateDataOffset + fShared->fDNGPrivateDataCount,
+ tcPentaxMakerNote);
+
+ return;
+
+ }
+
+ // Stop parsing if this is not an Adobe format block.
+
+ if (!privateName.Matches ("Adobe"))
+ {
+ return;
+ }
+
+ TempBigEndian temp_order (stream);
+
+ uint32 section_offset = 6;
+
+ while (section_offset + 8 < fShared->fDNGPrivateDataCount)
+ {
+
+ stream.SetReadPosition (fShared->fDNGPrivateDataOffset + section_offset);
+
+ uint32 section_key = stream.Get_uint32 ();
+ uint32 section_count = stream.Get_uint32 ();
+
+ if (section_key == DNG_CHAR4 ('M','a','k','N') && section_count > 6)
+ {
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("Found MakerNote inside DNGPrivateData\n\n");
+ }
+
+ #endif
+
+ uint16 order_mark = stream.Get_uint16 ();
+ int64 old_offset = stream.Get_uint32 ();
+
+ uint32 tempSize = section_count - 6;
+
+ AutoPtr<dng_memory_block> tempBlock (host.Allocate (tempSize));
+
+ uint64 positionInOriginalFile = stream.PositionInOriginalFile();
+
+ stream.Get (tempBlock->Buffer (), tempSize);
+
+ dng_stream tempStream (tempBlock->Buffer (),
+ tempSize,
+ positionInOriginalFile);
+
+ tempStream.SetBigEndian (order_mark == byteOrderMM);
+
+ ParseMakerNote (host,
+ tempStream,
+ tempSize,
+ 0,
+ 0 - old_offset,
+ 0,
+ tempSize);
+
+ }
+
+ else if (section_key == DNG_CHAR4 ('S','R','2',' ') && section_count > 6)
+ {
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("Found Sony private data inside DNGPrivateData\n\n");
+ }
+
+ #endif
+
+ uint16 order_mark = stream.Get_uint16 ();
+ uint64 old_offset = stream.Get_uint32 ();
+
+ uint64 new_offset = fShared->fDNGPrivateDataOffset + section_offset + 14;
+
+ TempBigEndian sr2_order (stream, order_mark == byteOrderMM);
+
+ ParseSonyPrivateData (host,
+ stream,
+ section_count - 6,
+ old_offset,
+ new_offset);
+
+ }
+
+ else if (section_key == DNG_CHAR4 ('R','A','F',' ') && section_count > 4)
+ {
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("Found Fuji RAF tags inside DNGPrivateData\n\n");
+ }
+
+ #endif
+
+ uint16 order_mark = stream.Get_uint16 ();
+
+ uint32 tagCount = stream.Get_uint32 ();
+
+ uint64 tagOffset = stream.Position ();
+
+ if (tagCount)
+ {
+
+ TempBigEndian raf_order (stream, order_mark == byteOrderMM);
+
+ ParseTag (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ tcFujiRAF,
+ tcFujiHeader,
+ ttUndefined,
+ tagCount,
+ tagOffset,
+ 0);
+
+ stream.SetReadPosition (tagOffset + tagCount);
+
+ }
+
+ tagCount = stream.Get_uint32 ();
+
+ tagOffset = stream.Position ();
+
+ if (tagCount)
+ {
+
+ TempBigEndian raf_order (stream, order_mark == byteOrderMM);
+
+ ParseTag (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ tcFujiRAF,
+ tcFujiRawInfo1,
+ ttUndefined,
+ tagCount,
+ tagOffset,
+ 0);
+
+ stream.SetReadPosition (tagOffset + tagCount);
+
+ }
+
+ tagCount = stream.Get_uint32 ();
+
+ tagOffset = stream.Position ();
+
+ if (tagCount)
+ {
+
+ TempBigEndian raf_order (stream, order_mark == byteOrderMM);
+
+ ParseTag (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ tcFujiRAF,
+ tcFujiRawInfo2,
+ ttUndefined,
+ tagCount,
+ tagOffset,
+ 0);
+
+ stream.SetReadPosition (tagOffset + tagCount);
+
+ }
+
+ }
+
+ else if (section_key == DNG_CHAR4 ('C','n','t','x') && section_count > 4)
+ {
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("Found Contax Raw header inside DNGPrivateData\n\n");
+ }
+
+ #endif
+
+ uint16 order_mark = stream.Get_uint16 ();
+
+ uint32 tagCount = stream.Get_uint32 ();
+
+ uint64 tagOffset = stream.Position ();
+
+ if (tagCount)
+ {
+
+ TempBigEndian contax_order (stream, order_mark == byteOrderMM);
+
+ ParseTag (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ tcContaxRAW,
+ tcContaxHeader,
+ ttUndefined,
+ tagCount,
+ tagOffset,
+ 0);
+
+ }
+
+ }
+
+ else if (section_key == DNG_CHAR4 ('C','R','W',' ') && section_count > 4)
+ {
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("Found Canon CRW tags inside DNGPrivateData\n\n");
+ }
+
+ #endif
+
+ uint16 order_mark = stream.Get_uint16 ();
+ uint32 entries = stream.Get_uint16 ();
+
+ uint64 crwTagStart = stream.Position ();
+
+ for (uint32 parsePass = 1; parsePass <= 2; parsePass++)
+ {
+
+ stream.SetReadPosition (crwTagStart);
+
+ for (uint32 index = 0; index < entries; index++)
+ {
+
+ uint32 tagCode = stream.Get_uint16 ();
+
+ uint32 tagCount = stream.Get_uint32 ();
+
+ uint64 tagOffset = stream.Position ();
+
+ // We need to grab the model id tag first, and then all the
+ // other tags.
+
+ if ((parsePass == 1) == (tagCode == 0x5834))
+ {
+
+ TempBigEndian tag_order (stream, order_mark == byteOrderMM);
+
+ ParseTag (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ tcCanonCRW,
+ tagCode,
+ ttUndefined,
+ tagCount,
+ tagOffset,
+ 0);
+
+ }
+
+ stream.SetReadPosition (tagOffset + tagCount);
+
+ }
+
+ }
+
+ }
+
+ else if (section_count > 4)
+ {
+
+ uint32 parentCode = 0;
+
+ bool code32 = false;
+ bool hasType = true;
+
+ switch (section_key)
+ {
+
+ case DNG_CHAR4 ('M','R','W',' '):
+ {
+ parentCode = tcMinoltaMRW;
+ code32 = true;
+ hasType = false;
+ break;
+ }
+
+ case DNG_CHAR4 ('P','a','n','o'):
+ {
+ parentCode = tcPanasonicRAW;
+ break;
+ }
+
+ case DNG_CHAR4 ('L','e','a','f'):
+ {
+ parentCode = tcLeafMOS;
+ break;
+ }
+
+ case DNG_CHAR4 ('K','o','d','a'):
+ {
+ parentCode = tcKodakDCRPrivateIFD;
+ break;
+ }
+
+ case DNG_CHAR4 ('K','D','C',' '):
+ {
+ parentCode = tcKodakKDCPrivateIFD;
+ break;
+ }
+
+ default:
+ break;
+
+ }
+
+ if (parentCode)
+ {
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("Found %s tags inside DNGPrivateData\n\n",
+ LookupParentCode (parentCode));
+ }
+
+ #endif
+
+ uint16 order_mark = stream.Get_uint16 ();
+ uint32 entries = stream.Get_uint16 ();
+
+ for (uint32 index = 0; index < entries; index++)
+ {
+
+ uint32 tagCode = code32 ? stream.Get_uint32 ()
+ : stream.Get_uint16 ();
+
+ uint32 tagType = hasType ? stream.Get_uint16 ()
+ : ttUndefined;
+
+ uint32 tagCount = stream.Get_uint32 ();
+
+ uint32 tagSize = tagCount * TagTypeSize (tagType);
+
+ uint64 tagOffset = stream.Position ();
+
+ TempBigEndian tag_order (stream, order_mark == byteOrderMM);
+
+ ParseTag (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ parentCode,
+ tagCode,
+ tagType,
+ tagCount,
+ tagOffset,
+ 0);
+
+ stream.SetReadPosition (tagOffset + tagSize);
+
+ }
+
+ }
+
+ }
+
+ section_offset += 8 + section_count;
+
+ if (section_offset & 1)
+ {
+ section_offset++;
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_info::Parse (dng_host &host,
+ dng_stream &stream)
+ {
+
+ fTIFFBlockOffset = stream.Position ();
+
+ fTIFFBlockOriginalOffset = stream.PositionInOriginalFile ();
+
+ // Check byte order indicator.
+
+ uint16 byteOrder = stream.Get_uint16 ();
+
+ if (byteOrder == byteOrderII)
+ {
+
+ fBigEndian = false;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("\nUses little-endian byte order\n");
+ }
+
+ #endif
+
+ stream.SetLittleEndian ();
+
+ }
+
+ else if (byteOrder == byteOrderMM)
+ {
+
+ fBigEndian = true;
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("\nUses big-endian byte order\n");
+ }
+
+ #endif
+
+ stream.SetBigEndian ();
+
+ }
+
+ else
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unknown byte order");
+
+ #endif
+
+ ThrowBadFormat ();
+
+ }
+
+ // Check "magic number" indicator.
+
+ fMagic = stream.Get_uint16 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+ printf ("Magic number = %u\n\n", (unsigned) fMagic);
+ }
+
+ #endif
+
+ ValidateMagic ();
+
+ // Parse IFD 0.
+
+ uint64 next_offset = stream.Get_uint32 ();
+
+ fExif.Reset (host.Make_dng_exif ());
+
+ fShared.Reset (host.Make_dng_shared ());
+
+ fIFD [0].Reset (host.Make_dng_ifd ());
+
+ ParseIFD (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ fIFD [0].Get (),
+ fTIFFBlockOffset + next_offset,
+ fTIFFBlockOffset,
+ 0);
+
+ next_offset = fIFD [0]->fNextIFD;
+
+ fIFDCount = 1;
+
+ // Parse chained IFDs.
+
+ while (next_offset)
+ {
+
+ if (next_offset >= stream.Length ())
+ {
+
+ #if qDNGValidate
+
+ {
+
+ ReportWarning ("Chained IFD offset past end of stream");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ // Some TIFF file writers forget about the next IFD offset, so
+ // validate the IFD at that offset before parsing it.
+
+ if (!ValidateIFD (stream,
+ fTIFFBlockOffset + next_offset,
+ fTIFFBlockOffset))
+ {
+
+ #if qDNGValidate
+
+ {
+
+ ReportWarning ("Chained IFD is not valid");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ if (fChainedIFDCount == kMaxChainedIFDs)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ ReportWarning ("Chained IFD count exceeds DNG SDK parsing limit");
+
+ }
+
+ #endif
+
+ break;
+
+ }
+
+ fChainedIFD [fChainedIFDCount].Reset (host.Make_dng_ifd ());
+
+ ParseIFD (host,
+ stream,
+ NULL,
+ NULL,
+ fChainedIFD [fChainedIFDCount].Get (),
+ fTIFFBlockOffset + next_offset,
+ fTIFFBlockOffset,
+ tcFirstChainedIFD + fChainedIFDCount);
+
+ next_offset = fChainedIFD [fChainedIFDCount]->fNextIFD;
+
+ fChainedIFDCount++;
+
+ }
+
+ // Parse SubIFDs.
+
+ uint32 searchedIFDs = 0;
+
+ bool tooManySubIFDs = false;
+
+ while (searchedIFDs < fIFDCount && !tooManySubIFDs)
+ {
+
+ uint32 searchLimit = fIFDCount;
+
+ for (uint32 searchIndex = searchedIFDs;
+ searchIndex < searchLimit && !tooManySubIFDs;
+ searchIndex++)
+ {
+
+ for (uint32 subIndex = 0;
+ subIndex < fIFD [searchIndex]->fSubIFDsCount;
+ subIndex++)
+ {
+
+ if (fIFDCount == kMaxSubIFDs + 1)
+ {
+
+ tooManySubIFDs = true;
+
+ break;
+
+ }
+
+ stream.SetReadPosition (fIFD [searchIndex]->fSubIFDsOffset +
+ subIndex * 4);
+
+ uint32 sub_ifd_offset = stream.Get_uint32 ();
+
+ fIFD [fIFDCount].Reset (host.Make_dng_ifd ());
+
+ ParseIFD (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ fIFD [fIFDCount].Get (),
+ fTIFFBlockOffset + sub_ifd_offset,
+ fTIFFBlockOffset,
+ tcFirstSubIFD + fIFDCount - 1);
+
+ fIFDCount++;
+
+ }
+
+ searchedIFDs = searchLimit;
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ {
+
+ if (tooManySubIFDs)
+ {
+
+ ReportWarning ("SubIFD count exceeds DNG SDK parsing limit");
+
+ }
+
+ }
+
+ #endif
+
+ // Parse EXIF IFD.
+
+ if (fShared->fExifIFD)
+ {
+
+ ParseIFD (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ fTIFFBlockOffset + fShared->fExifIFD,
+ fTIFFBlockOffset,
+ tcExifIFD);
+
+ }
+
+ // Parse GPS IFD.
+
+ if (fShared->fGPSInfo)
+ {
+
+ ParseIFD (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ fTIFFBlockOffset + fShared->fGPSInfo,
+ fTIFFBlockOffset,
+ tcGPSInfo);
+
+ }
+
+ // Parse Interoperability IFD.
+
+ if (fShared->fInteroperabilityIFD)
+ {
+
+ // Some Kodak KDC files have bogus Interoperability IFDs, so
+ // validate the IFD before trying to parse it.
+
+ if (ValidateIFD (stream,
+ fTIFFBlockOffset + fShared->fInteroperabilityIFD,
+ fTIFFBlockOffset))
+ {
+
+ ParseIFD (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ fTIFFBlockOffset + fShared->fInteroperabilityIFD,
+ fTIFFBlockOffset,
+ tcInteroperabilityIFD);
+
+ }
+
+ #if qDNGValidate
+
+ else
+ {
+
+ ReportWarning ("The Interoperability IFD is not a valid IFD");
+
+ }
+
+ #endif
+
+ }
+
+ // Parse Kodak DCR Private IFD.
+
+ if (fShared->fKodakDCRPrivateIFD)
+ {
+
+ ParseIFD (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ fTIFFBlockOffset + fShared->fKodakDCRPrivateIFD,
+ fTIFFBlockOffset,
+ tcKodakDCRPrivateIFD);
+
+ }
+
+ // Parse Kodak KDC Private IFD.
+
+ if (fShared->fKodakKDCPrivateIFD)
+ {
+
+ ParseIFD (host,
+ stream,
+ fExif.Get (),
+ fShared.Get (),
+ NULL,
+ fTIFFBlockOffset + fShared->fKodakKDCPrivateIFD,
+ fTIFFBlockOffset,
+ tcKodakKDCPrivateIFD);
+
+ }
+
+ // Parse MakerNote tag.
+
+ if (fShared->fMakerNoteCount)
+ {
+
+ ParseMakerNote (host,
+ stream,
+ (uint32) (fTIFFBlockOffset + fShared->fMakerNoteCount),
+ fShared->fMakerNoteOffset,
+ fTIFFBlockOffset,
+ 0,
+ stream.Length ());
+
+ }
+
+ // Parse DNGPrivateData tag.
+
+ if (fShared->fDNGPrivateDataCount &&
+ fShared->fDNGVersion)
+ {
+
+ ParseDNGPrivateData (host, stream);
+
+ }
+
+ #if qDNGValidate
+
+ // If we are running dng_validate on stand-alone camera profile file,
+ // complete the validation of the profile.
+
+ if (fMagic == magicExtendedProfile)
+ {
+
+ dng_camera_profile_info &profileInfo = fShared->fCameraProfile;
+
+ dng_camera_profile profile;
+
+ profile.Parse (stream, profileInfo);
+
+ if (profileInfo.fColorPlanes < 3 || !profile.IsValid (profileInfo.fColorPlanes))
+ {
+
+ ReportError ("Invalid camera profile file");
+
+ }
+
+ }
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+void dng_info::PostParse (dng_host &host)
+ {
+
+ uint32 index;
+
+ fExif->PostParse (host, *fShared.Get ());
+
+ fShared->PostParse (host, *fExif.Get ());
+
+ for (index = 0; index < fIFDCount; index++)
+ {
+
+ fIFD [index]->PostParse ();
+
+ }
+
+ for (index = 0; index < fChainedIFDCount; index++)
+ {
+
+ fChainedIFD [index]->PostParse ();
+
+ }
+
+ if (fShared->fDNGVersion != 0)
+ {
+
+ // Find main IFD.
+
+ fMainIndex = -1;
+
+ for (index = 0; index < fIFDCount; index++)
+ {
+
+ if (fIFD [index]->fUsesNewSubFileType &&
+ fIFD [index]->fNewSubFileType == sfMainImage)
+ {
+
+ if (fMainIndex == -1)
+ {
+
+ fMainIndex = index;
+
+ }
+
+ #if qDNGValidate
+
+ else
+ {
+
+ ReportError ("Multiple IFDs marked as main image");
+
+ }
+
+ #endif
+
+ }
+
+ else if (fIFD [index]->fNewSubFileType == sfPreviewImage ||
+ fIFD [index]->fNewSubFileType == sfAltPreviewImage)
+ {
+
+ // Fill in default color space for DNG previews if not included.
+
+ if (fIFD [index]->fPreviewInfo.fColorSpace == previewColorSpace_MaxEnum)
+ {
+
+ if (fIFD [index]->fSamplesPerPixel == 1)
+ {
+
+ fIFD [index]->fPreviewInfo.fColorSpace = previewColorSpace_GrayGamma22;
+
+ }
+
+ else
+ {
+
+ fIFD [index]->fPreviewInfo.fColorSpace = previewColorSpace_sRGB;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ // Deal with lossless JPEG bug in early DNG versions.
+
+ if (fShared->fDNGVersion < dngVersion_1_1_0_0)
+ {
+
+ if (fMainIndex != -1)
+ {
+
+ fIFD [fMainIndex]->fLosslessJPEGBug16 = true;
+
+ }
+
+ }
+
+ // Find mask index.
+
+ for (index = 0; index < fIFDCount; index++)
+ {
+
+ if (fIFD [index]->fNewSubFileType == sfTransparencyMask)
+ {
+
+ if (fMaskIndex == -1)
+ {
+
+ fMaskIndex = index;
+
+ }
+
+ #if qDNGValidate
+
+ else
+ {
+
+ ReportError ("Multiple IFDs marked as transparency mask image");
+
+ }
+
+ #endif
+
+ }
+
+ }
+
+ // Warn about Chained IFDs.
+
+ #if qDNGValidate
+
+ if (fChainedIFDCount > 0)
+ {
+
+ ReportWarning ("This file has Chained IFDs, which will be ignored by DNG readers");
+
+ }
+
+ #endif
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_info::IsValidDNG ()
+ {
+
+ // Check shared info.
+
+ if (!fShared->IsValidDNG ())
+ {
+
+ return false;
+
+ }
+
+ // Check TIFF magic number.
+
+ if (fMagic != 42)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Invalid TIFF magic number");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Make sure we have a main image IFD.
+
+ if (fMainIndex == -1)
+ {
+
+ #if qDNGValidate
+
+ ReportError ("Unable to find main image IFD");
+
+ #endif
+
+ return false;
+
+ }
+
+ // Make sure is each IFD is valid.
+
+ for (uint32 index = 0; index < fIFDCount; index++)
+ {
+
+ uint32 parentCode = (index == 0 ? 0 : tcFirstSubIFD + index - 1);
+
+ if (!fIFD [index]->IsValidDNG (*fShared.Get (),
+ parentCode))
+ {
+
+ // Only errors in the main and transparency mask IFDs are fatal to parsing.
+
+ if (index == (uint32) fMainIndex ||
+ index == (uint32) fMaskIndex)
+ {
+
+ return false;
+
+ }
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_info.h b/source/dng_info.h
index 3ccefd1..44b22d4 100644
--- a/source/dng_info.h
+++ b/source/dng_info.h
@@ -1,163 +1,163 @@
-/*****************************************************************************/
-// Copyright 2006-2011 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_info.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Class for holding top-level information about a DNG image.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_info__
-#define __dng_info__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_ifd.h"
-#include "dng_exif.h"
-#include "dng_shared.h"
-#include "dng_errors.h"
-#include "dng_sdk_limits.h"
-#include "dng_auto_ptr.h"
-
-/*****************************************************************************/
-
-/// \brief Top-level structure of DNG file with access to metadata.
-///
-/// See \ref spec_dng "DNG 1.1.0 specification" for information on member fields of this class.
-
-class dng_info
- {
-
- public:
-
- uint64 fTIFFBlockOffset;
-
- uint64 fTIFFBlockOriginalOffset;
-
- bool fBigEndian;
-
- uint32 fMagic;
-
- AutoPtr<dng_exif> fExif;
-
- AutoPtr<dng_shared> fShared;
-
- int32 fMainIndex;
-
- int32 fMaskIndex;
-
- uint32 fIFDCount;
-
- AutoPtr<dng_ifd> fIFD [kMaxSubIFDs + 1];
-
- uint32 fChainedIFDCount;
-
- AutoPtr<dng_ifd> fChainedIFD [kMaxChainedIFDs];
-
- protected:
-
- uint32 fMakerNoteNextIFD;
-
- public:
-
- dng_info ();
-
- virtual ~dng_info ();
-
- /// Read dng_info from a dng_stream
- /// \param host DNG host used for progress updating, abort testing, buffer allocation, etc.
- /// \param stream Stream to read DNG data from.
-
- virtual void Parse (dng_host &host,
- dng_stream &stream);
-
- /// Must be called immediately after a successful Parse operation.
-
- virtual void PostParse (dng_host &host);
-
- /// Test validity of DNG data.
- /// \retval true if stream provided a valid DNG.
-
- virtual bool IsValidDNG ();
-
- protected:
-
- virtual void ValidateMagic ();
-
- virtual void ParseTag (dng_host &host,
- dng_stream &stream,
- dng_exif *exif,
- dng_shared *shared,
- dng_ifd *ifd,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset,
- int64 offsetDelta);
-
- virtual bool ValidateIFD (dng_stream &stream,
- uint64 ifdOffset,
- int64 offsetDelta);
-
- virtual void ParseIFD (dng_host &host,
- dng_stream &stream,
- dng_exif *exif,
- dng_shared *shared,
- dng_ifd *ifd,
- uint64 ifdOffset,
- int64 offsetDelta,
- uint32 parentCode);
-
- virtual bool ParseMakerNoteIFD (dng_host &host,
- dng_stream &stream,
- uint64 ifdSize,
- uint64 ifdOffset,
- int64 offsetDelta,
- uint64 minOffset,
- uint64 maxOffset,
- uint32 parentCode);
-
- virtual void ParseMakerNote (dng_host &host,
- dng_stream &stream,
- uint32 makerNoteCount,
- uint64 makerNoteOffset,
- int64 offsetDelta,
- uint64 minOffset,
- uint64 maxOffset);
-
- virtual void ParseSonyPrivateData (dng_host &host,
- dng_stream &stream,
- uint64 count,
- uint64 oldOffset,
- uint64 newOffset);
-
- virtual void ParseDNGPrivateData (dng_host &host,
- dng_stream &stream);
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_info (const dng_info &info);
-
- dng_info & operator= (const dng_info &info);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2011 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_info.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Class for holding top-level information about a DNG image.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_info__
+#define __dng_info__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_ifd.h"
+#include "dng_exif.h"
+#include "dng_shared.h"
+#include "dng_errors.h"
+#include "dng_sdk_limits.h"
+#include "dng_auto_ptr.h"
+
+/*****************************************************************************/
+
+/// \brief Top-level structure of DNG file with access to metadata.
+///
+/// See \ref spec_dng "DNG 1.1.0 specification" for information on member fields of this class.
+
+class dng_info
+ {
+
+ public:
+
+ uint64 fTIFFBlockOffset;
+
+ uint64 fTIFFBlockOriginalOffset;
+
+ bool fBigEndian;
+
+ uint32 fMagic;
+
+ AutoPtr<dng_exif> fExif;
+
+ AutoPtr<dng_shared> fShared;
+
+ int32 fMainIndex;
+
+ int32 fMaskIndex;
+
+ uint32 fIFDCount;
+
+ AutoPtr<dng_ifd> fIFD [kMaxSubIFDs + 1];
+
+ uint32 fChainedIFDCount;
+
+ AutoPtr<dng_ifd> fChainedIFD [kMaxChainedIFDs];
+
+ protected:
+
+ uint32 fMakerNoteNextIFD;
+
+ public:
+
+ dng_info ();
+
+ virtual ~dng_info ();
+
+ /// Read dng_info from a dng_stream
+ /// \param host DNG host used for progress updating, abort testing, buffer allocation, etc.
+ /// \param stream Stream to read DNG data from.
+
+ virtual void Parse (dng_host &host,
+ dng_stream &stream);
+
+ /// Must be called immediately after a successful Parse operation.
+
+ virtual void PostParse (dng_host &host);
+
+ /// Test validity of DNG data.
+ /// \retval true if stream provided a valid DNG.
+
+ virtual bool IsValidDNG ();
+
+ protected:
+
+ virtual void ValidateMagic ();
+
+ virtual void ParseTag (dng_host &host,
+ dng_stream &stream,
+ dng_exif *exif,
+ dng_shared *shared,
+ dng_ifd *ifd,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset,
+ int64 offsetDelta);
+
+ virtual bool ValidateIFD (dng_stream &stream,
+ uint64 ifdOffset,
+ int64 offsetDelta);
+
+ virtual void ParseIFD (dng_host &host,
+ dng_stream &stream,
+ dng_exif *exif,
+ dng_shared *shared,
+ dng_ifd *ifd,
+ uint64 ifdOffset,
+ int64 offsetDelta,
+ uint32 parentCode);
+
+ virtual bool ParseMakerNoteIFD (dng_host &host,
+ dng_stream &stream,
+ uint64 ifdSize,
+ uint64 ifdOffset,
+ int64 offsetDelta,
+ uint64 minOffset,
+ uint64 maxOffset,
+ uint32 parentCode);
+
+ virtual void ParseMakerNote (dng_host &host,
+ dng_stream &stream,
+ uint32 makerNoteCount,
+ uint64 makerNoteOffset,
+ int64 offsetDelta,
+ uint64 minOffset,
+ uint64 maxOffset);
+
+ virtual void ParseSonyPrivateData (dng_host &host,
+ dng_stream &stream,
+ uint64 count,
+ uint64 oldOffset,
+ uint64 newOffset);
+
+ virtual void ParseDNGPrivateData (dng_host &host,
+ dng_stream &stream);
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_info (const dng_info &info);
+
+ dng_info & operator= (const dng_info &info);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_iptc.cpp b/source/dng_iptc.cpp
index 5b51904..055a7a6 100644
--- a/source/dng_iptc.cpp
+++ b/source/dng_iptc.cpp
@@ -1,985 +1,985 @@
-/*****************************************************************************/
-// Copyright 2006-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_iptc.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_iptc.h"
-
-#include "dng_assertions.h"
-#include "dng_auto_ptr.h"
-#include "dng_memory_stream.h"
-#include "dng_stream.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_iptc::dng_iptc ()
-
- : fTitle ()
-
- , fUrgency (-1)
-
- , fCategory ()
-
- , fSupplementalCategories ()
-
- , fKeywords ()
-
- , fInstructions ()
-
- , fDateTimeCreated ()
-
- , fDigitalCreationDateTime ()
-
- , fAuthors ()
- , fAuthorsPosition ()
-
- , fCity ()
- , fState ()
- , fCountry ()
- , fCountryCode ()
-
- , fLocation ()
-
- , fTransmissionReference ()
-
- , fHeadline ()
-
- , fCredit ()
-
- , fSource ()
-
- , fCopyrightNotice ()
-
- , fDescription ()
- , fDescriptionWriter ()
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_iptc::~dng_iptc ()
- {
-
- }
-
-/*****************************************************************************/
-
-bool dng_iptc::IsEmpty () const
- {
-
- if (fTitle.NotEmpty ())
- {
- return false;
- }
-
- if (fUrgency >= 0)
- {
- return false;
- }
-
- if (fCategory.NotEmpty ())
- {
- return false;
- }
-
- if (fSupplementalCategories.Count () > 0)
- {
- return false;
- }
-
- if (fKeywords.Count () > 0)
- {
- return false;
- }
-
- if (fInstructions.NotEmpty ())
- {
- return false;
- }
-
- if (fDateTimeCreated.IsValid ())
- {
- return false;
- }
-
- if (fDigitalCreationDateTime.IsValid ())
- {
- return false;
- }
-
- if (fAuthors.Count () != 0 ||
- fAuthorsPosition.NotEmpty ())
- {
- return false;
- }
-
- if (fCity .NotEmpty () ||
- fState .NotEmpty () ||
- fCountry.NotEmpty ())
- {
- return false;
- }
-
- if (fCountryCode.NotEmpty ())
- {
- return false;
- }
-
- if (fLocation.NotEmpty ())
- {
- return false;
- }
-
- if (fTransmissionReference.NotEmpty ())
- {
- return false;
- }
-
- if (fHeadline.NotEmpty ())
- {
- return false;
- }
-
- if (fCredit.NotEmpty ())
- {
- return false;
- }
-
- if (fSource.NotEmpty ())
- {
- return false;
- }
-
- if (fCopyrightNotice.NotEmpty ())
- {
- return false;
- }
-
- if (fDescription .NotEmpty () ||
- fDescriptionWriter.NotEmpty ())
- {
- return false;
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-void dng_iptc::ParseString (dng_stream &stream,
- dng_string &s,
- CharSet charSet)
- {
-
- uint32 length = stream.Get_uint16 ();
-
- dng_memory_data buffer (length + 1);
-
- char *c = buffer.Buffer_char ();
-
- stream.Get (c, length);
-
- c [length] = 0;
-
- switch (charSet)
- {
-
- case kCharSetUTF8:
- {
- s.Set_UTF8 (c);
- break;
- }
-
- default:
- {
- s.Set_SystemEncoding (c);
- }
-
- }
-
- s.SetLineEndingsToNewLines ();
-
- s.StripLowASCII ();
-
- s.TrimTrailingBlanks ();
-
- }
-
-/*****************************************************************************/
-
-void dng_iptc::Parse (const void *blockData,
- uint32 blockSize,
- uint64 offsetInOriginalFile)
- {
-
- dng_stream stream (blockData,
- blockSize,
- offsetInOriginalFile);
-
- stream.SetBigEndian ();
-
- // Make a first pass though the data, trying to figure out the
- // character set.
-
- CharSet charSet = kCharSetUnknown;
-
- bool isValidUTF8 = true;
-
- bool hasEncodingMarker = false;
-
- uint64 firstOffset = stream.Position ();
-
- uint64 nextOffset = firstOffset;
-
- while (nextOffset + 5 < stream.Length ())
- {
-
- stream.SetReadPosition (nextOffset);
-
- uint8 firstByte = stream.Get_uint8 ();
-
- if (firstByte != 0x1C) break;
-
- uint8 record = stream.Get_uint8 ();
- uint8 dataSet = stream.Get_uint8 ();
- uint32 dataSize = stream.Get_uint16 ();
-
- nextOffset = stream.Position () + dataSize;
-
- if (record == 1)
- {
-
- switch (dataSet)
- {
-
- case 90:
- {
-
- hasEncodingMarker = true;
-
- if (dataSize == 3)
- {
-
- uint32 byte1 = stream.Get_uint8 ();
- uint32 byte2 = stream.Get_uint8 ();
- uint32 byte3 = stream.Get_uint8 ();
-
- if (byte1 == 27 /* Escape */ &&
- byte2 == 0x25 &&
- byte3 == 0x47)
- {
-
- charSet = kCharSetUTF8;
-
- }
-
- }
-
- break;
-
- }
-
- default:
- break;
-
- }
-
- }
-
- else if (record == 2)
- {
-
- dng_memory_data buffer (dataSize + 1);
-
- char *s = buffer.Buffer_char ();
-
- stream.Get (s, dataSize);
-
- s [dataSize] = 0;
-
- isValidUTF8 = isValidUTF8 && dng_string::IsUTF8 (s);
-
- }
-
- }
-
- // If we don't have an encoding marker, and the data is valid
- // UTF-8, then assume that it is UTF-8 (rather than system encoding).
-
- if (!hasEncodingMarker && isValidUTF8)
- {
-
- charSet = kCharSetUTF8;
-
- }
-
- // Make a second pass though the data, actually reading the data.
-
- nextOffset = firstOffset;
-
- while (nextOffset + 5 < stream.Length ())
- {
-
- stream.SetReadPosition (nextOffset);
-
- uint8 firstByte = stream.Get_uint8 ();
-
- if (firstByte != 0x1C) break;
-
- uint8 record = stream.Get_uint8 ();
- uint8 dataSet = stream.Get_uint8 ();
- uint32 dataSize = stream.Get_uint16 ();
-
- nextOffset = stream.Position () + dataSize;
-
- if (record == 2)
- {
-
- stream.SetReadPosition (stream.Position () - 2);
-
- switch ((DataSet) dataSet)
- {
-
- case kObjectNameSet:
- {
- ParseString (stream, fTitle, charSet);
- break;
- }
-
- case kUrgencySet:
- {
-
- int32 size = stream.Get_uint16 ();
-
- if (size == 1)
- {
-
- char c = stream.Get_int8 ();
-
- if (c >= '0' && c <= '9')
- {
- fUrgency = c - '0';
- }
-
- }
-
- break;
-
- }
-
- case kCategorySet:
- {
- ParseString (stream, fCategory, charSet);
- break;
- }
-
- case kSupplementalCategoriesSet:
- {
-
- dng_string category;
-
- ParseString (stream, category, charSet);
-
- if (category.NotEmpty ())
- {
- fSupplementalCategories.Append (category);
- }
-
- break;
-
- }
-
- case kKeywordsSet:
- {
-
- dng_string keyword;
-
- ParseString (stream, keyword, charSet);
-
- if (keyword.NotEmpty ())
- {
- fKeywords.Append (keyword);
- }
-
- break;
-
- }
-
- case kSpecialInstructionsSet:
- {
- ParseString (stream, fInstructions, charSet);
- break;
- }
-
- case kDateCreatedSet:
- {
-
- uint32 length = stream.Get_uint16 ();
-
- if (length == 8)
- {
-
- char date [9];
-
- stream.Get (date, 8);
-
- date [8] = 0;
-
- fDateTimeCreated.Decode_IPTC_Date (date);
-
- }
-
- break;
-
- }
-
- case kTimeCreatedSet:
- {
-
- uint32 length = stream.Get_uint16 ();
-
- if (length >= 4 && length <= 11)
- {
-
- char time [12];
-
- stream.Get (time, length);
-
- time [length] = 0;
-
- fDateTimeCreated.Decode_IPTC_Time (time);
-
- }
-
- break;
-
- }
-
- case kDigitalCreationDateSet:
- {
-
- uint32 length = stream.Get_uint16 ();
-
- if (length == 8)
- {
-
- char date [9];
-
- stream.Get (date, 8);
-
- date [8] = 0;
-
- fDigitalCreationDateTime.Decode_IPTC_Date (date);
-
- }
-
- break;
-
- }
-
- case kDigitalCreationTimeSet:
- {
-
- uint32 length = stream.Get_uint16 ();
-
- if (length >= 4 && length <= 11)
- {
-
- char time [12];
-
- stream.Get (time, length);
-
- time [length] = 0;
-
- fDigitalCreationDateTime.Decode_IPTC_Time (time);
-
- }
-
- break;
-
- }
-
- case kBylineSet:
- {
-
- dng_string author;
-
- ParseString (stream, author, charSet);
-
- if (author.NotEmpty ())
- {
- fAuthors.Append (author);
- }
-
- break;
-
- }
-
- case kBylineTitleSet:
- {
- ParseString (stream, fAuthorsPosition, charSet);
- break;
- }
-
- case kCitySet:
- {
- ParseString (stream, fCity, charSet);
- break;
- }
-
- case kProvinceStateSet:
- {
- ParseString (stream, fState, charSet);
- break;
- }
-
- case kCountryNameSet:
- {
- ParseString (stream, fCountry, charSet);
- break;
- }
-
- case kCountryCodeSet:
- {
- ParseString (stream, fCountryCode, charSet);
- break;
- }
-
- case kSublocationSet:
- {
- ParseString (stream, fLocation, charSet);
- break;
- }
-
- case kOriginalTransmissionReferenceSet:
- {
- ParseString (stream, fTransmissionReference, charSet);
- break;
- }
-
- case kHeadlineSet:
- {
- ParseString (stream, fHeadline, charSet);
- break;
- }
-
- case kCreditSet:
- {
- ParseString (stream, fCredit, charSet);
- break;
- }
-
- case kSourceSet:
- {
- ParseString (stream, fSource, charSet);
- break;
- }
-
- case kCopyrightNoticeSet:
- {
- ParseString (stream, fCopyrightNotice, charSet);
- break;
- }
-
- case kCaptionSet:
- {
- ParseString (stream, fDescription, charSet);
- break;
- }
-
- case kCaptionWriterSet:
- {
- ParseString (stream, fDescriptionWriter, charSet);
- break;
- }
-
- // All other IPTC records are not part of the IPTC core
- // and/or are not kept in sync with XMP tags, so we ignore
- // them.
-
- default:
- break;
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_iptc::SpoolString (dng_stream &stream,
- const dng_string &s,
- uint8 dataSet,
- uint32 maxChars,
- CharSet charSet)
- {
-
- if (s.IsEmpty ())
- {
- return;
- }
-
- stream.Put_uint16 (0x1C02);
- stream.Put_uint8 (dataSet);
-
- dng_string ss (s);
-
- ss.SetLineEndingsToReturns ();
-
- if (charSet == kCharSetUTF8)
- {
-
- // UTF-8 encoding.
-
- if (ss.Length () > maxChars)
- {
- ss.Truncate (maxChars);
- }
-
- uint32 len = ss.Length ();
-
- stream.Put_uint16 ((uint16) len);
-
- stream.Put (ss.Get (), len);
-
- }
-
- else
- {
-
- // System character set encoding.
-
- dng_memory_data buffer;
-
- uint32 len = ss.Get_SystemEncoding (buffer);
-
- if (len > maxChars)
- {
-
- uint32 lower = 0;
- uint32 upper = ss.Length () - 1;
-
- while (upper > lower)
- {
-
- uint32 middle = (upper + lower + 1) >> 1;
-
- dng_string sss (ss);
-
- sss.Truncate (middle);
-
- len = sss.Get_SystemEncoding (buffer);
-
- if (len <= maxChars)
- {
-
- lower = middle;
-
- }
-
- else
- {
-
- upper = middle - 1;
-
- }
-
- }
-
- ss.Truncate (lower);
-
- len = ss.Get_SystemEncoding (buffer);
-
- }
-
- stream.Put_uint16 ((uint16) len);
-
- stream.Put (buffer.Buffer_char (), len);
-
- }
-
- }
-/*****************************************************************************/
-
-dng_memory_block * dng_iptc::Spool (dng_memory_allocator &allocator,
- bool padForTIFF)
- {
-
- uint32 j;
-
- char s [64];
-
- dng_memory_stream stream (allocator, NULL, 2048);
-
- stream.SetBigEndian ();
-
- // Medata working group - now we just always write UTF-8.
-
- CharSet charSet = kCharSetUTF8;
-
- // UTF-8 encoding marker.
-
- if (charSet == kCharSetUTF8)
- {
-
- stream.Put_uint16 (0x1C01);
- stream.Put_uint8 (90);
- stream.Put_uint16 (3);
- stream.Put_uint8 (27);
- stream.Put_uint8 (0x25);
- stream.Put_uint8 (0x47);
-
- }
-
- stream.Put_uint16 (0x1C02);
- stream.Put_uint8 (kRecordVersionSet);
- stream.Put_uint16 (2);
- stream.Put_uint16 (4);
-
- SpoolString (stream,
- fTitle,
- kObjectNameSet,
- 64,
- charSet);
-
- if (fUrgency >= 0)
- {
-
- sprintf (s, "%1u", (unsigned) fUrgency);
-
- stream.Put_uint16 (0x1C02);
- stream.Put_uint8 (kUrgencySet);
-
- stream.Put_uint16 (1);
-
- stream.Put (s, 1);
-
- }
-
- SpoolString (stream,
- fCategory,
- kCategorySet,
- 3,
- charSet);
-
- for (j = 0; j < fSupplementalCategories.Count (); j++)
- {
-
- SpoolString (stream,
- fSupplementalCategories [j],
- kSupplementalCategoriesSet,
- 32,
- charSet);
-
- }
-
- for (j = 0; j < fKeywords.Count (); j++)
- {
-
- SpoolString (stream,
- fKeywords [j],
- kKeywordsSet,
- 64,
- charSet);
-
- }
-
- SpoolString (stream,
- fInstructions,
- kSpecialInstructionsSet,
- 255,
- charSet);
-
- if (fDateTimeCreated.IsValid ())
- {
-
- dng_string dateString = fDateTimeCreated.Encode_IPTC_Date ();
-
- if (dateString.NotEmpty ())
- {
-
- DNG_ASSERT (dateString.Length () == 8, "Wrong length IPTC date");
-
- stream.Put_uint16 (0x1C02);
- stream.Put_uint8 (kDateCreatedSet);
-
- stream.Put_uint16 (8);
-
- stream.Put (dateString.Get (), 8);
-
- }
-
- dng_string timeString = fDateTimeCreated.Encode_IPTC_Time ();
-
- if (timeString.NotEmpty ())
- {
-
- stream.Put_uint16 (0x1C02);
- stream.Put_uint8 (kTimeCreatedSet);
-
- stream.Put_uint16 ((uint16)timeString.Length ());
-
- stream.Put (timeString.Get (), timeString.Length ());
-
- }
-
- }
-
- if (fDigitalCreationDateTime.IsValid ())
- {
-
- dng_string dateString = fDigitalCreationDateTime.Encode_IPTC_Date ();
-
- if (dateString.NotEmpty ())
- {
-
- DNG_ASSERT (dateString.Length () == 8, "Wrong length IPTC date");
-
- stream.Put_uint16 (0x1C02);
- stream.Put_uint8 (kDigitalCreationDateSet);
-
- stream.Put_uint16 (8);
-
- stream.Put (dateString.Get (), 8);
-
- }
-
- dng_string timeString = fDigitalCreationDateTime.Encode_IPTC_Time ();
-
- if (timeString.NotEmpty ())
- {
-
- stream.Put_uint16 (0x1C02);
- stream.Put_uint8 (kDigitalCreationTimeSet);
-
- stream.Put_uint16 ((uint16)timeString.Length ());
-
- stream.Put (timeString.Get (), timeString.Length ());
-
- }
-
- }
-
- for (j = 0; j < fAuthors.Count (); j++)
- {
-
- SpoolString (stream,
- fAuthors [j],
- kBylineSet,
- 32,
- charSet);
-
- }
-
- SpoolString (stream,
- fAuthorsPosition,
- kBylineTitleSet,
- 32,
- charSet);
-
- SpoolString (stream,
- fCity,
- kCitySet,
- 32,
- charSet);
-
- SpoolString (stream,
- fLocation,
- kSublocationSet,
- 32,
- charSet);
-
- SpoolString (stream,
- fState,
- kProvinceStateSet,
- 32,
- charSet);
-
- SpoolString (stream,
- fCountryCode,
- kCountryCodeSet,
- 3,
- charSet);
-
- SpoolString (stream,
- fCountry,
- kCountryNameSet,
- 64,
- charSet);
-
- SpoolString (stream,
- fTransmissionReference,
- kOriginalTransmissionReferenceSet,
- 32,
- charSet);
-
- SpoolString (stream,
- fHeadline,
- kHeadlineSet,
- 255,
- charSet);
-
- SpoolString (stream,
- fCredit,
- kCreditSet,
- 32,
- charSet);
-
- SpoolString (stream,
- fSource,
- kSourceSet,
- 32,
- charSet);
-
- SpoolString (stream,
- fCopyrightNotice,
- kCopyrightNoticeSet,
- 128,
- charSet);
-
- SpoolString (stream,
- fDescription,
- kCaptionSet,
- 2000,
- charSet);
-
- SpoolString (stream,
- fDescriptionWriter,
- kCaptionWriterSet,
- 32,
- charSet);
-
- if (padForTIFF)
- {
-
- while (stream.Length () & 3)
- {
- stream.Put_uint8 (0);
- }
-
- }
-
- stream.Flush ();
-
- return stream.AsMemoryBlock (allocator);
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_iptc.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_iptc.h"
+
+#include "dng_assertions.h"
+#include "dng_auto_ptr.h"
+#include "dng_memory_stream.h"
+#include "dng_stream.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_iptc::dng_iptc ()
+
+ : fTitle ()
+
+ , fUrgency (-1)
+
+ , fCategory ()
+
+ , fSupplementalCategories ()
+
+ , fKeywords ()
+
+ , fInstructions ()
+
+ , fDateTimeCreated ()
+
+ , fDigitalCreationDateTime ()
+
+ , fAuthors ()
+ , fAuthorsPosition ()
+
+ , fCity ()
+ , fState ()
+ , fCountry ()
+ , fCountryCode ()
+
+ , fLocation ()
+
+ , fTransmissionReference ()
+
+ , fHeadline ()
+
+ , fCredit ()
+
+ , fSource ()
+
+ , fCopyrightNotice ()
+
+ , fDescription ()
+ , fDescriptionWriter ()
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_iptc::~dng_iptc ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+bool dng_iptc::IsEmpty () const
+ {
+
+ if (fTitle.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fUrgency >= 0)
+ {
+ return false;
+ }
+
+ if (fCategory.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fSupplementalCategories.Count () > 0)
+ {
+ return false;
+ }
+
+ if (fKeywords.Count () > 0)
+ {
+ return false;
+ }
+
+ if (fInstructions.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fDateTimeCreated.IsValid ())
+ {
+ return false;
+ }
+
+ if (fDigitalCreationDateTime.IsValid ())
+ {
+ return false;
+ }
+
+ if (fAuthors.Count () != 0 ||
+ fAuthorsPosition.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fCity .NotEmpty () ||
+ fState .NotEmpty () ||
+ fCountry.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fCountryCode.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fLocation.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fTransmissionReference.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fHeadline.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fCredit.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fSource.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fCopyrightNotice.NotEmpty ())
+ {
+ return false;
+ }
+
+ if (fDescription .NotEmpty () ||
+ fDescriptionWriter.NotEmpty ())
+ {
+ return false;
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+void dng_iptc::ParseString (dng_stream &stream,
+ dng_string &s,
+ CharSet charSet)
+ {
+
+ uint32 length = stream.Get_uint16 ();
+
+ dng_memory_data buffer (length + 1);
+
+ char *c = buffer.Buffer_char ();
+
+ stream.Get (c, length);
+
+ c [length] = 0;
+
+ switch (charSet)
+ {
+
+ case kCharSetUTF8:
+ {
+ s.Set_UTF8 (c);
+ break;
+ }
+
+ default:
+ {
+ s.Set_SystemEncoding (c);
+ }
+
+ }
+
+ s.SetLineEndingsToNewLines ();
+
+ s.StripLowASCII ();
+
+ s.TrimTrailingBlanks ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_iptc::Parse (const void *blockData,
+ uint32 blockSize,
+ uint64 offsetInOriginalFile)
+ {
+
+ dng_stream stream (blockData,
+ blockSize,
+ offsetInOriginalFile);
+
+ stream.SetBigEndian ();
+
+ // Make a first pass though the data, trying to figure out the
+ // character set.
+
+ CharSet charSet = kCharSetUnknown;
+
+ bool isValidUTF8 = true;
+
+ bool hasEncodingMarker = false;
+
+ uint64 firstOffset = stream.Position ();
+
+ uint64 nextOffset = firstOffset;
+
+ while (nextOffset + 5 < stream.Length ())
+ {
+
+ stream.SetReadPosition (nextOffset);
+
+ uint8 firstByte = stream.Get_uint8 ();
+
+ if (firstByte != 0x1C) break;
+
+ uint8 record = stream.Get_uint8 ();
+ uint8 dataSet = stream.Get_uint8 ();
+ uint32 dataSize = stream.Get_uint16 ();
+
+ nextOffset = stream.Position () + dataSize;
+
+ if (record == 1)
+ {
+
+ switch (dataSet)
+ {
+
+ case 90:
+ {
+
+ hasEncodingMarker = true;
+
+ if (dataSize == 3)
+ {
+
+ uint32 byte1 = stream.Get_uint8 ();
+ uint32 byte2 = stream.Get_uint8 ();
+ uint32 byte3 = stream.Get_uint8 ();
+
+ if (byte1 == 27 /* Escape */ &&
+ byte2 == 0x25 &&
+ byte3 == 0x47)
+ {
+
+ charSet = kCharSetUTF8;
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ default:
+ break;
+
+ }
+
+ }
+
+ else if (record == 2)
+ {
+
+ dng_memory_data buffer (dataSize + 1);
+
+ char *s = buffer.Buffer_char ();
+
+ stream.Get (s, dataSize);
+
+ s [dataSize] = 0;
+
+ isValidUTF8 = isValidUTF8 && dng_string::IsUTF8 (s);
+
+ }
+
+ }
+
+ // If we don't have an encoding marker, and the data is valid
+ // UTF-8, then assume that it is UTF-8 (rather than system encoding).
+
+ if (!hasEncodingMarker && isValidUTF8)
+ {
+
+ charSet = kCharSetUTF8;
+
+ }
+
+ // Make a second pass though the data, actually reading the data.
+
+ nextOffset = firstOffset;
+
+ while (nextOffset + 5 < stream.Length ())
+ {
+
+ stream.SetReadPosition (nextOffset);
+
+ uint8 firstByte = stream.Get_uint8 ();
+
+ if (firstByte != 0x1C) break;
+
+ uint8 record = stream.Get_uint8 ();
+ uint8 dataSet = stream.Get_uint8 ();
+ uint32 dataSize = stream.Get_uint16 ();
+
+ nextOffset = stream.Position () + dataSize;
+
+ if (record == 2)
+ {
+
+ stream.SetReadPosition (stream.Position () - 2);
+
+ switch ((DataSet) dataSet)
+ {
+
+ case kObjectNameSet:
+ {
+ ParseString (stream, fTitle, charSet);
+ break;
+ }
+
+ case kUrgencySet:
+ {
+
+ int32 size = stream.Get_uint16 ();
+
+ if (size == 1)
+ {
+
+ char c = stream.Get_int8 ();
+
+ if (c >= '0' && c <= '9')
+ {
+ fUrgency = c - '0';
+ }
+
+ }
+
+ break;
+
+ }
+
+ case kCategorySet:
+ {
+ ParseString (stream, fCategory, charSet);
+ break;
+ }
+
+ case kSupplementalCategoriesSet:
+ {
+
+ dng_string category;
+
+ ParseString (stream, category, charSet);
+
+ if (category.NotEmpty ())
+ {
+ fSupplementalCategories.Append (category);
+ }
+
+ break;
+
+ }
+
+ case kKeywordsSet:
+ {
+
+ dng_string keyword;
+
+ ParseString (stream, keyword, charSet);
+
+ if (keyword.NotEmpty ())
+ {
+ fKeywords.Append (keyword);
+ }
+
+ break;
+
+ }
+
+ case kSpecialInstructionsSet:
+ {
+ ParseString (stream, fInstructions, charSet);
+ break;
+ }
+
+ case kDateCreatedSet:
+ {
+
+ uint32 length = stream.Get_uint16 ();
+
+ if (length == 8)
+ {
+
+ char date [9];
+
+ stream.Get (date, 8);
+
+ date [8] = 0;
+
+ fDateTimeCreated.Decode_IPTC_Date (date);
+
+ }
+
+ break;
+
+ }
+
+ case kTimeCreatedSet:
+ {
+
+ uint32 length = stream.Get_uint16 ();
+
+ if (length >= 4 && length <= 11)
+ {
+
+ char time [12];
+
+ stream.Get (time, length);
+
+ time [length] = 0;
+
+ fDateTimeCreated.Decode_IPTC_Time (time);
+
+ }
+
+ break;
+
+ }
+
+ case kDigitalCreationDateSet:
+ {
+
+ uint32 length = stream.Get_uint16 ();
+
+ if (length == 8)
+ {
+
+ char date [9];
+
+ stream.Get (date, 8);
+
+ date [8] = 0;
+
+ fDigitalCreationDateTime.Decode_IPTC_Date (date);
+
+ }
+
+ break;
+
+ }
+
+ case kDigitalCreationTimeSet:
+ {
+
+ uint32 length = stream.Get_uint16 ();
+
+ if (length >= 4 && length <= 11)
+ {
+
+ char time [12];
+
+ stream.Get (time, length);
+
+ time [length] = 0;
+
+ fDigitalCreationDateTime.Decode_IPTC_Time (time);
+
+ }
+
+ break;
+
+ }
+
+ case kBylineSet:
+ {
+
+ dng_string author;
+
+ ParseString (stream, author, charSet);
+
+ if (author.NotEmpty ())
+ {
+ fAuthors.Append (author);
+ }
+
+ break;
+
+ }
+
+ case kBylineTitleSet:
+ {
+ ParseString (stream, fAuthorsPosition, charSet);
+ break;
+ }
+
+ case kCitySet:
+ {
+ ParseString (stream, fCity, charSet);
+ break;
+ }
+
+ case kProvinceStateSet:
+ {
+ ParseString (stream, fState, charSet);
+ break;
+ }
+
+ case kCountryNameSet:
+ {
+ ParseString (stream, fCountry, charSet);
+ break;
+ }
+
+ case kCountryCodeSet:
+ {
+ ParseString (stream, fCountryCode, charSet);
+ break;
+ }
+
+ case kSublocationSet:
+ {
+ ParseString (stream, fLocation, charSet);
+ break;
+ }
+
+ case kOriginalTransmissionReferenceSet:
+ {
+ ParseString (stream, fTransmissionReference, charSet);
+ break;
+ }
+
+ case kHeadlineSet:
+ {
+ ParseString (stream, fHeadline, charSet);
+ break;
+ }
+
+ case kCreditSet:
+ {
+ ParseString (stream, fCredit, charSet);
+ break;
+ }
+
+ case kSourceSet:
+ {
+ ParseString (stream, fSource, charSet);
+ break;
+ }
+
+ case kCopyrightNoticeSet:
+ {
+ ParseString (stream, fCopyrightNotice, charSet);
+ break;
+ }
+
+ case kCaptionSet:
+ {
+ ParseString (stream, fDescription, charSet);
+ break;
+ }
+
+ case kCaptionWriterSet:
+ {
+ ParseString (stream, fDescriptionWriter, charSet);
+ break;
+ }
+
+ // All other IPTC records are not part of the IPTC core
+ // and/or are not kept in sync with XMP tags, so we ignore
+ // them.
+
+ default:
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_iptc::SpoolString (dng_stream &stream,
+ const dng_string &s,
+ uint8 dataSet,
+ uint32 maxChars,
+ CharSet charSet)
+ {
+
+ if (s.IsEmpty ())
+ {
+ return;
+ }
+
+ stream.Put_uint16 (0x1C02);
+ stream.Put_uint8 (dataSet);
+
+ dng_string ss (s);
+
+ ss.SetLineEndingsToReturns ();
+
+ if (charSet == kCharSetUTF8)
+ {
+
+ // UTF-8 encoding.
+
+ if (ss.Length () > maxChars)
+ {
+ ss.Truncate (maxChars);
+ }
+
+ uint32 len = ss.Length ();
+
+ stream.Put_uint16 ((uint16) len);
+
+ stream.Put (ss.Get (), len);
+
+ }
+
+ else
+ {
+
+ // System character set encoding.
+
+ dng_memory_data buffer;
+
+ uint32 len = ss.Get_SystemEncoding (buffer);
+
+ if (len > maxChars)
+ {
+
+ uint32 lower = 0;
+ uint32 upper = ss.Length () - 1;
+
+ while (upper > lower)
+ {
+
+ uint32 middle = (upper + lower + 1) >> 1;
+
+ dng_string sss (ss);
+
+ sss.Truncate (middle);
+
+ len = sss.Get_SystemEncoding (buffer);
+
+ if (len <= maxChars)
+ {
+
+ lower = middle;
+
+ }
+
+ else
+ {
+
+ upper = middle - 1;
+
+ }
+
+ }
+
+ ss.Truncate (lower);
+
+ len = ss.Get_SystemEncoding (buffer);
+
+ }
+
+ stream.Put_uint16 ((uint16) len);
+
+ stream.Put (buffer.Buffer_char (), len);
+
+ }
+
+ }
+/*****************************************************************************/
+
+dng_memory_block * dng_iptc::Spool (dng_memory_allocator &allocator,
+ bool padForTIFF)
+ {
+
+ uint32 j;
+
+ char s [64];
+
+ dng_memory_stream stream (allocator, NULL, 2048);
+
+ stream.SetBigEndian ();
+
+ // Medata working group - now we just always write UTF-8.
+
+ CharSet charSet = kCharSetUTF8;
+
+ // UTF-8 encoding marker.
+
+ if (charSet == kCharSetUTF8)
+ {
+
+ stream.Put_uint16 (0x1C01);
+ stream.Put_uint8 (90);
+ stream.Put_uint16 (3);
+ stream.Put_uint8 (27);
+ stream.Put_uint8 (0x25);
+ stream.Put_uint8 (0x47);
+
+ }
+
+ stream.Put_uint16 (0x1C02);
+ stream.Put_uint8 (kRecordVersionSet);
+ stream.Put_uint16 (2);
+ stream.Put_uint16 (4);
+
+ SpoolString (stream,
+ fTitle,
+ kObjectNameSet,
+ 64,
+ charSet);
+
+ if (fUrgency >= 0)
+ {
+
+ sprintf (s, "%1u", (unsigned) fUrgency);
+
+ stream.Put_uint16 (0x1C02);
+ stream.Put_uint8 (kUrgencySet);
+
+ stream.Put_uint16 (1);
+
+ stream.Put (s, 1);
+
+ }
+
+ SpoolString (stream,
+ fCategory,
+ kCategorySet,
+ 3,
+ charSet);
+
+ for (j = 0; j < fSupplementalCategories.Count (); j++)
+ {
+
+ SpoolString (stream,
+ fSupplementalCategories [j],
+ kSupplementalCategoriesSet,
+ 32,
+ charSet);
+
+ }
+
+ for (j = 0; j < fKeywords.Count (); j++)
+ {
+
+ SpoolString (stream,
+ fKeywords [j],
+ kKeywordsSet,
+ 64,
+ charSet);
+
+ }
+
+ SpoolString (stream,
+ fInstructions,
+ kSpecialInstructionsSet,
+ 255,
+ charSet);
+
+ if (fDateTimeCreated.IsValid ())
+ {
+
+ dng_string dateString = fDateTimeCreated.Encode_IPTC_Date ();
+
+ if (dateString.NotEmpty ())
+ {
+
+ DNG_ASSERT (dateString.Length () == 8, "Wrong length IPTC date");
+
+ stream.Put_uint16 (0x1C02);
+ stream.Put_uint8 (kDateCreatedSet);
+
+ stream.Put_uint16 (8);
+
+ stream.Put (dateString.Get (), 8);
+
+ }
+
+ dng_string timeString = fDateTimeCreated.Encode_IPTC_Time ();
+
+ if (timeString.NotEmpty ())
+ {
+
+ stream.Put_uint16 (0x1C02);
+ stream.Put_uint8 (kTimeCreatedSet);
+
+ stream.Put_uint16 ((uint16)timeString.Length ());
+
+ stream.Put (timeString.Get (), timeString.Length ());
+
+ }
+
+ }
+
+ if (fDigitalCreationDateTime.IsValid ())
+ {
+
+ dng_string dateString = fDigitalCreationDateTime.Encode_IPTC_Date ();
+
+ if (dateString.NotEmpty ())
+ {
+
+ DNG_ASSERT (dateString.Length () == 8, "Wrong length IPTC date");
+
+ stream.Put_uint16 (0x1C02);
+ stream.Put_uint8 (kDigitalCreationDateSet);
+
+ stream.Put_uint16 (8);
+
+ stream.Put (dateString.Get (), 8);
+
+ }
+
+ dng_string timeString = fDigitalCreationDateTime.Encode_IPTC_Time ();
+
+ if (timeString.NotEmpty ())
+ {
+
+ stream.Put_uint16 (0x1C02);
+ stream.Put_uint8 (kDigitalCreationTimeSet);
+
+ stream.Put_uint16 ((uint16)timeString.Length ());
+
+ stream.Put (timeString.Get (), timeString.Length ());
+
+ }
+
+ }
+
+ for (j = 0; j < fAuthors.Count (); j++)
+ {
+
+ SpoolString (stream,
+ fAuthors [j],
+ kBylineSet,
+ 32,
+ charSet);
+
+ }
+
+ SpoolString (stream,
+ fAuthorsPosition,
+ kBylineTitleSet,
+ 32,
+ charSet);
+
+ SpoolString (stream,
+ fCity,
+ kCitySet,
+ 32,
+ charSet);
+
+ SpoolString (stream,
+ fLocation,
+ kSublocationSet,
+ 32,
+ charSet);
+
+ SpoolString (stream,
+ fState,
+ kProvinceStateSet,
+ 32,
+ charSet);
+
+ SpoolString (stream,
+ fCountryCode,
+ kCountryCodeSet,
+ 3,
+ charSet);
+
+ SpoolString (stream,
+ fCountry,
+ kCountryNameSet,
+ 64,
+ charSet);
+
+ SpoolString (stream,
+ fTransmissionReference,
+ kOriginalTransmissionReferenceSet,
+ 32,
+ charSet);
+
+ SpoolString (stream,
+ fHeadline,
+ kHeadlineSet,
+ 255,
+ charSet);
+
+ SpoolString (stream,
+ fCredit,
+ kCreditSet,
+ 32,
+ charSet);
+
+ SpoolString (stream,
+ fSource,
+ kSourceSet,
+ 32,
+ charSet);
+
+ SpoolString (stream,
+ fCopyrightNotice,
+ kCopyrightNoticeSet,
+ 128,
+ charSet);
+
+ SpoolString (stream,
+ fDescription,
+ kCaptionSet,
+ 2000,
+ charSet);
+
+ SpoolString (stream,
+ fDescriptionWriter,
+ kCaptionWriterSet,
+ 32,
+ charSet);
+
+ if (padForTIFF)
+ {
+
+ while (stream.Length () & 3)
+ {
+ stream.Put_uint8 (0);
+ }
+
+ }
+
+ stream.Flush ();
+
+ return stream.AsMemoryBlock (allocator);
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_iptc.h b/source/dng_iptc.h
index 82ebaeb..3fcec27 100644
--- a/source/dng_iptc.h
+++ b/source/dng_iptc.h
@@ -1,172 +1,172 @@
-/*****************************************************************************/
-// Copyright 2006-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_iptc.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Support for IPTC metadata within DNG files.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_iptc__
-#define __dng_iptc__
-
-/*****************************************************************************/
-
-#include "dng_date_time.h"
-#include "dng_string.h"
-#include "dng_string_list.h"
-
-/*****************************************************************************/
-
-/// \brief Class for reading and holding IPTC metadata associated with a DNG file.
-///
-/// See the \ref spec_iptc "IPTC specification"
-/// for information on member fields of this class.
-
-class dng_iptc
- {
-
- public:
-
- dng_string fTitle;
-
- int32 fUrgency;
-
- dng_string fCategory;
-
- dng_string_list fSupplementalCategories;
-
- dng_string_list fKeywords;
-
- dng_string fInstructions;
-
- dng_date_time_info fDateTimeCreated;
-
- dng_date_time_info fDigitalCreationDateTime;
-
- dng_string_list fAuthors;
-
- dng_string fAuthorsPosition;
-
- dng_string fCity;
- dng_string fState;
- dng_string fCountry;
- dng_string fCountryCode;
-
- dng_string fLocation;
-
- dng_string fTransmissionReference;
-
- dng_string fHeadline;
-
- dng_string fCredit;
-
- dng_string fSource;
-
- dng_string fCopyrightNotice;
-
- dng_string fDescription;
- dng_string fDescriptionWriter;
-
- protected:
-
- enum DataSet
- {
- kRecordVersionSet = 0,
- kObjectNameSet = 5,
- kUrgencySet = 10,
- kCategorySet = 15,
- kSupplementalCategoriesSet = 20,
- kKeywordsSet = 25,
- kSpecialInstructionsSet = 40,
- kDateCreatedSet = 55,
- kTimeCreatedSet = 60,
- kDigitalCreationDateSet = 62,
- kDigitalCreationTimeSet = 63,
- kBylineSet = 80,
- kBylineTitleSet = 85,
- kCitySet = 90,
- kSublocationSet = 92,
- kProvinceStateSet = 95,
- kCountryCodeSet = 100,
- kCountryNameSet = 101,
- kOriginalTransmissionReferenceSet = 103,
- kHeadlineSet = 105,
- kCreditSet = 110,
- kSourceSet = 115,
- kCopyrightNoticeSet = 116,
- kCaptionSet = 120,
- kCaptionWriterSet = 122
- };
-
- enum CharSet
- {
- kCharSetUnknown = 0,
- kCharSetUTF8 = 1
- };
-
- public:
-
- dng_iptc ();
-
- virtual ~dng_iptc ();
-
- /// Test if IPTC metadata exists.
- /// \retval true if no IPTC metadata exists for this DNG.
-
- bool IsEmpty () const;
-
- /// Test if IPTC metadata exists.
- /// \retval true if IPTC metadata exists for this DNG.
-
- bool NotEmpty () const
- {
- return !IsEmpty ();
- }
-
- /// Parse a complete block of IPTC data.
- /// \param blockData The block of IPTC data.
- /// \param blockSize Size in bytes of data block.
- /// \param offsetInOriginalFile Used to enable certain file patching operations such as updating date/time in place.
-
- void Parse (const void *blockData,
- uint32 blockSize,
- uint64 offsetInOriginalFile);
-
- /// Serialize IPTC data to a memory block.
- /// \param allocator Memory allocator used to acquire memory block.
- /// \param padForTIFF Forces length of block to be a multiple of four bytes in accordance with TIFF standard.
- /// \retval Memory block
-
- dng_memory_block * Spool (dng_memory_allocator &allocator,
- bool padForTIFF);
-
- protected:
-
- void ParseString (dng_stream &stream,
- dng_string &s,
- CharSet charSet);
-
- void SpoolString (dng_stream &stream,
- const dng_string &s,
- uint8 dataSet,
- uint32 maxChars,
- CharSet charSet);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_iptc.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Support for IPTC metadata within DNG files.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_iptc__
+#define __dng_iptc__
+
+/*****************************************************************************/
+
+#include "dng_date_time.h"
+#include "dng_string.h"
+#include "dng_string_list.h"
+
+/*****************************************************************************/
+
+/// \brief Class for reading and holding IPTC metadata associated with a DNG file.
+///
+/// See the \ref spec_iptc "IPTC specification"
+/// for information on member fields of this class.
+
+class dng_iptc
+ {
+
+ public:
+
+ dng_string fTitle;
+
+ int32 fUrgency;
+
+ dng_string fCategory;
+
+ dng_string_list fSupplementalCategories;
+
+ dng_string_list fKeywords;
+
+ dng_string fInstructions;
+
+ dng_date_time_info fDateTimeCreated;
+
+ dng_date_time_info fDigitalCreationDateTime;
+
+ dng_string_list fAuthors;
+
+ dng_string fAuthorsPosition;
+
+ dng_string fCity;
+ dng_string fState;
+ dng_string fCountry;
+ dng_string fCountryCode;
+
+ dng_string fLocation;
+
+ dng_string fTransmissionReference;
+
+ dng_string fHeadline;
+
+ dng_string fCredit;
+
+ dng_string fSource;
+
+ dng_string fCopyrightNotice;
+
+ dng_string fDescription;
+ dng_string fDescriptionWriter;
+
+ protected:
+
+ enum DataSet
+ {
+ kRecordVersionSet = 0,
+ kObjectNameSet = 5,
+ kUrgencySet = 10,
+ kCategorySet = 15,
+ kSupplementalCategoriesSet = 20,
+ kKeywordsSet = 25,
+ kSpecialInstructionsSet = 40,
+ kDateCreatedSet = 55,
+ kTimeCreatedSet = 60,
+ kDigitalCreationDateSet = 62,
+ kDigitalCreationTimeSet = 63,
+ kBylineSet = 80,
+ kBylineTitleSet = 85,
+ kCitySet = 90,
+ kSublocationSet = 92,
+ kProvinceStateSet = 95,
+ kCountryCodeSet = 100,
+ kCountryNameSet = 101,
+ kOriginalTransmissionReferenceSet = 103,
+ kHeadlineSet = 105,
+ kCreditSet = 110,
+ kSourceSet = 115,
+ kCopyrightNoticeSet = 116,
+ kCaptionSet = 120,
+ kCaptionWriterSet = 122
+ };
+
+ enum CharSet
+ {
+ kCharSetUnknown = 0,
+ kCharSetUTF8 = 1
+ };
+
+ public:
+
+ dng_iptc ();
+
+ virtual ~dng_iptc ();
+
+ /// Test if IPTC metadata exists.
+ /// \retval true if no IPTC metadata exists for this DNG.
+
+ bool IsEmpty () const;
+
+ /// Test if IPTC metadata exists.
+ /// \retval true if IPTC metadata exists for this DNG.
+
+ bool NotEmpty () const
+ {
+ return !IsEmpty ();
+ }
+
+ /// Parse a complete block of IPTC data.
+ /// \param blockData The block of IPTC data.
+ /// \param blockSize Size in bytes of data block.
+ /// \param offsetInOriginalFile Used to enable certain file patching operations such as updating date/time in place.
+
+ void Parse (const void *blockData,
+ uint32 blockSize,
+ uint64 offsetInOriginalFile);
+
+ /// Serialize IPTC data to a memory block.
+ /// \param allocator Memory allocator used to acquire memory block.
+ /// \param padForTIFF Forces length of block to be a multiple of four bytes in accordance with TIFF standard.
+ /// \retval Memory block
+
+ dng_memory_block * Spool (dng_memory_allocator &allocator,
+ bool padForTIFF);
+
+ protected:
+
+ void ParseString (dng_stream &stream,
+ dng_string &s,
+ CharSet charSet);
+
+ void SpoolString (dng_stream &stream,
+ const dng_string &s,
+ uint8 dataSet,
+ uint32 maxChars,
+ CharSet charSet);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_jpeg_image.h b/source/dng_jpeg_image.h
index 01748bb..0bfc90b 100644
--- a/source/dng_jpeg_image.h
+++ b/source/dng_jpeg_image.h
@@ -1,92 +1,92 @@
-/*****************************************************************************/
-// Copyright 2011 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_jpeg_image.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_jpeg_image__
-#define __dng_jpeg_image__
-
-/*****************************************************************************/
-
-#include "dng_auto_ptr.h"
-#include "dng_memory.h"
-#include "dng_point.h"
-
-/*****************************************************************************/
-
-typedef AutoPtr<dng_memory_block> dng_jpeg_image_tile_ptr;
-
-/*****************************************************************************/
-
-class dng_jpeg_image
- {
-
- public:
-
- dng_point fImageSize;
-
- dng_point fTileSize;
-
- bool fUsesStrips;
-
- AutoPtr<dng_memory_block> fJPEGTables;
-
- AutoArray<dng_jpeg_image_tile_ptr> fJPEGData;
-
- public:
-
- dng_jpeg_image ();
-
- uint32 TilesAcross () const
- {
- if (fTileSize.h)
- {
- return (fImageSize.h + fTileSize.h - 1) / fTileSize.h;
- }
- else
- {
- return 0;
- }
- }
-
- uint32 TilesDown () const
- {
- if (fTileSize.v)
- {
- return (fImageSize.v + fTileSize.v - 1) / fTileSize.v;
- }
- else
- {
- return 0;
- }
- }
-
- uint32 TileCount () const
- {
- return TilesAcross () * TilesDown ();
- }
-
- void Encode (dng_host &host,
- const dng_negative &negative,
- dng_image_writer &writer,
- const dng_image &image);
-
- dng_fingerprint FindDigest (dng_host &host) const;
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2011 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_jpeg_image.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_jpeg_image__
+#define __dng_jpeg_image__
+
+/*****************************************************************************/
+
+#include "dng_auto_ptr.h"
+#include "dng_memory.h"
+#include "dng_point.h"
+
+/*****************************************************************************/
+
+typedef AutoPtr<dng_memory_block> dng_jpeg_image_tile_ptr;
+
+/*****************************************************************************/
+
+class dng_jpeg_image
+ {
+
+ public:
+
+ dng_point fImageSize;
+
+ dng_point fTileSize;
+
+ bool fUsesStrips;
+
+ AutoPtr<dng_memory_block> fJPEGTables;
+
+ AutoArray<dng_jpeg_image_tile_ptr> fJPEGData;
+
+ public:
+
+ dng_jpeg_image ();
+
+ uint32 TilesAcross () const
+ {
+ if (fTileSize.h)
+ {
+ return (fImageSize.h + fTileSize.h - 1) / fTileSize.h;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ uint32 TilesDown () const
+ {
+ if (fTileSize.v)
+ {
+ return (fImageSize.v + fTileSize.v - 1) / fTileSize.v;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+ uint32 TileCount () const
+ {
+ return TilesAcross () * TilesDown ();
+ }
+
+ void Encode (dng_host &host,
+ const dng_negative &negative,
+ dng_image_writer &writer,
+ const dng_image &image);
+
+ dng_fingerprint FindDigest (dng_host &host) const;
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_lens_correction.h b/source/dng_lens_correction.h
index 9035236..565de4f 100644
--- a/source/dng_lens_correction.h
+++ b/source/dng_lens_correction.h
@@ -1,639 +1,639 @@
-/*****************************************************************************/
-// 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 &params,
- 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 &params,
- 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> &params,
- const dng_point_real64 &center);
-
- 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 &params,
- 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
-
-/*****************************************************************************/
+/*****************************************************************************/
+// 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 &params,
+ 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 &params,
+ 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> &params,
+ const dng_point_real64 &center);
+
+ 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 &params,
+ 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
+
+/*****************************************************************************/
diff --git a/source/dng_linearization_info.h b/source/dng_linearization_info.h
index 510cf11..32137b5 100644
--- a/source/dng_linearization_info.h
+++ b/source/dng_linearization_info.h
@@ -1,164 +1,164 @@
-/*****************************************************************************/
-// Copyright 2006-2011 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_linearization_info.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Support for linearization table and black level tags.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_linearization_info__
-#define __dng_linearization_info__
-
-/*****************************************************************************/
-
-#include "dng_auto_ptr.h"
-#include "dng_classes.h"
-#include "dng_memory.h"
-#include "dng_rational.h"
-#include "dng_rect.h"
-#include "dng_sdk_limits.h"
-
-/*****************************************************************************/
-
-/// \brief Class for managing data values related to DNG linearization.
-///
-/// See LinearizationTable, BlackLevel, BlackLevelRepeatDim, BlackLevelDeltaH,
-/// BlackLevelDeltaV and WhiteLevel tags in the \ref spec_dng "DNG 1.1.0 specification".
-
-class dng_linearization_info
- {
-
- public:
-
- /// This rectangle defines the active (non-masked) pixels of the sensor.
- /// The order of the rectangle coordinates is: top, left, bottom, right.
-
- dng_rect fActiveArea;
-
- /// Number of rectangles in fMaskedArea
-
- uint32 fMaskedAreaCount;
-
- /// List of non-overlapping rectangle coordinates of fully masked pixels.
- /// Can be optionally used by DNG readers to measure the black encoding level.
- /// The order of each rectangle's coordinates is: top, left, bottom, right.
- /// If the raw image data has already had its black encoding level subtracted, then this tag should
- /// not be used, since the masked pixels are no longer useful.
- /// Note that DNG writers are still required to include an estimate and store the black encoding level
- /// using the black level DNG tags. Support for the MaskedAreas tag is not required of DNG
- /// readers.
-
- dng_rect fMaskedArea [kMaxMaskedAreas];
-
- /// A lookup table that maps stored values into linear values.
- /// This tag is typically used to increase compression ratios by storing the raw data in a non-linear, more
- /// visually uniform space with fewer total encoding levels.
- /// If SamplesPerPixel is not equal to one, e.g. Fuji S3 type sensor, this single table applies to all the samples for each
- /// pixel.
-
- AutoPtr<dng_memory_block> fLinearizationTable;
-
- /// Actual number of rows in fBlackLevel pattern
-
- uint32 fBlackLevelRepeatRows;
-
- /// Actual number of columns in fBlackLevel pattern
-
- uint32 fBlackLevelRepeatCols;
-
- /// Repeating pattern of black level deltas fBlackLevelRepeatRows by fBlackLevelRepeatCols in size.
-
- real64 fBlackLevel [kMaxBlackPattern] [kMaxBlackPattern] [kMaxSamplesPerPixel];
-
- /// Memory block of double-precision floating point deltas between baseline black level and a given column's black level
-
- AutoPtr<dng_memory_block> fBlackDeltaH;
-
- /// Memory block of double-precision floating point deltas between baseline black level and a given row's black level
-
- AutoPtr<dng_memory_block> fBlackDeltaV;
-
- /// Single white level (maximum sensor value) for each sample plane.
-
- real64 fWhiteLevel [kMaxSamplesPerPixel];
-
- protected:
-
- int32 fBlackDenom;
-
- public:
-
- dng_linearization_info ();
-
- virtual ~dng_linearization_info ();
-
- void RoundBlacks ();
-
- virtual void Parse (dng_host &host,
- dng_stream &stream,
- dng_info &info);
-
- virtual void PostParse (dng_host &host,
- dng_negative &negative);
-
- /// Compute the maximum black level for a given sample plane taking into account base
- /// black level, repeated black level patter, and row/column delta maps.
-
- real64 MaxBlackLevel (uint32 plane) const;
-
- /// Convert raw data from in-file format to a true linear image using linearization data from DNG.
- /// \param host Used to allocate buffers, check for aborts, and post progress updates.
- /// \param srcImage Input pre-linearization RAW samples.
- /// \param dstImage Output linearized image.
-
- virtual void Linearize (dng_host &host,
- const dng_image &srcImage,
- dng_image &dstImage);
-
- /// Compute black level for one coordinate and sample plane in the image.
- /// \param row Row to compute black level for.
- /// \param col Column to compute black level for.
- /// \param plane Sample plane to compute black level for.
-
- dng_urational BlackLevel (uint32 row,
- uint32 col,
- uint32 plane) const;
-
- /// Number of per-row black level deltas in fBlackDeltaV.
-
- uint32 RowBlackCount () const;
-
- /// Lookup black level delta for a given row.
- /// \param row Row to get black level for.
- /// \retval black level for indicated row.
-
- dng_srational RowBlack (uint32 row) const;
-
- /// Number of per-column black level deltas in fBlackDeltaV.
-
- uint32 ColumnBlackCount () const;
-
- /// Lookup black level delta for a given column.
- /// \param col Column to get black level for.
- /// \retval black level for indicated column.
-
- dng_srational ColumnBlack (uint32 col) const;
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2011 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_linearization_info.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Support for linearization table and black level tags.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_linearization_info__
+#define __dng_linearization_info__
+
+/*****************************************************************************/
+
+#include "dng_auto_ptr.h"
+#include "dng_classes.h"
+#include "dng_memory.h"
+#include "dng_rational.h"
+#include "dng_rect.h"
+#include "dng_sdk_limits.h"
+
+/*****************************************************************************/
+
+/// \brief Class for managing data values related to DNG linearization.
+///
+/// See LinearizationTable, BlackLevel, BlackLevelRepeatDim, BlackLevelDeltaH,
+/// BlackLevelDeltaV and WhiteLevel tags in the \ref spec_dng "DNG 1.1.0 specification".
+
+class dng_linearization_info
+ {
+
+ public:
+
+ /// This rectangle defines the active (non-masked) pixels of the sensor.
+ /// The order of the rectangle coordinates is: top, left, bottom, right.
+
+ dng_rect fActiveArea;
+
+ /// Number of rectangles in fMaskedArea
+
+ uint32 fMaskedAreaCount;
+
+ /// List of non-overlapping rectangle coordinates of fully masked pixels.
+ /// Can be optionally used by DNG readers to measure the black encoding level.
+ /// The order of each rectangle's coordinates is: top, left, bottom, right.
+ /// If the raw image data has already had its black encoding level subtracted, then this tag should
+ /// not be used, since the masked pixels are no longer useful.
+ /// Note that DNG writers are still required to include an estimate and store the black encoding level
+ /// using the black level DNG tags. Support for the MaskedAreas tag is not required of DNG
+ /// readers.
+
+ dng_rect fMaskedArea [kMaxMaskedAreas];
+
+ /// A lookup table that maps stored values into linear values.
+ /// This tag is typically used to increase compression ratios by storing the raw data in a non-linear, more
+ /// visually uniform space with fewer total encoding levels.
+ /// If SamplesPerPixel is not equal to one, e.g. Fuji S3 type sensor, this single table applies to all the samples for each
+ /// pixel.
+
+ AutoPtr<dng_memory_block> fLinearizationTable;
+
+ /// Actual number of rows in fBlackLevel pattern
+
+ uint32 fBlackLevelRepeatRows;
+
+ /// Actual number of columns in fBlackLevel pattern
+
+ uint32 fBlackLevelRepeatCols;
+
+ /// Repeating pattern of black level deltas fBlackLevelRepeatRows by fBlackLevelRepeatCols in size.
+
+ real64 fBlackLevel [kMaxBlackPattern] [kMaxBlackPattern] [kMaxSamplesPerPixel];
+
+ /// Memory block of double-precision floating point deltas between baseline black level and a given column's black level
+
+ AutoPtr<dng_memory_block> fBlackDeltaH;
+
+ /// Memory block of double-precision floating point deltas between baseline black level and a given row's black level
+
+ AutoPtr<dng_memory_block> fBlackDeltaV;
+
+ /// Single white level (maximum sensor value) for each sample plane.
+
+ real64 fWhiteLevel [kMaxSamplesPerPixel];
+
+ protected:
+
+ int32 fBlackDenom;
+
+ public:
+
+ dng_linearization_info ();
+
+ virtual ~dng_linearization_info ();
+
+ void RoundBlacks ();
+
+ virtual void Parse (dng_host &host,
+ dng_stream &stream,
+ dng_info &info);
+
+ virtual void PostParse (dng_host &host,
+ dng_negative &negative);
+
+ /// Compute the maximum black level for a given sample plane taking into account base
+ /// black level, repeated black level patter, and row/column delta maps.
+
+ real64 MaxBlackLevel (uint32 plane) const;
+
+ /// Convert raw data from in-file format to a true linear image using linearization data from DNG.
+ /// \param host Used to allocate buffers, check for aborts, and post progress updates.
+ /// \param srcImage Input pre-linearization RAW samples.
+ /// \param dstImage Output linearized image.
+
+ virtual void Linearize (dng_host &host,
+ const dng_image &srcImage,
+ dng_image &dstImage);
+
+ /// Compute black level for one coordinate and sample plane in the image.
+ /// \param row Row to compute black level for.
+ /// \param col Column to compute black level for.
+ /// \param plane Sample plane to compute black level for.
+
+ dng_urational BlackLevel (uint32 row,
+ uint32 col,
+ uint32 plane) const;
+
+ /// Number of per-row black level deltas in fBlackDeltaV.
+
+ uint32 RowBlackCount () const;
+
+ /// Lookup black level delta for a given row.
+ /// \param row Row to get black level for.
+ /// \retval black level for indicated row.
+
+ dng_srational RowBlack (uint32 row) const;
+
+ /// Number of per-column black level deltas in fBlackDeltaV.
+
+ uint32 ColumnBlackCount () const;
+
+ /// Lookup black level delta for a given column.
+ /// \param col Column to get black level for.
+ /// \retval black level for indicated column.
+
+ dng_srational ColumnBlack (uint32 col) const;
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_lossless_jpeg.cpp b/source/dng_lossless_jpeg.cpp
index eb61689..9257f88 100644
--- a/source/dng_lossless_jpeg.cpp
+++ b/source/dng_lossless_jpeg.cpp
@@ -1,3778 +1,3778 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_lossless_jpeg.cpp#2 $ */
-/* $DateTime: 2012/06/01 07:28:57 $ */
-/* $Change: 832715 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-// Lossless JPEG code adapted from:
-
-/* Copyright (C) 1991, 1992, Thomas G. Lane.
- * Part of the Independent JPEG Group's software.
- * See the file Copyright for more details.
- *
- * Copyright (c) 1993 Brian C. Smith, The Regents of the University
- * of California
- * All rights reserved.
- *
- * Copyright (c) 1994 Kongji Huang and Brian C. Smith.
- * Cornell University
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose, without fee, and without written agreement is
- * hereby granted, provided that the above copyright notice and the following
- * two paragraphs appear in all copies of this software.
- *
- * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
- * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-/*****************************************************************************/
-
-#include "dng_lossless_jpeg.h"
-
-#include "dng_assertions.h"
-#include "dng_exceptions.h"
-#include "dng_memory.h"
-#include "dng_stream.h"
-#include "dng_tag_codes.h"
-
-/*****************************************************************************/
-
-// This module contains routines that should be as fast as possible, even
-// at the expense of slight code size increases.
-
-#include "dng_fast_module.h"
-
-/*****************************************************************************/
-
-// The qSupportCanon_sRAW stuff not actually required for DNG support, but
-// only included to allow this code to be used on Canon sRAW files.
-
-#ifndef qSupportCanon_sRAW
-#define qSupportCanon_sRAW 1
-#endif
-
-// The qSupportHasselblad_3FR stuff not actually required for DNG support, but
-// only included to allow this code to be used on Hasselblad 3FR files.
-
-#ifndef qSupportHasselblad_3FR
-#define qSupportHasselblad_3FR 1
-#endif
-
-/*****************************************************************************/
-
-/*
- * One of the following structures is created for each huffman coding
- * table. We use the same structure for encoding and decoding, so there
- * may be some extra fields for encoding that aren't used in the decoding
- * and vice-versa.
- */
-
-struct HuffmanTable
- {
-
- /*
- * These two fields directly represent the contents of a JPEG DHT
- * marker
- */
- uint8 bits[17];
- uint8 huffval[256];
-
- /*
- * The remaining fields are computed from the above to allow more
- * efficient coding and decoding. These fields should be considered
- * private to the Huffman compression & decompression modules.
- */
-
- uint16 mincode[17];
- int32 maxcode[18];
- int16 valptr[17];
- int32 numbits[256];
- int32 value[256];
-
- uint16 ehufco[256];
- int8 ehufsi[256];
-
- };
-
-/*****************************************************************************/
-
-// Computes the derived fields in the Huffman table structure.
-
-static void FixHuffTbl (HuffmanTable *htbl)
- {
-
- int32 l;
- int32 i;
-
- const uint32 bitMask [] =
- {
- 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff,
- 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
- 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
- 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
- 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
- 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
- 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
- 0x0000000f, 0x00000007, 0x00000003, 0x00000001
- };
-
- // Figure C.1: make table of Huffman code length for each symbol
- // Note that this is in code-length order.
-
- int8 huffsize [257];
-
- int32 p = 0;
-
- for (l = 1; l <= 16; l++)
- {
-
- for (i = 1; i <= (int32) htbl->bits [l]; i++)
- huffsize [p++] = (int8) l;
-
- }
-
- huffsize [p] = 0;
-
- int32 lastp = p;
-
- // Figure C.2: generate the codes themselves
- // Note that this is in code-length order.
-
- uint16 huffcode [257];
-
- uint16 code = 0;
-
- int32 si = huffsize [0];
-
- p = 0;
-
- while (huffsize [p])
- {
-
- while (((int32) huffsize [p]) == si)
- {
- huffcode [p++] = code;
- code++;
- }
-
- code <<= 1;
-
- si++;
-
- }
-
- // Figure C.3: generate encoding tables
- // These are code and size indexed by symbol value
- // Set any codeless symbols to have code length 0; this allows
- // EmitBits to detect any attempt to emit such symbols.
-
- memset (htbl->ehufsi, 0, sizeof (htbl->ehufsi));
-
- for (p = 0; p < lastp; p++)
- {
-
- htbl->ehufco [htbl->huffval [p]] = huffcode [p];
- htbl->ehufsi [htbl->huffval [p]] = huffsize [p];
-
- }
-
- // Figure F.15: generate decoding tables
-
- p = 0;
-
- for (l = 1; l <= 16; l++)
- {
-
- if (htbl->bits [l])
- {
-
- htbl->valptr [l] = (int16) p;
- htbl->mincode [l] = huffcode [p];
-
- p += htbl->bits [l];
-
- htbl->maxcode [l] = huffcode [p - 1];
-
- }
-
- else
- {
- htbl->maxcode [l] = -1;
- }
-
- }
-
- // We put in this value to ensure HuffDecode terminates.
-
- htbl->maxcode[17] = 0xFFFFFL;
-
- // Build the numbits, value lookup tables.
- // These table allow us to gather 8 bits from the bits stream,
- // and immediately lookup the size and value of the huffman codes.
- // If size is zero, it means that more than 8 bits are in the huffman
- // code (this happens about 3-4% of the time).
-
- memset (htbl->numbits, 0, sizeof (htbl->numbits));
-
- for (p = 0; p < lastp; p++)
- {
-
- int32 size = huffsize [p];
-
- if (size <= 8)
- {
-
- int32 value = htbl->huffval [p];
-
- code = huffcode [p];
-
- int32 ll = code << (8 -size);
-
- int32 ul = (size < 8 ? ll | bitMask [24 + size]
- : ll);
- if (ul >= static_cast<int32>(sizeof(htbl->numbits) / sizeof(htbl->numbits[0])) ||
- ul >= static_cast<int32>(sizeof(htbl->value) / sizeof(htbl->value[0])))
- {
- ThrowBadFormat ();
- }
-
- for (i = ll; i <= ul; i++)
- {
- htbl->numbits [i] = size;
- htbl->value [i] = value;
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- * The following structure stores basic information about one component.
- */
-
-struct JpegComponentInfo
- {
-
- /*
- * These values are fixed over the whole image.
- * They are read from the SOF marker.
- */
- int16 componentId; /* identifier for this component (0..255) */
- int16 componentIndex; /* its index in SOF or cPtr->compInfo[] */
-
- /*
- * Downsampling is not normally used in lossless JPEG, although
- * it is permitted by the JPEG standard (DIS). We set all sampling
- * factors to 1 in this program.
- */
- int16 hSampFactor; /* horizontal sampling factor */
- int16 vSampFactor; /* vertical sampling factor */
-
- /*
- * Huffman table selector (0..3). The value may vary
- * between scans. It is read from the SOS marker.
- */
- int16 dcTblNo;
-
- };
-
-/*
- * One of the following structures is used to pass around the
- * decompression information.
- */
-
-struct DecompressInfo
- {
-
- /*
- * Image width, height, and image data precision (bits/sample)
- * These fields are set by ReadFileHeader or ReadScanHeader
- */
- int32 imageWidth;
- int32 imageHeight;
- int32 dataPrecision;
-
- /*
- * compInfo[i] describes component that appears i'th in SOF
- * numComponents is the # of color components in JPEG image.
- */
- JpegComponentInfo *compInfo;
- int16 numComponents;
-
- /*
- * *curCompInfo[i] describes component that appears i'th in SOS.
- * compsInScan is the # of color components in current scan.
- */
- JpegComponentInfo *curCompInfo[4];
- int16 compsInScan;
-
- /*
- * MCUmembership[i] indexes the i'th component of MCU into the
- * curCompInfo array.
- */
- int16 MCUmembership[10];
-
- /*
- * ptrs to Huffman coding tables, or NULL if not defined
- */
- HuffmanTable *dcHuffTblPtrs[4];
-
- /*
- * prediction selection value (PSV) and point transform parameter (Pt)
- */
- int32 Ss;
- int32 Pt;
-
- /*
- * In lossless JPEG, restart interval shall be an integer
- * multiple of the number of MCU in a MCU row.
- */
- int32 restartInterval;/* MCUs per restart interval, 0 = no restart */
- int32 restartInRows; /*if > 0, MCU rows per restart interval; 0 = no restart*/
-
- /*
- * these fields are private data for the entropy decoder
- */
- int32 restartRowsToGo; /* MCUs rows left in this restart interval */
- int16 nextRestartNum; /* # of next RSTn marker (0..7) */
-
- };
-
-/*****************************************************************************/
-
-// An MCU (minimum coding unit) is an array of samples.
-
-typedef uint16 ComponentType; // the type of image components
-
-typedef ComponentType *MCU; // MCU - array of samples
-
-/*****************************************************************************/
-
-class dng_lossless_decoder
- {
-
- private:
-
- dng_stream *fStream; // Input data.
-
- dng_spooler *fSpooler; // Output data.
-
- bool fBug16; // Decode data with the "16-bit" bug.
-
- dng_memory_data huffmanBuffer [4];
-
- dng_memory_data compInfoBuffer;
-
- DecompressInfo info;
-
- dng_memory_data mcuBuffer1;
- dng_memory_data mcuBuffer2;
- dng_memory_data mcuBuffer3;
- dng_memory_data mcuBuffer4;
-
- MCU *mcuROW1;
- MCU *mcuROW2;
-
- uint64 getBuffer; // current bit-extraction buffer
- int32 bitsLeft; // # of unused bits in it
-
- #if qSupportHasselblad_3FR
- bool fHasselblad3FR;
- #endif
-
- public:
-
- dng_lossless_decoder (dng_stream *stream,
- dng_spooler *spooler,
- bool bug16);
-
- void StartRead (uint32 &imageWidth,
- uint32 &imageHeight,
- uint32 &imageChannels);
-
- void FinishRead ();
-
- private:
-
- uint8 GetJpegChar ()
- {
- return fStream->Get_uint8 ();
- }
-
- void UnGetJpegChar ()
- {
- fStream->SetReadPosition (fStream->Position () - 1);
- }
-
- uint16 Get2bytes ();
-
- void SkipVariable ();
-
- void GetDht ();
-
- void GetDri ();
-
- void GetApp0 ();
-
- void GetSof (int32 code);
-
- void GetSos ();
-
- void GetSoi ();
-
- int32 NextMarker ();
-
- JpegMarker ProcessTables ();
-
- void ReadFileHeader ();
-
- int32 ReadScanHeader ();
-
- void DecoderStructInit ();
-
- void HuffDecoderInit ();
-
- void ProcessRestart ();
-
- int32 QuickPredict (int32 col,
- int32 curComp,
- MCU *curRowBuf,
- MCU *prevRowBuf);
-
- void FillBitBuffer (int32 nbits);
-
- int32 show_bits8 ();
-
- void flush_bits (int32 nbits);
-
- int32 get_bits (int32 nbits);
-
- int32 get_bit ();
-
- int32 HuffDecode (HuffmanTable *htbl);
-
- void HuffExtend (int32 &x, int32 s);
-
- void PmPutRow (MCU *buf,
- int32 numComp,
- int32 numCol,
- int32 row);
-
- void DecodeFirstRow (MCU *curRowBuf);
-
- void DecodeImage ();
-
- // Hidden copy constructor and assignment operator.
-
- dng_lossless_decoder (const dng_lossless_decoder &decoder);
-
- dng_lossless_decoder & operator= (const dng_lossless_decoder &decoder);
-
- };
-
-/*****************************************************************************/
-
-dng_lossless_decoder::dng_lossless_decoder (dng_stream *stream,
- dng_spooler *spooler,
- bool bug16)
-
- : fStream (stream )
- , fSpooler (spooler)
- , fBug16 (bug16 )
-
- , compInfoBuffer ()
- , info ()
- , mcuBuffer1 ()
- , mcuBuffer2 ()
- , mcuBuffer3 ()
- , mcuBuffer4 ()
- , mcuROW1 (NULL)
- , mcuROW2 (NULL)
- , getBuffer (0)
- , bitsLeft (0)
-
- #if qSupportHasselblad_3FR
- , fHasselblad3FR (false)
- #endif
-
- {
-
- memset (&info, 0, sizeof (info));
-
- }
-
-/*****************************************************************************/
-
-uint16 dng_lossless_decoder::Get2bytes ()
- {
-
- uint16 a = GetJpegChar ();
-
- return (uint16) ((a << 8) + GetJpegChar ());
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * SkipVariable --
- *
- * Skip over an unknown or uninteresting variable-length marker
- *
- * Results:
- * None.
- *
- * Side effects:
- * Bitstream is parsed over marker.
- *
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::SkipVariable ()
- {
-
- uint32 length = Get2bytes () - 2;
-
- fStream->Skip (length);
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * GetDht --
- *
- * Process a DHT marker
- *
- * Results:
- * None
- *
- * Side effects:
- * A huffman table is read.
- * Exits on error.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::GetDht ()
- {
-
- int32 length = Get2bytes () - 2;
-
- while (length > 0)
- {
-
- int32 index = GetJpegChar ();
-
- if (index < 0 || index >= 4)
- {
- ThrowBadFormat ();
- }
-
- HuffmanTable *&htblptr = info.dcHuffTblPtrs [index];
-
- if (htblptr == NULL)
- {
-
- huffmanBuffer [index] . Allocate (sizeof (HuffmanTable));
-
- htblptr = (HuffmanTable *) huffmanBuffer [index] . Buffer ();
-
- }
-
- htblptr->bits [0] = 0;
-
- int32 count = 0;
-
- for (int32 i = 1; i <= 16; i++)
- {
-
- htblptr->bits [i] = GetJpegChar ();
-
- count += htblptr->bits [i];
-
- }
-
- if (count > 256)
- {
- ThrowBadFormat ();
- }
-
- for (int32 j = 0; j < count; j++)
- {
-
- htblptr->huffval [j] = GetJpegChar ();
-
- }
-
- length -= 1 + 16 + count;
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * GetDri --
- *
- * Process a DRI marker
- *
- * Results:
- * None
- *
- * Side effects:
- * Exits on error.
- * Bitstream is parsed.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::GetDri ()
- {
-
- if (Get2bytes () != 4)
- {
- ThrowBadFormat ();
- }
-
- info.restartInterval = Get2bytes ();
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * GetApp0 --
- *
- * Process an APP0 marker.
- *
- * Results:
- * None
- *
- * Side effects:
- * Bitstream is parsed
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::GetApp0 ()
- {
-
- SkipVariable ();
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * GetSof --
- *
- * Process a SOFn marker
- *
- * Results:
- * None.
- *
- * Side effects:
- * Bitstream is parsed
- * Exits on error
- * info structure is filled in
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::GetSof (int32 /*code*/)
- {
-
- int32 length = Get2bytes ();
-
- info.dataPrecision = GetJpegChar ();
- info.imageHeight = Get2bytes ();
- info.imageWidth = Get2bytes ();
- info.numComponents = GetJpegChar ();
-
- // We don't support files in which the image height is initially
- // specified as 0 and is later redefined by DNL. As long as we
- // have to check that, might as well have a general sanity check.
-
- if ((info.imageHeight <= 0) ||
- (info.imageWidth <= 0) ||
- (info.numComponents <= 0))
- {
- ThrowBadFormat ();
- }
-
- // Lossless JPEG specifies data precision to be from 2 to 16 bits/sample.
-
- const int32 MinPrecisionBits = 2;
- const int32 MaxPrecisionBits = 16;
-
- if ((info.dataPrecision < MinPrecisionBits) ||
- (info.dataPrecision > MaxPrecisionBits))
- {
- ThrowBadFormat ();
- }
-
- // Check length of tag.
-
- if (length != (info.numComponents * 3 + 8))
- {
- ThrowBadFormat ();
- }
-
- // Allocate per component info.
-
- // We can cast info.numComponents to a uint32 because the check above
- // guarantees that it cannot be negative.
- compInfoBuffer.Allocate (static_cast<uint32> (info.numComponents),
- sizeof (JpegComponentInfo));
-
- info.compInfo = (JpegComponentInfo *) compInfoBuffer.Buffer ();
-
- // Read in the per compent info.
-
- for (int32 ci = 0; ci < info.numComponents; ci++)
- {
-
- JpegComponentInfo *compptr = &info.compInfo [ci];
-
- compptr->componentIndex = (int16) ci;
-
- compptr->componentId = GetJpegChar ();
-
- int32 c = GetJpegChar ();
-
- compptr->hSampFactor = (int16) ((c >> 4) & 15);
- compptr->vSampFactor = (int16) ((c ) & 15);
-
- (void) GetJpegChar (); /* skip Tq */
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * GetSos --
- *
- * Process a SOS marker
- *
- * Results:
- * None.
- *
- * Side effects:
- * Bitstream is parsed.
- * Exits on error.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::GetSos ()
- {
-
- int32 length = Get2bytes ();
-
- // Get the number of image components.
-
- int32 n = GetJpegChar ();
- info.compsInScan = (int16) n;
-
- // Check length.
-
- length -= 3;
-
- if (length != (n * 2 + 3) || n < 1 || n > 4)
- {
- ThrowBadFormat ();
- }
-
- // Find index and huffman table for each component.
-
- for (int32 i = 0; i < n; i++)
- {
-
- int32 cc = GetJpegChar ();
- int32 c = GetJpegChar ();
-
- int32 ci;
-
- for (ci = 0; ci < info.numComponents; ci++)
- {
-
- if (cc == info.compInfo[ci].componentId)
- {
- break;
- }
-
- }
-
- if (ci >= info.numComponents)
- {
- ThrowBadFormat ();
- }
-
- JpegComponentInfo *compptr = &info.compInfo [ci];
-
- info.curCompInfo [i] = compptr;
-
- compptr->dcTblNo = (int16) ((c >> 4) & 15);
-
- }
-
- // Get the PSV, skip Se, and get the point transform parameter.
-
- info.Ss = GetJpegChar ();
-
- (void) GetJpegChar ();
-
- info.Pt = GetJpegChar () & 0x0F;
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * GetSoi --
- *
- * Process an SOI marker
- *
- * Results:
- * None.
- *
- * Side effects:
- * Bitstream is parsed.
- * Exits on error.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::GetSoi ()
- {
-
- // Reset all parameters that are defined to be reset by SOI
-
- info.restartInterval = 0;
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * NextMarker --
- *
- * Find the next JPEG marker Note that the output might not
- * be a valid marker code but it will never be 0 or FF
- *
- * Results:
- * The marker found.
- *
- * Side effects:
- * Bitstream is parsed.
- *
- *--------------------------------------------------------------
- */
-
-int32 dng_lossless_decoder::NextMarker ()
- {
-
- int32 c;
-
- do
- {
-
- // skip any non-FF bytes
-
- do
- {
- c = GetJpegChar ();
- }
- while (c != 0xFF);
-
- // skip any duplicate FFs, since extra FFs are legal
-
- do
- {
- c = GetJpegChar();
- }
- while (c == 0xFF);
-
- }
- while (c == 0); // repeat if it was a stuffed FF/00
-
- return c;
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * ProcessTables --
- *
- * Scan and process JPEG markers that can appear in any order
- * Return when an SOI, EOI, SOFn, or SOS is found
- *
- * Results:
- * The marker found.
- *
- * Side effects:
- * Bitstream is parsed.
- *
- *--------------------------------------------------------------
- */
-
-JpegMarker dng_lossless_decoder::ProcessTables ()
- {
-
- while (true)
- {
-
- int32 c = NextMarker ();
-
- switch (c)
- {
-
- case M_SOF0:
- case M_SOF1:
- case M_SOF2:
- case M_SOF3:
- case M_SOF5:
- case M_SOF6:
- case M_SOF7:
- case M_JPG:
- case M_SOF9:
- case M_SOF10:
- case M_SOF11:
- case M_SOF13:
- case M_SOF14:
- case M_SOF15:
- case M_SOI:
- case M_EOI:
- case M_SOS:
- return (JpegMarker) c;
-
- case M_DHT:
- GetDht ();
- break;
-
- case M_DQT:
- break;
-
- case M_DRI:
- GetDri ();
- break;
-
- case M_APP0:
- GetApp0 ();
- break;
-
- case M_RST0: // these are all parameterless
- case M_RST1:
- case M_RST2:
- case M_RST3:
- case M_RST4:
- case M_RST5:
- case M_RST6:
- case M_RST7:
- case M_TEM:
- break;
-
- default: // must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn
- SkipVariable ();
- break;
-
- }
-
- }
-
- return M_ERROR;
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * ReadFileHeader --
- *
- * Initialize and read the stream header (everything through
- * the SOF marker).
- *
- * Results:
- * None
- *
- * Side effects:
- * Exit on error.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::ReadFileHeader ()
- {
-
- // Demand an SOI marker at the start of the stream --- otherwise it's
- // probably not a JPEG stream at all.
-
- int32 c = GetJpegChar ();
- int32 c2 = GetJpegChar ();
-
- if ((c != 0xFF) || (c2 != M_SOI))
- {
- ThrowBadFormat ();
- }
-
- // OK, process SOI
-
- GetSoi ();
-
- // Process markers until SOF
-
- c = ProcessTables ();
-
- switch (c)
- {
-
- case M_SOF0:
- case M_SOF1:
- case M_SOF3:
- GetSof (c);
- break;
-
- default:
- ThrowBadFormat ();
- break;
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * ReadScanHeader --
- *
- * Read the start of a scan (everything through the SOS marker).
- *
- * Results:
- * 1 if find SOS, 0 if find EOI
- *
- * Side effects:
- * Bitstream is parsed, may exit on errors.
- *
- *--------------------------------------------------------------
- */
-
-int32 dng_lossless_decoder::ReadScanHeader ()
- {
-
- // Process markers until SOS or EOI
-
- int32 c = ProcessTables ();
-
- switch (c)
- {
-
- case M_SOS:
- GetSos ();
- return 1;
-
- case M_EOI:
- return 0;
-
- default:
- ThrowBadFormat ();
- break;
-
- }
-
- return 0;
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * DecoderStructInit --
- *
- * Initalize the rest of the fields in the decompression
- * structure.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::DecoderStructInit ()
- {
-
- int32 ci;
-
- #if qSupportCanon_sRAW
-
- bool canon_sRAW = (info.numComponents == 3) &&
- (info.compInfo [0].hSampFactor == 2) &&
- (info.compInfo [1].hSampFactor == 1) &&
- (info.compInfo [2].hSampFactor == 1) &&
- (info.compInfo [0].vSampFactor == 1) &&
- (info.compInfo [1].vSampFactor == 1) &&
- (info.compInfo [2].vSampFactor == 1) &&
- (info.dataPrecision == 15) &&
- (info.Ss == 1) &&
- ((info.imageWidth & 1) == 0);
-
- bool canon_sRAW2 = (info.numComponents == 3) &&
- (info.compInfo [0].hSampFactor == 2) &&
- (info.compInfo [1].hSampFactor == 1) &&
- (info.compInfo [2].hSampFactor == 1) &&
- (info.compInfo [0].vSampFactor == 2) &&
- (info.compInfo [1].vSampFactor == 1) &&
- (info.compInfo [2].vSampFactor == 1) &&
- (info.dataPrecision == 15) &&
- (info.Ss == 1) &&
- ((info.imageWidth & 1) == 0) &&
- ((info.imageHeight & 1) == 0);
-
- if (!canon_sRAW && !canon_sRAW2)
-
- #endif
-
- {
-
- // Check sampling factor validity.
-
- for (ci = 0; ci < info.numComponents; ci++)
- {
-
- JpegComponentInfo *compPtr = &info.compInfo [ci];
-
- if (compPtr->hSampFactor != 1 ||
- compPtr->vSampFactor != 1)
- {
- ThrowBadFormat ();
- }
-
- }
-
- }
-
- // Prepare array describing MCU composition.
-
- if (info.compsInScan < 0 || info.compsInScan > 4)
- {
- ThrowBadFormat ();
- }
-
- for (ci = 0; ci < info.compsInScan; ci++)
- {
- info.MCUmembership [ci] = (int16) ci;
- }
-
- // Initialize mucROW1 and mcuROW2 which buffer two rows of
- // pixels for predictor calculation.
-
- // This multiplication cannot overflow because info.compsInScan is
- // guaranteed to be between 0 and 4 inclusive (see checks above).
- int32 mcuSize = info.compsInScan * (uint32) sizeof (ComponentType);
-
- mcuBuffer1.Allocate (info.imageWidth, sizeof (MCU));
- mcuBuffer2.Allocate (info.imageWidth, sizeof (MCU));
-
- mcuROW1 = (MCU *) mcuBuffer1.Buffer ();
- mcuROW2 = (MCU *) mcuBuffer2.Buffer ();
-
- mcuBuffer3.Allocate (info.imageWidth, mcuSize);
- mcuBuffer4.Allocate (info.imageWidth, mcuSize);
-
- mcuROW1 [0] = (ComponentType *) mcuBuffer3.Buffer ();
- mcuROW2 [0] = (ComponentType *) mcuBuffer4.Buffer ();
-
- for (int32 j = 1; j < info.imageWidth; j++)
- {
-
- mcuROW1 [j] = mcuROW1 [j - 1] + info.compsInScan;
- mcuROW2 [j] = mcuROW2 [j - 1] + info.compsInScan;
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * HuffDecoderInit --
- *
- * Initialize for a Huffman-compressed scan.
- * This is invoked after reading the SOS marker.
- *
- * Results:
- * None
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::HuffDecoderInit ()
- {
-
- // Initialize bit parser state
-
- getBuffer = 0;
- bitsLeft = 0;
-
- // Prepare Huffman tables.
-
- for (int16 ci = 0; ci < info.compsInScan; ci++)
- {
-
- JpegComponentInfo *compptr = info.curCompInfo [ci];
-
- // Make sure requested tables are present
-
- if (compptr->dcTblNo < 0 || compptr->dcTblNo > 3)
- {
- ThrowBadFormat ();
- }
-
- if (info.dcHuffTblPtrs [compptr->dcTblNo] == NULL)
- {
- ThrowBadFormat ();
- }
-
- // Compute derived values for Huffman tables.
- // We may do this more than once for same table, but it's not a
- // big deal
-
- FixHuffTbl (info.dcHuffTblPtrs [compptr->dcTblNo]);
-
- }
-
- // Initialize restart stuff
-
- info.restartInRows = info.restartInterval / info.imageWidth;
- info.restartRowsToGo = info.restartInRows;
- info.nextRestartNum = 0;
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * ProcessRestart --
- *
- * Check for a restart marker & resynchronize decoder.
- *
- * Results:
- * None.
- *
- * Side effects:
- * BitStream is parsed, bit buffer is reset, etc.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::ProcessRestart ()
- {
-
- // Throw away and unused odd bits in the bit buffer.
-
- fStream->SetReadPosition (fStream->Position () - bitsLeft / 8);
-
- bitsLeft = 0;
- getBuffer = 0;
-
- // Scan for next JPEG marker
-
- int32 c;
-
- do
- {
-
- // skip any non-FF bytes
-
- do
- {
- c = GetJpegChar ();
- }
- while (c != 0xFF);
-
- // skip any duplicate FFs
-
- do
- {
- c = GetJpegChar ();
- }
- while (c == 0xFF);
-
- }
- while (c == 0); // repeat if it was a stuffed FF/00
-
- // Verify correct restart code.
-
- if (c != (M_RST0 + info.nextRestartNum))
- {
- ThrowBadFormat ();
- }
-
- // Update restart state.
-
- info.restartRowsToGo = info.restartInRows;
- info.nextRestartNum = (info.nextRestartNum + 1) & 7;
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * QuickPredict --
- *
- * Calculate the predictor for sample curRowBuf[col][curComp].
- * It does not handle the special cases at image edges, such
- * as first row and first column of a scan. We put the special
- * case checkings outside so that the computations in main
- * loop can be simpler. This has enhenced the performance
- * significantly.
- *
- * Results:
- * predictor is passed out.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-inline int32 dng_lossless_decoder::QuickPredict (int32 col,
- int32 curComp,
- MCU *curRowBuf,
- MCU *prevRowBuf)
- {
-
- int32 diag = prevRowBuf [col - 1] [curComp];
- int32 upper = prevRowBuf [col ] [curComp];
- int32 left = curRowBuf [col - 1] [curComp];
-
- switch (info.Ss)
- {
-
- case 0:
- return 0;
-
- case 1:
- return left;
-
- case 2:
- return upper;
-
- case 3:
- return diag;
-
- case 4:
- return left + upper - diag;
-
- case 5:
- return left + ((upper - diag) >> 1);
-
- case 6:
- return upper + ((left - diag) >> 1);
-
- case 7:
- return (left + upper) >> 1;
-
- default:
- {
- ThrowBadFormat ();
- return 0;
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * FillBitBuffer --
- *
- * Load up the bit buffer with at least nbits
- * Process any stuffed bytes at this time.
- *
- * Results:
- * None
- *
- * Side effects:
- * The bitwise global variables are updated.
- *
- *--------------------------------------------------------------
- */
-
-inline void dng_lossless_decoder::FillBitBuffer (int32 nbits)
- {
-
- const int32 kMinGetBits = sizeof (uint32) * 8 - 7;
-
- #if qSupportHasselblad_3FR
-
- if (fHasselblad3FR)
- {
-
- while (bitsLeft < kMinGetBits)
- {
-
- int32 c0 = GetJpegChar ();
- int32 c1 = GetJpegChar ();
- int32 c2 = GetJpegChar ();
- int32 c3 = GetJpegChar ();
-
- getBuffer = (getBuffer << 8) | c3;
- getBuffer = (getBuffer << 8) | c2;
- getBuffer = (getBuffer << 8) | c1;
- getBuffer = (getBuffer << 8) | c0;
-
- bitsLeft += 32;
-
- }
-
- return;
-
- }
-
- #endif
-
- while (bitsLeft < kMinGetBits)
- {
-
- int32 c = GetJpegChar ();
-
- // If it's 0xFF, check and discard stuffed zero byte
-
- if (c == 0xFF)
- {
-
- int32 c2 = GetJpegChar ();
-
- if (c2 != 0)
- {
-
- // Oops, it's actually a marker indicating end of
- // compressed data. Better put it back for use later.
-
- UnGetJpegChar ();
- UnGetJpegChar ();
-
- // There should be enough bits still left in the data
- // segment; if so, just break out of the while loop.
-
- if (bitsLeft >= nbits)
- break;
-
- // Uh-oh. Corrupted data: stuff zeroes into the data
- // stream, since this sometimes occurs when we are on the
- // last show_bits8 during decoding of the Huffman
- // segment.
-
- c = 0;
-
- }
-
- }
-
- getBuffer = (getBuffer << 8) | c;
-
- bitsLeft += 8;
-
- }
-
- }
-
-/*****************************************************************************/
-
-inline int32 dng_lossless_decoder::show_bits8 ()
- {
-
- if (bitsLeft < 8)
- FillBitBuffer (8);
-
- return (int32) ((getBuffer >> (bitsLeft - 8)) & 0xff);
-
- }
-
-/*****************************************************************************/
-
-inline void dng_lossless_decoder::flush_bits (int32 nbits)
- {
-
- bitsLeft -= nbits;
-
- }
-
-/*****************************************************************************/
-
-inline int32 dng_lossless_decoder::get_bits (int32 nbits)
- {
-
- if (nbits > 16)
- {
- ThrowBadFormat ();
- }
-
- if (bitsLeft < nbits)
- FillBitBuffer (nbits);
-
- return (int32) ((getBuffer >> (bitsLeft -= nbits)) & (0x0FFFF >> (16 - nbits)));
-
- }
-
-/*****************************************************************************/
-
-inline int32 dng_lossless_decoder::get_bit ()
- {
-
- if (!bitsLeft)
- FillBitBuffer (1);
-
- return (int32) ((getBuffer >> (--bitsLeft)) & 1);
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * HuffDecode --
- *
- * Taken from Figure F.16: extract next coded symbol from
- * input stream. This should becode a macro.
- *
- * Results:
- * Next coded symbol
- *
- * Side effects:
- * Bitstream is parsed.
- *
- *--------------------------------------------------------------
- */
-
-inline int32 dng_lossless_decoder::HuffDecode (HuffmanTable *htbl)
- {
-
- // If the huffman code is less than 8 bits, we can use the fast
- // table lookup to get its value. It's more than 8 bits about
- // 3-4% of the time.
-
- int32 code = show_bits8 ();
-
- if (htbl->numbits [code])
- {
-
- flush_bits (htbl->numbits [code]);
-
- return htbl->value [code];
-
- }
-
- else
- {
-
- flush_bits (8);
-
- int32 l = 8;
-
- while (code > htbl->maxcode [l])
- {
- code = (code << 1) | get_bit ();
- l++;
- }
-
- // With garbage input we may reach the sentinel value l = 17.
-
- if (l > 16)
- {
- return 0; // fake a zero as the safest result
- }
- else
- {
- return htbl->huffval [htbl->valptr [l] +
- ((int32) (code - htbl->mincode [l]))];
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * HuffExtend --
- *
- * Code and table for Figure F.12: extend sign bit
- *
- * Results:
- * The extended value.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-inline void dng_lossless_decoder::HuffExtend (int32 &x, int32 s)
- {
-
- if (x < (0x08000 >> (16 - s)))
- {
- x += -(1 << s) + 1;
- }
-
- }
-
-/*****************************************************************************/
-
-// Called from DecodeImage () to write one row.
-
-void dng_lossless_decoder::PmPutRow (MCU *buf,
- int32 numComp,
- int32 numCol,
- int32 /* row */)
- {
-
- uint16 *sPtr = &buf [0] [0];
-
- uint32 pixels = numCol * numComp;
-
- fSpooler->Spool (sPtr, pixels * (uint32) sizeof (uint16));
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * DecodeFirstRow --
- *
- * Decode the first raster line of samples at the start of
- * the scan and at the beginning of each restart interval.
- * This includes modifying the component value so the real
- * value, not the difference is returned.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Bitstream is parsed.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::DecodeFirstRow (MCU *curRowBuf)
- {
-
- int32 compsInScan = info.compsInScan;
-
- // Process the first column in the row.
-
- for (int32 curComp = 0; curComp < compsInScan; curComp++)
- {
-
- int32 ci = info.MCUmembership [curComp];
-
- JpegComponentInfo *compptr = info.curCompInfo [ci];
-
- HuffmanTable *dctbl = info.dcHuffTblPtrs [compptr->dcTblNo];
-
- // Section F.2.2.1: decode the difference
-
- int32 d = 0;
-
- int32 s = HuffDecode (dctbl);
-
- if (s)
- {
-
- if (s == 16 && !fBug16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- // Add the predictor to the difference.
-
- int32 Pr = info.dataPrecision;
- int32 Pt = info.Pt;
-
- curRowBuf [0] [curComp] = (ComponentType) (d + (1 << (Pr-Pt-1)));
-
- }
-
- // Process the rest of the row.
-
- int32 numCOL = info.imageWidth;
-
- for (int32 col = 1; col < numCOL; col++)
- {
-
- for (int32 curComp = 0; curComp < compsInScan; curComp++)
- {
-
- int32 ci = info.MCUmembership [curComp];
-
- JpegComponentInfo *compptr = info.curCompInfo [ci];
-
- HuffmanTable *dctbl = info.dcHuffTblPtrs [compptr->dcTblNo];
-
- // Section F.2.2.1: decode the difference
-
- int32 d = 0;
-
- int32 s = HuffDecode (dctbl);
-
- if (s)
- {
-
- if (s == 16 && !fBug16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- // Add the predictor to the difference.
-
- curRowBuf [col] [curComp] = (ComponentType) (d + curRowBuf [col-1] [curComp]);
-
- }
-
- }
-
- // Update the restart counter
-
- if (info.restartInRows)
- {
- info.restartRowsToGo--;
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * DecodeImage --
- *
- * Decode the input stream. This includes modifying
- * the component value so the real value, not the
- * difference is returned.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Bitstream is parsed.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_decoder::DecodeImage ()
- {
-
- #define swap(type,a,b) {type c; c=(a); (a)=(b); (b)=c;}
-
- int32 numCOL = info.imageWidth;
- int32 numROW = info.imageHeight;
- int32 compsInScan = info.compsInScan;
-
- // Precompute the decoding table for each table.
-
- HuffmanTable *ht [4];
-
- for (int32 curComp = 0; curComp < compsInScan; curComp++)
- {
-
- int32 ci = info.MCUmembership [curComp];
-
- JpegComponentInfo *compptr = info.curCompInfo [ci];
-
- ht [curComp] = info.dcHuffTblPtrs [compptr->dcTblNo];
-
- }
-
- MCU *prevRowBuf = mcuROW1;
- MCU *curRowBuf = mcuROW2;
-
- #if qSupportCanon_sRAW
-
- // Canon sRAW support
-
- if (info.compInfo [0].hSampFactor == 2 &&
- info.compInfo [0].vSampFactor == 1)
- {
-
- for (int32 row = 0; row < numROW; row++)
- {
-
- // Initialize predictors.
-
- int32 p0;
- int32 p1;
- int32 p2;
-
- if (row == 0)
- {
- p0 = 1 << 14;
- p1 = 1 << 14;
- p2 = 1 << 14;
- }
-
- else
- {
- p0 = prevRowBuf [0] [0];
- p1 = prevRowBuf [0] [1];
- p2 = prevRowBuf [0] [2];
- }
-
- for (int32 col = 0; col < numCOL; col += 2)
- {
-
- // Read first luminance component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [0]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p0 += d;
-
- curRowBuf [col] [0] = (ComponentType) p0;
-
- }
-
- // Read second luminance component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [0]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p0 += d;
-
- curRowBuf [col + 1] [0] = (ComponentType) p0;
-
- }
-
- // Read first chroma component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [1]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p1 += d;
-
- curRowBuf [col ] [1] = (ComponentType) p1;
- curRowBuf [col + 1] [1] = (ComponentType) p1;
-
- }
-
- // Read second chroma component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [2]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p2 += d;
-
- curRowBuf [col ] [2] = (ComponentType) p2;
- curRowBuf [col + 1] [2] = (ComponentType) p2;
-
- }
-
- }
-
- PmPutRow (curRowBuf, compsInScan, numCOL, row);
-
- swap (MCU *, prevRowBuf, curRowBuf);
-
- }
-
- return;
-
- }
-
- if (info.compInfo [0].hSampFactor == 2 &&
- info.compInfo [0].vSampFactor == 2)
- {
-
- for (int32 row = 0; row < numROW; row += 2)
- {
-
- // Initialize predictors.
-
- int32 p0;
- int32 p1;
- int32 p2;
-
- if (row == 0)
- {
- p0 = 1 << 14;
- p1 = 1 << 14;
- p2 = 1 << 14;
- }
-
- else
- {
- p0 = prevRowBuf [0] [0];
- p1 = prevRowBuf [0] [1];
- p2 = prevRowBuf [0] [2];
- }
-
- for (int32 col = 0; col < numCOL; col += 2)
- {
-
- // Read first luminance component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [0]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p0 += d;
-
- prevRowBuf [col] [0] = (ComponentType) p0;
-
- }
-
- // Read second luminance component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [0]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p0 += d;
-
- prevRowBuf [col + 1] [0] = (ComponentType) p0;
-
- }
-
- // Read third luminance component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [0]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p0 += d;
-
- curRowBuf [col] [0] = (ComponentType) p0;
-
- }
-
- // Read fourth luminance component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [0]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p0 += d;
-
- curRowBuf [col + 1] [0] = (ComponentType) p0;
-
- }
-
- // Read first chroma component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [1]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p1 += d;
-
- prevRowBuf [col ] [1] = (ComponentType) p1;
- prevRowBuf [col + 1] [1] = (ComponentType) p1;
-
- curRowBuf [col ] [1] = (ComponentType) p1;
- curRowBuf [col + 1] [1] = (ComponentType) p1;
-
- }
-
- // Read second chroma component.
-
- {
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [2]);
-
- if (s)
- {
-
- if (s == 16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- p2 += d;
-
- prevRowBuf [col ] [2] = (ComponentType) p2;
- prevRowBuf [col + 1] [2] = (ComponentType) p2;
-
- curRowBuf [col ] [2] = (ComponentType) p2;
- curRowBuf [col + 1] [2] = (ComponentType) p2;
-
- }
-
- }
-
- PmPutRow (prevRowBuf, compsInScan, numCOL, row);
- PmPutRow (curRowBuf, compsInScan, numCOL, row);
-
- }
-
- return;
-
- }
-
- #endif
-
- #if qSupportHasselblad_3FR
-
- if (info.Ss == 8)
- {
-
- fHasselblad3FR = true;
-
- for (int32 row = 0; row < numROW; row++)
- {
-
- int32 p0 = 32768;
- int32 p1 = 32768;
-
- for (int32 col = 0; col < numCOL; col += 2)
- {
-
- int32 s0 = HuffDecode (ht [0]);
- int32 s1 = HuffDecode (ht [0]);
-
- if (s0)
- {
- int32 d = get_bits (s0);
- if (s0 == 16)
- {
- d = -32768;
- }
- else
- {
- HuffExtend (d, s0);
- }
- p0 += d;
- }
-
- if (s1)
- {
- int32 d = get_bits (s1);
- if (s1 == 16)
- {
- d = -32768;
- }
- else
- {
- HuffExtend (d, s1);
- }
- p1 += d;
- }
-
- curRowBuf [col ] [0] = (ComponentType) p0;
- curRowBuf [col + 1] [0] = (ComponentType) p1;
-
- }
-
- PmPutRow (curRowBuf, compsInScan, numCOL, row);
-
- }
-
- return;
-
- }
-
- #endif
-
- // Decode the first row of image. Output the row and
- // turn this row into a previous row for later predictor
- // calculation.
-
- DecodeFirstRow (mcuROW1);
-
- PmPutRow (mcuROW1, compsInScan, numCOL, 0);
-
- // Process each row.
-
- for (int32 row = 1; row < numROW; row++)
- {
-
- // Account for restart interval, process restart marker if needed.
-
- if (info.restartInRows)
- {
-
- if (info.restartRowsToGo == 0)
- {
-
- ProcessRestart ();
-
- // Reset predictors at restart.
-
- DecodeFirstRow (curRowBuf);
-
- PmPutRow (curRowBuf, compsInScan, numCOL, row);
-
- swap (MCU *, prevRowBuf, curRowBuf);
-
- continue;
-
- }
-
- info.restartRowsToGo--;
-
- }
-
- // The upper neighbors are predictors for the first column.
-
- for (int32 curComp = 0; curComp < compsInScan; curComp++)
- {
-
- // Section F.2.2.1: decode the difference
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [curComp]);
-
- if (s)
- {
-
- if (s == 16 && !fBug16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- // First column of row above is predictor for first column.
-
- curRowBuf [0] [curComp] = (ComponentType) (d + prevRowBuf [0] [curComp]);
-
- }
-
- // For the rest of the column on this row, predictor
- // calculations are based on PSV.
-
- if (compsInScan == 2 && info.Ss == 1)
- {
-
- // This is the combination used by both the Canon and Kodak raw formats.
- // Unrolling the general case logic results in a significant speed increase.
-
- uint16 *dPtr = &curRowBuf [1] [0];
-
- int32 prev0 = dPtr [-2];
- int32 prev1 = dPtr [-1];
-
- for (int32 col = 1; col < numCOL; col++)
- {
-
- int32 s = HuffDecode (ht [0]);
-
- if (s)
- {
-
- int32 d;
-
- if (s == 16 && !fBug16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- prev0 += d;
-
- }
-
- s = HuffDecode (ht [1]);
-
- if (s)
- {
-
- int32 d;
-
- if (s == 16 && !fBug16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- prev1 += d;
-
- }
-
- dPtr [0] = (uint16) prev0;
- dPtr [1] = (uint16) prev1;
-
- dPtr += 2;
-
- }
-
- }
-
- else
- {
-
- for (int32 col = 1; col < numCOL; col++)
- {
-
- for (int32 curComp = 0; curComp < compsInScan; curComp++)
- {
-
- // Section F.2.2.1: decode the difference
-
- int32 d = 0;
-
- int32 s = HuffDecode (ht [curComp]);
-
- if (s)
- {
-
- if (s == 16 && !fBug16)
- {
- d = -32768;
- }
-
- else
- {
- d = get_bits (s);
- HuffExtend (d, s);
- }
-
- }
-
- // Predict the pixel value.
-
- int32 predictor = QuickPredict (col,
- curComp,
- curRowBuf,
- prevRowBuf);
-
- // Save the difference.
-
- curRowBuf [col] [curComp] = (ComponentType) (d + predictor);
-
- }
-
- }
-
- }
-
- PmPutRow (curRowBuf, compsInScan, numCOL, row);
-
- swap (MCU *, prevRowBuf, curRowBuf);
-
- }
-
- #undef swap
-
- }
-
-/*****************************************************************************/
-
-void dng_lossless_decoder::StartRead (uint32 &imageWidth,
- uint32 &imageHeight,
- uint32 &imageChannels)
- {
-
- ReadFileHeader ();
- ReadScanHeader ();
- DecoderStructInit ();
- HuffDecoderInit ();
-
- imageWidth = info.imageWidth;
- imageHeight = info.imageHeight;
- imageChannels = info.compsInScan;
-
- }
-
-/*****************************************************************************/
-
-void dng_lossless_decoder::FinishRead ()
- {
-
- DecodeImage ();
-
- }
-
-/*****************************************************************************/
-
-void DecodeLosslessJPEG (dng_stream &stream,
- dng_spooler &spooler,
- uint32 minDecodedSize,
- uint32 maxDecodedSize,
- bool bug16)
- {
-
- dng_lossless_decoder decoder (&stream,
- &spooler,
- bug16);
-
- uint32 imageWidth;
- uint32 imageHeight;
- uint32 imageChannels;
-
- decoder.StartRead (imageWidth,
- imageHeight,
- imageChannels);
-
- uint32 decodedSize = imageWidth *
- imageHeight *
- imageChannels *
- (uint32) sizeof (uint16);
-
- if (decodedSize < minDecodedSize ||
- decodedSize > maxDecodedSize)
- {
- ThrowBadFormat ();
- }
-
- decoder.FinishRead ();
-
- }
-
-/*****************************************************************************/
-
-class dng_lossless_encoder
- {
-
- private:
-
- const uint16 *fSrcData;
-
- uint32 fSrcRows;
- uint32 fSrcCols;
- uint32 fSrcChannels;
- uint32 fSrcBitDepth;
-
- int32 fSrcRowStep;
- int32 fSrcColStep;
-
- dng_stream &fStream;
-
- HuffmanTable huffTable [4];
-
- uint32 freqCount [4] [257];
-
- // Current bit-accumulation buffer
-
- int32 huffPutBuffer;
- int32 huffPutBits;
-
- // Lookup table for number of bits in an 8 bit value.
-
- int numBitsTable [256];
-
- public:
-
- dng_lossless_encoder (const uint16 *srcData,
- uint32 srcRows,
- uint32 srcCols,
- uint32 srcChannels,
- uint32 srcBitDepth,
- int32 srcRowStep,
- int32 srcColStep,
- dng_stream &stream);
-
- void Encode ();
-
- private:
-
- void EmitByte (uint8 value);
-
- void EmitBits (int code, int size);
-
- void FlushBits ();
-
- void CountOneDiff (int diff, uint32 *countTable);
-
- void EncodeOneDiff (int diff, HuffmanTable *dctbl);
-
- void FreqCountSet ();
-
- void HuffEncode ();
-
- void GenHuffCoding (HuffmanTable *htbl, uint32 *freq);
-
- void HuffOptimize ();
-
- void EmitMarker (JpegMarker mark);
-
- void Emit2bytes (int value);
-
- void EmitDht (int index);
-
- void EmitSof (JpegMarker code);
-
- void EmitSos ();
-
- void WriteFileHeader ();
-
- void WriteScanHeader ();
-
- void WriteFileTrailer ();
-
- };
-
-/*****************************************************************************/
-
-dng_lossless_encoder::dng_lossless_encoder (const uint16 *srcData,
- uint32 srcRows,
- uint32 srcCols,
- uint32 srcChannels,
- uint32 srcBitDepth,
- int32 srcRowStep,
- int32 srcColStep,
- dng_stream &stream)
-
- : fSrcData (srcData )
- , fSrcRows (srcRows )
- , fSrcCols (srcCols )
- , fSrcChannels (srcChannels)
- , fSrcBitDepth (srcBitDepth)
- , fSrcRowStep (srcRowStep )
- , fSrcColStep (srcColStep )
- , fStream (stream )
-
- , huffPutBuffer (0)
- , huffPutBits (0)
-
- {
-
- // Initialize number of bits lookup table.
-
- numBitsTable [0] = 0;
-
- for (int i = 1; i < 256; i++)
- {
-
- int temp = i;
- int nbits = 1;
-
- while (temp >>= 1)
- {
- nbits++;
- }
-
- numBitsTable [i] = nbits;
-
- }
-
- }
-
-/*****************************************************************************/
-
-inline void dng_lossless_encoder::EmitByte (uint8 value)
- {
-
- fStream.Put_uint8 (value);
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * EmitBits --
- *
- * Code for outputting bits to the file
- *
- * Only the right 24 bits of huffPutBuffer are used; the valid
- * bits are left-justified in this part. At most 16 bits can be
- * passed to EmitBits in one call, and we never retain more than 7
- * bits in huffPutBuffer between calls, so 24 bits are
- * sufficient.
- *
- * Results:
- * None.
- *
- * Side effects:
- * huffPutBuffer and huffPutBits are updated.
- *
- *--------------------------------------------------------------
- */
-
-inline void dng_lossless_encoder::EmitBits (int code, int size)
- {
-
- DNG_ASSERT (size != 0, "Bad Huffman table entry");
-
- int putBits = size;
- int putBuffer = code;
-
- putBits += huffPutBits;
-
- putBuffer <<= 24 - putBits;
- putBuffer |= huffPutBuffer;
-
- while (putBits >= 8)
- {
-
- uint8 c = (uint8) (putBuffer >> 16);
-
- // Output whole bytes we've accumulated with byte stuffing
-
- EmitByte (c);
-
- if (c == 0xFF)
- {
- EmitByte (0);
- }
-
- putBuffer <<= 8;
- putBits -= 8;
-
- }
-
- huffPutBuffer = putBuffer;
- huffPutBits = putBits;
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * FlushBits --
- *
- * Flush any remaining bits in the bit buffer. Used before emitting
- * a marker.
- *
- * Results:
- * None.
- *
- * Side effects:
- * huffPutBuffer and huffPutBits are reset
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::FlushBits ()
- {
-
- // The first call forces output of any partial bytes.
-
- EmitBits (0x007F, 7);
-
- // We can then zero the buffer.
-
- huffPutBuffer = 0;
- huffPutBits = 0;
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * CountOneDiff --
- *
- * Count the difference value in countTable.
- *
- * Results:
- * diff is counted in countTable.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-inline void dng_lossless_encoder::CountOneDiff (int diff, uint32 *countTable)
- {
-
- // Encode the DC coefficient difference per section F.1.2.1
-
- int temp = diff;
-
- if (temp < 0)
- {
-
- temp = -temp;
-
- }
-
- // Find the number of bits needed for the magnitude of the coefficient
-
- int nbits = temp >= 256 ? numBitsTable [temp >> 8 ] + 8
- : numBitsTable [temp & 0xFF];
-
- // Update count for this bit length
-
- countTable [nbits] ++;
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * EncodeOneDiff --
- *
- * Encode a single difference value.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-inline void dng_lossless_encoder::EncodeOneDiff (int diff, HuffmanTable *dctbl)
- {
-
- // Encode the DC coefficient difference per section F.1.2.1
-
- int temp = diff;
- int temp2 = diff;
-
- if (temp < 0)
- {
-
- temp = -temp;
-
- // For a negative input, want temp2 = bitwise complement of
- // abs (input). This code assumes we are on a two's complement
- // machine.
-
- temp2--;
-
- }
-
- // Find the number of bits needed for the magnitude of the coefficient
-
- int nbits = temp >= 256 ? numBitsTable [temp >> 8 ] + 8
- : numBitsTable [temp & 0xFF];
-
- // Emit the Huffman-coded symbol for the number of bits
-
- EmitBits (dctbl->ehufco [nbits],
- dctbl->ehufsi [nbits]);
-
- // Emit that number of bits of the value, if positive,
- // or the complement of its magnitude, if negative.
-
- // If the number of bits is 16, there is only one possible difference
- // value (-32786), so the lossless JPEG spec says not to output anything
- // in that case. So we only need to output the diference value if
- // the number of bits is between 1 and 15.
-
- if (nbits & 15)
- {
-
- EmitBits (temp2 & (0x0FFFF >> (16 - nbits)),
- nbits);
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * FreqCountSet --
- *
- * Count the times each category symbol occurs in this image.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The freqCount has counted all category
- * symbols appeared in the image.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::FreqCountSet ()
- {
-
- memset (freqCount, 0, sizeof (freqCount));
-
- DNG_ASSERT ((int32)fSrcRows >= 0, "dng_lossless_encoder::FreqCountSet: fSrcRpws too large.");
-
- for (int32 row = 0; row < (int32)fSrcRows; row++)
- {
-
- const uint16 *sPtr = fSrcData + row * fSrcRowStep;
-
- // Initialize predictors for this row.
-
- int32 predictor [4];
-
- for (int32 channel = 0; channel < (int32)fSrcChannels; channel++)
- {
-
- if (row == 0)
- predictor [channel] = 1 << (fSrcBitDepth - 1);
-
- else
- predictor [channel] = sPtr [channel - fSrcRowStep];
-
- }
-
- // Unroll most common case of two channels
-
- if (fSrcChannels == 2)
- {
-
- int32 pred0 = predictor [0];
- int32 pred1 = predictor [1];
-
- uint32 srcCols = fSrcCols;
- int32 srcColStep = fSrcColStep;
-
- for (uint32 col = 0; col < srcCols; col++)
- {
-
- int32 pixel0 = sPtr [0];
- int32 pixel1 = sPtr [1];
-
- int16 diff0 = (int16) (pixel0 - pred0);
- int16 diff1 = (int16) (pixel1 - pred1);
-
- CountOneDiff (diff0, freqCount [0]);
- CountOneDiff (diff1, freqCount [1]);
-
- pred0 = pixel0;
- pred1 = pixel1;
-
- sPtr += srcColStep;
-
- }
-
- }
-
- // General case.
-
- else
- {
-
- for (uint32 col = 0; col < fSrcCols; col++)
- {
-
- for (uint32 channel = 0; channel < fSrcChannels; channel++)
- {
-
- int32 pixel = sPtr [channel];
-
- int16 diff = (int16) (pixel - predictor [channel]);
-
- CountOneDiff (diff, freqCount [channel]);
-
- predictor [channel] = pixel;
-
- }
-
- sPtr += fSrcColStep;
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * HuffEncode --
- *
- * Encode and output Huffman-compressed image data.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::HuffEncode ()
- {
-
- DNG_ASSERT ((int32)fSrcRows >= 0, "dng_lossless_encoder::HuffEncode: fSrcRows too large.");
-
- for (int32 row = 0; row < (int32)fSrcRows; row++)
- {
-
- const uint16 *sPtr = fSrcData + row * fSrcRowStep;
-
- // Initialize predictors for this row.
-
- int32 predictor [4];
-
- for (int32 channel = 0; channel < (int32)fSrcChannels; channel++)
- {
-
- if (row == 0)
- predictor [channel] = 1 << (fSrcBitDepth - 1);
-
- else
- predictor [channel] = sPtr [channel - fSrcRowStep];
-
- }
-
- // Unroll most common case of two channels
-
- if (fSrcChannels == 2)
- {
-
- int32 pred0 = predictor [0];
- int32 pred1 = predictor [1];
-
- uint32 srcCols = fSrcCols;
- int32 srcColStep = fSrcColStep;
-
- for (uint32 col = 0; col < srcCols; col++)
- {
-
- int32 pixel0 = sPtr [0];
- int32 pixel1 = sPtr [1];
-
- int16 diff0 = (int16) (pixel0 - pred0);
- int16 diff1 = (int16) (pixel1 - pred1);
-
- EncodeOneDiff (diff0, &huffTable [0]);
- EncodeOneDiff (diff1, &huffTable [1]);
-
- pred0 = pixel0;
- pred1 = pixel1;
-
- sPtr += srcColStep;
-
- }
-
- }
-
- // General case.
-
- else
- {
-
- for (uint32 col = 0; col < fSrcCols; col++)
- {
-
- for (uint32 channel = 0; channel < fSrcChannels; channel++)
- {
-
- int32 pixel = sPtr [channel];
-
- int16 diff = (int16) (pixel - predictor [channel]);
-
- EncodeOneDiff (diff, &huffTable [channel]);
-
- predictor [channel] = pixel;
-
- }
-
- sPtr += fSrcColStep;
-
- }
-
- }
-
- }
-
- FlushBits ();
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * GenHuffCoding --
- *
- * Generate the optimal coding for the given counts.
- * This algorithm is explained in section K.2 of the
- * JPEG standard.
- *
- * Results:
- * htbl->bits and htbl->huffval are constructed.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::GenHuffCoding (HuffmanTable *htbl, uint32 *freq)
- {
-
- int i;
- int j;
-
- const int MAX_CLEN = 32; // assumed maximum initial code length
-
- uint8 bits [MAX_CLEN + 1]; // bits [k] = # of symbols with code length k
- short codesize [257]; // codesize [k] = code length of symbol k
- short others [257]; // next symbol in current branch of tree
-
- memset (bits , 0, sizeof (bits ));
- memset (codesize, 0, sizeof (codesize));
-
- for (i = 0; i < 257; i++)
- others [i] = -1; // init links to empty
-
- // Including the pseudo-symbol 256 in the Huffman procedure guarantees
- // that no real symbol is given code-value of all ones, because 256
- // will be placed in the largest codeword category.
-
- freq [256] = 1; // make sure there is a nonzero count
-
- // Huffman's basic algorithm to assign optimal code lengths to symbols
-
- while (true)
- {
-
- // Find the smallest nonzero frequency, set c1 = its symbol.
- // In case of ties, take the larger symbol number.
-
- int c1 = -1;
-
- uint32 v = 0xFFFFFFFF;
-
- for (i = 0; i <= 256; i++)
- {
-
- if (freq [i] && freq [i] <= v)
- {
- v = freq [i];
- c1 = i;
- }
-
- }
-
- // Find the next smallest nonzero frequency, set c2 = its symbol.
- // In case of ties, take the larger symbol number.
-
- int c2 = -1;
-
- v = 0xFFFFFFFF;
-
- for (i = 0; i <= 256; i++)
- {
-
- if (freq [i] && freq [i] <= v && i != c1)
- {
- v = freq [i];
- c2 = i;
- }
-
- }
-
- // Done if we've merged everything into one frequency.
-
- if (c2 < 0)
- break;
-
- // Else merge the two counts/trees.
-
- freq [c1] += freq [c2];
- freq [c2] = 0;
-
- // Increment the codesize of everything in c1's tree branch.
-
- codesize [c1] ++;
-
- while (others [c1] >= 0)
- {
- c1 = others [c1];
- codesize [c1] ++;
- }
-
- // chain c2 onto c1's tree branch
-
- others [c1] = (short) c2;
-
- // Increment the codesize of everything in c2's tree branch.
-
- codesize [c2] ++;
-
- while (others [c2] >= 0)
- {
- c2 = others [c2];
- codesize [c2] ++;
- }
-
- }
-
- // Now count the number of symbols of each code length.
-
- for (i = 0; i <= 256; i++)
- {
-
- if (codesize [i])
- {
-
- // The JPEG standard seems to think that this can't happen,
- // but I'm paranoid...
-
- if (codesize [i] > MAX_CLEN)
- {
-
- DNG_REPORT ("Huffman code size table overflow");
-
- ThrowProgramError ();
-
- }
-
- bits [codesize [i]]++;
-
- }
-
- }
-
- // JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
- // Huffman procedure assigned any such lengths, we must adjust the coding.
- // Here is what the JPEG spec says about how this next bit works:
- // Since symbols are paired for the longest Huffman code, the symbols are
- // removed from this length category two at a time. The prefix for the pair
- // (which is one bit shorter) is allocated to one of the pair; then,
- // skipping the BITS entry for that prefix length, a code word from the next
- // shortest nonzero BITS entry is converted into a prefix for two code words
- // one bit longer.
-
- for (i = MAX_CLEN; i > 16; i--)
- {
-
- while (bits [i] > 0)
- {
-
- // Kludge: I have never been able to test this logic, and there
- // are comments on the web that this encoder has bugs with 16-bit
- // data, so just throw an error if we get here and revert to a
- // default table. - tknoll 12/1/03.
-
- DNG_REPORT ("Info: Optimal huffman table bigger than 16 bits");
-
- ThrowProgramError ();
-
- // Original logic:
-
- j = i - 2; // find length of new prefix to be used
-
- while (bits [j] == 0)
- j--;
-
- bits [i ] -= 2; // remove two symbols
- bits [i - 1] ++; // one goes in this length
- bits [j + 1] += 2; // two new symbols in this length
- bits [j ] --; // symbol of this length is now a prefix
-
- }
-
- }
-
- // Remove the count for the pseudo-symbol 256 from
- // the largest codelength.
-
- while (bits [i] == 0) // find largest codelength still in use
- i--;
-
- bits [i] --;
-
- // Return final symbol counts (only for lengths 0..16).
-
- memcpy (htbl->bits, bits, sizeof (htbl->bits));
-
- // Return a list of the symbols sorted by code length.
- // It's not real clear to me why we don't need to consider the codelength
- // changes made above, but the JPEG spec seems to think this works.
-
- int p = 0;
-
- for (i = 1; i <= MAX_CLEN; i++)
- {
-
- for (j = 0; j <= 255; j++)
- {
-
- if (codesize [j] == i)
- {
- htbl->huffval [p] = (uint8) j;
- p++;
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * HuffOptimize --
- *
- * Find the best coding parameters for a Huffman-coded scan.
- * When called, the scan data has already been converted to
- * a sequence of MCU groups of source image samples, which
- * are stored in a "big" array, mcuTable.
- *
- * It counts the times each category symbol occurs. Based on
- * this counting, optimal Huffman tables are built. Then it
- * uses this optimal Huffman table and counting table to find
- * the best PSV.
- *
- * Results:
- * Optimal Huffman tables are retured in cPtr->dcHuffTblPtrs[tbl].
- * Best PSV is retured in cPtr->Ss.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::HuffOptimize ()
- {
-
- // Collect the frequency counts.
-
- FreqCountSet ();
-
- // Generate Huffman encoding tables.
-
- for (uint32 channel = 0; channel < fSrcChannels; channel++)
- {
-
- try
- {
-
- GenHuffCoding (&huffTable [channel], freqCount [channel]);
-
- }
-
- catch (...)
- {
-
- DNG_REPORT ("Info: Reverting to default huffman table");
-
- for (uint32 j = 0; j <= 256; j++)
- {
-
- freqCount [channel] [j] = (j <= 16 ? 1 : 0);
-
- }
-
- GenHuffCoding (&huffTable [channel], freqCount [channel]);
-
- }
-
- FixHuffTbl (&huffTable [channel]);
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * EmitMarker --
- *
- * Emit a marker code into the output stream.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::EmitMarker (JpegMarker mark)
- {
-
- EmitByte (0xFF);
- EmitByte ((uint8) mark);
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * Emit2bytes --
- *
- * Emit a 2-byte integer; these are always MSB first in JPEG
- * files
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::Emit2bytes (int value)
- {
-
- EmitByte ((value >> 8) & 0xFF);
- EmitByte (value & 0xFF);
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * EmitDht --
- *
- * Emit a DHT marker, follwed by the huffman data.
- *
- * Results:
- * None
- *
- * Side effects:
- * None
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::EmitDht (int index)
- {
-
- int i;
-
- HuffmanTable *htbl = &huffTable [index];
-
- EmitMarker (M_DHT);
-
- int length = 0;
-
- for (i = 1; i <= 16; i++)
- length += htbl->bits [i];
-
- Emit2bytes (length + 2 + 1 + 16);
-
- EmitByte ((uint8) index);
-
- for (i = 1; i <= 16; i++)
- EmitByte (htbl->bits [i]);
-
- for (i = 0; i < length; i++)
- EmitByte (htbl->huffval [i]);
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * EmitSof --
- *
- * Emit a SOF marker plus data.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::EmitSof (JpegMarker code)
- {
-
- EmitMarker (code);
-
- Emit2bytes (3 * fSrcChannels + 2 + 5 + 1); // length
-
- EmitByte ((uint8) fSrcBitDepth);
-
- Emit2bytes (fSrcRows);
- Emit2bytes (fSrcCols);
-
- EmitByte ((uint8) fSrcChannels);
-
- for (uint32 i = 0; i < fSrcChannels; i++)
- {
-
- EmitByte ((uint8) i);
-
- EmitByte ((uint8) ((1 << 4) + 1)); // Not subsampled.
-
- EmitByte (0); // Tq shall be 0 for lossless.
-
- }
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * EmitSos --
- *
- * Emit a SOS marker plus data.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::EmitSos ()
- {
-
- EmitMarker (M_SOS);
-
- Emit2bytes (2 * fSrcChannels + 2 + 1 + 3); // length
-
- EmitByte ((uint8) fSrcChannels); // Ns
-
- for (uint32 i = 0; i < fSrcChannels; i++)
- {
-
- // Cs,Td,Ta
-
- EmitByte ((uint8) i);
- EmitByte ((uint8) (i << 4));
-
- }
-
- EmitByte (1); // PSV - hardcoded - tknoll
- EmitByte (0); // Spectral selection end - Se
- EmitByte (0); // The point transform parameter
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * WriteFileHeader --
- *
- * Write the file header.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::WriteFileHeader ()
- {
-
- EmitMarker (M_SOI); // first the SOI
-
- EmitSof (M_SOF3);
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * WriteScanHeader --
- *
- * Write the start of a scan (everything through the SOS marker).
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::WriteScanHeader ()
- {
-
- // Emit Huffman tables.
-
- for (uint32 i = 0; i < fSrcChannels; i++)
- {
-
- EmitDht (i);
-
- }
-
- EmitSos ();
-
- }
-
-/*****************************************************************************/
-
-/*
- *--------------------------------------------------------------
- *
- * WriteFileTrailer --
- *
- * Write the End of image marker at the end of a JPEG file.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *--------------------------------------------------------------
- */
-
-void dng_lossless_encoder::WriteFileTrailer ()
- {
-
- EmitMarker (M_EOI);
-
- }
-
-/*****************************************************************************/
-
-void dng_lossless_encoder::Encode ()
- {
-
- DNG_ASSERT (fSrcChannels <= 4, "Too many components in scan");
-
- // Count the times each difference category occurs.
- // Construct the optimal Huffman table.
-
- HuffOptimize ();
-
- // Write the frame and scan headers.
-
- WriteFileHeader ();
-
- WriteScanHeader ();
-
- // Encode the image.
-
- HuffEncode ();
-
- // Clean up everything.
-
- WriteFileTrailer ();
-
- }
-
-/*****************************************************************************/
-
-void EncodeLosslessJPEG (const uint16 *srcData,
- uint32 srcRows,
- uint32 srcCols,
- uint32 srcChannels,
- uint32 srcBitDepth,
- int32 srcRowStep,
- int32 srcColStep,
- dng_stream &stream)
- {
-
- dng_lossless_encoder encoder (srcData,
- srcRows,
- srcCols,
- srcChannels,
- srcBitDepth,
- srcRowStep,
- srcColStep,
- stream);
-
- encoder.Encode ();
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_lossless_jpeg.cpp#2 $ */
+/* $DateTime: 2012/06/01 07:28:57 $ */
+/* $Change: 832715 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+// Lossless JPEG code adapted from:
+
+/* Copyright (C) 1991, 1992, Thomas G. Lane.
+ * Part of the Independent JPEG Group's software.
+ * See the file Copyright for more details.
+ *
+ * Copyright (c) 1993 Brian C. Smith, The Regents of the University
+ * of California
+ * All rights reserved.
+ *
+ * Copyright (c) 1994 Kongji Huang and Brian C. Smith.
+ * Cornell University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+/*****************************************************************************/
+
+#include "dng_lossless_jpeg.h"
+
+#include "dng_assertions.h"
+#include "dng_exceptions.h"
+#include "dng_memory.h"
+#include "dng_stream.h"
+#include "dng_tag_codes.h"
+
+/*****************************************************************************/
+
+// This module contains routines that should be as fast as possible, even
+// at the expense of slight code size increases.
+
+#include "dng_fast_module.h"
+
+/*****************************************************************************/
+
+// The qSupportCanon_sRAW stuff not actually required for DNG support, but
+// only included to allow this code to be used on Canon sRAW files.
+
+#ifndef qSupportCanon_sRAW
+#define qSupportCanon_sRAW 1
+#endif
+
+// The qSupportHasselblad_3FR stuff not actually required for DNG support, but
+// only included to allow this code to be used on Hasselblad 3FR files.
+
+#ifndef qSupportHasselblad_3FR
+#define qSupportHasselblad_3FR 1
+#endif
+
+/*****************************************************************************/
+
+/*
+ * One of the following structures is created for each huffman coding
+ * table. We use the same structure for encoding and decoding, so there
+ * may be some extra fields for encoding that aren't used in the decoding
+ * and vice-versa.
+ */
+
+struct HuffmanTable
+ {
+
+ /*
+ * These two fields directly represent the contents of a JPEG DHT
+ * marker
+ */
+ uint8 bits[17];
+ uint8 huffval[256];
+
+ /*
+ * The remaining fields are computed from the above to allow more
+ * efficient coding and decoding. These fields should be considered
+ * private to the Huffman compression & decompression modules.
+ */
+
+ uint16 mincode[17];
+ int32 maxcode[18];
+ int16 valptr[17];
+ int32 numbits[256];
+ int32 value[256];
+
+ uint16 ehufco[256];
+ int8 ehufsi[256];
+
+ };
+
+/*****************************************************************************/
+
+// Computes the derived fields in the Huffman table structure.
+
+static void FixHuffTbl (HuffmanTable *htbl)
+ {
+
+ int32 l;
+ int32 i;
+
+ const uint32 bitMask [] =
+ {
+ 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff,
+ 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
+ 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
+ 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
+ 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
+ 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
+ 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
+ 0x0000000f, 0x00000007, 0x00000003, 0x00000001
+ };
+
+ // Figure C.1: make table of Huffman code length for each symbol
+ // Note that this is in code-length order.
+
+ int8 huffsize [257];
+
+ int32 p = 0;
+
+ for (l = 1; l <= 16; l++)
+ {
+
+ for (i = 1; i <= (int32) htbl->bits [l]; i++)
+ huffsize [p++] = (int8) l;
+
+ }
+
+ huffsize [p] = 0;
+
+ int32 lastp = p;
+
+ // Figure C.2: generate the codes themselves
+ // Note that this is in code-length order.
+
+ uint16 huffcode [257];
+
+ uint16 code = 0;
+
+ int32 si = huffsize [0];
+
+ p = 0;
+
+ while (huffsize [p])
+ {
+
+ while (((int32) huffsize [p]) == si)
+ {
+ huffcode [p++] = code;
+ code++;
+ }
+
+ code <<= 1;
+
+ si++;
+
+ }
+
+ // Figure C.3: generate encoding tables
+ // These are code and size indexed by symbol value
+ // Set any codeless symbols to have code length 0; this allows
+ // EmitBits to detect any attempt to emit such symbols.
+
+ memset (htbl->ehufsi, 0, sizeof (htbl->ehufsi));
+
+ for (p = 0; p < lastp; p++)
+ {
+
+ htbl->ehufco [htbl->huffval [p]] = huffcode [p];
+ htbl->ehufsi [htbl->huffval [p]] = huffsize [p];
+
+ }
+
+ // Figure F.15: generate decoding tables
+
+ p = 0;
+
+ for (l = 1; l <= 16; l++)
+ {
+
+ if (htbl->bits [l])
+ {
+
+ htbl->valptr [l] = (int16) p;
+ htbl->mincode [l] = huffcode [p];
+
+ p += htbl->bits [l];
+
+ htbl->maxcode [l] = huffcode [p - 1];
+
+ }
+
+ else
+ {
+ htbl->maxcode [l] = -1;
+ }
+
+ }
+
+ // We put in this value to ensure HuffDecode terminates.
+
+ htbl->maxcode[17] = 0xFFFFFL;
+
+ // Build the numbits, value lookup tables.
+ // These table allow us to gather 8 bits from the bits stream,
+ // and immediately lookup the size and value of the huffman codes.
+ // If size is zero, it means that more than 8 bits are in the huffman
+ // code (this happens about 3-4% of the time).
+
+ memset (htbl->numbits, 0, sizeof (htbl->numbits));
+
+ for (p = 0; p < lastp; p++)
+ {
+
+ int32 size = huffsize [p];
+
+ if (size <= 8)
+ {
+
+ int32 value = htbl->huffval [p];
+
+ code = huffcode [p];
+
+ int32 ll = code << (8 -size);
+
+ int32 ul = (size < 8 ? ll | bitMask [24 + size]
+ : ll);
+ if (ul >= static_cast<int32>(sizeof(htbl->numbits) / sizeof(htbl->numbits[0])) ||
+ ul >= static_cast<int32>(sizeof(htbl->value) / sizeof(htbl->value[0])))
+ {
+ ThrowBadFormat ();
+ }
+
+ for (i = ll; i <= ul; i++)
+ {
+ htbl->numbits [i] = size;
+ htbl->value [i] = value;
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ * The following structure stores basic information about one component.
+ */
+
+struct JpegComponentInfo
+ {
+
+ /*
+ * These values are fixed over the whole image.
+ * They are read from the SOF marker.
+ */
+ int16 componentId; /* identifier for this component (0..255) */
+ int16 componentIndex; /* its index in SOF or cPtr->compInfo[] */
+
+ /*
+ * Downsampling is not normally used in lossless JPEG, although
+ * it is permitted by the JPEG standard (DIS). We set all sampling
+ * factors to 1 in this program.
+ */
+ int16 hSampFactor; /* horizontal sampling factor */
+ int16 vSampFactor; /* vertical sampling factor */
+
+ /*
+ * Huffman table selector (0..3). The value may vary
+ * between scans. It is read from the SOS marker.
+ */
+ int16 dcTblNo;
+
+ };
+
+/*
+ * One of the following structures is used to pass around the
+ * decompression information.
+ */
+
+struct DecompressInfo
+ {
+
+ /*
+ * Image width, height, and image data precision (bits/sample)
+ * These fields are set by ReadFileHeader or ReadScanHeader
+ */
+ int32 imageWidth;
+ int32 imageHeight;
+ int32 dataPrecision;
+
+ /*
+ * compInfo[i] describes component that appears i'th in SOF
+ * numComponents is the # of color components in JPEG image.
+ */
+ JpegComponentInfo *compInfo;
+ int16 numComponents;
+
+ /*
+ * *curCompInfo[i] describes component that appears i'th in SOS.
+ * compsInScan is the # of color components in current scan.
+ */
+ JpegComponentInfo *curCompInfo[4];
+ int16 compsInScan;
+
+ /*
+ * MCUmembership[i] indexes the i'th component of MCU into the
+ * curCompInfo array.
+ */
+ int16 MCUmembership[10];
+
+ /*
+ * ptrs to Huffman coding tables, or NULL if not defined
+ */
+ HuffmanTable *dcHuffTblPtrs[4];
+
+ /*
+ * prediction selection value (PSV) and point transform parameter (Pt)
+ */
+ int32 Ss;
+ int32 Pt;
+
+ /*
+ * In lossless JPEG, restart interval shall be an integer
+ * multiple of the number of MCU in a MCU row.
+ */
+ int32 restartInterval;/* MCUs per restart interval, 0 = no restart */
+ int32 restartInRows; /*if > 0, MCU rows per restart interval; 0 = no restart*/
+
+ /*
+ * these fields are private data for the entropy decoder
+ */
+ int32 restartRowsToGo; /* MCUs rows left in this restart interval */
+ int16 nextRestartNum; /* # of next RSTn marker (0..7) */
+
+ };
+
+/*****************************************************************************/
+
+// An MCU (minimum coding unit) is an array of samples.
+
+typedef uint16 ComponentType; // the type of image components
+
+typedef ComponentType *MCU; // MCU - array of samples
+
+/*****************************************************************************/
+
+class dng_lossless_decoder
+ {
+
+ private:
+
+ dng_stream *fStream; // Input data.
+
+ dng_spooler *fSpooler; // Output data.
+
+ bool fBug16; // Decode data with the "16-bit" bug.
+
+ dng_memory_data huffmanBuffer [4];
+
+ dng_memory_data compInfoBuffer;
+
+ DecompressInfo info;
+
+ dng_memory_data mcuBuffer1;
+ dng_memory_data mcuBuffer2;
+ dng_memory_data mcuBuffer3;
+ dng_memory_data mcuBuffer4;
+
+ MCU *mcuROW1;
+ MCU *mcuROW2;
+
+ uint64 getBuffer; // current bit-extraction buffer
+ int32 bitsLeft; // # of unused bits in it
+
+ #if qSupportHasselblad_3FR
+ bool fHasselblad3FR;
+ #endif
+
+ public:
+
+ dng_lossless_decoder (dng_stream *stream,
+ dng_spooler *spooler,
+ bool bug16);
+
+ void StartRead (uint32 &imageWidth,
+ uint32 &imageHeight,
+ uint32 &imageChannels);
+
+ void FinishRead ();
+
+ private:
+
+ uint8 GetJpegChar ()
+ {
+ return fStream->Get_uint8 ();
+ }
+
+ void UnGetJpegChar ()
+ {
+ fStream->SetReadPosition (fStream->Position () - 1);
+ }
+
+ uint16 Get2bytes ();
+
+ void SkipVariable ();
+
+ void GetDht ();
+
+ void GetDri ();
+
+ void GetApp0 ();
+
+ void GetSof (int32 code);
+
+ void GetSos ();
+
+ void GetSoi ();
+
+ int32 NextMarker ();
+
+ JpegMarker ProcessTables ();
+
+ void ReadFileHeader ();
+
+ int32 ReadScanHeader ();
+
+ void DecoderStructInit ();
+
+ void HuffDecoderInit ();
+
+ void ProcessRestart ();
+
+ int32 QuickPredict (int32 col,
+ int32 curComp,
+ MCU *curRowBuf,
+ MCU *prevRowBuf);
+
+ void FillBitBuffer (int32 nbits);
+
+ int32 show_bits8 ();
+
+ void flush_bits (int32 nbits);
+
+ int32 get_bits (int32 nbits);
+
+ int32 get_bit ();
+
+ int32 HuffDecode (HuffmanTable *htbl);
+
+ void HuffExtend (int32 &x, int32 s);
+
+ void PmPutRow (MCU *buf,
+ int32 numComp,
+ int32 numCol,
+ int32 row);
+
+ void DecodeFirstRow (MCU *curRowBuf);
+
+ void DecodeImage ();
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_lossless_decoder (const dng_lossless_decoder &decoder);
+
+ dng_lossless_decoder & operator= (const dng_lossless_decoder &decoder);
+
+ };
+
+/*****************************************************************************/
+
+dng_lossless_decoder::dng_lossless_decoder (dng_stream *stream,
+ dng_spooler *spooler,
+ bool bug16)
+
+ : fStream (stream )
+ , fSpooler (spooler)
+ , fBug16 (bug16 )
+
+ , compInfoBuffer ()
+ , info ()
+ , mcuBuffer1 ()
+ , mcuBuffer2 ()
+ , mcuBuffer3 ()
+ , mcuBuffer4 ()
+ , mcuROW1 (NULL)
+ , mcuROW2 (NULL)
+ , getBuffer (0)
+ , bitsLeft (0)
+
+ #if qSupportHasselblad_3FR
+ , fHasselblad3FR (false)
+ #endif
+
+ {
+
+ memset (&info, 0, sizeof (info));
+
+ }
+
+/*****************************************************************************/
+
+uint16 dng_lossless_decoder::Get2bytes ()
+ {
+
+ uint16 a = GetJpegChar ();
+
+ return (uint16) ((a << 8) + GetJpegChar ());
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * SkipVariable --
+ *
+ * Skip over an unknown or uninteresting variable-length marker
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Bitstream is parsed over marker.
+ *
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::SkipVariable ()
+ {
+
+ uint32 length = Get2bytes () - 2;
+
+ fStream->Skip (length);
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetDht --
+ *
+ * Process a DHT marker
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * A huffman table is read.
+ * Exits on error.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::GetDht ()
+ {
+
+ int32 length = Get2bytes () - 2;
+
+ while (length > 0)
+ {
+
+ int32 index = GetJpegChar ();
+
+ if (index < 0 || index >= 4)
+ {
+ ThrowBadFormat ();
+ }
+
+ HuffmanTable *&htblptr = info.dcHuffTblPtrs [index];
+
+ if (htblptr == NULL)
+ {
+
+ huffmanBuffer [index] . Allocate (sizeof (HuffmanTable));
+
+ htblptr = (HuffmanTable *) huffmanBuffer [index] . Buffer ();
+
+ }
+
+ htblptr->bits [0] = 0;
+
+ int32 count = 0;
+
+ for (int32 i = 1; i <= 16; i++)
+ {
+
+ htblptr->bits [i] = GetJpegChar ();
+
+ count += htblptr->bits [i];
+
+ }
+
+ if (count > 256)
+ {
+ ThrowBadFormat ();
+ }
+
+ for (int32 j = 0; j < count; j++)
+ {
+
+ htblptr->huffval [j] = GetJpegChar ();
+
+ }
+
+ length -= 1 + 16 + count;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetDri --
+ *
+ * Process a DRI marker
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Exits on error.
+ * Bitstream is parsed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::GetDri ()
+ {
+
+ if (Get2bytes () != 4)
+ {
+ ThrowBadFormat ();
+ }
+
+ info.restartInterval = Get2bytes ();
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetApp0 --
+ *
+ * Process an APP0 marker.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Bitstream is parsed
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::GetApp0 ()
+ {
+
+ SkipVariable ();
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetSof --
+ *
+ * Process a SOFn marker
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Bitstream is parsed
+ * Exits on error
+ * info structure is filled in
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::GetSof (int32 /*code*/)
+ {
+
+ int32 length = Get2bytes ();
+
+ info.dataPrecision = GetJpegChar ();
+ info.imageHeight = Get2bytes ();
+ info.imageWidth = Get2bytes ();
+ info.numComponents = GetJpegChar ();
+
+ // We don't support files in which the image height is initially
+ // specified as 0 and is later redefined by DNL. As long as we
+ // have to check that, might as well have a general sanity check.
+
+ if ((info.imageHeight <= 0) ||
+ (info.imageWidth <= 0) ||
+ (info.numComponents <= 0))
+ {
+ ThrowBadFormat ();
+ }
+
+ // Lossless JPEG specifies data precision to be from 2 to 16 bits/sample.
+
+ const int32 MinPrecisionBits = 2;
+ const int32 MaxPrecisionBits = 16;
+
+ if ((info.dataPrecision < MinPrecisionBits) ||
+ (info.dataPrecision > MaxPrecisionBits))
+ {
+ ThrowBadFormat ();
+ }
+
+ // Check length of tag.
+
+ if (length != (info.numComponents * 3 + 8))
+ {
+ ThrowBadFormat ();
+ }
+
+ // Allocate per component info.
+
+ // We can cast info.numComponents to a uint32 because the check above
+ // guarantees that it cannot be negative.
+ compInfoBuffer.Allocate (static_cast<uint32> (info.numComponents),
+ sizeof (JpegComponentInfo));
+
+ info.compInfo = (JpegComponentInfo *) compInfoBuffer.Buffer ();
+
+ // Read in the per compent info.
+
+ for (int32 ci = 0; ci < info.numComponents; ci++)
+ {
+
+ JpegComponentInfo *compptr = &info.compInfo [ci];
+
+ compptr->componentIndex = (int16) ci;
+
+ compptr->componentId = GetJpegChar ();
+
+ int32 c = GetJpegChar ();
+
+ compptr->hSampFactor = (int16) ((c >> 4) & 15);
+ compptr->vSampFactor = (int16) ((c ) & 15);
+
+ (void) GetJpegChar (); /* skip Tq */
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetSos --
+ *
+ * Process a SOS marker
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Bitstream is parsed.
+ * Exits on error.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::GetSos ()
+ {
+
+ int32 length = Get2bytes ();
+
+ // Get the number of image components.
+
+ int32 n = GetJpegChar ();
+ info.compsInScan = (int16) n;
+
+ // Check length.
+
+ length -= 3;
+
+ if (length != (n * 2 + 3) || n < 1 || n > 4)
+ {
+ ThrowBadFormat ();
+ }
+
+ // Find index and huffman table for each component.
+
+ for (int32 i = 0; i < n; i++)
+ {
+
+ int32 cc = GetJpegChar ();
+ int32 c = GetJpegChar ();
+
+ int32 ci;
+
+ for (ci = 0; ci < info.numComponents; ci++)
+ {
+
+ if (cc == info.compInfo[ci].componentId)
+ {
+ break;
+ }
+
+ }
+
+ if (ci >= info.numComponents)
+ {
+ ThrowBadFormat ();
+ }
+
+ JpegComponentInfo *compptr = &info.compInfo [ci];
+
+ info.curCompInfo [i] = compptr;
+
+ compptr->dcTblNo = (int16) ((c >> 4) & 15);
+
+ }
+
+ // Get the PSV, skip Se, and get the point transform parameter.
+
+ info.Ss = GetJpegChar ();
+
+ (void) GetJpegChar ();
+
+ info.Pt = GetJpegChar () & 0x0F;
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GetSoi --
+ *
+ * Process an SOI marker
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Bitstream is parsed.
+ * Exits on error.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::GetSoi ()
+ {
+
+ // Reset all parameters that are defined to be reset by SOI
+
+ info.restartInterval = 0;
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * NextMarker --
+ *
+ * Find the next JPEG marker Note that the output might not
+ * be a valid marker code but it will never be 0 or FF
+ *
+ * Results:
+ * The marker found.
+ *
+ * Side effects:
+ * Bitstream is parsed.
+ *
+ *--------------------------------------------------------------
+ */
+
+int32 dng_lossless_decoder::NextMarker ()
+ {
+
+ int32 c;
+
+ do
+ {
+
+ // skip any non-FF bytes
+
+ do
+ {
+ c = GetJpegChar ();
+ }
+ while (c != 0xFF);
+
+ // skip any duplicate FFs, since extra FFs are legal
+
+ do
+ {
+ c = GetJpegChar();
+ }
+ while (c == 0xFF);
+
+ }
+ while (c == 0); // repeat if it was a stuffed FF/00
+
+ return c;
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ProcessTables --
+ *
+ * Scan and process JPEG markers that can appear in any order
+ * Return when an SOI, EOI, SOFn, or SOS is found
+ *
+ * Results:
+ * The marker found.
+ *
+ * Side effects:
+ * Bitstream is parsed.
+ *
+ *--------------------------------------------------------------
+ */
+
+JpegMarker dng_lossless_decoder::ProcessTables ()
+ {
+
+ while (true)
+ {
+
+ int32 c = NextMarker ();
+
+ switch (c)
+ {
+
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_JPG:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ case M_SOI:
+ case M_EOI:
+ case M_SOS:
+ return (JpegMarker) c;
+
+ case M_DHT:
+ GetDht ();
+ break;
+
+ case M_DQT:
+ break;
+
+ case M_DRI:
+ GetDri ();
+ break;
+
+ case M_APP0:
+ GetApp0 ();
+ break;
+
+ case M_RST0: // these are all parameterless
+ case M_RST1:
+ case M_RST2:
+ case M_RST3:
+ case M_RST4:
+ case M_RST5:
+ case M_RST6:
+ case M_RST7:
+ case M_TEM:
+ break;
+
+ default: // must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn
+ SkipVariable ();
+ break;
+
+ }
+
+ }
+
+ return M_ERROR;
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ReadFileHeader --
+ *
+ * Initialize and read the stream header (everything through
+ * the SOF marker).
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * Exit on error.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::ReadFileHeader ()
+ {
+
+ // Demand an SOI marker at the start of the stream --- otherwise it's
+ // probably not a JPEG stream at all.
+
+ int32 c = GetJpegChar ();
+ int32 c2 = GetJpegChar ();
+
+ if ((c != 0xFF) || (c2 != M_SOI))
+ {
+ ThrowBadFormat ();
+ }
+
+ // OK, process SOI
+
+ GetSoi ();
+
+ // Process markers until SOF
+
+ c = ProcessTables ();
+
+ switch (c)
+ {
+
+ case M_SOF0:
+ case M_SOF1:
+ case M_SOF3:
+ GetSof (c);
+ break;
+
+ default:
+ ThrowBadFormat ();
+ break;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ReadScanHeader --
+ *
+ * Read the start of a scan (everything through the SOS marker).
+ *
+ * Results:
+ * 1 if find SOS, 0 if find EOI
+ *
+ * Side effects:
+ * Bitstream is parsed, may exit on errors.
+ *
+ *--------------------------------------------------------------
+ */
+
+int32 dng_lossless_decoder::ReadScanHeader ()
+ {
+
+ // Process markers until SOS or EOI
+
+ int32 c = ProcessTables ();
+
+ switch (c)
+ {
+
+ case M_SOS:
+ GetSos ();
+ return 1;
+
+ case M_EOI:
+ return 0;
+
+ default:
+ ThrowBadFormat ();
+ break;
+
+ }
+
+ return 0;
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DecoderStructInit --
+ *
+ * Initalize the rest of the fields in the decompression
+ * structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::DecoderStructInit ()
+ {
+
+ int32 ci;
+
+ #if qSupportCanon_sRAW
+
+ bool canon_sRAW = (info.numComponents == 3) &&
+ (info.compInfo [0].hSampFactor == 2) &&
+ (info.compInfo [1].hSampFactor == 1) &&
+ (info.compInfo [2].hSampFactor == 1) &&
+ (info.compInfo [0].vSampFactor == 1) &&
+ (info.compInfo [1].vSampFactor == 1) &&
+ (info.compInfo [2].vSampFactor == 1) &&
+ (info.dataPrecision == 15) &&
+ (info.Ss == 1) &&
+ ((info.imageWidth & 1) == 0);
+
+ bool canon_sRAW2 = (info.numComponents == 3) &&
+ (info.compInfo [0].hSampFactor == 2) &&
+ (info.compInfo [1].hSampFactor == 1) &&
+ (info.compInfo [2].hSampFactor == 1) &&
+ (info.compInfo [0].vSampFactor == 2) &&
+ (info.compInfo [1].vSampFactor == 1) &&
+ (info.compInfo [2].vSampFactor == 1) &&
+ (info.dataPrecision == 15) &&
+ (info.Ss == 1) &&
+ ((info.imageWidth & 1) == 0) &&
+ ((info.imageHeight & 1) == 0);
+
+ if (!canon_sRAW && !canon_sRAW2)
+
+ #endif
+
+ {
+
+ // Check sampling factor validity.
+
+ for (ci = 0; ci < info.numComponents; ci++)
+ {
+
+ JpegComponentInfo *compPtr = &info.compInfo [ci];
+
+ if (compPtr->hSampFactor != 1 ||
+ compPtr->vSampFactor != 1)
+ {
+ ThrowBadFormat ();
+ }
+
+ }
+
+ }
+
+ // Prepare array describing MCU composition.
+
+ if (info.compsInScan < 0 || info.compsInScan > 4)
+ {
+ ThrowBadFormat ();
+ }
+
+ for (ci = 0; ci < info.compsInScan; ci++)
+ {
+ info.MCUmembership [ci] = (int16) ci;
+ }
+
+ // Initialize mucROW1 and mcuROW2 which buffer two rows of
+ // pixels for predictor calculation.
+
+ // This multiplication cannot overflow because info.compsInScan is
+ // guaranteed to be between 0 and 4 inclusive (see checks above).
+ int32 mcuSize = info.compsInScan * (uint32) sizeof (ComponentType);
+
+ mcuBuffer1.Allocate (info.imageWidth, sizeof (MCU));
+ mcuBuffer2.Allocate (info.imageWidth, sizeof (MCU));
+
+ mcuROW1 = (MCU *) mcuBuffer1.Buffer ();
+ mcuROW2 = (MCU *) mcuBuffer2.Buffer ();
+
+ mcuBuffer3.Allocate (info.imageWidth, mcuSize);
+ mcuBuffer4.Allocate (info.imageWidth, mcuSize);
+
+ mcuROW1 [0] = (ComponentType *) mcuBuffer3.Buffer ();
+ mcuROW2 [0] = (ComponentType *) mcuBuffer4.Buffer ();
+
+ for (int32 j = 1; j < info.imageWidth; j++)
+ {
+
+ mcuROW1 [j] = mcuROW1 [j - 1] + info.compsInScan;
+ mcuROW2 [j] = mcuROW2 [j - 1] + info.compsInScan;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * HuffDecoderInit --
+ *
+ * Initialize for a Huffman-compressed scan.
+ * This is invoked after reading the SOS marker.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::HuffDecoderInit ()
+ {
+
+ // Initialize bit parser state
+
+ getBuffer = 0;
+ bitsLeft = 0;
+
+ // Prepare Huffman tables.
+
+ for (int16 ci = 0; ci < info.compsInScan; ci++)
+ {
+
+ JpegComponentInfo *compptr = info.curCompInfo [ci];
+
+ // Make sure requested tables are present
+
+ if (compptr->dcTblNo < 0 || compptr->dcTblNo > 3)
+ {
+ ThrowBadFormat ();
+ }
+
+ if (info.dcHuffTblPtrs [compptr->dcTblNo] == NULL)
+ {
+ ThrowBadFormat ();
+ }
+
+ // Compute derived values for Huffman tables.
+ // We may do this more than once for same table, but it's not a
+ // big deal
+
+ FixHuffTbl (info.dcHuffTblPtrs [compptr->dcTblNo]);
+
+ }
+
+ // Initialize restart stuff
+
+ info.restartInRows = info.restartInterval / info.imageWidth;
+ info.restartRowsToGo = info.restartInRows;
+ info.nextRestartNum = 0;
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ProcessRestart --
+ *
+ * Check for a restart marker & resynchronize decoder.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * BitStream is parsed, bit buffer is reset, etc.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::ProcessRestart ()
+ {
+
+ // Throw away and unused odd bits in the bit buffer.
+
+ fStream->SetReadPosition (fStream->Position () - bitsLeft / 8);
+
+ bitsLeft = 0;
+ getBuffer = 0;
+
+ // Scan for next JPEG marker
+
+ int32 c;
+
+ do
+ {
+
+ // skip any non-FF bytes
+
+ do
+ {
+ c = GetJpegChar ();
+ }
+ while (c != 0xFF);
+
+ // skip any duplicate FFs
+
+ do
+ {
+ c = GetJpegChar ();
+ }
+ while (c == 0xFF);
+
+ }
+ while (c == 0); // repeat if it was a stuffed FF/00
+
+ // Verify correct restart code.
+
+ if (c != (M_RST0 + info.nextRestartNum))
+ {
+ ThrowBadFormat ();
+ }
+
+ // Update restart state.
+
+ info.restartRowsToGo = info.restartInRows;
+ info.nextRestartNum = (info.nextRestartNum + 1) & 7;
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * QuickPredict --
+ *
+ * Calculate the predictor for sample curRowBuf[col][curComp].
+ * It does not handle the special cases at image edges, such
+ * as first row and first column of a scan. We put the special
+ * case checkings outside so that the computations in main
+ * loop can be simpler. This has enhenced the performance
+ * significantly.
+ *
+ * Results:
+ * predictor is passed out.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+inline int32 dng_lossless_decoder::QuickPredict (int32 col,
+ int32 curComp,
+ MCU *curRowBuf,
+ MCU *prevRowBuf)
+ {
+
+ int32 diag = prevRowBuf [col - 1] [curComp];
+ int32 upper = prevRowBuf [col ] [curComp];
+ int32 left = curRowBuf [col - 1] [curComp];
+
+ switch (info.Ss)
+ {
+
+ case 0:
+ return 0;
+
+ case 1:
+ return left;
+
+ case 2:
+ return upper;
+
+ case 3:
+ return diag;
+
+ case 4:
+ return left + upper - diag;
+
+ case 5:
+ return left + ((upper - diag) >> 1);
+
+ case 6:
+ return upper + ((left - diag) >> 1);
+
+ case 7:
+ return (left + upper) >> 1;
+
+ default:
+ {
+ ThrowBadFormat ();
+ return 0;
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FillBitBuffer --
+ *
+ * Load up the bit buffer with at least nbits
+ * Process any stuffed bytes at this time.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The bitwise global variables are updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+inline void dng_lossless_decoder::FillBitBuffer (int32 nbits)
+ {
+
+ const int32 kMinGetBits = sizeof (uint32) * 8 - 7;
+
+ #if qSupportHasselblad_3FR
+
+ if (fHasselblad3FR)
+ {
+
+ while (bitsLeft < kMinGetBits)
+ {
+
+ int32 c0 = GetJpegChar ();
+ int32 c1 = GetJpegChar ();
+ int32 c2 = GetJpegChar ();
+ int32 c3 = GetJpegChar ();
+
+ getBuffer = (getBuffer << 8) | c3;
+ getBuffer = (getBuffer << 8) | c2;
+ getBuffer = (getBuffer << 8) | c1;
+ getBuffer = (getBuffer << 8) | c0;
+
+ bitsLeft += 32;
+
+ }
+
+ return;
+
+ }
+
+ #endif
+
+ while (bitsLeft < kMinGetBits)
+ {
+
+ int32 c = GetJpegChar ();
+
+ // If it's 0xFF, check and discard stuffed zero byte
+
+ if (c == 0xFF)
+ {
+
+ int32 c2 = GetJpegChar ();
+
+ if (c2 != 0)
+ {
+
+ // Oops, it's actually a marker indicating end of
+ // compressed data. Better put it back for use later.
+
+ UnGetJpegChar ();
+ UnGetJpegChar ();
+
+ // There should be enough bits still left in the data
+ // segment; if so, just break out of the while loop.
+
+ if (bitsLeft >= nbits)
+ break;
+
+ // Uh-oh. Corrupted data: stuff zeroes into the data
+ // stream, since this sometimes occurs when we are on the
+ // last show_bits8 during decoding of the Huffman
+ // segment.
+
+ c = 0;
+
+ }
+
+ }
+
+ getBuffer = (getBuffer << 8) | c;
+
+ bitsLeft += 8;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+inline int32 dng_lossless_decoder::show_bits8 ()
+ {
+
+ if (bitsLeft < 8)
+ FillBitBuffer (8);
+
+ return (int32) ((getBuffer >> (bitsLeft - 8)) & 0xff);
+
+ }
+
+/*****************************************************************************/
+
+inline void dng_lossless_decoder::flush_bits (int32 nbits)
+ {
+
+ bitsLeft -= nbits;
+
+ }
+
+/*****************************************************************************/
+
+inline int32 dng_lossless_decoder::get_bits (int32 nbits)
+ {
+
+ if (nbits > 16)
+ {
+ ThrowBadFormat ();
+ }
+
+ if (bitsLeft < nbits)
+ FillBitBuffer (nbits);
+
+ return (int32) ((getBuffer >> (bitsLeft -= nbits)) & (0x0FFFF >> (16 - nbits)));
+
+ }
+
+/*****************************************************************************/
+
+inline int32 dng_lossless_decoder::get_bit ()
+ {
+
+ if (!bitsLeft)
+ FillBitBuffer (1);
+
+ return (int32) ((getBuffer >> (--bitsLeft)) & 1);
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * HuffDecode --
+ *
+ * Taken from Figure F.16: extract next coded symbol from
+ * input stream. This should becode a macro.
+ *
+ * Results:
+ * Next coded symbol
+ *
+ * Side effects:
+ * Bitstream is parsed.
+ *
+ *--------------------------------------------------------------
+ */
+
+inline int32 dng_lossless_decoder::HuffDecode (HuffmanTable *htbl)
+ {
+
+ // If the huffman code is less than 8 bits, we can use the fast
+ // table lookup to get its value. It's more than 8 bits about
+ // 3-4% of the time.
+
+ int32 code = show_bits8 ();
+
+ if (htbl->numbits [code])
+ {
+
+ flush_bits (htbl->numbits [code]);
+
+ return htbl->value [code];
+
+ }
+
+ else
+ {
+
+ flush_bits (8);
+
+ int32 l = 8;
+
+ while (code > htbl->maxcode [l])
+ {
+ code = (code << 1) | get_bit ();
+ l++;
+ }
+
+ // With garbage input we may reach the sentinel value l = 17.
+
+ if (l > 16)
+ {
+ return 0; // fake a zero as the safest result
+ }
+ else
+ {
+ return htbl->huffval [htbl->valptr [l] +
+ ((int32) (code - htbl->mincode [l]))];
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * HuffExtend --
+ *
+ * Code and table for Figure F.12: extend sign bit
+ *
+ * Results:
+ * The extended value.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+inline void dng_lossless_decoder::HuffExtend (int32 &x, int32 s)
+ {
+
+ if (x < (0x08000 >> (16 - s)))
+ {
+ x += -(1 << s) + 1;
+ }
+
+ }
+
+/*****************************************************************************/
+
+// Called from DecodeImage () to write one row.
+
+void dng_lossless_decoder::PmPutRow (MCU *buf,
+ int32 numComp,
+ int32 numCol,
+ int32 /* row */)
+ {
+
+ uint16 *sPtr = &buf [0] [0];
+
+ uint32 pixels = numCol * numComp;
+
+ fSpooler->Spool (sPtr, pixels * (uint32) sizeof (uint16));
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DecodeFirstRow --
+ *
+ * Decode the first raster line of samples at the start of
+ * the scan and at the beginning of each restart interval.
+ * This includes modifying the component value so the real
+ * value, not the difference is returned.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Bitstream is parsed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::DecodeFirstRow (MCU *curRowBuf)
+ {
+
+ int32 compsInScan = info.compsInScan;
+
+ // Process the first column in the row.
+
+ for (int32 curComp = 0; curComp < compsInScan; curComp++)
+ {
+
+ int32 ci = info.MCUmembership [curComp];
+
+ JpegComponentInfo *compptr = info.curCompInfo [ci];
+
+ HuffmanTable *dctbl = info.dcHuffTblPtrs [compptr->dcTblNo];
+
+ // Section F.2.2.1: decode the difference
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (dctbl);
+
+ if (s)
+ {
+
+ if (s == 16 && !fBug16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ // Add the predictor to the difference.
+
+ int32 Pr = info.dataPrecision;
+ int32 Pt = info.Pt;
+
+ curRowBuf [0] [curComp] = (ComponentType) (d + (1 << (Pr-Pt-1)));
+
+ }
+
+ // Process the rest of the row.
+
+ int32 numCOL = info.imageWidth;
+
+ for (int32 col = 1; col < numCOL; col++)
+ {
+
+ for (int32 curComp = 0; curComp < compsInScan; curComp++)
+ {
+
+ int32 ci = info.MCUmembership [curComp];
+
+ JpegComponentInfo *compptr = info.curCompInfo [ci];
+
+ HuffmanTable *dctbl = info.dcHuffTblPtrs [compptr->dcTblNo];
+
+ // Section F.2.2.1: decode the difference
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (dctbl);
+
+ if (s)
+ {
+
+ if (s == 16 && !fBug16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ // Add the predictor to the difference.
+
+ curRowBuf [col] [curComp] = (ComponentType) (d + curRowBuf [col-1] [curComp]);
+
+ }
+
+ }
+
+ // Update the restart counter
+
+ if (info.restartInRows)
+ {
+ info.restartRowsToGo--;
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * DecodeImage --
+ *
+ * Decode the input stream. This includes modifying
+ * the component value so the real value, not the
+ * difference is returned.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Bitstream is parsed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_decoder::DecodeImage ()
+ {
+
+ #define swap(type,a,b) {type c; c=(a); (a)=(b); (b)=c;}
+
+ int32 numCOL = info.imageWidth;
+ int32 numROW = info.imageHeight;
+ int32 compsInScan = info.compsInScan;
+
+ // Precompute the decoding table for each table.
+
+ HuffmanTable *ht [4];
+
+ for (int32 curComp = 0; curComp < compsInScan; curComp++)
+ {
+
+ int32 ci = info.MCUmembership [curComp];
+
+ JpegComponentInfo *compptr = info.curCompInfo [ci];
+
+ ht [curComp] = info.dcHuffTblPtrs [compptr->dcTblNo];
+
+ }
+
+ MCU *prevRowBuf = mcuROW1;
+ MCU *curRowBuf = mcuROW2;
+
+ #if qSupportCanon_sRAW
+
+ // Canon sRAW support
+
+ if (info.compInfo [0].hSampFactor == 2 &&
+ info.compInfo [0].vSampFactor == 1)
+ {
+
+ for (int32 row = 0; row < numROW; row++)
+ {
+
+ // Initialize predictors.
+
+ int32 p0;
+ int32 p1;
+ int32 p2;
+
+ if (row == 0)
+ {
+ p0 = 1 << 14;
+ p1 = 1 << 14;
+ p2 = 1 << 14;
+ }
+
+ else
+ {
+ p0 = prevRowBuf [0] [0];
+ p1 = prevRowBuf [0] [1];
+ p2 = prevRowBuf [0] [2];
+ }
+
+ for (int32 col = 0; col < numCOL; col += 2)
+ {
+
+ // Read first luminance component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [0]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p0 += d;
+
+ curRowBuf [col] [0] = (ComponentType) p0;
+
+ }
+
+ // Read second luminance component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [0]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p0 += d;
+
+ curRowBuf [col + 1] [0] = (ComponentType) p0;
+
+ }
+
+ // Read first chroma component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [1]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p1 += d;
+
+ curRowBuf [col ] [1] = (ComponentType) p1;
+ curRowBuf [col + 1] [1] = (ComponentType) p1;
+
+ }
+
+ // Read second chroma component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [2]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p2 += d;
+
+ curRowBuf [col ] [2] = (ComponentType) p2;
+ curRowBuf [col + 1] [2] = (ComponentType) p2;
+
+ }
+
+ }
+
+ PmPutRow (curRowBuf, compsInScan, numCOL, row);
+
+ swap (MCU *, prevRowBuf, curRowBuf);
+
+ }
+
+ return;
+
+ }
+
+ if (info.compInfo [0].hSampFactor == 2 &&
+ info.compInfo [0].vSampFactor == 2)
+ {
+
+ for (int32 row = 0; row < numROW; row += 2)
+ {
+
+ // Initialize predictors.
+
+ int32 p0;
+ int32 p1;
+ int32 p2;
+
+ if (row == 0)
+ {
+ p0 = 1 << 14;
+ p1 = 1 << 14;
+ p2 = 1 << 14;
+ }
+
+ else
+ {
+ p0 = prevRowBuf [0] [0];
+ p1 = prevRowBuf [0] [1];
+ p2 = prevRowBuf [0] [2];
+ }
+
+ for (int32 col = 0; col < numCOL; col += 2)
+ {
+
+ // Read first luminance component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [0]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p0 += d;
+
+ prevRowBuf [col] [0] = (ComponentType) p0;
+
+ }
+
+ // Read second luminance component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [0]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p0 += d;
+
+ prevRowBuf [col + 1] [0] = (ComponentType) p0;
+
+ }
+
+ // Read third luminance component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [0]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p0 += d;
+
+ curRowBuf [col] [0] = (ComponentType) p0;
+
+ }
+
+ // Read fourth luminance component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [0]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p0 += d;
+
+ curRowBuf [col + 1] [0] = (ComponentType) p0;
+
+ }
+
+ // Read first chroma component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [1]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p1 += d;
+
+ prevRowBuf [col ] [1] = (ComponentType) p1;
+ prevRowBuf [col + 1] [1] = (ComponentType) p1;
+
+ curRowBuf [col ] [1] = (ComponentType) p1;
+ curRowBuf [col + 1] [1] = (ComponentType) p1;
+
+ }
+
+ // Read second chroma component.
+
+ {
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [2]);
+
+ if (s)
+ {
+
+ if (s == 16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ p2 += d;
+
+ prevRowBuf [col ] [2] = (ComponentType) p2;
+ prevRowBuf [col + 1] [2] = (ComponentType) p2;
+
+ curRowBuf [col ] [2] = (ComponentType) p2;
+ curRowBuf [col + 1] [2] = (ComponentType) p2;
+
+ }
+
+ }
+
+ PmPutRow (prevRowBuf, compsInScan, numCOL, row);
+ PmPutRow (curRowBuf, compsInScan, numCOL, row);
+
+ }
+
+ return;
+
+ }
+
+ #endif
+
+ #if qSupportHasselblad_3FR
+
+ if (info.Ss == 8)
+ {
+
+ fHasselblad3FR = true;
+
+ for (int32 row = 0; row < numROW; row++)
+ {
+
+ int32 p0 = 32768;
+ int32 p1 = 32768;
+
+ for (int32 col = 0; col < numCOL; col += 2)
+ {
+
+ int32 s0 = HuffDecode (ht [0]);
+ int32 s1 = HuffDecode (ht [0]);
+
+ if (s0)
+ {
+ int32 d = get_bits (s0);
+ if (s0 == 16)
+ {
+ d = -32768;
+ }
+ else
+ {
+ HuffExtend (d, s0);
+ }
+ p0 += d;
+ }
+
+ if (s1)
+ {
+ int32 d = get_bits (s1);
+ if (s1 == 16)
+ {
+ d = -32768;
+ }
+ else
+ {
+ HuffExtend (d, s1);
+ }
+ p1 += d;
+ }
+
+ curRowBuf [col ] [0] = (ComponentType) p0;
+ curRowBuf [col + 1] [0] = (ComponentType) p1;
+
+ }
+
+ PmPutRow (curRowBuf, compsInScan, numCOL, row);
+
+ }
+
+ return;
+
+ }
+
+ #endif
+
+ // Decode the first row of image. Output the row and
+ // turn this row into a previous row for later predictor
+ // calculation.
+
+ DecodeFirstRow (mcuROW1);
+
+ PmPutRow (mcuROW1, compsInScan, numCOL, 0);
+
+ // Process each row.
+
+ for (int32 row = 1; row < numROW; row++)
+ {
+
+ // Account for restart interval, process restart marker if needed.
+
+ if (info.restartInRows)
+ {
+
+ if (info.restartRowsToGo == 0)
+ {
+
+ ProcessRestart ();
+
+ // Reset predictors at restart.
+
+ DecodeFirstRow (curRowBuf);
+
+ PmPutRow (curRowBuf, compsInScan, numCOL, row);
+
+ swap (MCU *, prevRowBuf, curRowBuf);
+
+ continue;
+
+ }
+
+ info.restartRowsToGo--;
+
+ }
+
+ // The upper neighbors are predictors for the first column.
+
+ for (int32 curComp = 0; curComp < compsInScan; curComp++)
+ {
+
+ // Section F.2.2.1: decode the difference
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [curComp]);
+
+ if (s)
+ {
+
+ if (s == 16 && !fBug16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ // First column of row above is predictor for first column.
+
+ curRowBuf [0] [curComp] = (ComponentType) (d + prevRowBuf [0] [curComp]);
+
+ }
+
+ // For the rest of the column on this row, predictor
+ // calculations are based on PSV.
+
+ if (compsInScan == 2 && info.Ss == 1)
+ {
+
+ // This is the combination used by both the Canon and Kodak raw formats.
+ // Unrolling the general case logic results in a significant speed increase.
+
+ uint16 *dPtr = &curRowBuf [1] [0];
+
+ int32 prev0 = dPtr [-2];
+ int32 prev1 = dPtr [-1];
+
+ for (int32 col = 1; col < numCOL; col++)
+ {
+
+ int32 s = HuffDecode (ht [0]);
+
+ if (s)
+ {
+
+ int32 d;
+
+ if (s == 16 && !fBug16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ prev0 += d;
+
+ }
+
+ s = HuffDecode (ht [1]);
+
+ if (s)
+ {
+
+ int32 d;
+
+ if (s == 16 && !fBug16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ prev1 += d;
+
+ }
+
+ dPtr [0] = (uint16) prev0;
+ dPtr [1] = (uint16) prev1;
+
+ dPtr += 2;
+
+ }
+
+ }
+
+ else
+ {
+
+ for (int32 col = 1; col < numCOL; col++)
+ {
+
+ for (int32 curComp = 0; curComp < compsInScan; curComp++)
+ {
+
+ // Section F.2.2.1: decode the difference
+
+ int32 d = 0;
+
+ int32 s = HuffDecode (ht [curComp]);
+
+ if (s)
+ {
+
+ if (s == 16 && !fBug16)
+ {
+ d = -32768;
+ }
+
+ else
+ {
+ d = get_bits (s);
+ HuffExtend (d, s);
+ }
+
+ }
+
+ // Predict the pixel value.
+
+ int32 predictor = QuickPredict (col,
+ curComp,
+ curRowBuf,
+ prevRowBuf);
+
+ // Save the difference.
+
+ curRowBuf [col] [curComp] = (ComponentType) (d + predictor);
+
+ }
+
+ }
+
+ }
+
+ PmPutRow (curRowBuf, compsInScan, numCOL, row);
+
+ swap (MCU *, prevRowBuf, curRowBuf);
+
+ }
+
+ #undef swap
+
+ }
+
+/*****************************************************************************/
+
+void dng_lossless_decoder::StartRead (uint32 &imageWidth,
+ uint32 &imageHeight,
+ uint32 &imageChannels)
+ {
+
+ ReadFileHeader ();
+ ReadScanHeader ();
+ DecoderStructInit ();
+ HuffDecoderInit ();
+
+ imageWidth = info.imageWidth;
+ imageHeight = info.imageHeight;
+ imageChannels = info.compsInScan;
+
+ }
+
+/*****************************************************************************/
+
+void dng_lossless_decoder::FinishRead ()
+ {
+
+ DecodeImage ();
+
+ }
+
+/*****************************************************************************/
+
+void DecodeLosslessJPEG (dng_stream &stream,
+ dng_spooler &spooler,
+ uint32 minDecodedSize,
+ uint32 maxDecodedSize,
+ bool bug16)
+ {
+
+ dng_lossless_decoder decoder (&stream,
+ &spooler,
+ bug16);
+
+ uint32 imageWidth;
+ uint32 imageHeight;
+ uint32 imageChannels;
+
+ decoder.StartRead (imageWidth,
+ imageHeight,
+ imageChannels);
+
+ uint32 decodedSize = imageWidth *
+ imageHeight *
+ imageChannels *
+ (uint32) sizeof (uint16);
+
+ if (decodedSize < minDecodedSize ||
+ decodedSize > maxDecodedSize)
+ {
+ ThrowBadFormat ();
+ }
+
+ decoder.FinishRead ();
+
+ }
+
+/*****************************************************************************/
+
+class dng_lossless_encoder
+ {
+
+ private:
+
+ const uint16 *fSrcData;
+
+ uint32 fSrcRows;
+ uint32 fSrcCols;
+ uint32 fSrcChannels;
+ uint32 fSrcBitDepth;
+
+ int32 fSrcRowStep;
+ int32 fSrcColStep;
+
+ dng_stream &fStream;
+
+ HuffmanTable huffTable [4];
+
+ uint32 freqCount [4] [257];
+
+ // Current bit-accumulation buffer
+
+ int32 huffPutBuffer;
+ int32 huffPutBits;
+
+ // Lookup table for number of bits in an 8 bit value.
+
+ int numBitsTable [256];
+
+ public:
+
+ dng_lossless_encoder (const uint16 *srcData,
+ uint32 srcRows,
+ uint32 srcCols,
+ uint32 srcChannels,
+ uint32 srcBitDepth,
+ int32 srcRowStep,
+ int32 srcColStep,
+ dng_stream &stream);
+
+ void Encode ();
+
+ private:
+
+ void EmitByte (uint8 value);
+
+ void EmitBits (int code, int size);
+
+ void FlushBits ();
+
+ void CountOneDiff (int diff, uint32 *countTable);
+
+ void EncodeOneDiff (int diff, HuffmanTable *dctbl);
+
+ void FreqCountSet ();
+
+ void HuffEncode ();
+
+ void GenHuffCoding (HuffmanTable *htbl, uint32 *freq);
+
+ void HuffOptimize ();
+
+ void EmitMarker (JpegMarker mark);
+
+ void Emit2bytes (int value);
+
+ void EmitDht (int index);
+
+ void EmitSof (JpegMarker code);
+
+ void EmitSos ();
+
+ void WriteFileHeader ();
+
+ void WriteScanHeader ();
+
+ void WriteFileTrailer ();
+
+ };
+
+/*****************************************************************************/
+
+dng_lossless_encoder::dng_lossless_encoder (const uint16 *srcData,
+ uint32 srcRows,
+ uint32 srcCols,
+ uint32 srcChannels,
+ uint32 srcBitDepth,
+ int32 srcRowStep,
+ int32 srcColStep,
+ dng_stream &stream)
+
+ : fSrcData (srcData )
+ , fSrcRows (srcRows )
+ , fSrcCols (srcCols )
+ , fSrcChannels (srcChannels)
+ , fSrcBitDepth (srcBitDepth)
+ , fSrcRowStep (srcRowStep )
+ , fSrcColStep (srcColStep )
+ , fStream (stream )
+
+ , huffPutBuffer (0)
+ , huffPutBits (0)
+
+ {
+
+ // Initialize number of bits lookup table.
+
+ numBitsTable [0] = 0;
+
+ for (int i = 1; i < 256; i++)
+ {
+
+ int temp = i;
+ int nbits = 1;
+
+ while (temp >>= 1)
+ {
+ nbits++;
+ }
+
+ numBitsTable [i] = nbits;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+inline void dng_lossless_encoder::EmitByte (uint8 value)
+ {
+
+ fStream.Put_uint8 (value);
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmitBits --
+ *
+ * Code for outputting bits to the file
+ *
+ * Only the right 24 bits of huffPutBuffer are used; the valid
+ * bits are left-justified in this part. At most 16 bits can be
+ * passed to EmitBits in one call, and we never retain more than 7
+ * bits in huffPutBuffer between calls, so 24 bits are
+ * sufficient.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * huffPutBuffer and huffPutBits are updated.
+ *
+ *--------------------------------------------------------------
+ */
+
+inline void dng_lossless_encoder::EmitBits (int code, int size)
+ {
+
+ DNG_ASSERT (size != 0, "Bad Huffman table entry");
+
+ int putBits = size;
+ int putBuffer = code;
+
+ putBits += huffPutBits;
+
+ putBuffer <<= 24 - putBits;
+ putBuffer |= huffPutBuffer;
+
+ while (putBits >= 8)
+ {
+
+ uint8 c = (uint8) (putBuffer >> 16);
+
+ // Output whole bytes we've accumulated with byte stuffing
+
+ EmitByte (c);
+
+ if (c == 0xFF)
+ {
+ EmitByte (0);
+ }
+
+ putBuffer <<= 8;
+ putBits -= 8;
+
+ }
+
+ huffPutBuffer = putBuffer;
+ huffPutBits = putBits;
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FlushBits --
+ *
+ * Flush any remaining bits in the bit buffer. Used before emitting
+ * a marker.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * huffPutBuffer and huffPutBits are reset
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::FlushBits ()
+ {
+
+ // The first call forces output of any partial bytes.
+
+ EmitBits (0x007F, 7);
+
+ // We can then zero the buffer.
+
+ huffPutBuffer = 0;
+ huffPutBits = 0;
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * CountOneDiff --
+ *
+ * Count the difference value in countTable.
+ *
+ * Results:
+ * diff is counted in countTable.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+inline void dng_lossless_encoder::CountOneDiff (int diff, uint32 *countTable)
+ {
+
+ // Encode the DC coefficient difference per section F.1.2.1
+
+ int temp = diff;
+
+ if (temp < 0)
+ {
+
+ temp = -temp;
+
+ }
+
+ // Find the number of bits needed for the magnitude of the coefficient
+
+ int nbits = temp >= 256 ? numBitsTable [temp >> 8 ] + 8
+ : numBitsTable [temp & 0xFF];
+
+ // Update count for this bit length
+
+ countTable [nbits] ++;
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EncodeOneDiff --
+ *
+ * Encode a single difference value.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+inline void dng_lossless_encoder::EncodeOneDiff (int diff, HuffmanTable *dctbl)
+ {
+
+ // Encode the DC coefficient difference per section F.1.2.1
+
+ int temp = diff;
+ int temp2 = diff;
+
+ if (temp < 0)
+ {
+
+ temp = -temp;
+
+ // For a negative input, want temp2 = bitwise complement of
+ // abs (input). This code assumes we are on a two's complement
+ // machine.
+
+ temp2--;
+
+ }
+
+ // Find the number of bits needed for the magnitude of the coefficient
+
+ int nbits = temp >= 256 ? numBitsTable [temp >> 8 ] + 8
+ : numBitsTable [temp & 0xFF];
+
+ // Emit the Huffman-coded symbol for the number of bits
+
+ EmitBits (dctbl->ehufco [nbits],
+ dctbl->ehufsi [nbits]);
+
+ // Emit that number of bits of the value, if positive,
+ // or the complement of its magnitude, if negative.
+
+ // If the number of bits is 16, there is only one possible difference
+ // value (-32786), so the lossless JPEG spec says not to output anything
+ // in that case. So we only need to output the diference value if
+ // the number of bits is between 1 and 15.
+
+ if (nbits & 15)
+ {
+
+ EmitBits (temp2 & (0x0FFFF >> (16 - nbits)),
+ nbits);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * FreqCountSet --
+ *
+ * Count the times each category symbol occurs in this image.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The freqCount has counted all category
+ * symbols appeared in the image.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::FreqCountSet ()
+ {
+
+ memset (freqCount, 0, sizeof (freqCount));
+
+ DNG_ASSERT ((int32)fSrcRows >= 0, "dng_lossless_encoder::FreqCountSet: fSrcRpws too large.");
+
+ for (int32 row = 0; row < (int32)fSrcRows; row++)
+ {
+
+ const uint16 *sPtr = fSrcData + row * fSrcRowStep;
+
+ // Initialize predictors for this row.
+
+ int32 predictor [4];
+
+ for (int32 channel = 0; channel < (int32)fSrcChannels; channel++)
+ {
+
+ if (row == 0)
+ predictor [channel] = 1 << (fSrcBitDepth - 1);
+
+ else
+ predictor [channel] = sPtr [channel - fSrcRowStep];
+
+ }
+
+ // Unroll most common case of two channels
+
+ if (fSrcChannels == 2)
+ {
+
+ int32 pred0 = predictor [0];
+ int32 pred1 = predictor [1];
+
+ uint32 srcCols = fSrcCols;
+ int32 srcColStep = fSrcColStep;
+
+ for (uint32 col = 0; col < srcCols; col++)
+ {
+
+ int32 pixel0 = sPtr [0];
+ int32 pixel1 = sPtr [1];
+
+ int16 diff0 = (int16) (pixel0 - pred0);
+ int16 diff1 = (int16) (pixel1 - pred1);
+
+ CountOneDiff (diff0, freqCount [0]);
+ CountOneDiff (diff1, freqCount [1]);
+
+ pred0 = pixel0;
+ pred1 = pixel1;
+
+ sPtr += srcColStep;
+
+ }
+
+ }
+
+ // General case.
+
+ else
+ {
+
+ for (uint32 col = 0; col < fSrcCols; col++)
+ {
+
+ for (uint32 channel = 0; channel < fSrcChannels; channel++)
+ {
+
+ int32 pixel = sPtr [channel];
+
+ int16 diff = (int16) (pixel - predictor [channel]);
+
+ CountOneDiff (diff, freqCount [channel]);
+
+ predictor [channel] = pixel;
+
+ }
+
+ sPtr += fSrcColStep;
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * HuffEncode --
+ *
+ * Encode and output Huffman-compressed image data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::HuffEncode ()
+ {
+
+ DNG_ASSERT ((int32)fSrcRows >= 0, "dng_lossless_encoder::HuffEncode: fSrcRows too large.");
+
+ for (int32 row = 0; row < (int32)fSrcRows; row++)
+ {
+
+ const uint16 *sPtr = fSrcData + row * fSrcRowStep;
+
+ // Initialize predictors for this row.
+
+ int32 predictor [4];
+
+ for (int32 channel = 0; channel < (int32)fSrcChannels; channel++)
+ {
+
+ if (row == 0)
+ predictor [channel] = 1 << (fSrcBitDepth - 1);
+
+ else
+ predictor [channel] = sPtr [channel - fSrcRowStep];
+
+ }
+
+ // Unroll most common case of two channels
+
+ if (fSrcChannels == 2)
+ {
+
+ int32 pred0 = predictor [0];
+ int32 pred1 = predictor [1];
+
+ uint32 srcCols = fSrcCols;
+ int32 srcColStep = fSrcColStep;
+
+ for (uint32 col = 0; col < srcCols; col++)
+ {
+
+ int32 pixel0 = sPtr [0];
+ int32 pixel1 = sPtr [1];
+
+ int16 diff0 = (int16) (pixel0 - pred0);
+ int16 diff1 = (int16) (pixel1 - pred1);
+
+ EncodeOneDiff (diff0, &huffTable [0]);
+ EncodeOneDiff (diff1, &huffTable [1]);
+
+ pred0 = pixel0;
+ pred1 = pixel1;
+
+ sPtr += srcColStep;
+
+ }
+
+ }
+
+ // General case.
+
+ else
+ {
+
+ for (uint32 col = 0; col < fSrcCols; col++)
+ {
+
+ for (uint32 channel = 0; channel < fSrcChannels; channel++)
+ {
+
+ int32 pixel = sPtr [channel];
+
+ int16 diff = (int16) (pixel - predictor [channel]);
+
+ EncodeOneDiff (diff, &huffTable [channel]);
+
+ predictor [channel] = pixel;
+
+ }
+
+ sPtr += fSrcColStep;
+
+ }
+
+ }
+
+ }
+
+ FlushBits ();
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * GenHuffCoding --
+ *
+ * Generate the optimal coding for the given counts.
+ * This algorithm is explained in section K.2 of the
+ * JPEG standard.
+ *
+ * Results:
+ * htbl->bits and htbl->huffval are constructed.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::GenHuffCoding (HuffmanTable *htbl, uint32 *freq)
+ {
+
+ int i;
+ int j;
+
+ const int MAX_CLEN = 32; // assumed maximum initial code length
+
+ uint8 bits [MAX_CLEN + 1]; // bits [k] = # of symbols with code length k
+ short codesize [257]; // codesize [k] = code length of symbol k
+ short others [257]; // next symbol in current branch of tree
+
+ memset (bits , 0, sizeof (bits ));
+ memset (codesize, 0, sizeof (codesize));
+
+ for (i = 0; i < 257; i++)
+ others [i] = -1; // init links to empty
+
+ // Including the pseudo-symbol 256 in the Huffman procedure guarantees
+ // that no real symbol is given code-value of all ones, because 256
+ // will be placed in the largest codeword category.
+
+ freq [256] = 1; // make sure there is a nonzero count
+
+ // Huffman's basic algorithm to assign optimal code lengths to symbols
+
+ while (true)
+ {
+
+ // Find the smallest nonzero frequency, set c1 = its symbol.
+ // In case of ties, take the larger symbol number.
+
+ int c1 = -1;
+
+ uint32 v = 0xFFFFFFFF;
+
+ for (i = 0; i <= 256; i++)
+ {
+
+ if (freq [i] && freq [i] <= v)
+ {
+ v = freq [i];
+ c1 = i;
+ }
+
+ }
+
+ // Find the next smallest nonzero frequency, set c2 = its symbol.
+ // In case of ties, take the larger symbol number.
+
+ int c2 = -1;
+
+ v = 0xFFFFFFFF;
+
+ for (i = 0; i <= 256; i++)
+ {
+
+ if (freq [i] && freq [i] <= v && i != c1)
+ {
+ v = freq [i];
+ c2 = i;
+ }
+
+ }
+
+ // Done if we've merged everything into one frequency.
+
+ if (c2 < 0)
+ break;
+
+ // Else merge the two counts/trees.
+
+ freq [c1] += freq [c2];
+ freq [c2] = 0;
+
+ // Increment the codesize of everything in c1's tree branch.
+
+ codesize [c1] ++;
+
+ while (others [c1] >= 0)
+ {
+ c1 = others [c1];
+ codesize [c1] ++;
+ }
+
+ // chain c2 onto c1's tree branch
+
+ others [c1] = (short) c2;
+
+ // Increment the codesize of everything in c2's tree branch.
+
+ codesize [c2] ++;
+
+ while (others [c2] >= 0)
+ {
+ c2 = others [c2];
+ codesize [c2] ++;
+ }
+
+ }
+
+ // Now count the number of symbols of each code length.
+
+ for (i = 0; i <= 256; i++)
+ {
+
+ if (codesize [i])
+ {
+
+ // The JPEG standard seems to think that this can't happen,
+ // but I'm paranoid...
+
+ if (codesize [i] > MAX_CLEN)
+ {
+
+ DNG_REPORT ("Huffman code size table overflow");
+
+ ThrowProgramError ();
+
+ }
+
+ bits [codesize [i]]++;
+
+ }
+
+ }
+
+ // JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
+ // Huffman procedure assigned any such lengths, we must adjust the coding.
+ // Here is what the JPEG spec says about how this next bit works:
+ // Since symbols are paired for the longest Huffman code, the symbols are
+ // removed from this length category two at a time. The prefix for the pair
+ // (which is one bit shorter) is allocated to one of the pair; then,
+ // skipping the BITS entry for that prefix length, a code word from the next
+ // shortest nonzero BITS entry is converted into a prefix for two code words
+ // one bit longer.
+
+ for (i = MAX_CLEN; i > 16; i--)
+ {
+
+ while (bits [i] > 0)
+ {
+
+ // Kludge: I have never been able to test this logic, and there
+ // are comments on the web that this encoder has bugs with 16-bit
+ // data, so just throw an error if we get here and revert to a
+ // default table. - tknoll 12/1/03.
+
+ DNG_REPORT ("Info: Optimal huffman table bigger than 16 bits");
+
+ ThrowProgramError ();
+
+ // Original logic:
+
+ j = i - 2; // find length of new prefix to be used
+
+ while (bits [j] == 0)
+ j--;
+
+ bits [i ] -= 2; // remove two symbols
+ bits [i - 1] ++; // one goes in this length
+ bits [j + 1] += 2; // two new symbols in this length
+ bits [j ] --; // symbol of this length is now a prefix
+
+ }
+
+ }
+
+ // Remove the count for the pseudo-symbol 256 from
+ // the largest codelength.
+
+ while (bits [i] == 0) // find largest codelength still in use
+ i--;
+
+ bits [i] --;
+
+ // Return final symbol counts (only for lengths 0..16).
+
+ memcpy (htbl->bits, bits, sizeof (htbl->bits));
+
+ // Return a list of the symbols sorted by code length.
+ // It's not real clear to me why we don't need to consider the codelength
+ // changes made above, but the JPEG spec seems to think this works.
+
+ int p = 0;
+
+ for (i = 1; i <= MAX_CLEN; i++)
+ {
+
+ for (j = 0; j <= 255; j++)
+ {
+
+ if (codesize [j] == i)
+ {
+ htbl->huffval [p] = (uint8) j;
+ p++;
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * HuffOptimize --
+ *
+ * Find the best coding parameters for a Huffman-coded scan.
+ * When called, the scan data has already been converted to
+ * a sequence of MCU groups of source image samples, which
+ * are stored in a "big" array, mcuTable.
+ *
+ * It counts the times each category symbol occurs. Based on
+ * this counting, optimal Huffman tables are built. Then it
+ * uses this optimal Huffman table and counting table to find
+ * the best PSV.
+ *
+ * Results:
+ * Optimal Huffman tables are retured in cPtr->dcHuffTblPtrs[tbl].
+ * Best PSV is retured in cPtr->Ss.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::HuffOptimize ()
+ {
+
+ // Collect the frequency counts.
+
+ FreqCountSet ();
+
+ // Generate Huffman encoding tables.
+
+ for (uint32 channel = 0; channel < fSrcChannels; channel++)
+ {
+
+ try
+ {
+
+ GenHuffCoding (&huffTable [channel], freqCount [channel]);
+
+ }
+
+ catch (...)
+ {
+
+ DNG_REPORT ("Info: Reverting to default huffman table");
+
+ for (uint32 j = 0; j <= 256; j++)
+ {
+
+ freqCount [channel] [j] = (j <= 16 ? 1 : 0);
+
+ }
+
+ GenHuffCoding (&huffTable [channel], freqCount [channel]);
+
+ }
+
+ FixHuffTbl (&huffTable [channel]);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmitMarker --
+ *
+ * Emit a marker code into the output stream.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::EmitMarker (JpegMarker mark)
+ {
+
+ EmitByte (0xFF);
+ EmitByte ((uint8) mark);
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Emit2bytes --
+ *
+ * Emit a 2-byte integer; these are always MSB first in JPEG
+ * files
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::Emit2bytes (int value)
+ {
+
+ EmitByte ((value >> 8) & 0xFF);
+ EmitByte (value & 0xFF);
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmitDht --
+ *
+ * Emit a DHT marker, follwed by the huffman data.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * None
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::EmitDht (int index)
+ {
+
+ int i;
+
+ HuffmanTable *htbl = &huffTable [index];
+
+ EmitMarker (M_DHT);
+
+ int length = 0;
+
+ for (i = 1; i <= 16; i++)
+ length += htbl->bits [i];
+
+ Emit2bytes (length + 2 + 1 + 16);
+
+ EmitByte ((uint8) index);
+
+ for (i = 1; i <= 16; i++)
+ EmitByte (htbl->bits [i]);
+
+ for (i = 0; i < length; i++)
+ EmitByte (htbl->huffval [i]);
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmitSof --
+ *
+ * Emit a SOF marker plus data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::EmitSof (JpegMarker code)
+ {
+
+ EmitMarker (code);
+
+ Emit2bytes (3 * fSrcChannels + 2 + 5 + 1); // length
+
+ EmitByte ((uint8) fSrcBitDepth);
+
+ Emit2bytes (fSrcRows);
+ Emit2bytes (fSrcCols);
+
+ EmitByte ((uint8) fSrcChannels);
+
+ for (uint32 i = 0; i < fSrcChannels; i++)
+ {
+
+ EmitByte ((uint8) i);
+
+ EmitByte ((uint8) ((1 << 4) + 1)); // Not subsampled.
+
+ EmitByte (0); // Tq shall be 0 for lossless.
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * EmitSos --
+ *
+ * Emit a SOS marker plus data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::EmitSos ()
+ {
+
+ EmitMarker (M_SOS);
+
+ Emit2bytes (2 * fSrcChannels + 2 + 1 + 3); // length
+
+ EmitByte ((uint8) fSrcChannels); // Ns
+
+ for (uint32 i = 0; i < fSrcChannels; i++)
+ {
+
+ // Cs,Td,Ta
+
+ EmitByte ((uint8) i);
+ EmitByte ((uint8) (i << 4));
+
+ }
+
+ EmitByte (1); // PSV - hardcoded - tknoll
+ EmitByte (0); // Spectral selection end - Se
+ EmitByte (0); // The point transform parameter
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WriteFileHeader --
+ *
+ * Write the file header.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::WriteFileHeader ()
+ {
+
+ EmitMarker (M_SOI); // first the SOI
+
+ EmitSof (M_SOF3);
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WriteScanHeader --
+ *
+ * Write the start of a scan (everything through the SOS marker).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::WriteScanHeader ()
+ {
+
+ // Emit Huffman tables.
+
+ for (uint32 i = 0; i < fSrcChannels; i++)
+ {
+
+ EmitDht (i);
+
+ }
+
+ EmitSos ();
+
+ }
+
+/*****************************************************************************/
+
+/*
+ *--------------------------------------------------------------
+ *
+ * WriteFileTrailer --
+ *
+ * Write the End of image marker at the end of a JPEG file.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void dng_lossless_encoder::WriteFileTrailer ()
+ {
+
+ EmitMarker (M_EOI);
+
+ }
+
+/*****************************************************************************/
+
+void dng_lossless_encoder::Encode ()
+ {
+
+ DNG_ASSERT (fSrcChannels <= 4, "Too many components in scan");
+
+ // Count the times each difference category occurs.
+ // Construct the optimal Huffman table.
+
+ HuffOptimize ();
+
+ // Write the frame and scan headers.
+
+ WriteFileHeader ();
+
+ WriteScanHeader ();
+
+ // Encode the image.
+
+ HuffEncode ();
+
+ // Clean up everything.
+
+ WriteFileTrailer ();
+
+ }
+
+/*****************************************************************************/
+
+void EncodeLosslessJPEG (const uint16 *srcData,
+ uint32 srcRows,
+ uint32 srcCols,
+ uint32 srcChannels,
+ uint32 srcBitDepth,
+ int32 srcRowStep,
+ int32 srcColStep,
+ dng_stream &stream)
+ {
+
+ dng_lossless_encoder encoder (srcData,
+ srcRows,
+ srcCols,
+ srcChannels,
+ srcBitDepth,
+ srcRowStep,
+ srcColStep,
+ stream);
+
+ encoder.Encode ();
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_lossless_jpeg.h b/source/dng_lossless_jpeg.h
index be8bb50..f50d637 100644
--- a/source/dng_lossless_jpeg.h
+++ b/source/dng_lossless_jpeg.h
@@ -1,69 +1,69 @@
-/*****************************************************************************/
-// Copyright 2006 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_lossless_jpeg.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Functions for encoding and decoding lossless JPEG format.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_lossless_jpeg__
-#define __dng_lossless_jpeg__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-class dng_spooler
- {
-
- protected:
-
- virtual ~dng_spooler ()
- {
- }
-
- public:
-
- virtual void Spool (const void *data,
- uint32 count) = 0;
-
- };
-
-/*****************************************************************************/
-
-void DecodeLosslessJPEG (dng_stream &stream,
- dng_spooler &spooler,
- uint32 minDecodedSize,
- uint32 maxDecodedSize,
- bool bug16);
-
-/*****************************************************************************/
-
-void EncodeLosslessJPEG (const uint16 *srcData,
- uint32 srcRows,
- uint32 srcCols,
- uint32 srcChannels,
- uint32 srcBitDepth,
- int32 srcRowStep,
- int32 srcColStep,
- dng_stream &stream);
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_lossless_jpeg.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Functions for encoding and decoding lossless JPEG format.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_lossless_jpeg__
+#define __dng_lossless_jpeg__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+class dng_spooler
+ {
+
+ protected:
+
+ virtual ~dng_spooler ()
+ {
+ }
+
+ public:
+
+ virtual void Spool (const void *data,
+ uint32 count) = 0;
+
+ };
+
+/*****************************************************************************/
+
+void DecodeLosslessJPEG (dng_stream &stream,
+ dng_spooler &spooler,
+ uint32 minDecodedSize,
+ uint32 maxDecodedSize,
+ bool bug16);
+
+/*****************************************************************************/
+
+void EncodeLosslessJPEG (const uint16 *srcData,
+ uint32 srcRows,
+ uint32 srcCols,
+ uint32 srcChannels,
+ uint32 srcBitDepth,
+ int32 srcRowStep,
+ int32 srcColStep,
+ dng_stream &stream);
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_matrix.cpp b/source/dng_matrix.cpp
index b96f80b..894e419 100644
--- a/source/dng_matrix.cpp
+++ b/source/dng_matrix.cpp
@@ -1,1080 +1,1080 @@
-/*****************************************************************************/
-// Copyright 2006-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_matrix.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_matrix.h"
-
-#include "dng_exceptions.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_matrix::dng_matrix ()
-
- : fRows (0)
- , fCols (0)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_matrix::dng_matrix (uint32 rows,
- uint32 cols)
-
- : fRows (0)
- , fCols (0)
-
- {
-
- if (rows < 1 || rows > kMaxColorPlanes ||
- cols < 1 || cols > kMaxColorPlanes)
- {
-
- ThrowProgramError ();
-
- }
-
- fRows = rows;
- fCols = cols;
-
- for (uint32 row = 0; row < fRows; row++)
- for (uint32 col = 0; col < fCols; col++)
- {
-
- fData [row] [col] = 0.0;
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_matrix::dng_matrix (const dng_matrix &m)
-
- : fRows (m.fRows)
- , fCols (m.fCols)
-
- {
-
- for (uint32 row = 0; row < fRows; row++)
- for (uint32 col = 0; col < fCols; col++)
- {
-
- fData [row] [col] = m.fData [row] [col];
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_matrix::Clear ()
- {
-
- fRows = 0;
- fCols = 0;
-
- }
-
-/*****************************************************************************/
-
-void dng_matrix::SetIdentity (uint32 count)
- {
-
- *this = dng_matrix (count, count);
-
- for (uint32 j = 0; j < count; j++)
- {
-
- fData [j] [j] = 1.0;
-
- }
-
- }
-
-/******************************************************************************/
-
-bool dng_matrix::operator== (const dng_matrix &m) const
- {
-
- if (Rows () != m.Rows () ||
- Cols () != m.Cols ())
- {
-
- return false;
-
- }
-
- for (uint32 j = 0; j < Rows (); j++)
- for (uint32 k = 0; k < Cols (); k++)
- {
-
- if (fData [j] [k] != m.fData [j] [k])
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/******************************************************************************/
-
-bool dng_matrix::IsDiagonal () const
- {
-
- if (IsEmpty ())
- {
- return false;
- }
-
- if (Rows () != Cols ())
- {
- return false;
- }
-
- for (uint32 j = 0; j < Rows (); j++)
- for (uint32 k = 0; k < Cols (); k++)
- {
-
- if (j != k)
- {
-
- if (fData [j] [k] != 0.0)
- {
- return false;
- }
-
- }
-
- }
-
- return true;
-
- }
-
-/******************************************************************************/
-
-real64 dng_matrix::MaxEntry () const
- {
-
- if (IsEmpty ())
- {
-
- return 0.0;
-
- }
-
- real64 m = fData [0] [0];
-
- for (uint32 j = 0; j < Rows (); j++)
- for (uint32 k = 0; k < Cols (); k++)
- {
-
- m = Max_real64 (m, fData [j] [k]);
-
- }
-
- return m;
-
- }
-
-/******************************************************************************/
-
-real64 dng_matrix::MinEntry () const
- {
-
- if (IsEmpty ())
- {
-
- return 0.0;
-
- }
-
- real64 m = fData [0] [0];
-
- for (uint32 j = 0; j < Rows (); j++)
- for (uint32 k = 0; k < Cols (); k++)
- {
-
- m = Min_real64 (m, fData [j] [k]);
-
- }
-
- return m;
-
- }
-
-/*****************************************************************************/
-
-void dng_matrix::Scale (real64 factor)
- {
-
- for (uint32 j = 0; j < Rows (); j++)
- for (uint32 k = 0; k < Cols (); k++)
- {
-
- fData [j] [k] *= factor;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_matrix::Round (real64 factor)
- {
-
- real64 invFactor = 1.0 / factor;
-
- for (uint32 j = 0; j < Rows (); j++)
- for (uint32 k = 0; k < Cols (); k++)
- {
-
- fData [j] [k] = Round_int32 (fData [j] [k] * factor) * invFactor;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_matrix::SafeRound (real64 factor)
- {
-
- real64 invFactor = 1.0 / factor;
-
- for (uint32 j = 0; j < Rows (); j++)
- {
-
- // Round each row to the specified accuracy, but make sure the
- // a rounding does not affect the total of the elements in a row
- // more than necessary.
-
- real64 error = 0.0;
-
- for (uint32 k = 0; k < Cols (); k++)
- {
-
- fData [j] [k] += error;
-
- real64 rounded = Round_int32 (fData [j] [k] * factor) * invFactor;
-
- error = fData [j] [k] - rounded;
-
- fData [j] [k] = rounded;
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_matrix_3by3::dng_matrix_3by3 ()
-
- : dng_matrix (3, 3)
-
- {
- }
-
-/*****************************************************************************/
-
-dng_matrix_3by3::dng_matrix_3by3 (const dng_matrix &m)
-
- : dng_matrix (m)
-
- {
-
- if (Rows () != 3 ||
- Cols () != 3)
- {
-
- ThrowMatrixMath ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a01, real64 a02,
- real64 a10, real64 a11, real64 a12,
- real64 a20, real64 a21, real64 a22)
-
-
- : dng_matrix (3, 3)
-
- {
-
- fData [0] [0] = a00;
- fData [0] [1] = a01;
- fData [0] [2] = a02;
-
- fData [1] [0] = a10;
- fData [1] [1] = a11;
- fData [1] [2] = a12;
-
- fData [2] [0] = a20;
- fData [2] [1] = a21;
- fData [2] [2] = a22;
-
- }
-
-/*****************************************************************************/
-
-dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a11, real64 a22)
-
- : dng_matrix (3, 3)
-
- {
-
- fData [0] [0] = a00;
- fData [1] [1] = a11;
- fData [2] [2] = a22;
-
- }
-
-/*****************************************************************************/
-
-dng_matrix_4by3::dng_matrix_4by3 ()
-
- : dng_matrix (4, 3)
-
- {
- }
-
-/*****************************************************************************/
-
-dng_matrix_4by3::dng_matrix_4by3 (const dng_matrix &m)
-
- : dng_matrix (m)
-
- {
-
- if (Rows () != 4 ||
- Cols () != 3)
- {
-
- ThrowMatrixMath ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_matrix_4by3::dng_matrix_4by3 (real64 a00, real64 a01, real64 a02,
- real64 a10, real64 a11, real64 a12,
- real64 a20, real64 a21, real64 a22,
- real64 a30, real64 a31, real64 a32)
-
-
- : dng_matrix (4, 3)
-
- {
-
- fData [0] [0] = a00;
- fData [0] [1] = a01;
- fData [0] [2] = a02;
-
- fData [1] [0] = a10;
- fData [1] [1] = a11;
- fData [1] [2] = a12;
-
- fData [2] [0] = a20;
- fData [2] [1] = a21;
- fData [2] [2] = a22;
-
- fData [3] [0] = a30;
- fData [3] [1] = a31;
- fData [3] [2] = a32;
-
- }
-
-/*****************************************************************************/
-
-dng_vector::dng_vector ()
-
- : fCount (0)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_vector::dng_vector (uint32 count)
-
- : fCount (0)
-
- {
-
- if (count < 1 || count > kMaxColorPlanes)
- {
-
- ThrowProgramError ();
-
- }
-
- fCount = count;
-
- for (uint32 index = 0; index < fCount; index++)
- {
-
- fData [index] = 0.0;
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_vector::dng_vector (const dng_vector &v)
-
- : fCount (v.fCount)
-
- {
-
- for (uint32 index = 0; index < fCount; index++)
- {
-
- fData [index] = v.fData [index];
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_vector::Clear ()
- {
-
- fCount = 0;
-
- }
-
-/*****************************************************************************/
-
-void dng_vector::SetIdentity (uint32 count)
- {
-
- *this = dng_vector (count);
-
- for (uint32 j = 0; j < count; j++)
- {
-
- fData [j] = 1.0;
-
- }
-
- }
-
-/******************************************************************************/
-
-bool dng_vector::operator== (const dng_vector &v) const
- {
-
- if (Count () != v.Count ())
- {
-
- return false;
-
- }
-
- for (uint32 j = 0; j < Count (); j++)
- {
-
- if (fData [j] != v.fData [j])
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
-/******************************************************************************/
-
-real64 dng_vector::MaxEntry () const
- {
-
- if (IsEmpty ())
- {
-
- return 0.0;
-
- }
-
- real64 m = fData [0];
-
- for (uint32 j = 0; j < Count (); j++)
- {
-
- m = Max_real64 (m, fData [j]);
-
- }
-
- return m;
-
- }
-
-/******************************************************************************/
-
-real64 dng_vector::MinEntry () const
- {
-
- if (IsEmpty ())
- {
-
- return 0.0;
-
- }
-
- real64 m = fData [0];
-
- for (uint32 j = 0; j < Count (); j++)
- {
-
- m = Min_real64 (m, fData [j]);
-
- }
-
- return m;
-
- }
-
-/*****************************************************************************/
-
-void dng_vector::Scale (real64 factor)
- {
-
- for (uint32 j = 0; j < Count (); j++)
- {
-
- fData [j] *= factor;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_vector::Round (real64 factor)
- {
-
- real64 invFactor = 1.0 / factor;
-
- for (uint32 j = 0; j < Count (); j++)
- {
-
- fData [j] = Round_int32 (fData [j] * factor) * invFactor;
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_matrix dng_vector::AsDiagonal () const
- {
-
- dng_matrix M (Count (), Count ());
-
- for (uint32 j = 0; j < Count (); j++)
- {
-
- M [j] [j] = fData [j];
-
- }
-
- return M;
-
- }
-
-/*****************************************************************************/
-
-dng_matrix dng_vector::AsColumn () const
- {
-
- dng_matrix M (Count (), 1);
-
- for (uint32 j = 0; j < Count (); j++)
- {
-
- M [j] [0] = fData [j];
-
- }
-
- return M;
-
- }
-
-/******************************************************************************/
-
-dng_vector_3::dng_vector_3 ()
-
- : dng_vector (3)
-
- {
- }
-
-/******************************************************************************/
-
-dng_vector_3::dng_vector_3 (const dng_vector &v)
-
- : dng_vector (v)
-
- {
-
- if (Count () != 3)
- {
-
- ThrowMatrixMath ();
-
- }
-
- }
-
-/******************************************************************************/
-
-dng_vector_3::dng_vector_3 (real64 a0,
- real64 a1,
- real64 a2)
-
- : dng_vector (3)
-
- {
-
- fData [0] = a0;
- fData [1] = a1;
- fData [2] = a2;
-
- }
-
-/******************************************************************************/
-
-dng_vector_4::dng_vector_4 ()
-
- : dng_vector (4)
-
- {
- }
-
-/******************************************************************************/
-
-dng_vector_4::dng_vector_4 (const dng_vector &v)
-
- : dng_vector (v)
-
- {
-
- if (Count () != 4)
- {
-
- ThrowMatrixMath ();
-
- }
-
- }
-
-/******************************************************************************/
-
-dng_vector_4::dng_vector_4 (real64 a0,
- real64 a1,
- real64 a2,
- real64 a3)
-
- : dng_vector (4)
-
- {
-
- fData [0] = a0;
- fData [1] = a1;
- fData [2] = a2;
- fData [3] = a3;
-
- }
-
-/******************************************************************************/
-
-dng_matrix operator* (const dng_matrix &A,
- const dng_matrix &B)
- {
-
- if (A.Cols () != B.Rows ())
- {
-
- ThrowMatrixMath ();
-
- }
-
- dng_matrix C (A.Rows (), B.Cols ());
-
- for (uint32 j = 0; j < C.Rows (); j++)
- for (uint32 k = 0; k < C.Cols (); k++)
- {
-
- C [j] [k] = 0.0;
-
- for (uint32 m = 0; m < A.Cols (); m++)
- {
-
- real64 aa = A [j] [m];
-
- real64 bb = B [m] [k];
-
- C [j] [k] += aa * bb;
-
- }
-
- }
-
- return C;
-
- }
-
-/******************************************************************************/
-
-dng_vector operator* (const dng_matrix &A,
- const dng_vector &B)
- {
-
- if (A.Cols () != B.Count ())
- {
-
- ThrowMatrixMath ();
-
- }
-
- dng_vector C (A.Rows ());
-
- for (uint32 j = 0; j < C.Count (); j++)
- {
-
- C [j] = 0.0;
-
- for (uint32 m = 0; m < A.Cols (); m++)
- {
-
- real64 aa = A [j] [m];
-
- real64 bb = B [m];
-
- C [j] += aa * bb;
-
- }
-
- }
-
- return C;
-
- }
-
-/******************************************************************************/
-
-dng_matrix operator* (real64 scale,
- const dng_matrix &A)
- {
-
- dng_matrix B (A);
-
- B.Scale (scale);
-
- return B;
-
- }
-
-/******************************************************************************/
-
-dng_vector operator* (real64 scale,
- const dng_vector &A)
- {
-
- dng_vector B (A);
-
- B.Scale (scale);
-
- return B;
-
- }
-
-/******************************************************************************/
-
-dng_matrix operator+ (const dng_matrix &A,
- const dng_matrix &B)
- {
-
- if (A.Cols () != B.Cols () ||
- A.Rows () != B.Rows ())
- {
-
- ThrowMatrixMath ();
-
- }
-
- dng_matrix C (A);
-
- for (uint32 j = 0; j < C.Rows (); j++)
- for (uint32 k = 0; k < C.Cols (); k++)
- {
-
- C [j] [k] += B [j] [k];
-
- }
-
- return C;
-
- }
-
-/******************************************************************************/
-
-const real64 kNearZero = 1.0E-10;
-
-/******************************************************************************/
-
-// Work around bug #1294195, which may be a hardware problem on a specific machine.
-// This pragma turns on "improved" floating-point consistency.
-#ifdef _MSC_VER
-#pragma optimize ("p", on)
-#endif
-
-static dng_matrix Invert3by3 (const dng_matrix &A)
- {
-
- real64 a00 = A [0] [0];
- real64 a01 = A [0] [1];
- real64 a02 = A [0] [2];
- real64 a10 = A [1] [0];
- real64 a11 = A [1] [1];
- real64 a12 = A [1] [2];
- real64 a20 = A [2] [0];
- real64 a21 = A [2] [1];
- real64 a22 = A [2] [2];
-
- real64 temp [3] [3];
-
- temp [0] [0] = a11 * a22 - a21 * a12;
- temp [0] [1] = a21 * a02 - a01 * a22;
- temp [0] [2] = a01 * a12 - a11 * a02;
- temp [1] [0] = a20 * a12 - a10 * a22;
- temp [1] [1] = a00 * a22 - a20 * a02;
- temp [1] [2] = a10 * a02 - a00 * a12;
- temp [2] [0] = a10 * a21 - a20 * a11;
- temp [2] [1] = a20 * a01 - a00 * a21;
- temp [2] [2] = a00 * a11 - a10 * a01;
-
- real64 det = (a00 * temp [0] [0] +
- a01 * temp [1] [0] +
- a02 * temp [2] [0]);
-
- if (Abs_real64 (det) < kNearZero)
- {
-
- ThrowMatrixMath ();
-
- }
-
- dng_matrix B (3, 3);
-
- for (uint32 j = 0; j < 3; j++)
- for (uint32 k = 0; k < 3; k++)
- {
-
- B [j] [k] = temp [j] [k] / det;
-
- }
-
- return B;
-
- }
-
-// Reset floating-point optimization. See comment above.
-#ifdef _MSC_VER
-#pragma optimize ("p", off)
-#endif
-
-/******************************************************************************/
-
-static dng_matrix InvertNbyN (const dng_matrix &A)
- {
-
- uint32 i;
- uint32 j;
- uint32 k;
-
- uint32 n = A.Rows ();
-
- real64 temp [kMaxColorPlanes] [kMaxColorPlanes * 2];
-
- for (i = 0; i < n; i++)
- for (j = 0; j < n; j++)
- {
-
- temp [i] [j ] = A [i] [j];
-
- temp [i] [j + n] = (i == j ? 1.0 : 0.0);
-
- }
-
- for (i = 0; i < n; i++)
- {
-
- real64 alpha = temp [i] [i];
-
- if (Abs_real64 (alpha) < kNearZero)
- {
-
- ThrowMatrixMath ();
-
- }
-
- for (j = 0; j < n * 2; j++)
- {
-
- temp [i] [j] /= alpha;
-
- }
-
- for (k = 0; k < n; k++)
- {
-
- if (i != k)
- {
-
- real64 beta = temp [k] [i];
-
- for (j = 0; j < n * 2; j++)
- {
-
- temp [k] [j] -= beta * temp [i] [j];
-
- }
-
- }
-
- }
-
- }
-
- dng_matrix B (n, n);
-
- for (i = 0; i < n; i++)
- for (j = 0; j < n; j++)
- {
-
- B [i] [j] = temp [i] [j + n];
-
- }
-
- return B;
-
- }
-
-/******************************************************************************/
-
-dng_matrix Transpose (const dng_matrix &A)
- {
-
- dng_matrix B (A.Cols (), A.Rows ());
-
- for (uint32 j = 0; j < B.Rows (); j++)
- for (uint32 k = 0; k < B.Cols (); k++)
- {
-
- B [j] [k] = A [k] [j];
-
- }
-
- return B;
-
- }
-
-/******************************************************************************/
-
-dng_matrix Invert (const dng_matrix &A)
- {
-
- if (A.Rows () < 2 || A.Cols () < 2)
- {
-
- ThrowMatrixMath ();
-
- }
-
- if (A.Rows () == A.Cols ())
- {
-
- if (A.Rows () == 3)
- {
-
- return Invert3by3 (A);
-
- }
-
- return InvertNbyN (A);
-
- }
-
- else
- {
-
- // Compute the pseudo inverse.
-
- dng_matrix B = Transpose (A);
-
- return Invert (B * A) * B;
-
- }
-
- }
-
-/******************************************************************************/
-
-dng_matrix Invert (const dng_matrix &A,
- const dng_matrix &hint)
- {
-
- if (A.Rows () == A .Cols () ||
- A.Rows () != hint.Cols () ||
- A.Cols () != hint.Rows ())
- {
-
- return Invert (A);
-
- }
-
- else
- {
-
- // Use the specified hint matrix.
-
- return Invert (hint * A) * hint;
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_matrix.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_matrix.h"
+
+#include "dng_exceptions.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_matrix::dng_matrix ()
+
+ : fRows (0)
+ , fCols (0)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix::dng_matrix (uint32 rows,
+ uint32 cols)
+
+ : fRows (0)
+ , fCols (0)
+
+ {
+
+ if (rows < 1 || rows > kMaxColorPlanes ||
+ cols < 1 || cols > kMaxColorPlanes)
+ {
+
+ ThrowProgramError ();
+
+ }
+
+ fRows = rows;
+ fCols = cols;
+
+ for (uint32 row = 0; row < fRows; row++)
+ for (uint32 col = 0; col < fCols; col++)
+ {
+
+ fData [row] [col] = 0.0;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix::dng_matrix (const dng_matrix &m)
+
+ : fRows (m.fRows)
+ , fCols (m.fCols)
+
+ {
+
+ for (uint32 row = 0; row < fRows; row++)
+ for (uint32 col = 0; col < fCols; col++)
+ {
+
+ fData [row] [col] = m.fData [row] [col];
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::Clear ()
+ {
+
+ fRows = 0;
+ fCols = 0;
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::SetIdentity (uint32 count)
+ {
+
+ *this = dng_matrix (count, count);
+
+ for (uint32 j = 0; j < count; j++)
+ {
+
+ fData [j] [j] = 1.0;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+bool dng_matrix::operator== (const dng_matrix &m) const
+ {
+
+ if (Rows () != m.Rows () ||
+ Cols () != m.Cols ())
+ {
+
+ return false;
+
+ }
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ if (fData [j] [k] != m.fData [j] [k])
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+bool dng_matrix::IsDiagonal () const
+ {
+
+ if (IsEmpty ())
+ {
+ return false;
+ }
+
+ if (Rows () != Cols ())
+ {
+ return false;
+ }
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ if (j != k)
+ {
+
+ if (fData [j] [k] != 0.0)
+ {
+ return false;
+ }
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+real64 dng_matrix::MaxEntry () const
+ {
+
+ if (IsEmpty ())
+ {
+
+ return 0.0;
+
+ }
+
+ real64 m = fData [0] [0];
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ m = Max_real64 (m, fData [j] [k]);
+
+ }
+
+ return m;
+
+ }
+
+/******************************************************************************/
+
+real64 dng_matrix::MinEntry () const
+ {
+
+ if (IsEmpty ())
+ {
+
+ return 0.0;
+
+ }
+
+ real64 m = fData [0] [0];
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ m = Min_real64 (m, fData [j] [k]);
+
+ }
+
+ return m;
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::Scale (real64 factor)
+ {
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ fData [j] [k] *= factor;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::Round (real64 factor)
+ {
+
+ real64 invFactor = 1.0 / factor;
+
+ for (uint32 j = 0; j < Rows (); j++)
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ fData [j] [k] = Round_int32 (fData [j] [k] * factor) * invFactor;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_matrix::SafeRound (real64 factor)
+ {
+
+ real64 invFactor = 1.0 / factor;
+
+ for (uint32 j = 0; j < Rows (); j++)
+ {
+
+ // Round each row to the specified accuracy, but make sure the
+ // a rounding does not affect the total of the elements in a row
+ // more than necessary.
+
+ real64 error = 0.0;
+
+ for (uint32 k = 0; k < Cols (); k++)
+ {
+
+ fData [j] [k] += error;
+
+ real64 rounded = Round_int32 (fData [j] [k] * factor) * invFactor;
+
+ error = fData [j] [k] - rounded;
+
+ fData [j] [k] = rounded;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_3by3::dng_matrix_3by3 ()
+
+ : dng_matrix (3, 3)
+
+ {
+ }
+
+/*****************************************************************************/
+
+dng_matrix_3by3::dng_matrix_3by3 (const dng_matrix &m)
+
+ : dng_matrix (m)
+
+ {
+
+ if (Rows () != 3 ||
+ Cols () != 3)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a01, real64 a02,
+ real64 a10, real64 a11, real64 a12,
+ real64 a20, real64 a21, real64 a22)
+
+
+ : dng_matrix (3, 3)
+
+ {
+
+ fData [0] [0] = a00;
+ fData [0] [1] = a01;
+ fData [0] [2] = a02;
+
+ fData [1] [0] = a10;
+ fData [1] [1] = a11;
+ fData [1] [2] = a12;
+
+ fData [2] [0] = a20;
+ fData [2] [1] = a21;
+ fData [2] [2] = a22;
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_3by3::dng_matrix_3by3 (real64 a00, real64 a11, real64 a22)
+
+ : dng_matrix (3, 3)
+
+ {
+
+ fData [0] [0] = a00;
+ fData [1] [1] = a11;
+ fData [2] [2] = a22;
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_4by3::dng_matrix_4by3 ()
+
+ : dng_matrix (4, 3)
+
+ {
+ }
+
+/*****************************************************************************/
+
+dng_matrix_4by3::dng_matrix_4by3 (const dng_matrix &m)
+
+ : dng_matrix (m)
+
+ {
+
+ if (Rows () != 4 ||
+ Cols () != 3)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix_4by3::dng_matrix_4by3 (real64 a00, real64 a01, real64 a02,
+ real64 a10, real64 a11, real64 a12,
+ real64 a20, real64 a21, real64 a22,
+ real64 a30, real64 a31, real64 a32)
+
+
+ : dng_matrix (4, 3)
+
+ {
+
+ fData [0] [0] = a00;
+ fData [0] [1] = a01;
+ fData [0] [2] = a02;
+
+ fData [1] [0] = a10;
+ fData [1] [1] = a11;
+ fData [1] [2] = a12;
+
+ fData [2] [0] = a20;
+ fData [2] [1] = a21;
+ fData [2] [2] = a22;
+
+ fData [3] [0] = a30;
+ fData [3] [1] = a31;
+ fData [3] [2] = a32;
+
+ }
+
+/*****************************************************************************/
+
+dng_vector::dng_vector ()
+
+ : fCount (0)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_vector::dng_vector (uint32 count)
+
+ : fCount (0)
+
+ {
+
+ if (count < 1 || count > kMaxColorPlanes)
+ {
+
+ ThrowProgramError ();
+
+ }
+
+ fCount = count;
+
+ for (uint32 index = 0; index < fCount; index++)
+ {
+
+ fData [index] = 0.0;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_vector::dng_vector (const dng_vector &v)
+
+ : fCount (v.fCount)
+
+ {
+
+ for (uint32 index = 0; index < fCount; index++)
+ {
+
+ fData [index] = v.fData [index];
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_vector::Clear ()
+ {
+
+ fCount = 0;
+
+ }
+
+/*****************************************************************************/
+
+void dng_vector::SetIdentity (uint32 count)
+ {
+
+ *this = dng_vector (count);
+
+ for (uint32 j = 0; j < count; j++)
+ {
+
+ fData [j] = 1.0;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+bool dng_vector::operator== (const dng_vector &v) const
+ {
+
+ if (Count () != v.Count ())
+ {
+
+ return false;
+
+ }
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ if (fData [j] != v.fData [j])
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+real64 dng_vector::MaxEntry () const
+ {
+
+ if (IsEmpty ())
+ {
+
+ return 0.0;
+
+ }
+
+ real64 m = fData [0];
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ m = Max_real64 (m, fData [j]);
+
+ }
+
+ return m;
+
+ }
+
+/******************************************************************************/
+
+real64 dng_vector::MinEntry () const
+ {
+
+ if (IsEmpty ())
+ {
+
+ return 0.0;
+
+ }
+
+ real64 m = fData [0];
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ m = Min_real64 (m, fData [j]);
+
+ }
+
+ return m;
+
+ }
+
+/*****************************************************************************/
+
+void dng_vector::Scale (real64 factor)
+ {
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ fData [j] *= factor;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_vector::Round (real64 factor)
+ {
+
+ real64 invFactor = 1.0 / factor;
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ fData [j] = Round_int32 (fData [j] * factor) * invFactor;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix dng_vector::AsDiagonal () const
+ {
+
+ dng_matrix M (Count (), Count ());
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ M [j] [j] = fData [j];
+
+ }
+
+ return M;
+
+ }
+
+/*****************************************************************************/
+
+dng_matrix dng_vector::AsColumn () const
+ {
+
+ dng_matrix M (Count (), 1);
+
+ for (uint32 j = 0; j < Count (); j++)
+ {
+
+ M [j] [0] = fData [j];
+
+ }
+
+ return M;
+
+ }
+
+/******************************************************************************/
+
+dng_vector_3::dng_vector_3 ()
+
+ : dng_vector (3)
+
+ {
+ }
+
+/******************************************************************************/
+
+dng_vector_3::dng_vector_3 (const dng_vector &v)
+
+ : dng_vector (v)
+
+ {
+
+ if (Count () != 3)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ }
+
+/******************************************************************************/
+
+dng_vector_3::dng_vector_3 (real64 a0,
+ real64 a1,
+ real64 a2)
+
+ : dng_vector (3)
+
+ {
+
+ fData [0] = a0;
+ fData [1] = a1;
+ fData [2] = a2;
+
+ }
+
+/******************************************************************************/
+
+dng_vector_4::dng_vector_4 ()
+
+ : dng_vector (4)
+
+ {
+ }
+
+/******************************************************************************/
+
+dng_vector_4::dng_vector_4 (const dng_vector &v)
+
+ : dng_vector (v)
+
+ {
+
+ if (Count () != 4)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ }
+
+/******************************************************************************/
+
+dng_vector_4::dng_vector_4 (real64 a0,
+ real64 a1,
+ real64 a2,
+ real64 a3)
+
+ : dng_vector (4)
+
+ {
+
+ fData [0] = a0;
+ fData [1] = a1;
+ fData [2] = a2;
+ fData [3] = a3;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix operator* (const dng_matrix &A,
+ const dng_matrix &B)
+ {
+
+ if (A.Cols () != B.Rows ())
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ dng_matrix C (A.Rows (), B.Cols ());
+
+ for (uint32 j = 0; j < C.Rows (); j++)
+ for (uint32 k = 0; k < C.Cols (); k++)
+ {
+
+ C [j] [k] = 0.0;
+
+ for (uint32 m = 0; m < A.Cols (); m++)
+ {
+
+ real64 aa = A [j] [m];
+
+ real64 bb = B [m] [k];
+
+ C [j] [k] += aa * bb;
+
+ }
+
+ }
+
+ return C;
+
+ }
+
+/******************************************************************************/
+
+dng_vector operator* (const dng_matrix &A,
+ const dng_vector &B)
+ {
+
+ if (A.Cols () != B.Count ())
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ dng_vector C (A.Rows ());
+
+ for (uint32 j = 0; j < C.Count (); j++)
+ {
+
+ C [j] = 0.0;
+
+ for (uint32 m = 0; m < A.Cols (); m++)
+ {
+
+ real64 aa = A [j] [m];
+
+ real64 bb = B [m];
+
+ C [j] += aa * bb;
+
+ }
+
+ }
+
+ return C;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix operator* (real64 scale,
+ const dng_matrix &A)
+ {
+
+ dng_matrix B (A);
+
+ B.Scale (scale);
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+dng_vector operator* (real64 scale,
+ const dng_vector &A)
+ {
+
+ dng_vector B (A);
+
+ B.Scale (scale);
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix operator+ (const dng_matrix &A,
+ const dng_matrix &B)
+ {
+
+ if (A.Cols () != B.Cols () ||
+ A.Rows () != B.Rows ())
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ dng_matrix C (A);
+
+ for (uint32 j = 0; j < C.Rows (); j++)
+ for (uint32 k = 0; k < C.Cols (); k++)
+ {
+
+ C [j] [k] += B [j] [k];
+
+ }
+
+ return C;
+
+ }
+
+/******************************************************************************/
+
+const real64 kNearZero = 1.0E-10;
+
+/******************************************************************************/
+
+// Work around bug #1294195, which may be a hardware problem on a specific machine.
+// This pragma turns on "improved" floating-point consistency.
+#ifdef _MSC_VER
+#pragma optimize ("p", on)
+#endif
+
+static dng_matrix Invert3by3 (const dng_matrix &A)
+ {
+
+ real64 a00 = A [0] [0];
+ real64 a01 = A [0] [1];
+ real64 a02 = A [0] [2];
+ real64 a10 = A [1] [0];
+ real64 a11 = A [1] [1];
+ real64 a12 = A [1] [2];
+ real64 a20 = A [2] [0];
+ real64 a21 = A [2] [1];
+ real64 a22 = A [2] [2];
+
+ real64 temp [3] [3];
+
+ temp [0] [0] = a11 * a22 - a21 * a12;
+ temp [0] [1] = a21 * a02 - a01 * a22;
+ temp [0] [2] = a01 * a12 - a11 * a02;
+ temp [1] [0] = a20 * a12 - a10 * a22;
+ temp [1] [1] = a00 * a22 - a20 * a02;
+ temp [1] [2] = a10 * a02 - a00 * a12;
+ temp [2] [0] = a10 * a21 - a20 * a11;
+ temp [2] [1] = a20 * a01 - a00 * a21;
+ temp [2] [2] = a00 * a11 - a10 * a01;
+
+ real64 det = (a00 * temp [0] [0] +
+ a01 * temp [1] [0] +
+ a02 * temp [2] [0]);
+
+ if (Abs_real64 (det) < kNearZero)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ dng_matrix B (3, 3);
+
+ for (uint32 j = 0; j < 3; j++)
+ for (uint32 k = 0; k < 3; k++)
+ {
+
+ B [j] [k] = temp [j] [k] / det;
+
+ }
+
+ return B;
+
+ }
+
+// Reset floating-point optimization. See comment above.
+#ifdef _MSC_VER
+#pragma optimize ("p", off)
+#endif
+
+/******************************************************************************/
+
+static dng_matrix InvertNbyN (const dng_matrix &A)
+ {
+
+ uint32 i;
+ uint32 j;
+ uint32 k;
+
+ uint32 n = A.Rows ();
+
+ real64 temp [kMaxColorPlanes] [kMaxColorPlanes * 2];
+
+ for (i = 0; i < n; i++)
+ for (j = 0; j < n; j++)
+ {
+
+ temp [i] [j ] = A [i] [j];
+
+ temp [i] [j + n] = (i == j ? 1.0 : 0.0);
+
+ }
+
+ for (i = 0; i < n; i++)
+ {
+
+ real64 alpha = temp [i] [i];
+
+ if (Abs_real64 (alpha) < kNearZero)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ for (j = 0; j < n * 2; j++)
+ {
+
+ temp [i] [j] /= alpha;
+
+ }
+
+ for (k = 0; k < n; k++)
+ {
+
+ if (i != k)
+ {
+
+ real64 beta = temp [k] [i];
+
+ for (j = 0; j < n * 2; j++)
+ {
+
+ temp [k] [j] -= beta * temp [i] [j];
+
+ }
+
+ }
+
+ }
+
+ }
+
+ dng_matrix B (n, n);
+
+ for (i = 0; i < n; i++)
+ for (j = 0; j < n; j++)
+ {
+
+ B [i] [j] = temp [i] [j + n];
+
+ }
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix Transpose (const dng_matrix &A)
+ {
+
+ dng_matrix B (A.Cols (), A.Rows ());
+
+ for (uint32 j = 0; j < B.Rows (); j++)
+ for (uint32 k = 0; k < B.Cols (); k++)
+ {
+
+ B [j] [k] = A [k] [j];
+
+ }
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+dng_matrix Invert (const dng_matrix &A)
+ {
+
+ if (A.Rows () < 2 || A.Cols () < 2)
+ {
+
+ ThrowMatrixMath ();
+
+ }
+
+ if (A.Rows () == A.Cols ())
+ {
+
+ if (A.Rows () == 3)
+ {
+
+ return Invert3by3 (A);
+
+ }
+
+ return InvertNbyN (A);
+
+ }
+
+ else
+ {
+
+ // Compute the pseudo inverse.
+
+ dng_matrix B = Transpose (A);
+
+ return Invert (B * A) * B;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+dng_matrix Invert (const dng_matrix &A,
+ const dng_matrix &hint)
+ {
+
+ if (A.Rows () == A .Cols () ||
+ A.Rows () != hint.Cols () ||
+ A.Cols () != hint.Rows ())
+ {
+
+ return Invert (A);
+
+ }
+
+ else
+ {
+
+ // Use the specified hint matrix.
+
+ return Invert (hint * A) * hint;
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_matrix.h b/source/dng_matrix.h
index cdac55a..5c3e5b7 100644
--- a/source/dng_matrix.h
+++ b/source/dng_matrix.h
@@ -1,326 +1,326 @@
-/*****************************************************************************/
-// Copyright 2006-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_matrix.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Matrix and vector classes, including specialized 3x3 and 4x3 versions as
- * well as length 3 vectors.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_matrix__
-#define __dng_matrix__
-
-/*****************************************************************************/
-
-#include "dng_sdk_limits.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief Class to represent 2D matrix up to kMaxColorPlanes x kMaxColorPlanes
-/// in size.
-
-class dng_matrix
- {
-
- protected:
-
- uint32 fRows;
- uint32 fCols;
-
- real64 fData [kMaxColorPlanes] [kMaxColorPlanes];
-
- public:
-
- dng_matrix ();
-
- dng_matrix (uint32 rows,
- uint32 cols);
-
- dng_matrix (const dng_matrix &m);
-
- virtual ~dng_matrix ()
- {
- }
-
- void Clear ();
-
- void SetIdentity (uint32 count);
-
- uint32 Rows () const
- {
- return fRows;
- }
-
- uint32 Cols () const
- {
- return fCols;
- }
-
- real64 * operator [] (uint32 row)
- {
- return fData [row];
- }
-
- const real64 * operator [] (uint32 row) const
- {
- return fData [row];
- }
-
- bool operator== (const dng_matrix &m) const;
-
- bool operator!= (const dng_matrix &m) const
- {
- return !(*this == m);
- }
-
- bool IsEmpty () const
- {
- return fRows == 0 || fCols == 0;
- }
-
- bool NotEmpty () const
- {
- return !IsEmpty ();
- }
-
- bool IsDiagonal () const;
-
- real64 MaxEntry () const;
-
- real64 MinEntry () const;
-
- void Scale (real64 factor);
-
- void Round (real64 factor);
-
- void SafeRound (real64 factor);
-
- };
-
-/*****************************************************************************/
-
-/// \brief A 3x3 matrix.
-
-class dng_matrix_3by3: public dng_matrix
- {
-
- public:
-
- dng_matrix_3by3 ();
-
- dng_matrix_3by3 (const dng_matrix &m);
-
- dng_matrix_3by3 (real64 a00, real64 a01, real64 a02,
- real64 a10, real64 a11, real64 a12,
- real64 a20, real64 a21, real64 a22);
-
- dng_matrix_3by3 (real64 a00, real64 a11, real64 a22);
-
- };
-
-/*****************************************************************************/
-
-/// \brief A 4x3 matrix. Handy for working with 4-color cameras.
-
-class dng_matrix_4by3: public dng_matrix
- {
-
- public:
-
- dng_matrix_4by3 ();
-
- dng_matrix_4by3 (const dng_matrix &m);
-
- dng_matrix_4by3 (real64 a00, real64 a01, real64 a02,
- real64 a10, real64 a11, real64 a12,
- real64 a20, real64 a21, real64 a22,
- real64 a30, real64 a31, real64 a32);
-
- };
-
-/*****************************************************************************/
-
-/// \brief Class to represent 1-dimensional vector with up to kMaxColorPlanes
-/// components.
-
-class dng_vector
- {
-
- protected:
-
- uint32 fCount;
-
- real64 fData [kMaxColorPlanes];
-
- public:
-
- dng_vector ();
-
- dng_vector (uint32 count);
-
- dng_vector (const dng_vector &v);
-
- virtual ~dng_vector ()
- {
- }
-
- void Clear ();
-
- void SetIdentity (uint32 count);
-
- uint32 Count () const
- {
- return fCount;
- }
-
- real64 & operator [] (uint32 index)
- {
- return fData [index];
- }
-
- const real64 & operator [] (uint32 index) const
- {
- return fData [index];
- }
-
- bool operator== (const dng_vector &v) const;
-
- bool operator!= (const dng_vector &v) const
- {
- return !(*this == v);
- }
-
- bool IsEmpty () const
- {
- return fCount == 0;
- }
-
- bool NotEmpty () const
- {
- return !IsEmpty ();
- }
-
- real64 MaxEntry () const;
-
- real64 MinEntry () const;
-
- void Scale (real64 factor);
-
- void Round (real64 factor);
-
- dng_matrix AsDiagonal () const;
-
- dng_matrix AsColumn () const;
-
- };
-
-/*****************************************************************************/
-
-/// \brief A 3-element vector.
-
-class dng_vector_3: public dng_vector
- {
-
- public:
-
- dng_vector_3 ();
-
- dng_vector_3 (const dng_vector &v);
-
- dng_vector_3 (real64 a0,
- real64 a1,
- real64 a2);
-
- };
-
-/*****************************************************************************/
-
-/// \brief A 4-element vector.
-
-class dng_vector_4: public dng_vector
- {
-
- public:
-
- dng_vector_4 ();
-
- dng_vector_4 (const dng_vector &v);
-
- dng_vector_4 (real64 a0,
- real64 a1,
- real64 a2,
- real64 a3);
-
- };
-
-/*****************************************************************************/
-
-dng_matrix operator* (const dng_matrix &A,
- const dng_matrix &B);
-
-dng_vector operator* (const dng_matrix &A,
- const dng_vector &B);
-
-dng_matrix operator* (real64 scale,
- const dng_matrix &A);
-
-dng_vector operator* (real64 scale,
- const dng_vector &A);
-
-/*****************************************************************************/
-
-dng_matrix operator+ (const dng_matrix &A,
- const dng_matrix &B);
-
-/*****************************************************************************/
-
-dng_matrix Transpose (const dng_matrix &A);
-
-/*****************************************************************************/
-
-dng_matrix Invert (const dng_matrix &A);
-
-dng_matrix Invert (const dng_matrix &A,
- const dng_matrix &hint);
-
-/*****************************************************************************/
-
-inline real64 MaxEntry (const dng_matrix &A)
- {
- return A.MaxEntry ();
- }
-
-inline real64 MaxEntry (const dng_vector &A)
- {
- return A.MaxEntry ();
- }
-
-/*****************************************************************************/
-
-inline real64 MinEntry (const dng_matrix &A)
- {
- return A.MinEntry ();
- }
-
-inline real64 MinEntry (const dng_vector &A)
- {
- return A.MinEntry ();
- }
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_matrix.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Matrix and vector classes, including specialized 3x3 and 4x3 versions as
+ * well as length 3 vectors.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_matrix__
+#define __dng_matrix__
+
+/*****************************************************************************/
+
+#include "dng_sdk_limits.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief Class to represent 2D matrix up to kMaxColorPlanes x kMaxColorPlanes
+/// in size.
+
+class dng_matrix
+ {
+
+ protected:
+
+ uint32 fRows;
+ uint32 fCols;
+
+ real64 fData [kMaxColorPlanes] [kMaxColorPlanes];
+
+ public:
+
+ dng_matrix ();
+
+ dng_matrix (uint32 rows,
+ uint32 cols);
+
+ dng_matrix (const dng_matrix &m);
+
+ virtual ~dng_matrix ()
+ {
+ }
+
+ void Clear ();
+
+ void SetIdentity (uint32 count);
+
+ uint32 Rows () const
+ {
+ return fRows;
+ }
+
+ uint32 Cols () const
+ {
+ return fCols;
+ }
+
+ real64 * operator [] (uint32 row)
+ {
+ return fData [row];
+ }
+
+ const real64 * operator [] (uint32 row) const
+ {
+ return fData [row];
+ }
+
+ bool operator== (const dng_matrix &m) const;
+
+ bool operator!= (const dng_matrix &m) const
+ {
+ return !(*this == m);
+ }
+
+ bool IsEmpty () const
+ {
+ return fRows == 0 || fCols == 0;
+ }
+
+ bool NotEmpty () const
+ {
+ return !IsEmpty ();
+ }
+
+ bool IsDiagonal () const;
+
+ real64 MaxEntry () const;
+
+ real64 MinEntry () const;
+
+ void Scale (real64 factor);
+
+ void Round (real64 factor);
+
+ void SafeRound (real64 factor);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief A 3x3 matrix.
+
+class dng_matrix_3by3: public dng_matrix
+ {
+
+ public:
+
+ dng_matrix_3by3 ();
+
+ dng_matrix_3by3 (const dng_matrix &m);
+
+ dng_matrix_3by3 (real64 a00, real64 a01, real64 a02,
+ real64 a10, real64 a11, real64 a12,
+ real64 a20, real64 a21, real64 a22);
+
+ dng_matrix_3by3 (real64 a00, real64 a11, real64 a22);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief A 4x3 matrix. Handy for working with 4-color cameras.
+
+class dng_matrix_4by3: public dng_matrix
+ {
+
+ public:
+
+ dng_matrix_4by3 ();
+
+ dng_matrix_4by3 (const dng_matrix &m);
+
+ dng_matrix_4by3 (real64 a00, real64 a01, real64 a02,
+ real64 a10, real64 a11, real64 a12,
+ real64 a20, real64 a21, real64 a22,
+ real64 a30, real64 a31, real64 a32);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Class to represent 1-dimensional vector with up to kMaxColorPlanes
+/// components.
+
+class dng_vector
+ {
+
+ protected:
+
+ uint32 fCount;
+
+ real64 fData [kMaxColorPlanes];
+
+ public:
+
+ dng_vector ();
+
+ dng_vector (uint32 count);
+
+ dng_vector (const dng_vector &v);
+
+ virtual ~dng_vector ()
+ {
+ }
+
+ void Clear ();
+
+ void SetIdentity (uint32 count);
+
+ uint32 Count () const
+ {
+ return fCount;
+ }
+
+ real64 & operator [] (uint32 index)
+ {
+ return fData [index];
+ }
+
+ const real64 & operator [] (uint32 index) const
+ {
+ return fData [index];
+ }
+
+ bool operator== (const dng_vector &v) const;
+
+ bool operator!= (const dng_vector &v) const
+ {
+ return !(*this == v);
+ }
+
+ bool IsEmpty () const
+ {
+ return fCount == 0;
+ }
+
+ bool NotEmpty () const
+ {
+ return !IsEmpty ();
+ }
+
+ real64 MaxEntry () const;
+
+ real64 MinEntry () const;
+
+ void Scale (real64 factor);
+
+ void Round (real64 factor);
+
+ dng_matrix AsDiagonal () const;
+
+ dng_matrix AsColumn () const;
+
+ };
+
+/*****************************************************************************/
+
+/// \brief A 3-element vector.
+
+class dng_vector_3: public dng_vector
+ {
+
+ public:
+
+ dng_vector_3 ();
+
+ dng_vector_3 (const dng_vector &v);
+
+ dng_vector_3 (real64 a0,
+ real64 a1,
+ real64 a2);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief A 4-element vector.
+
+class dng_vector_4: public dng_vector
+ {
+
+ public:
+
+ dng_vector_4 ();
+
+ dng_vector_4 (const dng_vector &v);
+
+ dng_vector_4 (real64 a0,
+ real64 a1,
+ real64 a2,
+ real64 a3);
+
+ };
+
+/*****************************************************************************/
+
+dng_matrix operator* (const dng_matrix &A,
+ const dng_matrix &B);
+
+dng_vector operator* (const dng_matrix &A,
+ const dng_vector &B);
+
+dng_matrix operator* (real64 scale,
+ const dng_matrix &A);
+
+dng_vector operator* (real64 scale,
+ const dng_vector &A);
+
+/*****************************************************************************/
+
+dng_matrix operator+ (const dng_matrix &A,
+ const dng_matrix &B);
+
+/*****************************************************************************/
+
+dng_matrix Transpose (const dng_matrix &A);
+
+/*****************************************************************************/
+
+dng_matrix Invert (const dng_matrix &A);
+
+dng_matrix Invert (const dng_matrix &A,
+ const dng_matrix &hint);
+
+/*****************************************************************************/
+
+inline real64 MaxEntry (const dng_matrix &A)
+ {
+ return A.MaxEntry ();
+ }
+
+inline real64 MaxEntry (const dng_vector &A)
+ {
+ return A.MaxEntry ();
+ }
+
+/*****************************************************************************/
+
+inline real64 MinEntry (const dng_matrix &A)
+ {
+ return A.MinEntry ();
+ }
+
+inline real64 MinEntry (const dng_vector &A)
+ {
+ return A.MinEntry ();
+ }
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_memory_stream.h b/source/dng_memory_stream.h
index 4477936..3b297a4 100644
--- a/source/dng_memory_stream.h
+++ b/source/dng_memory_stream.h
@@ -1,97 +1,97 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_memory_stream.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Stream abstraction to/from in-memory data.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_memory_stream__
-#define __dng_memory_stream__
-
-/*****************************************************************************/
-
-#include "dng_stream.h"
-
-/*****************************************************************************/
-
-/// \brief A dng_stream which can be read from or written to memory.
-///
-/// Stream is populated via writing and either read or accessed by asking for contents as a pointer.
-
-class dng_memory_stream: public dng_stream
- {
-
- protected:
-
- dng_memory_allocator &fAllocator;
-
- uint32 fPageSize;
-
- uint32 fPageCount;
- uint32 fPagesAllocated;
-
- dng_memory_block **fPageList;
-
- uint64 fMemoryStreamLength;
-
- public:
-
- /// Construct a new memory-based stream.
- /// \param allocator Allocator to use to allocate memory in stream as needed.
- /// \param sniffer If non-NULL used to check for user cancellation.
- /// \param pageSize Unit of allocation for data stored in stream.
-
- dng_memory_stream (dng_memory_allocator &allocator,
- dng_abort_sniffer *sniffer = NULL,
- uint32 pageSize = 64 * 1024);
-
- virtual ~dng_memory_stream ();
-
- /// Copy a specified number of bytes to a target stream.
- /// \param dstStream The target stream.
- /// \param count The number of bytes to copy.
-
- virtual void CopyToStream (dng_stream &dstStream,
- uint64 count);
-
- protected:
-
- virtual uint64 DoGetLength ();
-
- virtual void DoRead (void *data,
- uint32 count,
- uint64 offset);
-
- virtual void DoSetLength (uint64 length);
-
- virtual void DoWrite (const void *data,
- uint32 count,
- uint64 offset);
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_memory_stream (const dng_memory_stream &stream);
-
- dng_memory_stream & operator= (const dng_memory_stream &stream);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_memory_stream.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Stream abstraction to/from in-memory data.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_memory_stream__
+#define __dng_memory_stream__
+
+/*****************************************************************************/
+
+#include "dng_stream.h"
+
+/*****************************************************************************/
+
+/// \brief A dng_stream which can be read from or written to memory.
+///
+/// Stream is populated via writing and either read or accessed by asking for contents as a pointer.
+
+class dng_memory_stream: public dng_stream
+ {
+
+ protected:
+
+ dng_memory_allocator &fAllocator;
+
+ uint32 fPageSize;
+
+ uint32 fPageCount;
+ uint32 fPagesAllocated;
+
+ dng_memory_block **fPageList;
+
+ uint64 fMemoryStreamLength;
+
+ public:
+
+ /// Construct a new memory-based stream.
+ /// \param allocator Allocator to use to allocate memory in stream as needed.
+ /// \param sniffer If non-NULL used to check for user cancellation.
+ /// \param pageSize Unit of allocation for data stored in stream.
+
+ dng_memory_stream (dng_memory_allocator &allocator,
+ dng_abort_sniffer *sniffer = NULL,
+ uint32 pageSize = 64 * 1024);
+
+ virtual ~dng_memory_stream ();
+
+ /// Copy a specified number of bytes to a target stream.
+ /// \param dstStream The target stream.
+ /// \param count The number of bytes to copy.
+
+ virtual void CopyToStream (dng_stream &dstStream,
+ uint64 count);
+
+ protected:
+
+ virtual uint64 DoGetLength ();
+
+ virtual void DoRead (void *data,
+ uint32 count,
+ uint64 offset);
+
+ virtual void DoSetLength (uint64 length);
+
+ virtual void DoWrite (const void *data,
+ uint32 count,
+ uint64 offset);
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_memory_stream (const dng_memory_stream &stream);
+
+ dng_memory_stream & operator= (const dng_memory_stream &stream);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_misc_opcodes.h b/source/dng_misc_opcodes.h
index a211a9a..970e8b4 100644
--- a/source/dng_misc_opcodes.h
+++ b/source/dng_misc_opcodes.h
@@ -1,417 +1,417 @@
-/*****************************************************************************/
-// Copyright 2008-2009 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_misc_opcodes.h#2 $ */
-/* $DateTime: 2012/08/02 06:09:06 $ */
-/* $Change: 841096 $ */
-/* $Author: erichan $ */
-
-/** \file
- * Miscellaneous DNG opcodes.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_misc_opcodes__
-#define __dng_misc_opcodes__
-
-/*****************************************************************************/
-
-#include "dng_opcodes.h"
-
-/*****************************************************************************/
-
-/// \brief Opcode to trim image to a specified rectangle.
-
-class dng_opcode_TrimBounds: public dng_opcode
- {
-
- private:
-
- dng_rect fBounds;
-
- public:
-
- /// Create opcode to trim image to the specified bounds.
-
- dng_opcode_TrimBounds (const dng_rect &bounds);
-
- dng_opcode_TrimBounds (dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual void Apply (dng_host &host,
- dng_negative &negative,
- AutoPtr<dng_image> &image);
-
- };
-
-/*****************************************************************************/
-
-/// \brief A class to describe an area of an image, including a pixel subrectangle,
-/// plane range, and row/column pitch (e.g., for mosaic images). Useful for
-/// specifying opcodes that only apply to specific color planes or pixel types (e.g.,
-/// only one of the two green Bayer pixels).
-
-class dng_area_spec
- {
-
- public:
-
- enum
- {
- kDataSize = 32
- };
-
- private:
-
- dng_rect fArea;
-
- uint32 fPlane;
- uint32 fPlanes;
-
- uint32 fRowPitch;
- uint32 fColPitch;
-
- public:
-
- /// Create an empty area.
-
- dng_area_spec (const dng_rect &area = dng_rect (),
- uint32 plane = 0,
- uint32 planes = 1,
- uint32 rowPitch = 1,
- uint32 colPitch = 1)
-
- : fArea (area)
- , fPlane (plane)
- , fPlanes (planes)
- , fRowPitch (rowPitch)
- , fColPitch (colPitch)
-
- {
- }
-
- /// The pixel area.
-
- const dng_rect & Area () const
- {
- return fArea;
- }
-
- /// The first plane.
-
- const uint32 Plane () const
- {
- return fPlane;
- }
-
- /// The total number of planes.
-
- const uint32 Planes () const
- {
- return fPlanes;
- }
-
- /// The row pitch (i.e., stride). A pitch of 1 means all rows.
-
- const uint32 RowPitch () const
- {
- return fRowPitch;
- }
-
- /// The column pitch (i.e., stride). A pitch of 1 means all columns.
-
- const uint32 ColPitch () const
- {
- return fColPitch;
- }
-
- /// Read area data from the specified stream.
-
- void GetData (dng_stream &stream);
-
- /// Write area data to the specified stream.
-
- void PutData (dng_stream &stream) const;
-
- /// Compute and return pixel area overlap (i.e., intersection) between this
- /// area and the specified tile.
-
- dng_rect Overlap (const dng_rect &tile) const;
-
- };
-
-/*****************************************************************************/
-
-/// \brief An opcode to apply a 1D function (represented as a 16-bit table) to an
-/// image area.
-
-class dng_opcode_MapTable: public dng_inplace_opcode
- {
-
- private:
-
- dng_area_spec fAreaSpec;
-
- AutoPtr<dng_memory_block> fTable;
-
- uint32 fCount;
-
- public:
-
- /// Create a MapTable opcode with the specified area, table, and number of
- /// table entries.
-
- dng_opcode_MapTable (dng_host &host,
- const dng_area_spec &areaSpec,
- const uint16 *table,
- uint32 count = 0x10000);
-
- dng_opcode_MapTable (dng_host &host,
- dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual uint32 BufferPixelType (uint32 imagePixelType);
-
- virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
-
- virtual void ProcessArea (dng_negative &negative,
- uint32 threadIndex,
- dng_pixel_buffer &buffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- private:
-
- void ReplicateLastEntry ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief An opcode to apply a 1D function (represented as a polynomial) to an
-/// image area.
-
-class dng_opcode_MapPolynomial: public dng_inplace_opcode
- {
-
- public:
-
- enum
- {
- kMaxDegree = 8
- };
-
- private:
-
- dng_area_spec fAreaSpec;
-
- uint32 fDegree;
-
- real64 fCoefficient [kMaxDegree + 1];
-
- real32 fCoefficient32 [kMaxDegree + 1];
-
- public:
-
- /// Create a MapPolynomial opcode with the specified area, polynomial
- /// degree, and polynomial coefficients. The function that will be
- /// applied to each pixel x is:
- ///
- /// f (x) = coefficient [0] + ((x * coefficient [1]) +
- /// (x^2 * coefficient [2]) +
- /// (x^3 * coefficient [3]) +
- /// (x^4 * coefficient [4]) ...
-
- dng_opcode_MapPolynomial (const dng_area_spec &areaSpec,
- uint32 degree,
- const real64 *coefficient);
-
- dng_opcode_MapPolynomial (dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual uint32 BufferPixelType (uint32 imagePixelType);
-
- virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
-
- virtual void ProcessArea (dng_negative &negative,
- uint32 threadIndex,
- dng_pixel_buffer &buffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- };
-
-/*****************************************************************************/
-
-/// \brief An opcode to apply a delta (i.e., offset) that varies per row. Within
-/// a row, the same delta value is applied to all specified pixels.
-
-class dng_opcode_DeltaPerRow: public dng_inplace_opcode
- {
-
- private:
-
- dng_area_spec fAreaSpec;
-
- AutoPtr<dng_memory_block> fTable;
-
- real32 fScale;
-
- public:
-
- /// Create a DeltaPerRow opcode with the specified area and row deltas
- /// (specified as a table of 32-bit floats).
-
- dng_opcode_DeltaPerRow (const dng_area_spec &areaSpec,
- AutoPtr<dng_memory_block> &table);
-
- dng_opcode_DeltaPerRow (dng_host &host,
- dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual uint32 BufferPixelType (uint32 imagePixelType);
-
- virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
-
- virtual void ProcessArea (dng_negative &negative,
- uint32 threadIndex,
- dng_pixel_buffer &buffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- };
-
-/*****************************************************************************/
-
-/// \brief An opcode to apply a delta (i.e., offset) that varies per column.
-/// Within a column, the same delta value is applied to all specified pixels.
-
-class dng_opcode_DeltaPerColumn: public dng_inplace_opcode
- {
-
- private:
-
- dng_area_spec fAreaSpec;
-
- AutoPtr<dng_memory_block> fTable;
-
- real32 fScale;
-
- public:
-
- /// Create a DeltaPerColumn opcode with the specified area and column
- /// deltas (specified as a table of 32-bit floats).
-
- dng_opcode_DeltaPerColumn (const dng_area_spec &areaSpec,
- AutoPtr<dng_memory_block> &table);
-
- dng_opcode_DeltaPerColumn (dng_host &host,
- dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual uint32 BufferPixelType (uint32 imagePixelType);
-
- virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
-
- virtual void ProcessArea (dng_negative &negative,
- uint32 threadIndex,
- dng_pixel_buffer &buffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- };
-
-/*****************************************************************************/
-
-/// \brief An opcode to apply a scale factor that varies per row. Within a row,
-/// the same scale factor is applied to all specified pixels.
-
-class dng_opcode_ScalePerRow: public dng_inplace_opcode
- {
-
- private:
-
- dng_area_spec fAreaSpec;
-
- AutoPtr<dng_memory_block> fTable;
-
- public:
-
- /// Create a ScalePerRow opcode with the specified area and row scale
- /// factors (specified as a table of 32-bit floats).
-
- dng_opcode_ScalePerRow (const dng_area_spec &areaSpec,
- AutoPtr<dng_memory_block> &table);
-
- dng_opcode_ScalePerRow (dng_host &host,
- dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual uint32 BufferPixelType (uint32 imagePixelType);
-
- virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
-
- virtual void ProcessArea (dng_negative &negative,
- uint32 threadIndex,
- dng_pixel_buffer &buffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- };
-
-/*****************************************************************************/
-
-/// \brief An opcode to apply a scale factor that varies per column. Within a
-/// column, the same scale factor is applied to all specified pixels.
-
-class dng_opcode_ScalePerColumn: public dng_inplace_opcode
- {
-
- private:
-
- dng_area_spec fAreaSpec;
-
- AutoPtr<dng_memory_block> fTable;
-
- public:
-
- /// Create a ScalePerColumn opcode with the specified area and column
- /// scale factors (specified as a table of 32-bit floats).
-
- dng_opcode_ScalePerColumn (const dng_area_spec &areaSpec,
- AutoPtr<dng_memory_block> &table);
-
- dng_opcode_ScalePerColumn (dng_host &host,
- dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual uint32 BufferPixelType (uint32 imagePixelType);
-
- virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
-
- virtual void ProcessArea (dng_negative &negative,
- uint32 threadIndex,
- dng_pixel_buffer &buffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2008-2009 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_misc_opcodes.h#2 $ */
+/* $DateTime: 2012/08/02 06:09:06 $ */
+/* $Change: 841096 $ */
+/* $Author: erichan $ */
+
+/** \file
+ * Miscellaneous DNG opcodes.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_misc_opcodes__
+#define __dng_misc_opcodes__
+
+/*****************************************************************************/
+
+#include "dng_opcodes.h"
+
+/*****************************************************************************/
+
+/// \brief Opcode to trim image to a specified rectangle.
+
+class dng_opcode_TrimBounds: public dng_opcode
+ {
+
+ private:
+
+ dng_rect fBounds;
+
+ public:
+
+ /// Create opcode to trim image to the specified bounds.
+
+ dng_opcode_TrimBounds (const dng_rect &bounds);
+
+ dng_opcode_TrimBounds (dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual void Apply (dng_host &host,
+ dng_negative &negative,
+ AutoPtr<dng_image> &image);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief A class to describe an area of an image, including a pixel subrectangle,
+/// plane range, and row/column pitch (e.g., for mosaic images). Useful for
+/// specifying opcodes that only apply to specific color planes or pixel types (e.g.,
+/// only one of the two green Bayer pixels).
+
+class dng_area_spec
+ {
+
+ public:
+
+ enum
+ {
+ kDataSize = 32
+ };
+
+ private:
+
+ dng_rect fArea;
+
+ uint32 fPlane;
+ uint32 fPlanes;
+
+ uint32 fRowPitch;
+ uint32 fColPitch;
+
+ public:
+
+ /// Create an empty area.
+
+ dng_area_spec (const dng_rect &area = dng_rect (),
+ uint32 plane = 0,
+ uint32 planes = 1,
+ uint32 rowPitch = 1,
+ uint32 colPitch = 1)
+
+ : fArea (area)
+ , fPlane (plane)
+ , fPlanes (planes)
+ , fRowPitch (rowPitch)
+ , fColPitch (colPitch)
+
+ {
+ }
+
+ /// The pixel area.
+
+ const dng_rect & Area () const
+ {
+ return fArea;
+ }
+
+ /// The first plane.
+
+ const uint32 Plane () const
+ {
+ return fPlane;
+ }
+
+ /// The total number of planes.
+
+ const uint32 Planes () const
+ {
+ return fPlanes;
+ }
+
+ /// The row pitch (i.e., stride). A pitch of 1 means all rows.
+
+ const uint32 RowPitch () const
+ {
+ return fRowPitch;
+ }
+
+ /// The column pitch (i.e., stride). A pitch of 1 means all columns.
+
+ const uint32 ColPitch () const
+ {
+ return fColPitch;
+ }
+
+ /// Read area data from the specified stream.
+
+ void GetData (dng_stream &stream);
+
+ /// Write area data to the specified stream.
+
+ void PutData (dng_stream &stream) const;
+
+ /// Compute and return pixel area overlap (i.e., intersection) between this
+ /// area and the specified tile.
+
+ dng_rect Overlap (const dng_rect &tile) const;
+
+ };
+
+/*****************************************************************************/
+
+/// \brief An opcode to apply a 1D function (represented as a 16-bit table) to an
+/// image area.
+
+class dng_opcode_MapTable: public dng_inplace_opcode
+ {
+
+ private:
+
+ dng_area_spec fAreaSpec;
+
+ AutoPtr<dng_memory_block> fTable;
+
+ uint32 fCount;
+
+ public:
+
+ /// Create a MapTable opcode with the specified area, table, and number of
+ /// table entries.
+
+ dng_opcode_MapTable (dng_host &host,
+ const dng_area_spec &areaSpec,
+ const uint16 *table,
+ uint32 count = 0x10000);
+
+ dng_opcode_MapTable (dng_host &host,
+ dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual uint32 BufferPixelType (uint32 imagePixelType);
+
+ virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
+
+ virtual void ProcessArea (dng_negative &negative,
+ uint32 threadIndex,
+ dng_pixel_buffer &buffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ private:
+
+ void ReplicateLastEntry ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief An opcode to apply a 1D function (represented as a polynomial) to an
+/// image area.
+
+class dng_opcode_MapPolynomial: public dng_inplace_opcode
+ {
+
+ public:
+
+ enum
+ {
+ kMaxDegree = 8
+ };
+
+ private:
+
+ dng_area_spec fAreaSpec;
+
+ uint32 fDegree;
+
+ real64 fCoefficient [kMaxDegree + 1];
+
+ real32 fCoefficient32 [kMaxDegree + 1];
+
+ public:
+
+ /// Create a MapPolynomial opcode with the specified area, polynomial
+ /// degree, and polynomial coefficients. The function that will be
+ /// applied to each pixel x is:
+ ///
+ /// f (x) = coefficient [0] + ((x * coefficient [1]) +
+ /// (x^2 * coefficient [2]) +
+ /// (x^3 * coefficient [3]) +
+ /// (x^4 * coefficient [4]) ...
+
+ dng_opcode_MapPolynomial (const dng_area_spec &areaSpec,
+ uint32 degree,
+ const real64 *coefficient);
+
+ dng_opcode_MapPolynomial (dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual uint32 BufferPixelType (uint32 imagePixelType);
+
+ virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
+
+ virtual void ProcessArea (dng_negative &negative,
+ uint32 threadIndex,
+ dng_pixel_buffer &buffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief An opcode to apply a delta (i.e., offset) that varies per row. Within
+/// a row, the same delta value is applied to all specified pixels.
+
+class dng_opcode_DeltaPerRow: public dng_inplace_opcode
+ {
+
+ private:
+
+ dng_area_spec fAreaSpec;
+
+ AutoPtr<dng_memory_block> fTable;
+
+ real32 fScale;
+
+ public:
+
+ /// Create a DeltaPerRow opcode with the specified area and row deltas
+ /// (specified as a table of 32-bit floats).
+
+ dng_opcode_DeltaPerRow (const dng_area_spec &areaSpec,
+ AutoPtr<dng_memory_block> &table);
+
+ dng_opcode_DeltaPerRow (dng_host &host,
+ dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual uint32 BufferPixelType (uint32 imagePixelType);
+
+ virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
+
+ virtual void ProcessArea (dng_negative &negative,
+ uint32 threadIndex,
+ dng_pixel_buffer &buffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief An opcode to apply a delta (i.e., offset) that varies per column.
+/// Within a column, the same delta value is applied to all specified pixels.
+
+class dng_opcode_DeltaPerColumn: public dng_inplace_opcode
+ {
+
+ private:
+
+ dng_area_spec fAreaSpec;
+
+ AutoPtr<dng_memory_block> fTable;
+
+ real32 fScale;
+
+ public:
+
+ /// Create a DeltaPerColumn opcode with the specified area and column
+ /// deltas (specified as a table of 32-bit floats).
+
+ dng_opcode_DeltaPerColumn (const dng_area_spec &areaSpec,
+ AutoPtr<dng_memory_block> &table);
+
+ dng_opcode_DeltaPerColumn (dng_host &host,
+ dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual uint32 BufferPixelType (uint32 imagePixelType);
+
+ virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
+
+ virtual void ProcessArea (dng_negative &negative,
+ uint32 threadIndex,
+ dng_pixel_buffer &buffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief An opcode to apply a scale factor that varies per row. Within a row,
+/// the same scale factor is applied to all specified pixels.
+
+class dng_opcode_ScalePerRow: public dng_inplace_opcode
+ {
+
+ private:
+
+ dng_area_spec fAreaSpec;
+
+ AutoPtr<dng_memory_block> fTable;
+
+ public:
+
+ /// Create a ScalePerRow opcode with the specified area and row scale
+ /// factors (specified as a table of 32-bit floats).
+
+ dng_opcode_ScalePerRow (const dng_area_spec &areaSpec,
+ AutoPtr<dng_memory_block> &table);
+
+ dng_opcode_ScalePerRow (dng_host &host,
+ dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual uint32 BufferPixelType (uint32 imagePixelType);
+
+ virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
+
+ virtual void ProcessArea (dng_negative &negative,
+ uint32 threadIndex,
+ dng_pixel_buffer &buffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief An opcode to apply a scale factor that varies per column. Within a
+/// column, the same scale factor is applied to all specified pixels.
+
+class dng_opcode_ScalePerColumn: public dng_inplace_opcode
+ {
+
+ private:
+
+ dng_area_spec fAreaSpec;
+
+ AutoPtr<dng_memory_block> fTable;
+
+ public:
+
+ /// Create a ScalePerColumn opcode with the specified area and column
+ /// scale factors (specified as a table of 32-bit floats).
+
+ dng_opcode_ScalePerColumn (const dng_area_spec &areaSpec,
+ AutoPtr<dng_memory_block> &table);
+
+ dng_opcode_ScalePerColumn (dng_host &host,
+ dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual uint32 BufferPixelType (uint32 imagePixelType);
+
+ virtual dng_rect ModifiedBounds (const dng_rect &imageBounds);
+
+ virtual void ProcessArea (dng_negative &negative,
+ uint32 threadIndex,
+ dng_pixel_buffer &buffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_mosaic_info.cpp b/source/dng_mosaic_info.cpp
index c810197..0fb50e6 100644
--- a/source/dng_mosaic_info.cpp
+++ b/source/dng_mosaic_info.cpp
@@ -1,1988 +1,1988 @@
-/*****************************************************************************/
-// Copyright 2006-2009 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_mosaic_info.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_mosaic_info.h"
-
-#include "dng_area_task.h"
-#include "dng_assertions.h"
-#include "dng_bottlenecks.h"
-#include "dng_exceptions.h"
-#include "dng_filter_task.h"
-#include "dng_host.h"
-#include "dng_ifd.h"
-#include "dng_image.h"
-#include "dng_info.h"
-#include "dng_negative.h"
-#include "dng_pixel_buffer.h"
-#include "dng_tag_types.h"
-#include "dng_tag_values.h"
-#include "dng_tile_iterator.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-// A interpolation kernel for a single pixel of a single plane.
-
-class dng_bilinear_kernel
- {
-
- public:
-
- enum
- {
- kMaxCount = 8
- };
-
- uint32 fCount;
-
- dng_point fDelta [kMaxCount];
-
- real32 fWeight32 [kMaxCount];
- uint16 fWeight16 [kMaxCount];
-
- int32 fOffset [kMaxCount];
-
- public:
-
- dng_bilinear_kernel ()
- : fCount (0)
- {
- }
-
- void Add (const dng_point &delta,
- real32 weight);
-
- void Finalize (const dng_point &scale,
- uint32 patRow,
- uint32 patCol,
- int32 rowStep,
- int32 colStep);
-
- };
-
-/*****************************************************************************/
-
-void dng_bilinear_kernel::Add (const dng_point &delta,
- real32 weight)
- {
-
- // Don't add zero weight elements.
-
- if (weight <= 0.0f)
- {
- return;
- }
-
- // If the delta already matches an existing element, just combine the
- // weights.
-
- for (uint32 j = 0; j < fCount; j++)
- {
-
- if (fDelta [j] == delta)
- {
-
- fWeight32 [j] += weight;
-
- return;
-
- }
-
- }
-
- // Add element to list.
-
- DNG_ASSERT (fCount < kMaxCount, "Too many kernel entries")
-
- fDelta [fCount] = delta;
- fWeight32 [fCount] = weight;
-
- fCount++;
-
- }
-
-/*****************************************************************************/
-
-void dng_bilinear_kernel::Finalize (const dng_point &scale,
- uint32 patRow,
- uint32 patCol,
- int32 rowStep,
- int32 colStep)
- {
-
- uint32 j;
-
- // Adjust deltas to compensate for interpolation upscaling.
-
- for (j = 0; j < fCount; j++)
- {
-
- dng_point &delta = fDelta [j];
-
- if (scale.v == 2)
- {
-
- delta.v = (delta.v + (int32) (patRow & 1)) >> 1;
-
- }
-
- if (scale.h == 2)
- {
-
- delta.h = (delta.h + (int32) (patCol & 1)) >> 1;
-
- }
-
- }
-
- // Sort entries into row-column scan order.
-
- while (true)
- {
-
- bool didSwap = false;
-
- for (j = 1; j < fCount; j++)
- {
-
- dng_point &delta0 = fDelta [j - 1];
- dng_point &delta1 = fDelta [j ];
-
- if (delta0.v > delta1.v ||
- (delta0.v == delta1.v &&
- delta0.h > delta1.h))
- {
-
- didSwap = true;
-
- dng_point tempDelta = delta0;
-
- delta0 = delta1;
- delta1 = tempDelta;
-
- real32 tempWeight = fWeight32 [j - 1];
-
- fWeight32 [j - 1] = fWeight32 [j];
- fWeight32 [j ] = tempWeight;
-
- }
-
- }
-
- if (!didSwap)
- {
- break;
- }
-
- }
-
- // Calculate offsets.
-
- for (j = 0; j < fCount; j++)
- {
-
- fOffset [j] = rowStep * fDelta [j].v +
- colStep * fDelta [j].h;
-
- }
-
- // Calculate 16-bit weights.
-
- uint16 total = 0;
- uint32 biggest = 0;
-
- for (j = 0; j < fCount; j++)
- {
-
- // Round weights to 8 fractional bits.
-
- fWeight16 [j] = (uint16) Round_uint32 (fWeight32 [j] * 256.0);
-
- // Keep track of total of weights.
-
- total += fWeight16 [j];
-
- // Keep track of which weight is biggest.
-
- if (fWeight16 [biggest] < fWeight16 [j])
- {
-
- biggest = j;
-
- }
-
- }
-
- // Adjust largest entry so total of weights is exactly 256.
-
- fWeight16 [biggest] += (256 - total);
-
- // Recompute the floating point weights from the rounded integer weights
- // so results match more closely.
-
- for (j = 0; j < fCount; j++)
- {
-
- fWeight32 [j] = fWeight16 [j] * (1.0f / 256.0f);
-
- }
-
- }
-
-/*****************************************************************************/
-
-class dng_bilinear_pattern
- {
-
- public:
-
- enum
- {
- kMaxPattern = kMaxCFAPattern * 2
- };
-
- dng_point fScale;
-
- uint32 fPatRows;
- uint32 fPatCols;
-
- dng_bilinear_kernel fKernel [kMaxPattern]
- [kMaxPattern];
-
- uint32 fCounts [kMaxPattern]
- [kMaxPattern];
-
- int32 *fOffsets [kMaxPattern]
- [kMaxPattern];
-
- uint16 *fWeights16 [kMaxPattern]
- [kMaxPattern];
-
- real32 *fWeights32 [kMaxPattern]
- [kMaxPattern];
-
- public:
-
- dng_bilinear_pattern ()
-
- : fScale ()
- , fPatRows (0)
- , fPatCols (0)
-
- {
- }
-
- private:
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
- uint32 DeltaRow (uint32 row, int32 delta)
- {
- return (row + fPatRows + (uint32) delta) % fPatRows;
- }
-
-#if defined(__clang__) && defined(__has_attribute)
-#if __has_attribute(no_sanitize)
-__attribute__((no_sanitize("unsigned-integer-overflow")))
-#endif
-#endif
- uint32 DeltaCol (uint32 col, int32 delta)
- {
- return (col + fPatCols + (uint32) delta) % fPatCols;
- }
-
- real32 LinearWeight1 (int32 d1, int32 d2)
- {
- if (d1 == d2)
- return 1.0f;
- else
- return d2 / (real32) (d2 - d1);
- }
-
- real32 LinearWeight2 (int32 d1, int32 d2)
- {
- if (d1 == d2)
- return 0.0f;
- else
- return -d1 / (real32) (d2 - d1);
- }
-
- public:
-
- void Calculate (const dng_mosaic_info &info,
- uint32 dstPlane,
- int32 rowStep,
- int32 colStep);
-
- };
-
-/*****************************************************************************/
-
-void dng_bilinear_pattern::Calculate (const dng_mosaic_info &info,
- uint32 dstPlane,
- int32 rowStep,
- int32 colStep)
- {
-
- uint32 j;
- uint32 k;
- uint32 patRow;
- uint32 patCol;
-
- // Find destination pattern size.
-
- fScale = info.FullScale ();
-
- fPatRows = info.fCFAPatternSize.v * fScale.v;
- fPatCols = info.fCFAPatternSize.h * fScale.h;
-
- // See if we need to scale up just while computing the kernels.
-
- dng_point tempScale (1, 1);
-
- if (info.fCFALayout >= 6)
- {
-
- tempScale = dng_point (2, 2);
-
- fPatRows *= tempScale.v;
- fPatCols *= tempScale.h;
-
- }
-
- // Find a boolean map for this plane color and layout.
-
- bool map [kMaxPattern]
- [kMaxPattern];
-
- uint8 planeColor = info.fCFAPlaneColor [dstPlane];
-
- switch (info.fCFALayout)
- {
-
- case 1: // Rectangular (or square) layout
- {
-
- for (j = 0; j < fPatRows; j++)
- {
-
- for (k = 0; k < fPatCols; k++)
- {
-
- map [j] [k] = (info.fCFAPattern [j] [k] == planeColor);
-
- }
-
- }
-
- break;
-
- }
-
- // Note that when the descriptions of the staggered patterns refer to even rows or
- // columns, this mean the second, fourth, etc. (i.e. using one-based numbering).
- // This needs to be clarified in the DNG specification.
-
- case 2: // Staggered layout A: even (1-based) columns are offset down by 1/2 row
- {
-
- for (j = 0; j < fPatRows; j++)
- {
-
- for (k = 0; k < fPatCols; k++)
- {
-
- if ((j & 1) != (k & 1))
- {
-
- map [j] [k] = false;
-
- }
-
- else
- {
-
- map [j] [k] = (info.fCFAPattern [j >> 1] [k] == planeColor);
-
- }
-
- }
-
- }
-
- break;
-
- }
-
- case 3: // Staggered layout B: even (1-based) columns are offset up by 1/2 row
- {
-
- for (j = 0; j < fPatRows; j++)
- {
-
- for (k = 0; k < fPatCols; k++)
- {
-
- if ((j & 1) == (k & 1))
- {
-
- map [j] [k] = false;
-
- }
-
- else
- {
-
- map [j] [k] = (info.fCFAPattern [j >> 1] [k] == planeColor);
-
- }
-
- }
-
- }
-
- break;
-
- }
-
- case 4: // Staggered layout C: even (1-based) rows are offset right by 1/2 column
- {
-
- for (j = 0; j < fPatRows; j++)
- {
-
- for (k = 0; k < fPatCols; k++)
- {
-
- if ((j & 1) != (k & 1))
- {
-
- map [j] [k] = false;
-
- }
-
- else
- {
-
- map [j] [k] = (info.fCFAPattern [j] [k >> 1] == planeColor);
-
- }
-
- }
-
- }
-
- break;
-
- }
-
- case 5: // Staggered layout D: even (1-based) rows are offset left by 1/2 column
- {
-
- for (j = 0; j < fPatRows; j++)
- {
-
- for (k = 0; k < fPatCols; k++)
- {
-
- if ((j & 1) == (k & 1))
- {
-
- map [j] [k] = false;
-
- }
-
- else
- {
-
- map [j] [k] = (info.fCFAPattern [j] [k >> 1] == planeColor);
-
- }
-
- }
-
- }
-
- break;
-
- }
-
- case 6: // Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column
- case 7: // Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column
- case 8: // Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column
- case 9: // Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column
- {
-
- uint32 eRow = (info.fCFALayout == 6 ||
- info.fCFALayout == 7) ? 1 : 3;
-
- uint32 eCol = (info.fCFALayout == 6 ||
- info.fCFALayout == 8) ? 1 : 3;
-
- for (j = 0; j < fPatRows; j++)
- {
-
- for (k = 0; k < fPatCols; k++)
- {
-
- uint32 jj = j & 3;
- uint32 kk = k & 3;
-
- if ((jj != 0 && jj != eRow) ||
- (kk != 0 && kk != eCol))
- {
-
- map [j] [k] = false;
-
- }
-
- else
- {
-
- map [j] [k] = (info.fCFAPattern [((j >> 1) & ~1) + Min_uint32 (jj, 1)]
- [((k >> 1) & ~1) + Min_uint32 (kk, 1)] == planeColor);
-
- }
-
- }
-
- }
-
- break;
-
- }
-
- default:
- ThrowProgramError ();
-
- }
-
- // Find projections of maps.
-
- bool mapH [kMaxPattern];
- bool mapV [kMaxPattern];
-
- for (j = 0; j < kMaxPattern; j++)
- {
-
- mapH [j] = false;
- mapV [j] = false;
-
- }
-
- for (j = 0; j < fPatRows; j++)
- {
-
- for (k = 0; k < fPatCols; k++)
- {
-
- if (map [j] [k])
- {
-
- mapV [j] = true;
- mapH [k] = true;
-
- }
-
- }
-
- }
-
- // Find kernel for each patten entry.
-
- for (patRow = 0; patRow < fPatRows; patRow += tempScale.v)
- {
-
- for (patCol = 0; patCol < fPatCols; patCol += tempScale.h)
- {
-
- dng_bilinear_kernel &kernel = fKernel [patRow] [patCol];
-
- // Special case no interpolation case.
-
- if (map [patRow] [patCol])
- {
-
- kernel.Add (dng_point (0, 0), 1.0f);
-
- continue;
-
- }
-
- // Special case common patterns in 3 by 3 neighborhood.
-
- uint32 n = DeltaRow (patRow, -1);
- uint32 s = DeltaRow (patRow, 1);
- uint32 w = DeltaCol (patCol, -1);
- uint32 e = DeltaCol (patCol, 1);
-
- bool mapNW = map [n] [w];
- bool mapN = map [n] [patCol];
- bool mapNE = map [n] [e];
-
- bool mapW = map [patRow] [w];
- bool mapE = map [patRow] [e];
-
- bool mapSW = map [s] [w];
- bool mapS = map [s] [patCol];
- bool mapSE = map [s] [e];
-
- // All sides.
-
- if (mapN && mapS && mapW && mapW)
- {
-
- kernel.Add (dng_point (-1, 0), 0.25f);
- kernel.Add (dng_point ( 0, -1), 0.25f);
- kernel.Add (dng_point ( 0, 1), 0.25f);
- kernel.Add (dng_point ( 1, 0), 0.25f);
-
- continue;
-
- }
-
- // N & S.
-
- if (mapN && mapS)
- {
-
- kernel.Add (dng_point (-1, 0), 0.5f);
- kernel.Add (dng_point ( 1, 0), 0.5f);
-
- continue;
-
- }
-
- // E & W.
-
- if (mapW && mapE)
- {
-
- kernel.Add (dng_point ( 0, -1), 0.5f);
- kernel.Add (dng_point ( 0, 1), 0.5f);
-
- continue;
-
- }
-
- // N & SW & SE.
-
- if (mapN && mapSW && mapSE)
- {
-
- kernel.Add (dng_point (-1, 0), 0.50f);
- kernel.Add (dng_point ( 1, -1), 0.25f);
- kernel.Add (dng_point ( 1, 1), 0.25f);
-
- continue;
-
- }
-
- // S & NW & NE.
-
- if (mapS && mapNW && mapNE)
- {
-
- kernel.Add (dng_point (-1, -1), 0.25f);
- kernel.Add (dng_point (-1, 1), 0.25f);
- kernel.Add (dng_point ( 1, 0), 0.50f);
-
- continue;
-
- }
-
- // W & NE & SE.
-
- if (mapW && mapNE && mapSE)
- {
-
- kernel.Add (dng_point (-1, 1), 0.25f);
- kernel.Add (dng_point ( 0, -1), 0.50f);
- kernel.Add (dng_point ( 1, 1), 0.25f);
-
- continue;
-
- }
-
- // E & NW & SW.
-
- if (mapE && mapNW && mapSW)
- {
-
- kernel.Add (dng_point (-1, -1), 0.25f);
- kernel.Add (dng_point ( 0, 1), 0.50f);
- kernel.Add (dng_point ( 1, -1), 0.25f);
-
- continue;
-
- }
-
- // Four corners.
-
- if (mapNW && mapNE && mapSE && mapSW)
- {
-
- kernel.Add (dng_point (-1, -1), 0.25f);
- kernel.Add (dng_point (-1, 1), 0.25f);
- kernel.Add (dng_point ( 1, -1), 0.25f);
- kernel.Add (dng_point ( 1, 1), 0.25f);
-
- continue;
-
- }
-
- // NW & SE
-
- if (mapNW && mapSE)
- {
-
- kernel.Add (dng_point (-1, -1), 0.50f);
- kernel.Add (dng_point ( 1, 1), 0.50f);
-
- continue;
-
- }
-
- // NE & SW
-
- if (mapNE && mapSW)
- {
-
- kernel.Add (dng_point (-1, 1), 0.50f);
- kernel.Add (dng_point ( 1, -1), 0.50f);
-
- continue;
-
- }
-
- // Else use double-bilinear kernel.
-
- int32 dv1 = 0;
- int32 dv2 = 0;
-
- while (!mapV [DeltaRow (patRow, dv1)])
- {
- dv1--;
- }
-
- while (!mapV [DeltaRow (patRow, dv2)])
- {
- dv2++;
- }
-
- real32 w1 = LinearWeight1 (dv1, dv2) * 0.5f;
- real32 w2 = LinearWeight2 (dv1, dv2) * 0.5f;
-
- int32 v1 = DeltaRow (patRow, dv1);
- int32 v2 = DeltaRow (patRow, dv2);
-
- int32 dh1 = 0;
- int32 dh2 = 0;
-
- while (!map [v1] [DeltaCol (patCol, dh1)])
- {
- dh1--;
- }
-
- while (!map [v1] [DeltaCol (patCol, dh2)])
- {
- dh2++;
- }
-
- kernel.Add (dng_point (dv1, dh1),
- LinearWeight1 (dh1, dh2) * w1);
-
- kernel.Add (dng_point (dv1, dh2),
- LinearWeight2 (dh1, dh2) * w1);
-
- dh1 = 0;
- dh2 = 0;
-
- while (!map [v2] [DeltaCol (patCol, dh1)])
- {
- dh1--;
- }
-
- while (!map [v2] [DeltaCol (patCol, dh2)])
- {
- dh2++;
- }
-
- kernel.Add (dng_point (dv2, dh1),
- LinearWeight1 (dh1, dh2) * w2);
-
- kernel.Add (dng_point (dv2, dh2),
- LinearWeight2 (dh1, dh2) * w2);
-
- dh1 = 0;
- dh2 = 0;
-
- while (!mapH [DeltaCol (patCol, dh1)])
- {
- dh1--;
- }
-
- while (!mapH [DeltaCol (patCol, dh2)])
- {
- dh2++;
- }
-
- w1 = LinearWeight1 (dh1, dh2) * 0.5f;
- w2 = LinearWeight2 (dh1, dh2) * 0.5f;
-
- int32 h1 = DeltaCol (patCol, dh1);
- int32 h2 = DeltaCol (patCol, dh2);
-
- dv1 = 0;
- dv2 = 0;
-
- while (!map [DeltaRow (patRow, dv1)] [h1])
- {
- dv1--;
- }
-
- while (!map [DeltaRow (patRow, dv2)] [h1])
- {
- dv2++;
- }
-
- kernel.Add (dng_point (dv1, dh1),
- LinearWeight1 (dv1, dv2) * w1);
-
- kernel.Add (dng_point (dv2, dh1),
- LinearWeight2 (dv1, dv2) * w1);
-
- dv1 = 0;
- dv2 = 0;
-
- while (!map [DeltaRow (patRow, dv1)] [h2])
- {
- dv1--;
- }
-
- while (!map [DeltaRow (patRow, dv2)] [h2])
- {
- dv2++;
- }
-
- kernel.Add (dng_point (dv1, dh2),
- LinearWeight1 (dv1, dv2) * w2);
-
- kernel.Add (dng_point (dv2, dh2),
- LinearWeight2 (dv1, dv2) * w2);
-
- }
-
- }
-
- // Deal with temp scale case.
-
- if (tempScale == dng_point (2, 2))
- {
-
- fPatRows /= tempScale.v;
- fPatCols /= tempScale.h;
-
- for (patRow = 0; patRow < fPatRows; patRow++)
- {
-
- for (patCol = 0; patCol < fPatCols; patCol++)
- {
-
- int32 patRow2 = patRow << 1;
- int32 patCol2 = patCol << 1;
-
- dng_bilinear_kernel &kernel = fKernel [patRow2] [patCol2];
-
- for (j = 0; j < kernel.fCount; j++)
- {
-
- int32 x = patRow2 + kernel.fDelta [j].v;
-
- if ((x & 3) != 0)
- {
- x = (x & ~3) + 2;
- }
-
- kernel.fDelta [j].v = ((x - patRow2) >> 1);
-
- x = patCol2 + kernel.fDelta [j].h;
-
- if ((x & 3) != 0)
- {
- x = (x & ~3) + 2;
- }
-
- kernel.fDelta [j].h = ((x - patCol2) >> 1);
-
- }
-
- kernel.Finalize (fScale,
- patRow,
- patCol,
- rowStep,
- colStep);
-
- fCounts [patRow] [patCol] = kernel.fCount;
- fOffsets [patRow] [patCol] = kernel.fOffset;
- fWeights16 [patRow] [patCol] = kernel.fWeight16;
- fWeights32 [patRow] [patCol] = kernel.fWeight32;
-
- }
-
- }
-
- }
-
- // Non-temp scale case.
-
- else
- {
-
- for (patRow = 0; patRow < fPatRows; patRow++)
- {
-
- for (patCol = 0; patCol < fPatCols; patCol++)
- {
-
- dng_bilinear_kernel &kernel = fKernel [patRow] [patCol];
-
- kernel.Finalize (fScale,
- patRow,
- patCol,
- rowStep,
- colStep);
-
- fCounts [patRow] [patCol] = kernel.fCount;
- fOffsets [patRow] [patCol] = kernel.fOffset;
- fWeights16 [patRow] [patCol] = kernel.fWeight16;
- fWeights32 [patRow] [patCol] = kernel.fWeight32;
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-class dng_bilinear_interpolator
- {
-
- private:
-
- dng_bilinear_pattern fPattern [kMaxColorPlanes];
-
- public:
-
- dng_bilinear_interpolator (const dng_mosaic_info &info,
- int32 rowStep,
- int32 colStep);
-
- void Interpolate (dng_pixel_buffer &srcBuffer,
- dng_pixel_buffer &dstBuffer);
-
- };
-
-/*****************************************************************************/
-
-dng_bilinear_interpolator::dng_bilinear_interpolator (const dng_mosaic_info &info,
- int32 rowStep,
- int32 colStep)
- {
-
- for (uint32 dstPlane = 0; dstPlane < info.fColorPlanes; dstPlane++)
- {
-
- fPattern [dstPlane] . Calculate (info,
- dstPlane,
- rowStep,
- colStep);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_bilinear_interpolator::Interpolate (dng_pixel_buffer &srcBuffer,
- dng_pixel_buffer &dstBuffer)
- {
-
- uint32 patCols = fPattern [0] . fPatCols;
- uint32 patRows = fPattern [0] . fPatRows;
-
- dng_point scale = fPattern [0] . fScale;
-
- uint32 sRowShift = scale.v - 1;
- uint32 sColShift = scale.h - 1;
-
- int32 dstCol = dstBuffer.fArea.l;
-
- int32 srcCol = dstCol >> sColShift;
-
- uint32 patPhase = dstCol % patCols;
-
- for (int32 dstRow = dstBuffer.fArea.t;
- dstRow < dstBuffer.fArea.b;
- dstRow++)
- {
-
- int32 srcRow = dstRow >> sRowShift;
-
- uint32 patRow = dstRow % patRows;
-
- for (uint32 dstPlane = 0;
- dstPlane < dstBuffer.fPlanes;
- dstPlane++)
- {
-
- const void *sPtr = srcBuffer.ConstPixel (srcRow,
- srcCol,
- srcBuffer.fPlane);
-
- void *dPtr = dstBuffer.DirtyPixel (dstRow,
- dstCol,
- dstPlane);
-
- if (dstBuffer.fPixelType == ttShort)
- {
-
- DoBilinearRow16 ((const uint16 *) sPtr,
- (uint16 *) dPtr,
- dstBuffer.fArea.W (),
- patPhase,
- patCols,
- fPattern [dstPlane].fCounts [patRow],
- fPattern [dstPlane].fOffsets [patRow],
- fPattern [dstPlane].fWeights16 [patRow],
- sColShift);
-
- }
-
- else
- {
-
- DoBilinearRow32 ((const real32 *) sPtr,
- (real32 *) dPtr,
- dstBuffer.fArea.W (),
- patPhase,
- patCols,
- fPattern [dstPlane].fCounts [patRow],
- fPattern [dstPlane].fOffsets [patRow],
- fPattern [dstPlane].fWeights32 [patRow],
- sColShift);
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-class dng_fast_interpolator: public dng_filter_task
- {
-
- protected:
-
- const dng_mosaic_info &fInfo;
-
- dng_point fDownScale;
-
- uint32 fFilterColor [kMaxCFAPattern] [kMaxCFAPattern];
-
- public:
-
- dng_fast_interpolator (const dng_mosaic_info &info,
- const dng_image &srcImage,
- dng_image &dstImage,
- const dng_point &downScale,
- uint32 srcPlane);
-
- virtual dng_rect SrcArea (const dng_rect &dstArea);
-
- virtual void ProcessArea (uint32 threadIndex,
- dng_pixel_buffer &srcBuffer,
- dng_pixel_buffer &dstBuffer);
-
- };
-
-/*****************************************************************************/
-
-dng_fast_interpolator::dng_fast_interpolator (const dng_mosaic_info &info,
- const dng_image &srcImage,
- dng_image &dstImage,
- const dng_point &downScale,
- uint32 srcPlane)
-
- : dng_filter_task (srcImage,
- dstImage)
-
- , fInfo (info )
- , fDownScale (downScale)
-
- {
-
- fSrcPlane = srcPlane;
- fSrcPlanes = 1;
-
- fSrcPixelType = ttShort;
- fDstPixelType = ttShort;
-
- fSrcRepeat = fInfo.fCFAPatternSize;
-
- fUnitCell = fInfo.fCFAPatternSize;
-
- fMaxTileSize = dng_point (256 / fDownScale.v,
- 256 / fDownScale.h);
-
- fMaxTileSize.h = Max_int32 (fMaxTileSize.h, fUnitCell.h);
- fMaxTileSize.v = Max_int32 (fMaxTileSize.v, fUnitCell.v);
-
- // Find color map.
-
- {
-
- for (int32 r = 0; r < fInfo.fCFAPatternSize.v; r++)
- {
-
- for (int32 c = 0; c < fInfo.fCFAPatternSize.h; c++)
- {
-
- uint8 key = fInfo.fCFAPattern [r] [c];
-
- for (uint32 index = 0; index < fInfo.fColorPlanes; index++)
- {
-
- if (key == fInfo.fCFAPlaneColor [index])
- {
-
- fFilterColor [r] [c] = index;
-
- break;
-
- }
-
- }
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_rect dng_fast_interpolator::SrcArea (const dng_rect &dstArea)
- {
-
- return dng_rect (dstArea.t * fDownScale.v,
- dstArea.l * fDownScale.h,
- dstArea.b * fDownScale.v,
- dstArea.r * fDownScale.h);
-
- }
-
-/*****************************************************************************/
-
-void dng_fast_interpolator::ProcessArea (uint32 /* threadIndex */,
- dng_pixel_buffer &srcBuffer,
- dng_pixel_buffer &dstBuffer)
- {
-
- dng_rect srcArea = srcBuffer.fArea;
- dng_rect dstArea = dstBuffer.fArea;
-
- // Downsample buffer.
-
- int32 srcRow = srcArea.t;
-
- uint32 srcRowPhase1 = 0;
- uint32 srcRowPhase2 = 0;
-
- uint32 patRows = fInfo.fCFAPatternSize.v;
- uint32 patCols = fInfo.fCFAPatternSize.h;
-
- uint32 cellRows = fDownScale.v;
- uint32 cellCols = fDownScale.h;
-
- uint32 plane;
- uint32 planes = fInfo.fColorPlanes;
-
- int32 dstPlaneStep = dstBuffer.fPlaneStep;
-
- uint32 total [kMaxColorPlanes];
- uint32 count [kMaxColorPlanes];
-
- for (plane = 0; plane < planes; plane++)
- {
- total [plane] = 0;
- count [plane] = 0;
- }
-
- for (int32 dstRow = dstArea.t; dstRow < dstArea.b; dstRow++)
- {
-
- const uint16 *sPtr = srcBuffer.ConstPixel_uint16 (srcRow,
- srcArea.l,
- fSrcPlane);
-
- uint16 *dPtr = dstBuffer.DirtyPixel_uint16 (dstRow,
- dstArea.l,
- 0);
-
- uint32 srcColPhase1 = 0;
- uint32 srcColPhase2 = 0;
-
- for (int32 dstCol = dstArea.l; dstCol < dstArea.r; dstCol++)
- {
-
- const uint16 *ssPtr = sPtr;
-
- srcRowPhase2 = srcRowPhase1;
-
- for (uint32 cellRow = 0; cellRow < cellRows; cellRow++)
- {
-
- const uint32 *filterRow = fFilterColor [srcRowPhase2];
-
- if (++srcRowPhase2 == patRows)
- {
- srcRowPhase2 = 0;
- }
-
- srcColPhase2 = srcColPhase1;
-
- for (uint32 cellCol = 0; cellCol < cellCols; cellCol++)
- {
-
- uint32 color = filterRow [srcColPhase2];
-
- if (++srcColPhase2 == patCols)
- {
- srcColPhase2 = 0;
- }
-
- total [color] += (uint32) ssPtr [cellCol];
- count [color] ++;
-
- }
-
- ssPtr += srcBuffer.fRowStep;
-
- }
-
- for (plane = 0; plane < planes; plane++)
- {
-
- uint32 t = total [plane];
- uint32 c = count [plane];
-
- dPtr [plane * dstPlaneStep] = (uint16) ((t + (c >> 1)) / c);
-
- total [plane] = 0;
- count [plane] = 0;
-
- }
-
- srcColPhase1 = srcColPhase2;
-
- sPtr += cellCols;
-
- dPtr ++;
-
- }
-
- srcRowPhase1 = srcRowPhase2;
-
- srcRow += cellRows;
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_mosaic_info::dng_mosaic_info ()
-
- : fCFAPatternSize ()
- , fColorPlanes (0)
- , fCFALayout (1)
- , fBayerGreenSplit (0)
- , fSrcSize ()
- , fCroppedSize ()
- , fAspectRatio (1.0)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_mosaic_info::~dng_mosaic_info ()
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_mosaic_info::Parse (dng_host & /* host */,
- dng_stream & /* stream */,
- dng_info &info)
- {
-
- // Find main image IFD.
-
- dng_ifd &rawIFD = *info.fIFD [info.fMainIndex].Get ();
-
- // This information only applies to CFA images.
-
- if (rawIFD.fPhotometricInterpretation != piCFA)
- {
- return;
- }
-
- // Copy CFA pattern.
-
- fCFAPatternSize.v = rawIFD.fCFARepeatPatternRows;
- fCFAPatternSize.h = rawIFD.fCFARepeatPatternCols;
-
- for (int32 j = 0; j < fCFAPatternSize.v; j++)
- {
- for (int32 k = 0; k < fCFAPatternSize.h; k++)
- {
- fCFAPattern [j] [k] = rawIFD.fCFAPattern [j] [k];
- }
- }
-
- // Copy CFA plane information.
-
- fColorPlanes = info.fShared->fCameraProfile.fColorPlanes;
-
- for (uint32 n = 0; n < fColorPlanes; n++)
- {
- fCFAPlaneColor [n] = rawIFD.fCFAPlaneColor [n];
- }
-
- // Copy CFA layout information.
-
- fCFALayout = rawIFD.fCFALayout;
-
- // Green split value for Bayer patterns.
-
- fBayerGreenSplit = rawIFD.fBayerGreenSplit;
-
- }
-
-/*****************************************************************************/
-
-void dng_mosaic_info::PostParse (dng_host & /* host */,
- dng_negative &negative)
- {
-
- // Keep track of source image size.
-
- fSrcSize = negative.Stage2Image ()->Size ();
-
- // Default cropped size.
-
- fCroppedSize.v = Round_int32 (negative.DefaultCropSizeV ().As_real64 ());
- fCroppedSize.h = Round_int32 (negative.DefaultCropSizeH ().As_real64 ());
-
- // Pixel aspect ratio.
-
- fAspectRatio = negative.DefaultScaleH ().As_real64 () /
- negative.DefaultScaleV ().As_real64 ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_mosaic_info::SetFourColorBayer ()
- {
-
- if (fCFAPatternSize != dng_point (2, 2))
- {
- return false;
- }
-
- if (fColorPlanes != 3)
- {
- return false;
- }
-
- uint8 color0 = fCFAPlaneColor [0];
- uint8 color1 = fCFAPlaneColor [1];
- uint8 color2 = fCFAPlaneColor [2];
-
- // Look for color 1 repeated twice in a diagonal.
-
- if ((fCFAPattern [0] [0] == color1 && fCFAPattern [1] [1] == color1) ||
- (fCFAPattern [0] [1] == color1 && fCFAPattern [1] [0] == color1))
- {
-
- // OK, this looks like a Bayer pattern.
-
- // Find unused color code.
-
- uint8 color3 = 0;
-
- while (color3 == color0 ||
- color3 == color1 ||
- color3 == color2)
- {
- color3++;
- }
-
- // Switch the four color mosaic.
-
- fColorPlanes = 4;
-
- fCFAPlaneColor [3] = color3;
-
- // Replace the "green" in the "blue" rows with the new color.
-
- if (fCFAPattern [0] [0] == color0)
- {
- fCFAPattern [1] [0] = color3;
- }
-
- else if (fCFAPattern [0] [1] == color0)
- {
- fCFAPattern [1] [1] = color3;
- }
-
- else if (fCFAPattern [1] [0] == color0)
- {
- fCFAPattern [0] [0] = color3;
- }
-
- else
- {
- fCFAPattern [0] [1] = color3;
- }
-
- return true;
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-dng_point dng_mosaic_info::FullScale () const
- {
-
- switch (fCFALayout)
- {
-
- // Staggered layouts with offset columns double the row count
- // during interpolation.
-
- case 2:
- case 3:
- return dng_point (2, 1);
-
- // Staggered layouts with offset rows double the column count
- // during interpolation.
-
- case 4:
- case 5:
- return dng_point (1, 2);
-
- // Otherwise there is no size change during interpolation.
-
- default:
- break;
-
- }
-
- return dng_point (1, 1);
-
- }
-
-/*****************************************************************************/
-
-bool dng_mosaic_info::IsSafeDownScale (const dng_point &downScale) const
- {
-
- if (downScale.v >= fCFAPatternSize.v &&
- downScale.h >= fCFAPatternSize.h)
- {
-
- return true;
-
- }
-
- dng_point test;
-
- test.v = Min_int32 (downScale.v, fCFAPatternSize.v);
- test.h = Min_int32 (downScale.h, fCFAPatternSize.h);
-
- for (int32 phaseV = 0; phaseV <= fCFAPatternSize.v - test.v; phaseV++)
- {
-
- for (int32 phaseH = 0; phaseH <= fCFAPatternSize.h - test.h; phaseH++)
- {
-
- uint32 plane;
-
- bool contains [kMaxColorPlanes];
-
- for (plane = 0; plane < fColorPlanes; plane++)
- {
-
- contains [plane] = false;
-
- }
-
- for (int32 srcRow = 0; srcRow < test.v; srcRow++)
- {
-
- for (int32 srcCol = 0; srcCol < test.h; srcCol++)
- {
-
- uint8 srcKey = fCFAPattern [srcRow + phaseV]
- [srcCol + phaseH];
-
- for (plane = 0; plane < fColorPlanes; plane++)
- {
-
- if (srcKey == fCFAPlaneColor [plane])
- {
-
- contains [plane] = true;
-
- }
-
- }
-
-
- }
-
- }
-
- for (plane = 0; plane < fColorPlanes; plane++)
- {
-
- if (!contains [plane])
- {
-
- return false;
-
- }
-
- }
-
- }
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_mosaic_info::SizeForDownScale (const dng_point &downScale) const
- {
-
- uint32 sizeV = Max_uint32 (1, (fCroppedSize.v + (downScale.v >> 1)) / downScale.v);
- uint32 sizeH = Max_uint32 (1, (fCroppedSize.h + (downScale.h >> 1)) / downScale.h);
-
- return Max_int32 (sizeV, sizeH);
-
- }
-
-/*****************************************************************************/
-
-bool dng_mosaic_info::ValidSizeDownScale (const dng_point &downScale,
- uint32 minSize) const
- {
-
- const int32 kMaxDownScale = 64;
-
- if (downScale.h > kMaxDownScale ||
- downScale.v > kMaxDownScale)
- {
-
- return false;
-
- }
-
- return SizeForDownScale (downScale) >= minSize;
-
- }
-
-/*****************************************************************************/
-
-dng_point dng_mosaic_info::DownScale (uint32 minSize,
- uint32 prefSize,
- real64 cropFactor) const
- {
-
- dng_point bestScale (1, 1);
-
- if (prefSize && IsColorFilterArray ())
- {
-
- // Adjust sizes for crop factor.
-
- minSize = Round_uint32 (minSize / cropFactor);
- prefSize = Round_uint32 (prefSize / cropFactor);
-
- prefSize = Max_uint32 (prefSize, minSize);
-
- // Start by assuming we need the full size image.
-
- int32 bestSize = SizeForDownScale (bestScale);
-
- // Find size of nearly square cell.
-
- dng_point squareCell (1, 1);
-
- if (fAspectRatio < 1.0 / 1.8)
- {
-
- squareCell.h = Min_int32 (4, Round_int32 (1.0 / fAspectRatio));
-
- }
-
- if (fAspectRatio > 1.8)
- {
-
- squareCell.v = Min_int32 (4, Round_int32 (fAspectRatio));
-
- }
-
- // Find minimum safe cell size.
-
- dng_point testScale = squareCell;
-
- while (!IsSafeDownScale (testScale))
- {
-
- testScale.v += squareCell.v;
- testScale.h += squareCell.h;
-
- }
-
- // See if this scale is usable.
-
- if (!ValidSizeDownScale (testScale, minSize))
- {
-
- // We cannot downsample at all...
-
- return bestScale;
-
- }
-
- // See if this is closer to the preferred size.
-
- int32 testSize = SizeForDownScale (testScale);
-
- if (Abs_int32 (testSize - (int32) prefSize) <=
- Abs_int32 (bestSize - (int32) prefSize))
- {
- bestScale = testScale;
- bestSize = testSize;
- }
-
- else
- {
- return bestScale;
- }
-
- // Now keep adding square cells as long as possible.
-
- while (true)
- {
-
- testScale.v += squareCell.v;
- testScale.h += squareCell.h;
-
- if (IsSafeDownScale (testScale))
- {
-
- if (!ValidSizeDownScale (testScale, minSize))
- {
- return bestScale;
- }
-
- // See if this is closer to the preferred size.
-
- testSize = SizeForDownScale (testScale);
-
- if (Abs_int32 (testSize - (int32) prefSize) <=
- Abs_int32 (bestSize - (int32) prefSize))
- {
- bestScale = testScale;
- bestSize = testSize;
- }
-
- else
- {
- return bestScale;
- }
-
- }
-
- }
-
- }
-
- return bestScale;
-
- }
-
-/*****************************************************************************/
-
-dng_point dng_mosaic_info::DstSize (const dng_point &downScale) const
- {
-
- if (downScale == dng_point (1, 1))
- {
-
- dng_point scale = FullScale ();
-
- return dng_point (fSrcSize.v * scale.v,
- fSrcSize.h * scale.h);
-
- }
-
- const int32 kMaxDownScale = 64;
-
- if (downScale.h > kMaxDownScale ||
- downScale.v > kMaxDownScale)
- {
-
- return dng_point (0, 0);
-
- }
-
- dng_point size;
-
- size.v = Max_int32 (1, (fSrcSize.v + (downScale.v >> 1)) / downScale.v);
- size.h = Max_int32 (1, (fSrcSize.h + (downScale.h >> 1)) / downScale.h);
-
- return size;
-
- }
-
-/*****************************************************************************/
-
-void dng_mosaic_info::InterpolateGeneric (dng_host &host,
- dng_negative & /* negative */,
- const dng_image &srcImage,
- dng_image &dstImage,
- uint32 srcPlane) const
- {
-
- // Find destination to source bit shifts.
-
- dng_point scale = FullScale ();
-
- uint32 srcShiftV = scale.v - 1;
- uint32 srcShiftH = scale.h - 1;
-
- // Find tile sizes.
-
- const uint32 kMaxDstTileRows = 128;
- const uint32 kMaxDstTileCols = 128;
-
- dng_point dstTileSize = dstImage.RepeatingTile ().Size ();
-
- dstTileSize.v = Min_int32 (dstTileSize.v, kMaxDstTileRows);
- dstTileSize.h = Min_int32 (dstTileSize.h, kMaxDstTileCols);
-
- dng_point srcTileSize = dstTileSize;
-
- srcTileSize.v >>= srcShiftV;
- srcTileSize.h >>= srcShiftH;
-
- srcTileSize.v += fCFAPatternSize.v * 2;
- srcTileSize.h += fCFAPatternSize.h * 2;
-
- // Allocate source buffer.
-
- dng_pixel_buffer srcBuffer (dng_rect (srcTileSize), srcPlane, 1,
- srcImage.PixelType (), pcInterleaved, NULL);
-
- uint32 srcBufferSize = ComputeBufferSize (srcBuffer.fPixelType,
- srcTileSize, srcBuffer.fPlanes,
- padNone);
-
- AutoPtr<dng_memory_block> srcData (host.Allocate (srcBufferSize));
-
- srcBuffer.fData = srcData->Buffer ();
-
- // Allocate destination buffer.
-
- dng_pixel_buffer dstBuffer (dng_rect (dstTileSize), 0, fColorPlanes,
- dstImage.PixelType (), pcRowInterleaved, NULL);
-
- uint32 dstBufferSize = ComputeBufferSize (dstBuffer.fPixelType,
- dstTileSize, dstBuffer.fPlanes,
- padNone);
-
- AutoPtr<dng_memory_block> dstData (host.Allocate (dstBufferSize));
-
- dstBuffer.fData = dstData->Buffer ();
-
- // Create interpolator.
-
- AutoPtr<dng_bilinear_interpolator> interpolator (new dng_bilinear_interpolator (*this,
- srcBuffer.fRowStep,
- srcBuffer.fColStep));
-
- // Iterate over destination tiles.
-
- dng_rect dstArea;
-
- dng_tile_iterator iter1 (dstImage, dstImage.Bounds ());
-
- while (iter1.GetOneTile (dstArea))
- {
-
- // Break into buffer sized tiles.
-
- dng_rect dstTile;
-
- dng_tile_iterator iter2 (dstTileSize, dstArea);
-
- while (iter2.GetOneTile (dstTile))
- {
-
- host.SniffForAbort ();
-
- // Setup buffers for this tile.
-
- dng_rect srcTile (dstTile);
-
- srcTile.t >>= srcShiftV;
- srcTile.b >>= srcShiftV;
-
- srcTile.l >>= srcShiftH;
- srcTile.r >>= srcShiftH;
-
- srcTile.t -= fCFAPatternSize.v;
- srcTile.b += fCFAPatternSize.v;
-
- srcTile.l -= fCFAPatternSize.h;
- srcTile.r += fCFAPatternSize.h;
-
- srcBuffer.fArea = srcTile;
- dstBuffer.fArea = dstTile;
-
- // Get source data.
-
- srcImage.Get (srcBuffer,
- dng_image::edge_repeat,
- fCFAPatternSize.v,
- fCFAPatternSize.h);
-
- // Process data.
-
- interpolator->Interpolate (srcBuffer,
- dstBuffer);
-
- // Save results.
-
- dstImage.Put (dstBuffer);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_mosaic_info::InterpolateFast (dng_host &host,
- dng_negative & /* negative */,
- const dng_image &srcImage,
- dng_image &dstImage,
- const dng_point &downScale,
- uint32 srcPlane) const
- {
-
- // Create fast interpolator task.
-
- dng_fast_interpolator interpolator (*this,
- srcImage,
- dstImage,
- downScale,
- srcPlane);
-
- // Find area to process.
-
- dng_rect bounds = dstImage.Bounds ();
-
- // Do the interpolation.
-
- host.PerformAreaTask (interpolator,
- bounds);
-
- }
-
-/*****************************************************************************/
-
-void dng_mosaic_info::Interpolate (dng_host &host,
- dng_negative &negative,
- const dng_image &srcImage,
- dng_image &dstImage,
- const dng_point &downScale,
- uint32 srcPlane) const
- {
-
- if (downScale == dng_point (1, 1))
- {
-
- InterpolateGeneric (host,
- negative,
- srcImage,
- dstImage,
- srcPlane);
-
- }
-
- else
- {
-
- InterpolateFast (host,
- negative,
- srcImage,
- dstImage,
- downScale,
- srcPlane);
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2009 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_mosaic_info.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_mosaic_info.h"
+
+#include "dng_area_task.h"
+#include "dng_assertions.h"
+#include "dng_bottlenecks.h"
+#include "dng_exceptions.h"
+#include "dng_filter_task.h"
+#include "dng_host.h"
+#include "dng_ifd.h"
+#include "dng_image.h"
+#include "dng_info.h"
+#include "dng_negative.h"
+#include "dng_pixel_buffer.h"
+#include "dng_tag_types.h"
+#include "dng_tag_values.h"
+#include "dng_tile_iterator.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+// A interpolation kernel for a single pixel of a single plane.
+
+class dng_bilinear_kernel
+ {
+
+ public:
+
+ enum
+ {
+ kMaxCount = 8
+ };
+
+ uint32 fCount;
+
+ dng_point fDelta [kMaxCount];
+
+ real32 fWeight32 [kMaxCount];
+ uint16 fWeight16 [kMaxCount];
+
+ int32 fOffset [kMaxCount];
+
+ public:
+
+ dng_bilinear_kernel ()
+ : fCount (0)
+ {
+ }
+
+ void Add (const dng_point &delta,
+ real32 weight);
+
+ void Finalize (const dng_point &scale,
+ uint32 patRow,
+ uint32 patCol,
+ int32 rowStep,
+ int32 colStep);
+
+ };
+
+/*****************************************************************************/
+
+void dng_bilinear_kernel::Add (const dng_point &delta,
+ real32 weight)
+ {
+
+ // Don't add zero weight elements.
+
+ if (weight <= 0.0f)
+ {
+ return;
+ }
+
+ // If the delta already matches an existing element, just combine the
+ // weights.
+
+ for (uint32 j = 0; j < fCount; j++)
+ {
+
+ if (fDelta [j] == delta)
+ {
+
+ fWeight32 [j] += weight;
+
+ return;
+
+ }
+
+ }
+
+ // Add element to list.
+
+ DNG_ASSERT (fCount < kMaxCount, "Too many kernel entries")
+
+ fDelta [fCount] = delta;
+ fWeight32 [fCount] = weight;
+
+ fCount++;
+
+ }
+
+/*****************************************************************************/
+
+void dng_bilinear_kernel::Finalize (const dng_point &scale,
+ uint32 patRow,
+ uint32 patCol,
+ int32 rowStep,
+ int32 colStep)
+ {
+
+ uint32 j;
+
+ // Adjust deltas to compensate for interpolation upscaling.
+
+ for (j = 0; j < fCount; j++)
+ {
+
+ dng_point &delta = fDelta [j];
+
+ if (scale.v == 2)
+ {
+
+ delta.v = (delta.v + (int32) (patRow & 1)) >> 1;
+
+ }
+
+ if (scale.h == 2)
+ {
+
+ delta.h = (delta.h + (int32) (patCol & 1)) >> 1;
+
+ }
+
+ }
+
+ // Sort entries into row-column scan order.
+
+ while (true)
+ {
+
+ bool didSwap = false;
+
+ for (j = 1; j < fCount; j++)
+ {
+
+ dng_point &delta0 = fDelta [j - 1];
+ dng_point &delta1 = fDelta [j ];
+
+ if (delta0.v > delta1.v ||
+ (delta0.v == delta1.v &&
+ delta0.h > delta1.h))
+ {
+
+ didSwap = true;
+
+ dng_point tempDelta = delta0;
+
+ delta0 = delta1;
+ delta1 = tempDelta;
+
+ real32 tempWeight = fWeight32 [j - 1];
+
+ fWeight32 [j - 1] = fWeight32 [j];
+ fWeight32 [j ] = tempWeight;
+
+ }
+
+ }
+
+ if (!didSwap)
+ {
+ break;
+ }
+
+ }
+
+ // Calculate offsets.
+
+ for (j = 0; j < fCount; j++)
+ {
+
+ fOffset [j] = rowStep * fDelta [j].v +
+ colStep * fDelta [j].h;
+
+ }
+
+ // Calculate 16-bit weights.
+
+ uint16 total = 0;
+ uint32 biggest = 0;
+
+ for (j = 0; j < fCount; j++)
+ {
+
+ // Round weights to 8 fractional bits.
+
+ fWeight16 [j] = (uint16) Round_uint32 (fWeight32 [j] * 256.0);
+
+ // Keep track of total of weights.
+
+ total += fWeight16 [j];
+
+ // Keep track of which weight is biggest.
+
+ if (fWeight16 [biggest] < fWeight16 [j])
+ {
+
+ biggest = j;
+
+ }
+
+ }
+
+ // Adjust largest entry so total of weights is exactly 256.
+
+ fWeight16 [biggest] += (256 - total);
+
+ // Recompute the floating point weights from the rounded integer weights
+ // so results match more closely.
+
+ for (j = 0; j < fCount; j++)
+ {
+
+ fWeight32 [j] = fWeight16 [j] * (1.0f / 256.0f);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+class dng_bilinear_pattern
+ {
+
+ public:
+
+ enum
+ {
+ kMaxPattern = kMaxCFAPattern * 2
+ };
+
+ dng_point fScale;
+
+ uint32 fPatRows;
+ uint32 fPatCols;
+
+ dng_bilinear_kernel fKernel [kMaxPattern]
+ [kMaxPattern];
+
+ uint32 fCounts [kMaxPattern]
+ [kMaxPattern];
+
+ int32 *fOffsets [kMaxPattern]
+ [kMaxPattern];
+
+ uint16 *fWeights16 [kMaxPattern]
+ [kMaxPattern];
+
+ real32 *fWeights32 [kMaxPattern]
+ [kMaxPattern];
+
+ public:
+
+ dng_bilinear_pattern ()
+
+ : fScale ()
+ , fPatRows (0)
+ , fPatCols (0)
+
+ {
+ }
+
+ private:
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+ uint32 DeltaRow (uint32 row, int32 delta)
+ {
+ return (row + fPatRows + (uint32) delta) % fPatRows;
+ }
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+__attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+ uint32 DeltaCol (uint32 col, int32 delta)
+ {
+ return (col + fPatCols + (uint32) delta) % fPatCols;
+ }
+
+ real32 LinearWeight1 (int32 d1, int32 d2)
+ {
+ if (d1 == d2)
+ return 1.0f;
+ else
+ return d2 / (real32) (d2 - d1);
+ }
+
+ real32 LinearWeight2 (int32 d1, int32 d2)
+ {
+ if (d1 == d2)
+ return 0.0f;
+ else
+ return -d1 / (real32) (d2 - d1);
+ }
+
+ public:
+
+ void Calculate (const dng_mosaic_info &info,
+ uint32 dstPlane,
+ int32 rowStep,
+ int32 colStep);
+
+ };
+
+/*****************************************************************************/
+
+void dng_bilinear_pattern::Calculate (const dng_mosaic_info &info,
+ uint32 dstPlane,
+ int32 rowStep,
+ int32 colStep)
+ {
+
+ uint32 j;
+ uint32 k;
+ uint32 patRow;
+ uint32 patCol;
+
+ // Find destination pattern size.
+
+ fScale = info.FullScale ();
+
+ fPatRows = info.fCFAPatternSize.v * fScale.v;
+ fPatCols = info.fCFAPatternSize.h * fScale.h;
+
+ // See if we need to scale up just while computing the kernels.
+
+ dng_point tempScale (1, 1);
+
+ if (info.fCFALayout >= 6)
+ {
+
+ tempScale = dng_point (2, 2);
+
+ fPatRows *= tempScale.v;
+ fPatCols *= tempScale.h;
+
+ }
+
+ // Find a boolean map for this plane color and layout.
+
+ bool map [kMaxPattern]
+ [kMaxPattern];
+
+ uint8 planeColor = info.fCFAPlaneColor [dstPlane];
+
+ switch (info.fCFALayout)
+ {
+
+ case 1: // Rectangular (or square) layout
+ {
+
+ for (j = 0; j < fPatRows; j++)
+ {
+
+ for (k = 0; k < fPatCols; k++)
+ {
+
+ map [j] [k] = (info.fCFAPattern [j] [k] == planeColor);
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ // Note that when the descriptions of the staggered patterns refer to even rows or
+ // columns, this mean the second, fourth, etc. (i.e. using one-based numbering).
+ // This needs to be clarified in the DNG specification.
+
+ case 2: // Staggered layout A: even (1-based) columns are offset down by 1/2 row
+ {
+
+ for (j = 0; j < fPatRows; j++)
+ {
+
+ for (k = 0; k < fPatCols; k++)
+ {
+
+ if ((j & 1) != (k & 1))
+ {
+
+ map [j] [k] = false;
+
+ }
+
+ else
+ {
+
+ map [j] [k] = (info.fCFAPattern [j >> 1] [k] == planeColor);
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ case 3: // Staggered layout B: even (1-based) columns are offset up by 1/2 row
+ {
+
+ for (j = 0; j < fPatRows; j++)
+ {
+
+ for (k = 0; k < fPatCols; k++)
+ {
+
+ if ((j & 1) == (k & 1))
+ {
+
+ map [j] [k] = false;
+
+ }
+
+ else
+ {
+
+ map [j] [k] = (info.fCFAPattern [j >> 1] [k] == planeColor);
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ case 4: // Staggered layout C: even (1-based) rows are offset right by 1/2 column
+ {
+
+ for (j = 0; j < fPatRows; j++)
+ {
+
+ for (k = 0; k < fPatCols; k++)
+ {
+
+ if ((j & 1) != (k & 1))
+ {
+
+ map [j] [k] = false;
+
+ }
+
+ else
+ {
+
+ map [j] [k] = (info.fCFAPattern [j] [k >> 1] == planeColor);
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ case 5: // Staggered layout D: even (1-based) rows are offset left by 1/2 column
+ {
+
+ for (j = 0; j < fPatRows; j++)
+ {
+
+ for (k = 0; k < fPatCols; k++)
+ {
+
+ if ((j & 1) == (k & 1))
+ {
+
+ map [j] [k] = false;
+
+ }
+
+ else
+ {
+
+ map [j] [k] = (info.fCFAPattern [j] [k >> 1] == planeColor);
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ case 6: // Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column
+ case 7: // Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column
+ case 8: // Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column
+ case 9: // Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column
+ {
+
+ uint32 eRow = (info.fCFALayout == 6 ||
+ info.fCFALayout == 7) ? 1 : 3;
+
+ uint32 eCol = (info.fCFALayout == 6 ||
+ info.fCFALayout == 8) ? 1 : 3;
+
+ for (j = 0; j < fPatRows; j++)
+ {
+
+ for (k = 0; k < fPatCols; k++)
+ {
+
+ uint32 jj = j & 3;
+ uint32 kk = k & 3;
+
+ if ((jj != 0 && jj != eRow) ||
+ (kk != 0 && kk != eCol))
+ {
+
+ map [j] [k] = false;
+
+ }
+
+ else
+ {
+
+ map [j] [k] = (info.fCFAPattern [((j >> 1) & ~1) + Min_uint32 (jj, 1)]
+ [((k >> 1) & ~1) + Min_uint32 (kk, 1)] == planeColor);
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ }
+
+ default:
+ ThrowProgramError ();
+
+ }
+
+ // Find projections of maps.
+
+ bool mapH [kMaxPattern];
+ bool mapV [kMaxPattern];
+
+ for (j = 0; j < kMaxPattern; j++)
+ {
+
+ mapH [j] = false;
+ mapV [j] = false;
+
+ }
+
+ for (j = 0; j < fPatRows; j++)
+ {
+
+ for (k = 0; k < fPatCols; k++)
+ {
+
+ if (map [j] [k])
+ {
+
+ mapV [j] = true;
+ mapH [k] = true;
+
+ }
+
+ }
+
+ }
+
+ // Find kernel for each patten entry.
+
+ for (patRow = 0; patRow < fPatRows; patRow += tempScale.v)
+ {
+
+ for (patCol = 0; patCol < fPatCols; patCol += tempScale.h)
+ {
+
+ dng_bilinear_kernel &kernel = fKernel [patRow] [patCol];
+
+ // Special case no interpolation case.
+
+ if (map [patRow] [patCol])
+ {
+
+ kernel.Add (dng_point (0, 0), 1.0f);
+
+ continue;
+
+ }
+
+ // Special case common patterns in 3 by 3 neighborhood.
+
+ uint32 n = DeltaRow (patRow, -1);
+ uint32 s = DeltaRow (patRow, 1);
+ uint32 w = DeltaCol (patCol, -1);
+ uint32 e = DeltaCol (patCol, 1);
+
+ bool mapNW = map [n] [w];
+ bool mapN = map [n] [patCol];
+ bool mapNE = map [n] [e];
+
+ bool mapW = map [patRow] [w];
+ bool mapE = map [patRow] [e];
+
+ bool mapSW = map [s] [w];
+ bool mapS = map [s] [patCol];
+ bool mapSE = map [s] [e];
+
+ // All sides.
+
+ if (mapN && mapS && mapW && mapW)
+ {
+
+ kernel.Add (dng_point (-1, 0), 0.25f);
+ kernel.Add (dng_point ( 0, -1), 0.25f);
+ kernel.Add (dng_point ( 0, 1), 0.25f);
+ kernel.Add (dng_point ( 1, 0), 0.25f);
+
+ continue;
+
+ }
+
+ // N & S.
+
+ if (mapN && mapS)
+ {
+
+ kernel.Add (dng_point (-1, 0), 0.5f);
+ kernel.Add (dng_point ( 1, 0), 0.5f);
+
+ continue;
+
+ }
+
+ // E & W.
+
+ if (mapW && mapE)
+ {
+
+ kernel.Add (dng_point ( 0, -1), 0.5f);
+ kernel.Add (dng_point ( 0, 1), 0.5f);
+
+ continue;
+
+ }
+
+ // N & SW & SE.
+
+ if (mapN && mapSW && mapSE)
+ {
+
+ kernel.Add (dng_point (-1, 0), 0.50f);
+ kernel.Add (dng_point ( 1, -1), 0.25f);
+ kernel.Add (dng_point ( 1, 1), 0.25f);
+
+ continue;
+
+ }
+
+ // S & NW & NE.
+
+ if (mapS && mapNW && mapNE)
+ {
+
+ kernel.Add (dng_point (-1, -1), 0.25f);
+ kernel.Add (dng_point (-1, 1), 0.25f);
+ kernel.Add (dng_point ( 1, 0), 0.50f);
+
+ continue;
+
+ }
+
+ // W & NE & SE.
+
+ if (mapW && mapNE && mapSE)
+ {
+
+ kernel.Add (dng_point (-1, 1), 0.25f);
+ kernel.Add (dng_point ( 0, -1), 0.50f);
+ kernel.Add (dng_point ( 1, 1), 0.25f);
+
+ continue;
+
+ }
+
+ // E & NW & SW.
+
+ if (mapE && mapNW && mapSW)
+ {
+
+ kernel.Add (dng_point (-1, -1), 0.25f);
+ kernel.Add (dng_point ( 0, 1), 0.50f);
+ kernel.Add (dng_point ( 1, -1), 0.25f);
+
+ continue;
+
+ }
+
+ // Four corners.
+
+ if (mapNW && mapNE && mapSE && mapSW)
+ {
+
+ kernel.Add (dng_point (-1, -1), 0.25f);
+ kernel.Add (dng_point (-1, 1), 0.25f);
+ kernel.Add (dng_point ( 1, -1), 0.25f);
+ kernel.Add (dng_point ( 1, 1), 0.25f);
+
+ continue;
+
+ }
+
+ // NW & SE
+
+ if (mapNW && mapSE)
+ {
+
+ kernel.Add (dng_point (-1, -1), 0.50f);
+ kernel.Add (dng_point ( 1, 1), 0.50f);
+
+ continue;
+
+ }
+
+ // NE & SW
+
+ if (mapNE && mapSW)
+ {
+
+ kernel.Add (dng_point (-1, 1), 0.50f);
+ kernel.Add (dng_point ( 1, -1), 0.50f);
+
+ continue;
+
+ }
+
+ // Else use double-bilinear kernel.
+
+ int32 dv1 = 0;
+ int32 dv2 = 0;
+
+ while (!mapV [DeltaRow (patRow, dv1)])
+ {
+ dv1--;
+ }
+
+ while (!mapV [DeltaRow (patRow, dv2)])
+ {
+ dv2++;
+ }
+
+ real32 w1 = LinearWeight1 (dv1, dv2) * 0.5f;
+ real32 w2 = LinearWeight2 (dv1, dv2) * 0.5f;
+
+ int32 v1 = DeltaRow (patRow, dv1);
+ int32 v2 = DeltaRow (patRow, dv2);
+
+ int32 dh1 = 0;
+ int32 dh2 = 0;
+
+ while (!map [v1] [DeltaCol (patCol, dh1)])
+ {
+ dh1--;
+ }
+
+ while (!map [v1] [DeltaCol (patCol, dh2)])
+ {
+ dh2++;
+ }
+
+ kernel.Add (dng_point (dv1, dh1),
+ LinearWeight1 (dh1, dh2) * w1);
+
+ kernel.Add (dng_point (dv1, dh2),
+ LinearWeight2 (dh1, dh2) * w1);
+
+ dh1 = 0;
+ dh2 = 0;
+
+ while (!map [v2] [DeltaCol (patCol, dh1)])
+ {
+ dh1--;
+ }
+
+ while (!map [v2] [DeltaCol (patCol, dh2)])
+ {
+ dh2++;
+ }
+
+ kernel.Add (dng_point (dv2, dh1),
+ LinearWeight1 (dh1, dh2) * w2);
+
+ kernel.Add (dng_point (dv2, dh2),
+ LinearWeight2 (dh1, dh2) * w2);
+
+ dh1 = 0;
+ dh2 = 0;
+
+ while (!mapH [DeltaCol (patCol, dh1)])
+ {
+ dh1--;
+ }
+
+ while (!mapH [DeltaCol (patCol, dh2)])
+ {
+ dh2++;
+ }
+
+ w1 = LinearWeight1 (dh1, dh2) * 0.5f;
+ w2 = LinearWeight2 (dh1, dh2) * 0.5f;
+
+ int32 h1 = DeltaCol (patCol, dh1);
+ int32 h2 = DeltaCol (patCol, dh2);
+
+ dv1 = 0;
+ dv2 = 0;
+
+ while (!map [DeltaRow (patRow, dv1)] [h1])
+ {
+ dv1--;
+ }
+
+ while (!map [DeltaRow (patRow, dv2)] [h1])
+ {
+ dv2++;
+ }
+
+ kernel.Add (dng_point (dv1, dh1),
+ LinearWeight1 (dv1, dv2) * w1);
+
+ kernel.Add (dng_point (dv2, dh1),
+ LinearWeight2 (dv1, dv2) * w1);
+
+ dv1 = 0;
+ dv2 = 0;
+
+ while (!map [DeltaRow (patRow, dv1)] [h2])
+ {
+ dv1--;
+ }
+
+ while (!map [DeltaRow (patRow, dv2)] [h2])
+ {
+ dv2++;
+ }
+
+ kernel.Add (dng_point (dv1, dh2),
+ LinearWeight1 (dv1, dv2) * w2);
+
+ kernel.Add (dng_point (dv2, dh2),
+ LinearWeight2 (dv1, dv2) * w2);
+
+ }
+
+ }
+
+ // Deal with temp scale case.
+
+ if (tempScale == dng_point (2, 2))
+ {
+
+ fPatRows /= tempScale.v;
+ fPatCols /= tempScale.h;
+
+ for (patRow = 0; patRow < fPatRows; patRow++)
+ {
+
+ for (patCol = 0; patCol < fPatCols; patCol++)
+ {
+
+ int32 patRow2 = patRow << 1;
+ int32 patCol2 = patCol << 1;
+
+ dng_bilinear_kernel &kernel = fKernel [patRow2] [patCol2];
+
+ for (j = 0; j < kernel.fCount; j++)
+ {
+
+ int32 x = patRow2 + kernel.fDelta [j].v;
+
+ if ((x & 3) != 0)
+ {
+ x = (x & ~3) + 2;
+ }
+
+ kernel.fDelta [j].v = ((x - patRow2) >> 1);
+
+ x = patCol2 + kernel.fDelta [j].h;
+
+ if ((x & 3) != 0)
+ {
+ x = (x & ~3) + 2;
+ }
+
+ kernel.fDelta [j].h = ((x - patCol2) >> 1);
+
+ }
+
+ kernel.Finalize (fScale,
+ patRow,
+ patCol,
+ rowStep,
+ colStep);
+
+ fCounts [patRow] [patCol] = kernel.fCount;
+ fOffsets [patRow] [patCol] = kernel.fOffset;
+ fWeights16 [patRow] [patCol] = kernel.fWeight16;
+ fWeights32 [patRow] [patCol] = kernel.fWeight32;
+
+ }
+
+ }
+
+ }
+
+ // Non-temp scale case.
+
+ else
+ {
+
+ for (patRow = 0; patRow < fPatRows; patRow++)
+ {
+
+ for (patCol = 0; patCol < fPatCols; patCol++)
+ {
+
+ dng_bilinear_kernel &kernel = fKernel [patRow] [patCol];
+
+ kernel.Finalize (fScale,
+ patRow,
+ patCol,
+ rowStep,
+ colStep);
+
+ fCounts [patRow] [patCol] = kernel.fCount;
+ fOffsets [patRow] [patCol] = kernel.fOffset;
+ fWeights16 [patRow] [patCol] = kernel.fWeight16;
+ fWeights32 [patRow] [patCol] = kernel.fWeight32;
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+class dng_bilinear_interpolator
+ {
+
+ private:
+
+ dng_bilinear_pattern fPattern [kMaxColorPlanes];
+
+ public:
+
+ dng_bilinear_interpolator (const dng_mosaic_info &info,
+ int32 rowStep,
+ int32 colStep);
+
+ void Interpolate (dng_pixel_buffer &srcBuffer,
+ dng_pixel_buffer &dstBuffer);
+
+ };
+
+/*****************************************************************************/
+
+dng_bilinear_interpolator::dng_bilinear_interpolator (const dng_mosaic_info &info,
+ int32 rowStep,
+ int32 colStep)
+ {
+
+ for (uint32 dstPlane = 0; dstPlane < info.fColorPlanes; dstPlane++)
+ {
+
+ fPattern [dstPlane] . Calculate (info,
+ dstPlane,
+ rowStep,
+ colStep);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_bilinear_interpolator::Interpolate (dng_pixel_buffer &srcBuffer,
+ dng_pixel_buffer &dstBuffer)
+ {
+
+ uint32 patCols = fPattern [0] . fPatCols;
+ uint32 patRows = fPattern [0] . fPatRows;
+
+ dng_point scale = fPattern [0] . fScale;
+
+ uint32 sRowShift = scale.v - 1;
+ uint32 sColShift = scale.h - 1;
+
+ int32 dstCol = dstBuffer.fArea.l;
+
+ int32 srcCol = dstCol >> sColShift;
+
+ uint32 patPhase = dstCol % patCols;
+
+ for (int32 dstRow = dstBuffer.fArea.t;
+ dstRow < dstBuffer.fArea.b;
+ dstRow++)
+ {
+
+ int32 srcRow = dstRow >> sRowShift;
+
+ uint32 patRow = dstRow % patRows;
+
+ for (uint32 dstPlane = 0;
+ dstPlane < dstBuffer.fPlanes;
+ dstPlane++)
+ {
+
+ const void *sPtr = srcBuffer.ConstPixel (srcRow,
+ srcCol,
+ srcBuffer.fPlane);
+
+ void *dPtr = dstBuffer.DirtyPixel (dstRow,
+ dstCol,
+ dstPlane);
+
+ if (dstBuffer.fPixelType == ttShort)
+ {
+
+ DoBilinearRow16 ((const uint16 *) sPtr,
+ (uint16 *) dPtr,
+ dstBuffer.fArea.W (),
+ patPhase,
+ patCols,
+ fPattern [dstPlane].fCounts [patRow],
+ fPattern [dstPlane].fOffsets [patRow],
+ fPattern [dstPlane].fWeights16 [patRow],
+ sColShift);
+
+ }
+
+ else
+ {
+
+ DoBilinearRow32 ((const real32 *) sPtr,
+ (real32 *) dPtr,
+ dstBuffer.fArea.W (),
+ patPhase,
+ patCols,
+ fPattern [dstPlane].fCounts [patRow],
+ fPattern [dstPlane].fOffsets [patRow],
+ fPattern [dstPlane].fWeights32 [patRow],
+ sColShift);
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+class dng_fast_interpolator: public dng_filter_task
+ {
+
+ protected:
+
+ const dng_mosaic_info &fInfo;
+
+ dng_point fDownScale;
+
+ uint32 fFilterColor [kMaxCFAPattern] [kMaxCFAPattern];
+
+ public:
+
+ dng_fast_interpolator (const dng_mosaic_info &info,
+ const dng_image &srcImage,
+ dng_image &dstImage,
+ const dng_point &downScale,
+ uint32 srcPlane);
+
+ virtual dng_rect SrcArea (const dng_rect &dstArea);
+
+ virtual void ProcessArea (uint32 threadIndex,
+ dng_pixel_buffer &srcBuffer,
+ dng_pixel_buffer &dstBuffer);
+
+ };
+
+/*****************************************************************************/
+
+dng_fast_interpolator::dng_fast_interpolator (const dng_mosaic_info &info,
+ const dng_image &srcImage,
+ dng_image &dstImage,
+ const dng_point &downScale,
+ uint32 srcPlane)
+
+ : dng_filter_task (srcImage,
+ dstImage)
+
+ , fInfo (info )
+ , fDownScale (downScale)
+
+ {
+
+ fSrcPlane = srcPlane;
+ fSrcPlanes = 1;
+
+ fSrcPixelType = ttShort;
+ fDstPixelType = ttShort;
+
+ fSrcRepeat = fInfo.fCFAPatternSize;
+
+ fUnitCell = fInfo.fCFAPatternSize;
+
+ fMaxTileSize = dng_point (256 / fDownScale.v,
+ 256 / fDownScale.h);
+
+ fMaxTileSize.h = Max_int32 (fMaxTileSize.h, fUnitCell.h);
+ fMaxTileSize.v = Max_int32 (fMaxTileSize.v, fUnitCell.v);
+
+ // Find color map.
+
+ {
+
+ for (int32 r = 0; r < fInfo.fCFAPatternSize.v; r++)
+ {
+
+ for (int32 c = 0; c < fInfo.fCFAPatternSize.h; c++)
+ {
+
+ uint8 key = fInfo.fCFAPattern [r] [c];
+
+ for (uint32 index = 0; index < fInfo.fColorPlanes; index++)
+ {
+
+ if (key == fInfo.fCFAPlaneColor [index])
+ {
+
+ fFilterColor [r] [c] = index;
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_rect dng_fast_interpolator::SrcArea (const dng_rect &dstArea)
+ {
+
+ return dng_rect (dstArea.t * fDownScale.v,
+ dstArea.l * fDownScale.h,
+ dstArea.b * fDownScale.v,
+ dstArea.r * fDownScale.h);
+
+ }
+
+/*****************************************************************************/
+
+void dng_fast_interpolator::ProcessArea (uint32 /* threadIndex */,
+ dng_pixel_buffer &srcBuffer,
+ dng_pixel_buffer &dstBuffer)
+ {
+
+ dng_rect srcArea = srcBuffer.fArea;
+ dng_rect dstArea = dstBuffer.fArea;
+
+ // Downsample buffer.
+
+ int32 srcRow = srcArea.t;
+
+ uint32 srcRowPhase1 = 0;
+ uint32 srcRowPhase2 = 0;
+
+ uint32 patRows = fInfo.fCFAPatternSize.v;
+ uint32 patCols = fInfo.fCFAPatternSize.h;
+
+ uint32 cellRows = fDownScale.v;
+ uint32 cellCols = fDownScale.h;
+
+ uint32 plane;
+ uint32 planes = fInfo.fColorPlanes;
+
+ int32 dstPlaneStep = dstBuffer.fPlaneStep;
+
+ uint32 total [kMaxColorPlanes];
+ uint32 count [kMaxColorPlanes];
+
+ for (plane = 0; plane < planes; plane++)
+ {
+ total [plane] = 0;
+ count [plane] = 0;
+ }
+
+ for (int32 dstRow = dstArea.t; dstRow < dstArea.b; dstRow++)
+ {
+
+ const uint16 *sPtr = srcBuffer.ConstPixel_uint16 (srcRow,
+ srcArea.l,
+ fSrcPlane);
+
+ uint16 *dPtr = dstBuffer.DirtyPixel_uint16 (dstRow,
+ dstArea.l,
+ 0);
+
+ uint32 srcColPhase1 = 0;
+ uint32 srcColPhase2 = 0;
+
+ for (int32 dstCol = dstArea.l; dstCol < dstArea.r; dstCol++)
+ {
+
+ const uint16 *ssPtr = sPtr;
+
+ srcRowPhase2 = srcRowPhase1;
+
+ for (uint32 cellRow = 0; cellRow < cellRows; cellRow++)
+ {
+
+ const uint32 *filterRow = fFilterColor [srcRowPhase2];
+
+ if (++srcRowPhase2 == patRows)
+ {
+ srcRowPhase2 = 0;
+ }
+
+ srcColPhase2 = srcColPhase1;
+
+ for (uint32 cellCol = 0; cellCol < cellCols; cellCol++)
+ {
+
+ uint32 color = filterRow [srcColPhase2];
+
+ if (++srcColPhase2 == patCols)
+ {
+ srcColPhase2 = 0;
+ }
+
+ total [color] += (uint32) ssPtr [cellCol];
+ count [color] ++;
+
+ }
+
+ ssPtr += srcBuffer.fRowStep;
+
+ }
+
+ for (plane = 0; plane < planes; plane++)
+ {
+
+ uint32 t = total [plane];
+ uint32 c = count [plane];
+
+ dPtr [plane * dstPlaneStep] = (uint16) ((t + (c >> 1)) / c);
+
+ total [plane] = 0;
+ count [plane] = 0;
+
+ }
+
+ srcColPhase1 = srcColPhase2;
+
+ sPtr += cellCols;
+
+ dPtr ++;
+
+ }
+
+ srcRowPhase1 = srcRowPhase2;
+
+ srcRow += cellRows;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_mosaic_info::dng_mosaic_info ()
+
+ : fCFAPatternSize ()
+ , fColorPlanes (0)
+ , fCFALayout (1)
+ , fBayerGreenSplit (0)
+ , fSrcSize ()
+ , fCroppedSize ()
+ , fAspectRatio (1.0)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_mosaic_info::~dng_mosaic_info ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_mosaic_info::Parse (dng_host & /* host */,
+ dng_stream & /* stream */,
+ dng_info &info)
+ {
+
+ // Find main image IFD.
+
+ dng_ifd &rawIFD = *info.fIFD [info.fMainIndex].Get ();
+
+ // This information only applies to CFA images.
+
+ if (rawIFD.fPhotometricInterpretation != piCFA)
+ {
+ return;
+ }
+
+ // Copy CFA pattern.
+
+ fCFAPatternSize.v = rawIFD.fCFARepeatPatternRows;
+ fCFAPatternSize.h = rawIFD.fCFARepeatPatternCols;
+
+ for (int32 j = 0; j < fCFAPatternSize.v; j++)
+ {
+ for (int32 k = 0; k < fCFAPatternSize.h; k++)
+ {
+ fCFAPattern [j] [k] = rawIFD.fCFAPattern [j] [k];
+ }
+ }
+
+ // Copy CFA plane information.
+
+ fColorPlanes = info.fShared->fCameraProfile.fColorPlanes;
+
+ for (uint32 n = 0; n < fColorPlanes; n++)
+ {
+ fCFAPlaneColor [n] = rawIFD.fCFAPlaneColor [n];
+ }
+
+ // Copy CFA layout information.
+
+ fCFALayout = rawIFD.fCFALayout;
+
+ // Green split value for Bayer patterns.
+
+ fBayerGreenSplit = rawIFD.fBayerGreenSplit;
+
+ }
+
+/*****************************************************************************/
+
+void dng_mosaic_info::PostParse (dng_host & /* host */,
+ dng_negative &negative)
+ {
+
+ // Keep track of source image size.
+
+ fSrcSize = negative.Stage2Image ()->Size ();
+
+ // Default cropped size.
+
+ fCroppedSize.v = Round_int32 (negative.DefaultCropSizeV ().As_real64 ());
+ fCroppedSize.h = Round_int32 (negative.DefaultCropSizeH ().As_real64 ());
+
+ // Pixel aspect ratio.
+
+ fAspectRatio = negative.DefaultScaleH ().As_real64 () /
+ negative.DefaultScaleV ().As_real64 ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_mosaic_info::SetFourColorBayer ()
+ {
+
+ if (fCFAPatternSize != dng_point (2, 2))
+ {
+ return false;
+ }
+
+ if (fColorPlanes != 3)
+ {
+ return false;
+ }
+
+ uint8 color0 = fCFAPlaneColor [0];
+ uint8 color1 = fCFAPlaneColor [1];
+ uint8 color2 = fCFAPlaneColor [2];
+
+ // Look for color 1 repeated twice in a diagonal.
+
+ if ((fCFAPattern [0] [0] == color1 && fCFAPattern [1] [1] == color1) ||
+ (fCFAPattern [0] [1] == color1 && fCFAPattern [1] [0] == color1))
+ {
+
+ // OK, this looks like a Bayer pattern.
+
+ // Find unused color code.
+
+ uint8 color3 = 0;
+
+ while (color3 == color0 ||
+ color3 == color1 ||
+ color3 == color2)
+ {
+ color3++;
+ }
+
+ // Switch the four color mosaic.
+
+ fColorPlanes = 4;
+
+ fCFAPlaneColor [3] = color3;
+
+ // Replace the "green" in the "blue" rows with the new color.
+
+ if (fCFAPattern [0] [0] == color0)
+ {
+ fCFAPattern [1] [0] = color3;
+ }
+
+ else if (fCFAPattern [0] [1] == color0)
+ {
+ fCFAPattern [1] [1] = color3;
+ }
+
+ else if (fCFAPattern [1] [0] == color0)
+ {
+ fCFAPattern [0] [0] = color3;
+ }
+
+ else
+ {
+ fCFAPattern [0] [1] = color3;
+ }
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+dng_point dng_mosaic_info::FullScale () const
+ {
+
+ switch (fCFALayout)
+ {
+
+ // Staggered layouts with offset columns double the row count
+ // during interpolation.
+
+ case 2:
+ case 3:
+ return dng_point (2, 1);
+
+ // Staggered layouts with offset rows double the column count
+ // during interpolation.
+
+ case 4:
+ case 5:
+ return dng_point (1, 2);
+
+ // Otherwise there is no size change during interpolation.
+
+ default:
+ break;
+
+ }
+
+ return dng_point (1, 1);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_mosaic_info::IsSafeDownScale (const dng_point &downScale) const
+ {
+
+ if (downScale.v >= fCFAPatternSize.v &&
+ downScale.h >= fCFAPatternSize.h)
+ {
+
+ return true;
+
+ }
+
+ dng_point test;
+
+ test.v = Min_int32 (downScale.v, fCFAPatternSize.v);
+ test.h = Min_int32 (downScale.h, fCFAPatternSize.h);
+
+ for (int32 phaseV = 0; phaseV <= fCFAPatternSize.v - test.v; phaseV++)
+ {
+
+ for (int32 phaseH = 0; phaseH <= fCFAPatternSize.h - test.h; phaseH++)
+ {
+
+ uint32 plane;
+
+ bool contains [kMaxColorPlanes];
+
+ for (plane = 0; plane < fColorPlanes; plane++)
+ {
+
+ contains [plane] = false;
+
+ }
+
+ for (int32 srcRow = 0; srcRow < test.v; srcRow++)
+ {
+
+ for (int32 srcCol = 0; srcCol < test.h; srcCol++)
+ {
+
+ uint8 srcKey = fCFAPattern [srcRow + phaseV]
+ [srcCol + phaseH];
+
+ for (plane = 0; plane < fColorPlanes; plane++)
+ {
+
+ if (srcKey == fCFAPlaneColor [plane])
+ {
+
+ contains [plane] = true;
+
+ }
+
+ }
+
+
+ }
+
+ }
+
+ for (plane = 0; plane < fColorPlanes; plane++)
+ {
+
+ if (!contains [plane])
+ {
+
+ return false;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_mosaic_info::SizeForDownScale (const dng_point &downScale) const
+ {
+
+ uint32 sizeV = Max_uint32 (1, (fCroppedSize.v + (downScale.v >> 1)) / downScale.v);
+ uint32 sizeH = Max_uint32 (1, (fCroppedSize.h + (downScale.h >> 1)) / downScale.h);
+
+ return Max_int32 (sizeV, sizeH);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_mosaic_info::ValidSizeDownScale (const dng_point &downScale,
+ uint32 minSize) const
+ {
+
+ const int32 kMaxDownScale = 64;
+
+ if (downScale.h > kMaxDownScale ||
+ downScale.v > kMaxDownScale)
+ {
+
+ return false;
+
+ }
+
+ return SizeForDownScale (downScale) >= minSize;
+
+ }
+
+/*****************************************************************************/
+
+dng_point dng_mosaic_info::DownScale (uint32 minSize,
+ uint32 prefSize,
+ real64 cropFactor) const
+ {
+
+ dng_point bestScale (1, 1);
+
+ if (prefSize && IsColorFilterArray ())
+ {
+
+ // Adjust sizes for crop factor.
+
+ minSize = Round_uint32 (minSize / cropFactor);
+ prefSize = Round_uint32 (prefSize / cropFactor);
+
+ prefSize = Max_uint32 (prefSize, minSize);
+
+ // Start by assuming we need the full size image.
+
+ int32 bestSize = SizeForDownScale (bestScale);
+
+ // Find size of nearly square cell.
+
+ dng_point squareCell (1, 1);
+
+ if (fAspectRatio < 1.0 / 1.8)
+ {
+
+ squareCell.h = Min_int32 (4, Round_int32 (1.0 / fAspectRatio));
+
+ }
+
+ if (fAspectRatio > 1.8)
+ {
+
+ squareCell.v = Min_int32 (4, Round_int32 (fAspectRatio));
+
+ }
+
+ // Find minimum safe cell size.
+
+ dng_point testScale = squareCell;
+
+ while (!IsSafeDownScale (testScale))
+ {
+
+ testScale.v += squareCell.v;
+ testScale.h += squareCell.h;
+
+ }
+
+ // See if this scale is usable.
+
+ if (!ValidSizeDownScale (testScale, minSize))
+ {
+
+ // We cannot downsample at all...
+
+ return bestScale;
+
+ }
+
+ // See if this is closer to the preferred size.
+
+ int32 testSize = SizeForDownScale (testScale);
+
+ if (Abs_int32 (testSize - (int32) prefSize) <=
+ Abs_int32 (bestSize - (int32) prefSize))
+ {
+ bestScale = testScale;
+ bestSize = testSize;
+ }
+
+ else
+ {
+ return bestScale;
+ }
+
+ // Now keep adding square cells as long as possible.
+
+ while (true)
+ {
+
+ testScale.v += squareCell.v;
+ testScale.h += squareCell.h;
+
+ if (IsSafeDownScale (testScale))
+ {
+
+ if (!ValidSizeDownScale (testScale, minSize))
+ {
+ return bestScale;
+ }
+
+ // See if this is closer to the preferred size.
+
+ testSize = SizeForDownScale (testScale);
+
+ if (Abs_int32 (testSize - (int32) prefSize) <=
+ Abs_int32 (bestSize - (int32) prefSize))
+ {
+ bestScale = testScale;
+ bestSize = testSize;
+ }
+
+ else
+ {
+ return bestScale;
+ }
+
+ }
+
+ }
+
+ }
+
+ return bestScale;
+
+ }
+
+/*****************************************************************************/
+
+dng_point dng_mosaic_info::DstSize (const dng_point &downScale) const
+ {
+
+ if (downScale == dng_point (1, 1))
+ {
+
+ dng_point scale = FullScale ();
+
+ return dng_point (fSrcSize.v * scale.v,
+ fSrcSize.h * scale.h);
+
+ }
+
+ const int32 kMaxDownScale = 64;
+
+ if (downScale.h > kMaxDownScale ||
+ downScale.v > kMaxDownScale)
+ {
+
+ return dng_point (0, 0);
+
+ }
+
+ dng_point size;
+
+ size.v = Max_int32 (1, (fSrcSize.v + (downScale.v >> 1)) / downScale.v);
+ size.h = Max_int32 (1, (fSrcSize.h + (downScale.h >> 1)) / downScale.h);
+
+ return size;
+
+ }
+
+/*****************************************************************************/
+
+void dng_mosaic_info::InterpolateGeneric (dng_host &host,
+ dng_negative & /* negative */,
+ const dng_image &srcImage,
+ dng_image &dstImage,
+ uint32 srcPlane) const
+ {
+
+ // Find destination to source bit shifts.
+
+ dng_point scale = FullScale ();
+
+ uint32 srcShiftV = scale.v - 1;
+ uint32 srcShiftH = scale.h - 1;
+
+ // Find tile sizes.
+
+ const uint32 kMaxDstTileRows = 128;
+ const uint32 kMaxDstTileCols = 128;
+
+ dng_point dstTileSize = dstImage.RepeatingTile ().Size ();
+
+ dstTileSize.v = Min_int32 (dstTileSize.v, kMaxDstTileRows);
+ dstTileSize.h = Min_int32 (dstTileSize.h, kMaxDstTileCols);
+
+ dng_point srcTileSize = dstTileSize;
+
+ srcTileSize.v >>= srcShiftV;
+ srcTileSize.h >>= srcShiftH;
+
+ srcTileSize.v += fCFAPatternSize.v * 2;
+ srcTileSize.h += fCFAPatternSize.h * 2;
+
+ // Allocate source buffer.
+
+ dng_pixel_buffer srcBuffer (dng_rect (srcTileSize), srcPlane, 1,
+ srcImage.PixelType (), pcInterleaved, NULL);
+
+ uint32 srcBufferSize = ComputeBufferSize (srcBuffer.fPixelType,
+ srcTileSize, srcBuffer.fPlanes,
+ padNone);
+
+ AutoPtr<dng_memory_block> srcData (host.Allocate (srcBufferSize));
+
+ srcBuffer.fData = srcData->Buffer ();
+
+ // Allocate destination buffer.
+
+ dng_pixel_buffer dstBuffer (dng_rect (dstTileSize), 0, fColorPlanes,
+ dstImage.PixelType (), pcRowInterleaved, NULL);
+
+ uint32 dstBufferSize = ComputeBufferSize (dstBuffer.fPixelType,
+ dstTileSize, dstBuffer.fPlanes,
+ padNone);
+
+ AutoPtr<dng_memory_block> dstData (host.Allocate (dstBufferSize));
+
+ dstBuffer.fData = dstData->Buffer ();
+
+ // Create interpolator.
+
+ AutoPtr<dng_bilinear_interpolator> interpolator (new dng_bilinear_interpolator (*this,
+ srcBuffer.fRowStep,
+ srcBuffer.fColStep));
+
+ // Iterate over destination tiles.
+
+ dng_rect dstArea;
+
+ dng_tile_iterator iter1 (dstImage, dstImage.Bounds ());
+
+ while (iter1.GetOneTile (dstArea))
+ {
+
+ // Break into buffer sized tiles.
+
+ dng_rect dstTile;
+
+ dng_tile_iterator iter2 (dstTileSize, dstArea);
+
+ while (iter2.GetOneTile (dstTile))
+ {
+
+ host.SniffForAbort ();
+
+ // Setup buffers for this tile.
+
+ dng_rect srcTile (dstTile);
+
+ srcTile.t >>= srcShiftV;
+ srcTile.b >>= srcShiftV;
+
+ srcTile.l >>= srcShiftH;
+ srcTile.r >>= srcShiftH;
+
+ srcTile.t -= fCFAPatternSize.v;
+ srcTile.b += fCFAPatternSize.v;
+
+ srcTile.l -= fCFAPatternSize.h;
+ srcTile.r += fCFAPatternSize.h;
+
+ srcBuffer.fArea = srcTile;
+ dstBuffer.fArea = dstTile;
+
+ // Get source data.
+
+ srcImage.Get (srcBuffer,
+ dng_image::edge_repeat,
+ fCFAPatternSize.v,
+ fCFAPatternSize.h);
+
+ // Process data.
+
+ interpolator->Interpolate (srcBuffer,
+ dstBuffer);
+
+ // Save results.
+
+ dstImage.Put (dstBuffer);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_mosaic_info::InterpolateFast (dng_host &host,
+ dng_negative & /* negative */,
+ const dng_image &srcImage,
+ dng_image &dstImage,
+ const dng_point &downScale,
+ uint32 srcPlane) const
+ {
+
+ // Create fast interpolator task.
+
+ dng_fast_interpolator interpolator (*this,
+ srcImage,
+ dstImage,
+ downScale,
+ srcPlane);
+
+ // Find area to process.
+
+ dng_rect bounds = dstImage.Bounds ();
+
+ // Do the interpolation.
+
+ host.PerformAreaTask (interpolator,
+ bounds);
+
+ }
+
+/*****************************************************************************/
+
+void dng_mosaic_info::Interpolate (dng_host &host,
+ dng_negative &negative,
+ const dng_image &srcImage,
+ dng_image &dstImage,
+ const dng_point &downScale,
+ uint32 srcPlane) const
+ {
+
+ if (downScale == dng_point (1, 1))
+ {
+
+ InterpolateGeneric (host,
+ negative,
+ srcImage,
+ dstImage,
+ srcPlane);
+
+ }
+
+ else
+ {
+
+ InterpolateFast (host,
+ negative,
+ srcImage,
+ dstImage,
+ downScale,
+ srcPlane);
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_mosaic_info.h b/source/dng_mosaic_info.h
index 477c105..8a31753 100644
--- a/source/dng_mosaic_info.h
+++ b/source/dng_mosaic_info.h
@@ -1,200 +1,200 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_mosaic_info.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Support for descriptive information about color filter array patterns.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_mosaic_info__
-#define __dng_mosaic_info__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_rect.h"
-#include "dng_sdk_limits.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief Support for describing color filter array patterns and manipulating mosaic sample data.
-///
-/// See CFAPattern tag in \ref spec_tiff_ep "TIFF/EP specification" and CFAPlaneColor, CFALayout, and BayerGreenSplit
-/// tags in the \ref spec_dng "DNG 1.1.0 specification".
-
-class dng_mosaic_info
- {
-
- public:
-
- /// Size of fCFAPattern.
-
- dng_point fCFAPatternSize;
-
- /// CFA pattern from CFAPattern tag in the \ref spec_tiff_ep "TIFF/EP specification."
-
- uint8 fCFAPattern [kMaxCFAPattern] [kMaxCFAPattern];
-
- /// Number of color planes in DNG input.
-
- uint32 fColorPlanes;
-
- uint8 fCFAPlaneColor [kMaxColorPlanes];
-
- /// Value of CFALayout tag in the \ref spec_dng "DNG 1.3 specification."
- /// CFALayout describes the spatial layout of the CFA. The currently defined values are:
- /// - 1 = Rectangular (or square) layout.
- /// - 2 = Staggered layout A: even columns are offset down by 1/2 row.
- /// - 3 = Staggered layout B: even columns are offset up by 1/2 row.
- /// - 4 = Staggered layout C: even rows are offset right by 1/2 column.
- /// - 5 = Staggered layout D: even rows are offset left by 1/2 column.
- /// - 6 = Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column.
- /// - 7 = Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column.
- /// - 8 = Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column.
- /// - 9 = Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column.
-
- uint32 fCFALayout;
-
- /// Value of BayerGreeSplit tag in DNG file.
- /// BayerGreenSplit only applies to CFA images using a Bayer pattern filter array. This tag
- /// specifies, in arbitrary units, how closely the values of the green pixels in the blue/green rows
- /// track the values of the green pixels in the red/green rows.
- ///
- /// A value of zero means the two kinds of green pixels track closely, while a non-zero value
- /// means they sometimes diverge. The useful range for this tag is from 0 (no divergence) to about
- /// 5000 (large divergence).
-
- uint32 fBayerGreenSplit;
-
- protected:
-
- dng_point fSrcSize;
-
- dng_point fCroppedSize;
-
- real64 fAspectRatio;
-
- public:
-
- dng_mosaic_info ();
-
- virtual ~dng_mosaic_info ();
-
- virtual void Parse (dng_host &host,
- dng_stream &stream,
- dng_info &info);
-
- virtual void PostParse (dng_host &host,
- dng_negative &negative);
-
- /// Returns whether the RAW data in this DNG file from a color filter array (mosaiced) source.
- /// \retval true if this DNG file is from a color filter array (mosiaced) source.
-
- bool IsColorFilterArray () const
- {
- return fCFAPatternSize != dng_point (0, 0);
- }
-
- /// Enable generating four-plane output from three-plane Bayer input.
- /// Extra plane is a second version of the green channel. First green is produced
- /// using green mosaic samples from one set of rows/columns (even/odd) and the second
- /// green channel is produced using the other set of rows/columns. One can compare the
- /// two versions to judge whether BayerGreenSplit needs to be set for a given input source.
-
- virtual bool SetFourColorBayer ();
-
- /// Returns scaling factor relative to input size needed to capture output data.
- /// Staggered (or rotated) sensing arrays are produced to a larger output than the number of input samples.
- /// This method indicates how much larger.
- /// \retval a point with integer scaling factors for the horizotal and vertical dimensions.
-
- virtual dng_point FullScale () const;
-
- /// Returns integer factors by which mosaic data must be downsampled to produce an image which is as close
- /// to prefSize as possible in longer dimension, but no smaller than minSize.
- /// \param minSize Number of pixels as minium for longer dimension of downsampled image.
- /// \param prefSize Number of pixels as target for longer dimension of downsampled image.
- /// \param cropFactor Faction of the image to be used after cropping.
- /// \retval Point containing integer factors by which image must be downsampled.
-
- virtual dng_point DownScale (uint32 minSize,
- uint32 prefSize,
- real64 cropFactor) const;
-
- /// Return size of demosaiced image for passed in downscaling factor.
- /// \param downScale Integer downsampling factor obtained from DownScale method.
- /// \retval Size of resulting demosaiced image.
-
- virtual dng_point DstSize (const dng_point &downScale) const;
-
- /// Demosaic interpolation of a single plane for non-downsampled case.
- /// \param host dng_host to use for buffer allocation requests, user cancellation testing, and progress updates.
- /// \param negative DNG negative of mosaiced data.
- /// \param srcImage Source image for mosaiced data.
- /// \param dstImage Destination image for resulting interpolated data.
- /// \param srcPlane Which plane to interpolate.
-
- virtual void InterpolateGeneric (dng_host &host,
- dng_negative &negative,
- const dng_image &srcImage,
- dng_image &dstImage,
- uint32 srcPlane = 0) const;
-
- /// Demosaic interpolation of a single plane for downsampled case.
- /// \param host dng_host to use for buffer allocation requests, user cancellation testing, and progress updates.
- /// \param negative DNG negative of mosaiced data.
- /// \param srcImage Source image for mosaiced data.
- /// \param dstImage Destination image for resulting interpolated data.
- /// \param downScale Amount (in horizontal and vertical) by which to subsample image.
- /// \param srcPlane Which plane to interpolate.
-
- virtual void InterpolateFast (dng_host &host,
- dng_negative &negative,
- const dng_image &srcImage,
- dng_image &dstImage,
- const dng_point &downScale,
- uint32 srcPlane = 0) const;
-
- /// Demosaic interpolation of a single plane. Chooses between generic and fast interpolators based on parameters.
- /// \param host dng_host to use for buffer allocation requests, user cancellation testing, and progress updates.
- /// \param negative DNG negative of mosaiced data.
- /// \param srcImage Source image for mosaiced data.
- /// \param dstImage Destination image for resulting interpolated data.
- /// \param downScale Amount (in horizontal and vertical) by which to subsample image.
- /// \param srcPlane Which plane to interpolate.
-
- virtual void Interpolate (dng_host &host,
- dng_negative &negative,
- const dng_image &srcImage,
- dng_image &dstImage,
- const dng_point &downScale,
- uint32 srcPlane = 0) const;
-
- protected:
-
- virtual bool IsSafeDownScale (const dng_point &downScale) const;
-
- uint32 SizeForDownScale (const dng_point &downScale) const;
-
- virtual bool ValidSizeDownScale (const dng_point &downScale,
- uint32 minSize) const;
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_mosaic_info.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Support for descriptive information about color filter array patterns.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_mosaic_info__
+#define __dng_mosaic_info__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_rect.h"
+#include "dng_sdk_limits.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief Support for describing color filter array patterns and manipulating mosaic sample data.
+///
+/// See CFAPattern tag in \ref spec_tiff_ep "TIFF/EP specification" and CFAPlaneColor, CFALayout, and BayerGreenSplit
+/// tags in the \ref spec_dng "DNG 1.1.0 specification".
+
+class dng_mosaic_info
+ {
+
+ public:
+
+ /// Size of fCFAPattern.
+
+ dng_point fCFAPatternSize;
+
+ /// CFA pattern from CFAPattern tag in the \ref spec_tiff_ep "TIFF/EP specification."
+
+ uint8 fCFAPattern [kMaxCFAPattern] [kMaxCFAPattern];
+
+ /// Number of color planes in DNG input.
+
+ uint32 fColorPlanes;
+
+ uint8 fCFAPlaneColor [kMaxColorPlanes];
+
+ /// Value of CFALayout tag in the \ref spec_dng "DNG 1.3 specification."
+ /// CFALayout describes the spatial layout of the CFA. The currently defined values are:
+ /// - 1 = Rectangular (or square) layout.
+ /// - 2 = Staggered layout A: even columns are offset down by 1/2 row.
+ /// - 3 = Staggered layout B: even columns are offset up by 1/2 row.
+ /// - 4 = Staggered layout C: even rows are offset right by 1/2 column.
+ /// - 5 = Staggered layout D: even rows are offset left by 1/2 column.
+ /// - 6 = Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column.
+ /// - 7 = Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column.
+ /// - 8 = Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column.
+ /// - 9 = Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column.
+
+ uint32 fCFALayout;
+
+ /// Value of BayerGreeSplit tag in DNG file.
+ /// BayerGreenSplit only applies to CFA images using a Bayer pattern filter array. This tag
+ /// specifies, in arbitrary units, how closely the values of the green pixels in the blue/green rows
+ /// track the values of the green pixels in the red/green rows.
+ ///
+ /// A value of zero means the two kinds of green pixels track closely, while a non-zero value
+ /// means they sometimes diverge. The useful range for this tag is from 0 (no divergence) to about
+ /// 5000 (large divergence).
+
+ uint32 fBayerGreenSplit;
+
+ protected:
+
+ dng_point fSrcSize;
+
+ dng_point fCroppedSize;
+
+ real64 fAspectRatio;
+
+ public:
+
+ dng_mosaic_info ();
+
+ virtual ~dng_mosaic_info ();
+
+ virtual void Parse (dng_host &host,
+ dng_stream &stream,
+ dng_info &info);
+
+ virtual void PostParse (dng_host &host,
+ dng_negative &negative);
+
+ /// Returns whether the RAW data in this DNG file from a color filter array (mosaiced) source.
+ /// \retval true if this DNG file is from a color filter array (mosiaced) source.
+
+ bool IsColorFilterArray () const
+ {
+ return fCFAPatternSize != dng_point (0, 0);
+ }
+
+ /// Enable generating four-plane output from three-plane Bayer input.
+ /// Extra plane is a second version of the green channel. First green is produced
+ /// using green mosaic samples from one set of rows/columns (even/odd) and the second
+ /// green channel is produced using the other set of rows/columns. One can compare the
+ /// two versions to judge whether BayerGreenSplit needs to be set for a given input source.
+
+ virtual bool SetFourColorBayer ();
+
+ /// Returns scaling factor relative to input size needed to capture output data.
+ /// Staggered (or rotated) sensing arrays are produced to a larger output than the number of input samples.
+ /// This method indicates how much larger.
+ /// \retval a point with integer scaling factors for the horizotal and vertical dimensions.
+
+ virtual dng_point FullScale () const;
+
+ /// Returns integer factors by which mosaic data must be downsampled to produce an image which is as close
+ /// to prefSize as possible in longer dimension, but no smaller than minSize.
+ /// \param minSize Number of pixels as minium for longer dimension of downsampled image.
+ /// \param prefSize Number of pixels as target for longer dimension of downsampled image.
+ /// \param cropFactor Faction of the image to be used after cropping.
+ /// \retval Point containing integer factors by which image must be downsampled.
+
+ virtual dng_point DownScale (uint32 minSize,
+ uint32 prefSize,
+ real64 cropFactor) const;
+
+ /// Return size of demosaiced image for passed in downscaling factor.
+ /// \param downScale Integer downsampling factor obtained from DownScale method.
+ /// \retval Size of resulting demosaiced image.
+
+ virtual dng_point DstSize (const dng_point &downScale) const;
+
+ /// Demosaic interpolation of a single plane for non-downsampled case.
+ /// \param host dng_host to use for buffer allocation requests, user cancellation testing, and progress updates.
+ /// \param negative DNG negative of mosaiced data.
+ /// \param srcImage Source image for mosaiced data.
+ /// \param dstImage Destination image for resulting interpolated data.
+ /// \param srcPlane Which plane to interpolate.
+
+ virtual void InterpolateGeneric (dng_host &host,
+ dng_negative &negative,
+ const dng_image &srcImage,
+ dng_image &dstImage,
+ uint32 srcPlane = 0) const;
+
+ /// Demosaic interpolation of a single plane for downsampled case.
+ /// \param host dng_host to use for buffer allocation requests, user cancellation testing, and progress updates.
+ /// \param negative DNG negative of mosaiced data.
+ /// \param srcImage Source image for mosaiced data.
+ /// \param dstImage Destination image for resulting interpolated data.
+ /// \param downScale Amount (in horizontal and vertical) by which to subsample image.
+ /// \param srcPlane Which plane to interpolate.
+
+ virtual void InterpolateFast (dng_host &host,
+ dng_negative &negative,
+ const dng_image &srcImage,
+ dng_image &dstImage,
+ const dng_point &downScale,
+ uint32 srcPlane = 0) const;
+
+ /// Demosaic interpolation of a single plane. Chooses between generic and fast interpolators based on parameters.
+ /// \param host dng_host to use for buffer allocation requests, user cancellation testing, and progress updates.
+ /// \param negative DNG negative of mosaiced data.
+ /// \param srcImage Source image for mosaiced data.
+ /// \param dstImage Destination image for resulting interpolated data.
+ /// \param downScale Amount (in horizontal and vertical) by which to subsample image.
+ /// \param srcPlane Which plane to interpolate.
+
+ virtual void Interpolate (dng_host &host,
+ dng_negative &negative,
+ const dng_image &srcImage,
+ dng_image &dstImage,
+ const dng_point &downScale,
+ uint32 srcPlane = 0) const;
+
+ protected:
+
+ virtual bool IsSafeDownScale (const dng_point &downScale) const;
+
+ uint32 SizeForDownScale (const dng_point &downScale) const;
+
+ virtual bool ValidSizeDownScale (const dng_point &downScale,
+ uint32 minSize) const;
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_mutex.cpp b/source/dng_mutex.cpp
index 7451c7c..a8b2a6f 100644
--- a/source/dng_mutex.cpp
+++ b/source/dng_mutex.cpp
@@ -1,394 +1,394 @@
-/*****************************************************************************/
-// Copyright 2006-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_mutex.cpp#3 $ */
-/* $DateTime: 2012/09/05 12:31:51 $ */
-/* $Change: 847652 $ */
-/* $Author: tknoll $ */
-
-#include "dng_mutex.h"
-
-#include "dng_assertions.h"
-#include "dng_exceptions.h"
-
-#include <stdlib.h>
-
-/*****************************************************************************/
-
-#if qDNGThreadSafe
-
-namespace
- {
-
- class InnermostMutexHolder
- {
-
- private:
-
- pthread_key_t fInnermostMutexKey;
-
- public:
-
- InnermostMutexHolder ()
-
- : fInnermostMutexKey ()
-
- {
-
- int result = pthread_key_create (&fInnermostMutexKey, NULL);
-
- DNG_ASSERT (result == 0, "pthread_key_create failed.");
-
- if (result != 0)
- ThrowProgramError ();
-
- }
-
- ~InnermostMutexHolder ()
- {
-
- pthread_key_delete (fInnermostMutexKey);
-
- }
-
- void SetInnermostMutex (dng_mutex *mutex)
- {
-
- int result;
-
- result = pthread_setspecific (fInnermostMutexKey, (void *)mutex);
-
- DNG_ASSERT (result == 0, "pthread_setspecific failed.");
-
- #if 0 // Hard failure here was causing crash on quit.
-
- if (result != 0)
- ThrowProgramError ();
-
- #endif
-
- }
-
- dng_mutex *GetInnermostMutex ()
- {
-
- void *result = pthread_getspecific (fInnermostMutexKey);
-
- return reinterpret_cast<dng_mutex *> (result);
-
- }
-
- };
-
- InnermostMutexHolder gInnermostMutexHolder;
-
- }
-
-#endif
-
-/*****************************************************************************/
-
-dng_mutex::dng_mutex (const char *mutexName, uint32 mutexLevel)
-
- #if qDNGThreadSafe
-
- : fPthreadMutex ()
- , fMutexLevel (mutexLevel)
- , fRecursiveLockCount (0)
- , fPrevHeldMutex (NULL)
- , fMutexName (mutexName)
-
- #endif
-
- {
-
- #if qDNGThreadSafe
-
- if (pthread_mutex_init (&fPthreadMutex, NULL) != 0)
- {
- ThrowMemoryFull ();
- }
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-dng_mutex::~dng_mutex ()
- {
-
- #if qDNGThreadSafe
-
- pthread_mutex_destroy (&fPthreadMutex);
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-void dng_mutex::Lock ()
- {
-
- #if qDNGThreadSafe
-
- dng_mutex *innermostMutex = gInnermostMutexHolder.GetInnermostMutex ();
-
- if (innermostMutex != NULL)
- {
-
- if (innermostMutex == this)
- {
-
- fRecursiveLockCount++;
-
- return;
-
- }
-
- bool lockOrderPreserved = fMutexLevel > innermostMutex->fMutexLevel /* ||
- (fMutexLevel == innermostMutex->fMutexLevel && innermostMutex < this) */;
-
- if (!lockOrderPreserved)
- {
-
- DNG_REPORT ("Lock ordering violation.");
-
- #if qDNGDebug
-
- dng_show_message_f ("This mutex: %s v Innermost mutex: %s",
- this->MutexName (),
- innermostMutex->MutexName ());
-
- #endif
-
- }
-
- }
-
- pthread_mutex_lock (&fPthreadMutex);
-
- fPrevHeldMutex = innermostMutex;
-
- gInnermostMutexHolder.SetInnermostMutex (this);
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-void dng_mutex::Unlock ()
- {
-
- #if qDNGThreadSafe
-
- DNG_ASSERT (gInnermostMutexHolder.GetInnermostMutex () == this, "Mutexes unlocked out of order!!!");
-
- if (fRecursiveLockCount > 0)
- {
-
- fRecursiveLockCount--;
-
- return;
-
- }
-
- gInnermostMutexHolder.SetInnermostMutex (fPrevHeldMutex);
-
- fPrevHeldMutex = NULL;
-
- pthread_mutex_unlock (&fPthreadMutex);
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-const char *dng_mutex::MutexName () const
- {
-
- #if qDNGThreadSafe
-
- if (fMutexName)
- return fMutexName;
-
- #endif
-
- return "< unknown >";
-
- }
-
-/*****************************************************************************/
-
-dng_lock_mutex::dng_lock_mutex (dng_mutex *mutex)
-
- : fMutex (mutex)
-
- {
-
- if (fMutex)
- fMutex->Lock ();
-
- }
-
-/*****************************************************************************/
-
-dng_lock_mutex::~dng_lock_mutex ()
- {
-
- if (fMutex)
- fMutex->Unlock ();
-
- }
-
-/*****************************************************************************/
-
-dng_unlock_mutex::dng_unlock_mutex (dng_mutex *mutex)
-
- : fMutex (mutex)
-
- {
-
- if (fMutex)
- fMutex->Unlock ();
-
- }
-
-/*****************************************************************************/
-
-dng_unlock_mutex::~dng_unlock_mutex ()
- {
-
- if (fMutex)
- fMutex->Lock ();
-
- }
-
-/*****************************************************************************/
-
-#if qDNGThreadSafe
-
-/*****************************************************************************/
-
-dng_condition::dng_condition ()
-
- : fPthreadCondition ()
-
- {
-
- int result;
-
- result = pthread_cond_init (&fPthreadCondition, NULL);
-
- DNG_ASSERT (result == 0, "pthread_cond_init failed.");
-
- if (result != 0)
- {
- ThrowProgramError ();
- }
-
- }
-
-/*****************************************************************************/
-
-dng_condition::~dng_condition ()
- {
-
- pthread_cond_destroy (&fPthreadCondition);
-
- }
-
-/*****************************************************************************/
-
-bool dng_condition::Wait (dng_mutex &mutex, double timeoutSecs)
- {
-
- bool timedOut = false;
-
- dng_mutex *innermostMutex = gInnermostMutexHolder.GetInnermostMutex ();
-
- DNG_ASSERT (innermostMutex == &mutex, "Attempt to wait on non-innermost mutex.");
-
- innermostMutex = mutex.fPrevHeldMutex;
-
- gInnermostMutexHolder.SetInnermostMutex (innermostMutex);
-
- mutex.fPrevHeldMutex = NULL;
-
- if (timeoutSecs < 0)
- {
-
- pthread_cond_wait (&fPthreadCondition, &mutex.fPthreadMutex);
-
- }
-
- else
- {
-
- struct timespec now;
-
- dng_pthread_now (&now);
-
- timeoutSecs += now.tv_sec;
- timeoutSecs += now.tv_nsec / 1000000000.0;
-
- now.tv_sec = (long) timeoutSecs;
- now.tv_nsec = (long) ((timeoutSecs - now.tv_sec) * 1000000000);
-
- timedOut = (pthread_cond_timedwait (&fPthreadCondition, &mutex.fPthreadMutex, &now) == ETIMEDOUT);
-
- }
-
- mutex.fPrevHeldMutex = innermostMutex;
-
- gInnermostMutexHolder.SetInnermostMutex (&mutex);
-
- return !timedOut;
-
- }
-
-/*****************************************************************************/
-
-void dng_condition::Signal ()
- {
-
- int result;
-
- result = pthread_cond_signal (&fPthreadCondition);
-
- DNG_ASSERT (result == 0, "pthread_cond_signal failed.");
-
- if (result != 0)
- ThrowProgramError ();
-
- }
-
-/*****************************************************************************/
-
-void dng_condition::Broadcast ()
- {
-
- int result;
-
- result = pthread_cond_broadcast (&fPthreadCondition);
-
- DNG_ASSERT (result == 0, "pthread_cond_broadcast failed.");
-
- if (result != 0)
- ThrowProgramError ();
-
- }
-
-/*****************************************************************************/
-
-#endif // qDNGThreadSafe
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_mutex.cpp#3 $ */
+/* $DateTime: 2012/09/05 12:31:51 $ */
+/* $Change: 847652 $ */
+/* $Author: tknoll $ */
+
+#include "dng_mutex.h"
+
+#include "dng_assertions.h"
+#include "dng_exceptions.h"
+
+#include <stdlib.h>
+
+/*****************************************************************************/
+
+#if qDNGThreadSafe
+
+namespace
+ {
+
+ class InnermostMutexHolder
+ {
+
+ private:
+
+ pthread_key_t fInnermostMutexKey;
+
+ public:
+
+ InnermostMutexHolder ()
+
+ : fInnermostMutexKey ()
+
+ {
+
+ int result = pthread_key_create (&fInnermostMutexKey, NULL);
+
+ DNG_ASSERT (result == 0, "pthread_key_create failed.");
+
+ if (result != 0)
+ ThrowProgramError ();
+
+ }
+
+ ~InnermostMutexHolder ()
+ {
+
+ pthread_key_delete (fInnermostMutexKey);
+
+ }
+
+ void SetInnermostMutex (dng_mutex *mutex)
+ {
+
+ int result;
+
+ result = pthread_setspecific (fInnermostMutexKey, (void *)mutex);
+
+ DNG_ASSERT (result == 0, "pthread_setspecific failed.");
+
+ #if 0 // Hard failure here was causing crash on quit.
+
+ if (result != 0)
+ ThrowProgramError ();
+
+ #endif
+
+ }
+
+ dng_mutex *GetInnermostMutex ()
+ {
+
+ void *result = pthread_getspecific (fInnermostMutexKey);
+
+ return reinterpret_cast<dng_mutex *> (result);
+
+ }
+
+ };
+
+ InnermostMutexHolder gInnermostMutexHolder;
+
+ }
+
+#endif
+
+/*****************************************************************************/
+
+dng_mutex::dng_mutex (const char *mutexName, uint32 mutexLevel)
+
+ #if qDNGThreadSafe
+
+ : fPthreadMutex ()
+ , fMutexLevel (mutexLevel)
+ , fRecursiveLockCount (0)
+ , fPrevHeldMutex (NULL)
+ , fMutexName (mutexName)
+
+ #endif
+
+ {
+
+ #if qDNGThreadSafe
+
+ if (pthread_mutex_init (&fPthreadMutex, NULL) != 0)
+ {
+ ThrowMemoryFull ();
+ }
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+dng_mutex::~dng_mutex ()
+ {
+
+ #if qDNGThreadSafe
+
+ pthread_mutex_destroy (&fPthreadMutex);
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+void dng_mutex::Lock ()
+ {
+
+ #if qDNGThreadSafe
+
+ dng_mutex *innermostMutex = gInnermostMutexHolder.GetInnermostMutex ();
+
+ if (innermostMutex != NULL)
+ {
+
+ if (innermostMutex == this)
+ {
+
+ fRecursiveLockCount++;
+
+ return;
+
+ }
+
+ bool lockOrderPreserved = fMutexLevel > innermostMutex->fMutexLevel /* ||
+ (fMutexLevel == innermostMutex->fMutexLevel && innermostMutex < this) */;
+
+ if (!lockOrderPreserved)
+ {
+
+ DNG_REPORT ("Lock ordering violation.");
+
+ #if qDNGDebug
+
+ dng_show_message_f ("This mutex: %s v Innermost mutex: %s",
+ this->MutexName (),
+ innermostMutex->MutexName ());
+
+ #endif
+
+ }
+
+ }
+
+ pthread_mutex_lock (&fPthreadMutex);
+
+ fPrevHeldMutex = innermostMutex;
+
+ gInnermostMutexHolder.SetInnermostMutex (this);
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+void dng_mutex::Unlock ()
+ {
+
+ #if qDNGThreadSafe
+
+ DNG_ASSERT (gInnermostMutexHolder.GetInnermostMutex () == this, "Mutexes unlocked out of order!!!");
+
+ if (fRecursiveLockCount > 0)
+ {
+
+ fRecursiveLockCount--;
+
+ return;
+
+ }
+
+ gInnermostMutexHolder.SetInnermostMutex (fPrevHeldMutex);
+
+ fPrevHeldMutex = NULL;
+
+ pthread_mutex_unlock (&fPthreadMutex);
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+const char *dng_mutex::MutexName () const
+ {
+
+ #if qDNGThreadSafe
+
+ if (fMutexName)
+ return fMutexName;
+
+ #endif
+
+ return "< unknown >";
+
+ }
+
+/*****************************************************************************/
+
+dng_lock_mutex::dng_lock_mutex (dng_mutex *mutex)
+
+ : fMutex (mutex)
+
+ {
+
+ if (fMutex)
+ fMutex->Lock ();
+
+ }
+
+/*****************************************************************************/
+
+dng_lock_mutex::~dng_lock_mutex ()
+ {
+
+ if (fMutex)
+ fMutex->Unlock ();
+
+ }
+
+/*****************************************************************************/
+
+dng_unlock_mutex::dng_unlock_mutex (dng_mutex *mutex)
+
+ : fMutex (mutex)
+
+ {
+
+ if (fMutex)
+ fMutex->Unlock ();
+
+ }
+
+/*****************************************************************************/
+
+dng_unlock_mutex::~dng_unlock_mutex ()
+ {
+
+ if (fMutex)
+ fMutex->Lock ();
+
+ }
+
+/*****************************************************************************/
+
+#if qDNGThreadSafe
+
+/*****************************************************************************/
+
+dng_condition::dng_condition ()
+
+ : fPthreadCondition ()
+
+ {
+
+ int result;
+
+ result = pthread_cond_init (&fPthreadCondition, NULL);
+
+ DNG_ASSERT (result == 0, "pthread_cond_init failed.");
+
+ if (result != 0)
+ {
+ ThrowProgramError ();
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_condition::~dng_condition ()
+ {
+
+ pthread_cond_destroy (&fPthreadCondition);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_condition::Wait (dng_mutex &mutex, double timeoutSecs)
+ {
+
+ bool timedOut = false;
+
+ dng_mutex *innermostMutex = gInnermostMutexHolder.GetInnermostMutex ();
+
+ DNG_ASSERT (innermostMutex == &mutex, "Attempt to wait on non-innermost mutex.");
+
+ innermostMutex = mutex.fPrevHeldMutex;
+
+ gInnermostMutexHolder.SetInnermostMutex (innermostMutex);
+
+ mutex.fPrevHeldMutex = NULL;
+
+ if (timeoutSecs < 0)
+ {
+
+ pthread_cond_wait (&fPthreadCondition, &mutex.fPthreadMutex);
+
+ }
+
+ else
+ {
+
+ struct timespec now;
+
+ dng_pthread_now (&now);
+
+ timeoutSecs += now.tv_sec;
+ timeoutSecs += now.tv_nsec / 1000000000.0;
+
+ now.tv_sec = (long) timeoutSecs;
+ now.tv_nsec = (long) ((timeoutSecs - now.tv_sec) * 1000000000);
+
+ timedOut = (pthread_cond_timedwait (&fPthreadCondition, &mutex.fPthreadMutex, &now) == ETIMEDOUT);
+
+ }
+
+ mutex.fPrevHeldMutex = innermostMutex;
+
+ gInnermostMutexHolder.SetInnermostMutex (&mutex);
+
+ return !timedOut;
+
+ }
+
+/*****************************************************************************/
+
+void dng_condition::Signal ()
+ {
+
+ int result;
+
+ result = pthread_cond_signal (&fPthreadCondition);
+
+ DNG_ASSERT (result == 0, "pthread_cond_signal failed.");
+
+ if (result != 0)
+ ThrowProgramError ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_condition::Broadcast ()
+ {
+
+ int result;
+
+ result = pthread_cond_broadcast (&fPthreadCondition);
+
+ DNG_ASSERT (result == 0, "pthread_cond_broadcast failed.");
+
+ if (result != 0)
+ ThrowProgramError ();
+
+ }
+
+/*****************************************************************************/
+
+#endif // qDNGThreadSafe
+
+/*****************************************************************************/
diff --git a/source/dng_mutex.h b/source/dng_mutex.h
index b067728..1111f39 100644
--- a/source/dng_mutex.h
+++ b/source/dng_mutex.h
@@ -1,177 +1,177 @@
-/*****************************************************************************/
-// Copyright 2006-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_mutex.h#2 $ */
-/* $DateTime: 2012/09/05 12:31:51 $ */
-/* $Change: 847652 $ */
-/* $Author: tknoll $ */
-
-/******************************************************************************/
-
-#ifndef __dng_mutex__
-#define __dng_mutex__
-
-/******************************************************************************/
-
-#include "dng_flags.h"
-
-/******************************************************************************/
-
-#include "dng_types.h"
-
-#if qDNGThreadSafe
-
-#include "dng_pthread.h"
-
-#endif
-
-/******************************************************************************/
-
-class dng_mutex
- {
-
- public:
-
- enum
- {
- kDNGMutexLevelLeaf = 0x70000000u
- };
-
- dng_mutex (const char *mutexName,
- uint32 mutexLevel = kDNGMutexLevelLeaf);
-
- virtual ~dng_mutex ();
-
- void Lock ();
-
- void Unlock ();
-
- const char *MutexName () const;
-
- protected:
-
- #if qDNGThreadSafe
-
- pthread_mutex_t fPthreadMutex;
-
- const uint32 fMutexLevel;
-
- uint32 fRecursiveLockCount;
-
- dng_mutex *fPrevHeldMutex;
-
- const char * const fMutexName;
-
- friend class dng_condition;
-
- #endif
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_mutex (const dng_mutex &mutex);
-
- dng_mutex & operator= (const dng_mutex &mutex);
-
- };
-
-/*****************************************************************************/
-
-class dng_lock_mutex
- {
-
- private:
-
- dng_mutex *fMutex;
-
- public:
-
- dng_lock_mutex (dng_mutex *mutex);
-
- ~dng_lock_mutex ();
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_lock_mutex (const dng_lock_mutex &lock);
-
- dng_lock_mutex & operator= (const dng_lock_mutex &lock);
-
- };
-
-/*****************************************************************************/
-
-class dng_unlock_mutex
- {
-
- private:
-
- dng_mutex *fMutex;
-
- public:
-
- dng_unlock_mutex (dng_mutex *mutex);
-
- ~dng_unlock_mutex ();
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_unlock_mutex (const dng_unlock_mutex &unlock);
-
- dng_unlock_mutex & operator= (const dng_unlock_mutex &unlock);
-
- };
-
-/*****************************************************************************/
-
-#if qDNGThreadSafe
-
-/*****************************************************************************/
-
-class dng_condition
- {
-
- public:
-
- dng_condition ();
-
- ~dng_condition ();
-
- bool Wait (dng_mutex &mutex, double timeoutSecs = -1.0);
-
- void Signal ();
-
- void Broadcast ();
-
- protected:
-
- pthread_cond_t fPthreadCondition;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_condition (const dng_condition &condition);
-
- dng_condition & operator= (const dng_condition &condition);
-
- };
-
-/*****************************************************************************/
-
-#endif // qDNGThreadSafe
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_mutex.h#2 $ */
+/* $DateTime: 2012/09/05 12:31:51 $ */
+/* $Change: 847652 $ */
+/* $Author: tknoll $ */
+
+/******************************************************************************/
+
+#ifndef __dng_mutex__
+#define __dng_mutex__
+
+/******************************************************************************/
+
+#include "dng_flags.h"
+
+/******************************************************************************/
+
+#include "dng_types.h"
+
+#if qDNGThreadSafe
+
+#include "dng_pthread.h"
+
+#endif
+
+/******************************************************************************/
+
+class dng_mutex
+ {
+
+ public:
+
+ enum
+ {
+ kDNGMutexLevelLeaf = 0x70000000u
+ };
+
+ dng_mutex (const char *mutexName,
+ uint32 mutexLevel = kDNGMutexLevelLeaf);
+
+ virtual ~dng_mutex ();
+
+ void Lock ();
+
+ void Unlock ();
+
+ const char *MutexName () const;
+
+ protected:
+
+ #if qDNGThreadSafe
+
+ pthread_mutex_t fPthreadMutex;
+
+ const uint32 fMutexLevel;
+
+ uint32 fRecursiveLockCount;
+
+ dng_mutex *fPrevHeldMutex;
+
+ const char * const fMutexName;
+
+ friend class dng_condition;
+
+ #endif
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_mutex (const dng_mutex &mutex);
+
+ dng_mutex & operator= (const dng_mutex &mutex);
+
+ };
+
+/*****************************************************************************/
+
+class dng_lock_mutex
+ {
+
+ private:
+
+ dng_mutex *fMutex;
+
+ public:
+
+ dng_lock_mutex (dng_mutex *mutex);
+
+ ~dng_lock_mutex ();
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_lock_mutex (const dng_lock_mutex &lock);
+
+ dng_lock_mutex & operator= (const dng_lock_mutex &lock);
+
+ };
+
+/*****************************************************************************/
+
+class dng_unlock_mutex
+ {
+
+ private:
+
+ dng_mutex *fMutex;
+
+ public:
+
+ dng_unlock_mutex (dng_mutex *mutex);
+
+ ~dng_unlock_mutex ();
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_unlock_mutex (const dng_unlock_mutex &unlock);
+
+ dng_unlock_mutex & operator= (const dng_unlock_mutex &unlock);
+
+ };
+
+/*****************************************************************************/
+
+#if qDNGThreadSafe
+
+/*****************************************************************************/
+
+class dng_condition
+ {
+
+ public:
+
+ dng_condition ();
+
+ ~dng_condition ();
+
+ bool Wait (dng_mutex &mutex, double timeoutSecs = -1.0);
+
+ void Signal ();
+
+ void Broadcast ();
+
+ protected:
+
+ pthread_cond_t fPthreadCondition;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_condition (const dng_condition &condition);
+
+ dng_condition & operator= (const dng_condition &condition);
+
+ };
+
+/*****************************************************************************/
+
+#endif // qDNGThreadSafe
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_opcode_list.cpp b/source/dng_opcode_list.cpp
index a5af89a..58e0e3b 100644
--- a/source/dng_opcode_list.cpp
+++ b/source/dng_opcode_list.cpp
@@ -1,274 +1,274 @@
-/*****************************************************************************/
-// Copyright 2008-2009 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_opcode_list.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_opcode_list.h"
-
-#include "dng_globals.h"
-#include "dng_host.h"
-#include "dng_memory_stream.h"
-#include "dng_negative.h"
-#include "dng_tag_values.h"
-#include "dng_utils.h"
-
-#include <algorithm>
-
-/*****************************************************************************/
-
-dng_opcode_list::dng_opcode_list (uint32 stage)
-
- : fList ()
- , fAlwaysApply (false)
- , fStage (stage)
-
- {
-
- }
-
-/******************************************************************************/
-
-dng_opcode_list::~dng_opcode_list ()
- {
-
- Clear ();
-
- }
-
-/******************************************************************************/
-
-void dng_opcode_list::Clear ()
- {
-
- for (size_t index = 0; index < fList.size (); index++)
- {
-
- if (fList [index])
- {
-
- delete fList [index];
-
- fList [index] = NULL;
-
- }
-
- }
-
- fList.clear ();
-
- fAlwaysApply = false;
-
- }
-
-/******************************************************************************/
-
-void dng_opcode_list::Swap (dng_opcode_list &otherList)
- {
-
- fList.swap (otherList.fList);
-
- std::swap (fAlwaysApply, otherList.fAlwaysApply);
-
- std::swap (fStage, otherList.fStage);
-
- }
-
-/******************************************************************************/
-
-uint32 dng_opcode_list::MinVersion (bool includeOptional) const
- {
-
- uint32 result = dngVersion_None;
-
- for (size_t index = 0; index < fList.size (); index++)
- {
-
- if (includeOptional || !fList [index]->Optional ())
- {
-
- result = Max_uint32 (result, fList [index]->MinVersion ());
-
- }
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_list::Apply (dng_host &host,
- dng_negative &negative,
- AutoPtr<dng_image> &image)
- {
-
- for (uint32 index = 0; index < Count (); index++)
- {
-
- dng_opcode &opcode (Entry (index));
-
- if (opcode.AboutToApply (host, negative))
- {
-
- opcode.Apply (host,
- negative,
- image);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_list::Append (AutoPtr<dng_opcode> &opcode)
- {
-
- if (opcode->OpcodeID () == dngOpcode_Private)
- {
- SetAlwaysApply ();
- }
-
- opcode->SetStage (fStage);
-
- fList.push_back (NULL);
-
- fList [fList.size () - 1] = opcode.Release ();
-
- }
-
-/*****************************************************************************/
-
-dng_memory_block * dng_opcode_list::Spool (dng_host &host) const
- {
-
- if (IsEmpty ())
- {
- return NULL;
- }
-
- if (AlwaysApply ())
- {
- ThrowProgramError ();
- }
-
- dng_memory_stream stream (host.Allocator ());
-
- stream.SetBigEndian ();
-
- stream.Put_uint32 ((uint32) fList.size ());
-
- for (size_t index = 0; index < fList.size (); index++)
- {
-
- stream.Put_uint32 (fList [index]->OpcodeID ());
- stream.Put_uint32 (fList [index]->MinVersion ());
- stream.Put_uint32 (fList [index]->Flags ());
-
- fList [index]->PutData (stream);
-
- }
-
- return stream.AsMemoryBlock (host.Allocator ());
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_list::FingerprintToStream (dng_stream &stream) const
- {
-
- if (IsEmpty ())
- {
- return;
- }
-
- stream.Put_uint32 ((uint32) fList.size ());
-
- for (size_t index = 0; index < fList.size (); index++)
- {
-
- stream.Put_uint32 (fList [index]->OpcodeID ());
- stream.Put_uint32 (fList [index]->MinVersion ());
- stream.Put_uint32 (fList [index]->Flags ());
-
- if (fList [index]->OpcodeID () != dngOpcode_Private)
- {
-
- fList [index]->PutData (stream);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_list::Parse (dng_host &host,
- dng_stream &stream,
- uint32 byteCount,
- uint64 streamOffset)
- {
-
- Clear ();
-
- TempBigEndian tempBigEndian (stream);
-
- stream.SetReadPosition (streamOffset);
-
- uint32 count = stream.Get_uint32 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- if (count == 1)
- {
- printf ("1 opcode\n");
- }
-
- else
- {
- printf ("%u opcodes\n", (unsigned) count);
- }
-
- }
-
- #endif
-
- for (uint32 index = 0; index < count; index++)
- {
-
- uint32 opcodeID = stream.Get_uint32 ();
-
- AutoPtr<dng_opcode> opcode (host.Make_dng_opcode (opcodeID,
- stream));
-
- Append (opcode);
-
- }
-
- if (stream.Position () != streamOffset + byteCount)
- {
-
- ThrowBadFormat ("Error parsing opcode list");
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2008-2009 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_opcode_list.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_opcode_list.h"
+
+#include "dng_globals.h"
+#include "dng_host.h"
+#include "dng_memory_stream.h"
+#include "dng_negative.h"
+#include "dng_tag_values.h"
+#include "dng_utils.h"
+
+#include <algorithm>
+
+/*****************************************************************************/
+
+dng_opcode_list::dng_opcode_list (uint32 stage)
+
+ : fList ()
+ , fAlwaysApply (false)
+ , fStage (stage)
+
+ {
+
+ }
+
+/******************************************************************************/
+
+dng_opcode_list::~dng_opcode_list ()
+ {
+
+ Clear ();
+
+ }
+
+/******************************************************************************/
+
+void dng_opcode_list::Clear ()
+ {
+
+ for (size_t index = 0; index < fList.size (); index++)
+ {
+
+ if (fList [index])
+ {
+
+ delete fList [index];
+
+ fList [index] = NULL;
+
+ }
+
+ }
+
+ fList.clear ();
+
+ fAlwaysApply = false;
+
+ }
+
+/******************************************************************************/
+
+void dng_opcode_list::Swap (dng_opcode_list &otherList)
+ {
+
+ fList.swap (otherList.fList);
+
+ std::swap (fAlwaysApply, otherList.fAlwaysApply);
+
+ std::swap (fStage, otherList.fStage);
+
+ }
+
+/******************************************************************************/
+
+uint32 dng_opcode_list::MinVersion (bool includeOptional) const
+ {
+
+ uint32 result = dngVersion_None;
+
+ for (size_t index = 0; index < fList.size (); index++)
+ {
+
+ if (includeOptional || !fList [index]->Optional ())
+ {
+
+ result = Max_uint32 (result, fList [index]->MinVersion ());
+
+ }
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_list::Apply (dng_host &host,
+ dng_negative &negative,
+ AutoPtr<dng_image> &image)
+ {
+
+ for (uint32 index = 0; index < Count (); index++)
+ {
+
+ dng_opcode &opcode (Entry (index));
+
+ if (opcode.AboutToApply (host, negative))
+ {
+
+ opcode.Apply (host,
+ negative,
+ image);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_list::Append (AutoPtr<dng_opcode> &opcode)
+ {
+
+ if (opcode->OpcodeID () == dngOpcode_Private)
+ {
+ SetAlwaysApply ();
+ }
+
+ opcode->SetStage (fStage);
+
+ fList.push_back (NULL);
+
+ fList [fList.size () - 1] = opcode.Release ();
+
+ }
+
+/*****************************************************************************/
+
+dng_memory_block * dng_opcode_list::Spool (dng_host &host) const
+ {
+
+ if (IsEmpty ())
+ {
+ return NULL;
+ }
+
+ if (AlwaysApply ())
+ {
+ ThrowProgramError ();
+ }
+
+ dng_memory_stream stream (host.Allocator ());
+
+ stream.SetBigEndian ();
+
+ stream.Put_uint32 ((uint32) fList.size ());
+
+ for (size_t index = 0; index < fList.size (); index++)
+ {
+
+ stream.Put_uint32 (fList [index]->OpcodeID ());
+ stream.Put_uint32 (fList [index]->MinVersion ());
+ stream.Put_uint32 (fList [index]->Flags ());
+
+ fList [index]->PutData (stream);
+
+ }
+
+ return stream.AsMemoryBlock (host.Allocator ());
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_list::FingerprintToStream (dng_stream &stream) const
+ {
+
+ if (IsEmpty ())
+ {
+ return;
+ }
+
+ stream.Put_uint32 ((uint32) fList.size ());
+
+ for (size_t index = 0; index < fList.size (); index++)
+ {
+
+ stream.Put_uint32 (fList [index]->OpcodeID ());
+ stream.Put_uint32 (fList [index]->MinVersion ());
+ stream.Put_uint32 (fList [index]->Flags ());
+
+ if (fList [index]->OpcodeID () != dngOpcode_Private)
+ {
+
+ fList [index]->PutData (stream);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_list::Parse (dng_host &host,
+ dng_stream &stream,
+ uint32 byteCount,
+ uint64 streamOffset)
+ {
+
+ Clear ();
+
+ TempBigEndian tempBigEndian (stream);
+
+ stream.SetReadPosition (streamOffset);
+
+ uint32 count = stream.Get_uint32 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ if (count == 1)
+ {
+ printf ("1 opcode\n");
+ }
+
+ else
+ {
+ printf ("%u opcodes\n", (unsigned) count);
+ }
+
+ }
+
+ #endif
+
+ for (uint32 index = 0; index < count; index++)
+ {
+
+ uint32 opcodeID = stream.Get_uint32 ();
+
+ AutoPtr<dng_opcode> opcode (host.Make_dng_opcode (opcodeID,
+ stream));
+
+ Append (opcode);
+
+ }
+
+ if (stream.Position () != streamOffset + byteCount)
+ {
+
+ ThrowBadFormat ("Error parsing opcode list");
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_opcode_list.h b/source/dng_opcode_list.h
index 2d7c902..78f5e6f 100644
--- a/source/dng_opcode_list.h
+++ b/source/dng_opcode_list.h
@@ -1,166 +1,166 @@
-/*****************************************************************************/
-// Copyright 2008-2009 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_opcode_list.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * List of opcodes.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_opcode_list__
-#define __dng_opcode_list__
-
-/*****************************************************************************/
-
-#include "dng_auto_ptr.h"
-#include "dng_classes.h"
-#include "dng_memory.h"
-#include "dng_opcodes.h"
-
-#include <vector>
-
-/*****************************************************************************/
-
-/// A list of opcodes.
-
-class dng_opcode_list
- {
-
- private:
-
- dng_std_vector<dng_opcode *> fList;
-
- bool fAlwaysApply;
-
- uint32 fStage;
-
- public:
-
- /// Create an empty opcode list for the specific image stage (1, 2, or 3).
-
- dng_opcode_list (uint32 stage);
-
- ~dng_opcode_list ();
-
- /// Is the opcode list empty?
-
- bool IsEmpty () const
- {
- return fList.size () == 0;
- }
-
- /// Does the list contain at least 1 opcode?
-
- bool NotEmpty () const
- {
- return !IsEmpty ();
- }
-
- /// Should the opcode list always be applied to the image?
-
- bool AlwaysApply () const
- {
- return fAlwaysApply && NotEmpty ();
- }
-
- /// Set internal flag to indicate this opcode list should always be
- /// applied.
-
- void SetAlwaysApply ()
- {
- fAlwaysApply = true;
- }
-
- /// The number of opcodes in this list.
-
- uint32 Count () const
- {
- return (uint32) fList.size ();
- }
-
- /// Retrieve read/write opcode by index (must be in the range 0 to Count
- /// () - 1).
-
- dng_opcode & Entry (uint32 index)
- {
- return *fList [index];
- }
-
- /// Retrieve read-only opcode by index (must be in the range 0 to Count
- /// () - 1).
-
- const dng_opcode & Entry (uint32 index) const
- {
- return *fList [index];
- }
-
- /// Remove all opcodes from the list.
-
- void Clear ();
-
- /// Swap two opcode lists.
-
- void Swap (dng_opcode_list &otherList);
-
- /// Return minimum DNG version required to support all opcodes in this
- /// list. If includeOptional is set to true, then this calculation will
- /// include optional opcodes.
-
- uint32 MinVersion (bool includeOptional) const;
-
- /// Apply this opcode list to the specified image with corresponding
- /// negative.
-
- void Apply (dng_host &host,
- dng_negative &negative,
- AutoPtr<dng_image> &image);
-
- /// Append the specified opcode to this list.
-
- void Append (AutoPtr<dng_opcode> &opcode);
-
- /// Serialize this opcode list to a block of memory. The caller is
- /// responsible for deleting this block.
-
- dng_memory_block * Spool (dng_host &host) const;
-
- /// Write a fingerprint of this opcode list to the specified stream.
-
- void FingerprintToStream (dng_stream &stream) const;
-
- /// Read an opcode list from the specified stream, starting at the
- /// specified offset (streamOffset, in bytes). byteCount is provided for
- /// error checking purposes. A bad format exception
- /// will be thrown if the length of the opcode stream does not exactly
- /// match byteCount.
-
- void Parse (dng_host &host,
- dng_stream &stream,
- uint32 byteCount,
- uint64 streamOffset);
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_opcode_list (const dng_opcode_list &list);
-
- dng_opcode_list & operator= (const dng_opcode_list &list);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2008-2009 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_opcode_list.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * List of opcodes.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_opcode_list__
+#define __dng_opcode_list__
+
+/*****************************************************************************/
+
+#include "dng_auto_ptr.h"
+#include "dng_classes.h"
+#include "dng_memory.h"
+#include "dng_opcodes.h"
+
+#include <vector>
+
+/*****************************************************************************/
+
+/// A list of opcodes.
+
+class dng_opcode_list
+ {
+
+ private:
+
+ dng_std_vector<dng_opcode *> fList;
+
+ bool fAlwaysApply;
+
+ uint32 fStage;
+
+ public:
+
+ /// Create an empty opcode list for the specific image stage (1, 2, or 3).
+
+ dng_opcode_list (uint32 stage);
+
+ ~dng_opcode_list ();
+
+ /// Is the opcode list empty?
+
+ bool IsEmpty () const
+ {
+ return fList.size () == 0;
+ }
+
+ /// Does the list contain at least 1 opcode?
+
+ bool NotEmpty () const
+ {
+ return !IsEmpty ();
+ }
+
+ /// Should the opcode list always be applied to the image?
+
+ bool AlwaysApply () const
+ {
+ return fAlwaysApply && NotEmpty ();
+ }
+
+ /// Set internal flag to indicate this opcode list should always be
+ /// applied.
+
+ void SetAlwaysApply ()
+ {
+ fAlwaysApply = true;
+ }
+
+ /// The number of opcodes in this list.
+
+ uint32 Count () const
+ {
+ return (uint32) fList.size ();
+ }
+
+ /// Retrieve read/write opcode by index (must be in the range 0 to Count
+ /// () - 1).
+
+ dng_opcode & Entry (uint32 index)
+ {
+ return *fList [index];
+ }
+
+ /// Retrieve read-only opcode by index (must be in the range 0 to Count
+ /// () - 1).
+
+ const dng_opcode & Entry (uint32 index) const
+ {
+ return *fList [index];
+ }
+
+ /// Remove all opcodes from the list.
+
+ void Clear ();
+
+ /// Swap two opcode lists.
+
+ void Swap (dng_opcode_list &otherList);
+
+ /// Return minimum DNG version required to support all opcodes in this
+ /// list. If includeOptional is set to true, then this calculation will
+ /// include optional opcodes.
+
+ uint32 MinVersion (bool includeOptional) const;
+
+ /// Apply this opcode list to the specified image with corresponding
+ /// negative.
+
+ void Apply (dng_host &host,
+ dng_negative &negative,
+ AutoPtr<dng_image> &image);
+
+ /// Append the specified opcode to this list.
+
+ void Append (AutoPtr<dng_opcode> &opcode);
+
+ /// Serialize this opcode list to a block of memory. The caller is
+ /// responsible for deleting this block.
+
+ dng_memory_block * Spool (dng_host &host) const;
+
+ /// Write a fingerprint of this opcode list to the specified stream.
+
+ void FingerprintToStream (dng_stream &stream) const;
+
+ /// Read an opcode list from the specified stream, starting at the
+ /// specified offset (streamOffset, in bytes). byteCount is provided for
+ /// error checking purposes. A bad format exception
+ /// will be thrown if the length of the opcode stream does not exactly
+ /// match byteCount.
+
+ void Parse (dng_host &host,
+ dng_stream &stream,
+ uint32 byteCount,
+ uint64 streamOffset);
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_opcode_list (const dng_opcode_list &list);
+
+ dng_opcode_list & operator= (const dng_opcode_list &list);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_opcodes.cpp b/source/dng_opcodes.cpp
index 7e756ff..0804959 100644
--- a/source/dng_opcodes.cpp
+++ b/source/dng_opcodes.cpp
@@ -1,554 +1,554 @@
-/*****************************************************************************/
-// 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_opcodes.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_opcodes.h"
-
-#include "dng_bottlenecks.h"
-#include "dng_exceptions.h"
-#include "dng_filter_task.h"
-#include "dng_globals.h"
-#include "dng_host.h"
-#include "dng_image.h"
-#include "dng_negative.h"
-#include "dng_parse_utils.h"
-#include "dng_stream.h"
-#include "dng_tag_values.h"
-
-/*****************************************************************************/
-
-dng_opcode::dng_opcode (uint32 opcodeID,
- uint32 minVersion,
- uint32 flags)
-
- : fOpcodeID (opcodeID)
- , fMinVersion (minVersion)
- , fFlags (flags)
- , fWasReadFromStream (false)
- , fStage (0)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_opcode::dng_opcode (uint32 opcodeID,
- dng_stream &stream,
- const char *name)
-
- : fOpcodeID (opcodeID)
- , fMinVersion (0)
- , fFlags (0)
- , fWasReadFromStream (true)
- , fStage (0)
-
- {
-
- fMinVersion = stream.Get_uint32 ();
- fFlags = stream.Get_uint32 ();
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- printf ("\nOpcode: ");
-
- if (name)
- {
- printf ("%s", name);
- }
- else
- {
- printf ("Unknown (%u)", (unsigned) opcodeID);
- }
-
- printf (", minVersion = %u.%u.%u.%u",
- (unsigned) ((fMinVersion >> 24) & 0x0FF),
- (unsigned) ((fMinVersion >> 16) & 0x0FF),
- (unsigned) ((fMinVersion >> 8) & 0x0FF),
- (unsigned) ((fMinVersion ) & 0x0FF));
-
- printf (", flags = %u\n", (unsigned) fFlags);
-
- }
-
- #else
-
- (void) name;
-
- #endif
-
- }
-
-/*****************************************************************************/
-
-dng_opcode::~dng_opcode ()
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode::PutData (dng_stream &stream) const
- {
-
- // No data by default
-
- stream.Put_uint32 (0);
-
- }
-
-/*****************************************************************************/
-
-bool dng_opcode::AboutToApply (dng_host &host,
- dng_negative &negative)
- {
-
- if (SkipIfPreview () && host.ForPreview ())
- {
-
- negative.SetIsPreview (true);
-
- }
-
- else if (MinVersion () > dngVersion_Current &&
- WasReadFromStream ())
- {
-
- if (!Optional ())
- {
-
- // Somebody screwed up computing the DNGBackwardVersion...
-
- ThrowBadFormat ();
-
- }
-
- }
-
- else if (!IsValidForNegative (negative))
- {
-
- ThrowBadFormat ();
-
- }
-
- else if (!IsNOP ())
- {
-
- return true;
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-dng_opcode_Unknown::dng_opcode_Unknown (dng_host &host,
- uint32 opcodeID,
- dng_stream &stream)
-
- : dng_opcode (opcodeID,
- stream,
- NULL)
-
- , fData ()
-
- {
-
- uint32 size = stream.Get_uint32 ();
-
- if (size)
- {
-
- fData.Reset (host.Allocate (size));
-
- stream.Get (fData->Buffer (),
- fData->LogicalSize ());
-
- #if qDNGValidate
-
- if (gVerbose)
- {
-
- DumpHexAscii (fData->Buffer_uint8 (),
- fData->LogicalSize ());
-
- }
-
- #endif
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_Unknown::PutData (dng_stream &stream) const
- {
-
- if (fData.Get ())
- {
-
- stream.Put_uint32 (fData->LogicalSize ());
-
- stream.Put (fData->Buffer (),
- fData->LogicalSize ());
-
- }
-
- else
- {
-
- stream.Put_uint32 (0);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_opcode_Unknown::Apply (dng_host & /* host */,
- dng_negative & /* negative */,
- AutoPtr<dng_image> & /* image */)
- {
-
- // We should never need to apply an unknown opcode.
-
- if (!Optional ())
- {
-
- ThrowBadFormat ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-class dng_filter_opcode_task: public dng_filter_task
- {
-
- private:
-
- dng_filter_opcode &fOpcode;
-
- dng_negative &fNegative;
-
- public:
-
- dng_filter_opcode_task (dng_filter_opcode &opcode,
- dng_negative &negative,
- const dng_image &srcImage,
- dng_image &dstImage)
-
- : dng_filter_task (srcImage,
- dstImage)
-
- , fOpcode (opcode)
- , fNegative (negative)
-
- {
-
- fSrcPixelType = fOpcode.BufferPixelType (srcImage.PixelType ());
-
- fDstPixelType = fSrcPixelType;
-
- fSrcRepeat = opcode.SrcRepeat ();
-
- }
-
- virtual dng_rect SrcArea (const dng_rect &dstArea)
- {
-
- return fOpcode.SrcArea (dstArea,
- fDstImage.Bounds ());
-
- }
-
- virtual dng_point SrcTileSize (const dng_point &dstTileSize)
- {
-
- return fOpcode.SrcTileSize (dstTileSize,
- fDstImage.Bounds ());
-
- }
-
- virtual void ProcessArea (uint32 threadIndex,
- dng_pixel_buffer &srcBuffer,
- dng_pixel_buffer &dstBuffer)
- {
-
- fOpcode.ProcessArea (fNegative,
- threadIndex,
- srcBuffer,
- dstBuffer,
- dstBuffer.Area (),
- fDstImage.Bounds ());
-
- }
-
- virtual void Start (uint32 threadCount,
- const dng_point &tileSize,
- dng_memory_allocator *allocator,
- dng_abort_sniffer *sniffer)
- {
-
- dng_filter_task::Start (threadCount,
- tileSize,
- allocator,
- sniffer);
-
- fOpcode.Prepare (fNegative,
- threadCount,
- tileSize,
- fDstImage.Bounds (),
- fDstImage.Planes (),
- fDstPixelType,
- *allocator);
-
- }
-
- };
-
-/*****************************************************************************/
-
-dng_filter_opcode::dng_filter_opcode (uint32 opcodeID,
- uint32 minVersion,
- uint32 flags)
-
- : dng_opcode (opcodeID,
- minVersion,
- flags)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_filter_opcode::dng_filter_opcode (uint32 opcodeID,
- dng_stream &stream,
- const char *name)
-
- : dng_opcode (opcodeID,
- stream,
- name)
-
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_filter_opcode::Apply (dng_host &host,
- dng_negative &negative,
- AutoPtr<dng_image> &image)
- {
-
- dng_rect modifiedBounds = ModifiedBounds (image->Bounds ());
-
- if (modifiedBounds.NotEmpty ())
- {
-
- // Allocate destination image.
-
- AutoPtr<dng_image> dstImage;
-
- // If we are processing the entire image, allocate an
- // undefined image.
-
- if (modifiedBounds == image->Bounds ())
- {
-
- dstImage.Reset (host.Make_dng_image (image->Bounds (),
- image->Planes (),
- image->PixelType ()));
-
- }
-
- // Else start with a clone of the existing image.
-
- else
- {
-
- dstImage.Reset (image->Clone ());
-
- }
-
- // Filter the image.
-
- dng_filter_opcode_task task (*this,
- negative,
- *image,
- *dstImage);
-
- host.PerformAreaTask (task,
- modifiedBounds);
-
- // Return the new image.
-
- image.Reset (dstImage.Release ());
-
- }
-
- }
-
-/*****************************************************************************/
-
-class dng_inplace_opcode_task: public dng_area_task
- {
-
- private:
-
- dng_inplace_opcode &fOpcode;
-
- dng_negative &fNegative;
-
- dng_image &fImage;
-
- uint32 fPixelType;
-
- AutoPtr<dng_memory_block> fBuffer [kMaxMPThreads];
-
- public:
-
- dng_inplace_opcode_task (dng_inplace_opcode &opcode,
- dng_negative &negative,
- dng_image &image)
-
- : dng_area_task ()
-
- , fOpcode (opcode)
- , fNegative (negative)
- , fImage (image)
- , fPixelType (opcode.BufferPixelType (image.PixelType ()))
-
- {
-
- }
-
- virtual void Start (uint32 threadCount,
- const dng_point &tileSize,
- dng_memory_allocator *allocator,
- dng_abort_sniffer * /* sniffer */)
- {
-
- uint32 bufferSize = ComputeBufferSize(fPixelType, tileSize,
- fImage.Planes(), pad16Bytes);
-
- for (uint32 threadIndex = 0; threadIndex < threadCount; threadIndex++)
- {
-
- fBuffer [threadIndex] . Reset (allocator->Allocate (bufferSize));
-
- }
-
- fOpcode.Prepare (fNegative,
- threadCount,
- tileSize,
- fImage.Bounds (),
- fImage.Planes (),
- fPixelType,
- *allocator);
-
- }
-
- virtual void Process (uint32 threadIndex,
- const dng_rect &tile,
- dng_abort_sniffer * /* sniffer */)
- {
-
- // Setup buffer.
-
- dng_pixel_buffer buffer(tile, 0, fImage.Planes (), fPixelType,
- pcRowInterleavedAlign16,
- fBuffer [threadIndex]->Buffer ());
-
- // Get source pixels.
-
- fImage.Get (buffer);
-
- // Process area.
-
- fOpcode.ProcessArea (fNegative,
- threadIndex,
- buffer,
- tile,
- fImage.Bounds ());
-
- // Save result pixels.
-
- fImage.Put (buffer);
-
- }
-
- };
-
-/*****************************************************************************/
-
-dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID,
- uint32 minVersion,
- uint32 flags)
-
- : dng_opcode (opcodeID,
- minVersion,
- flags)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID,
- dng_stream &stream,
- const char *name)
-
- : dng_opcode (opcodeID,
- stream,
- name)
-
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_inplace_opcode::Apply (dng_host &host,
- dng_negative &negative,
- AutoPtr<dng_image> &image)
- {
-
- dng_rect modifiedBounds = ModifiedBounds (image->Bounds ());
-
- if (modifiedBounds.NotEmpty ())
- {
-
- dng_inplace_opcode_task task (*this,
- negative,
- *image);
-
- host.PerformAreaTask (task,
- modifiedBounds);
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// 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_opcodes.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_opcodes.h"
+
+#include "dng_bottlenecks.h"
+#include "dng_exceptions.h"
+#include "dng_filter_task.h"
+#include "dng_globals.h"
+#include "dng_host.h"
+#include "dng_image.h"
+#include "dng_negative.h"
+#include "dng_parse_utils.h"
+#include "dng_stream.h"
+#include "dng_tag_values.h"
+
+/*****************************************************************************/
+
+dng_opcode::dng_opcode (uint32 opcodeID,
+ uint32 minVersion,
+ uint32 flags)
+
+ : fOpcodeID (opcodeID)
+ , fMinVersion (minVersion)
+ , fFlags (flags)
+ , fWasReadFromStream (false)
+ , fStage (0)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_opcode::dng_opcode (uint32 opcodeID,
+ dng_stream &stream,
+ const char *name)
+
+ : fOpcodeID (opcodeID)
+ , fMinVersion (0)
+ , fFlags (0)
+ , fWasReadFromStream (true)
+ , fStage (0)
+
+ {
+
+ fMinVersion = stream.Get_uint32 ();
+ fFlags = stream.Get_uint32 ();
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ printf ("\nOpcode: ");
+
+ if (name)
+ {
+ printf ("%s", name);
+ }
+ else
+ {
+ printf ("Unknown (%u)", (unsigned) opcodeID);
+ }
+
+ printf (", minVersion = %u.%u.%u.%u",
+ (unsigned) ((fMinVersion >> 24) & 0x0FF),
+ (unsigned) ((fMinVersion >> 16) & 0x0FF),
+ (unsigned) ((fMinVersion >> 8) & 0x0FF),
+ (unsigned) ((fMinVersion ) & 0x0FF));
+
+ printf (", flags = %u\n", (unsigned) fFlags);
+
+ }
+
+ #else
+
+ (void) name;
+
+ #endif
+
+ }
+
+/*****************************************************************************/
+
+dng_opcode::~dng_opcode ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode::PutData (dng_stream &stream) const
+ {
+
+ // No data by default
+
+ stream.Put_uint32 (0);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_opcode::AboutToApply (dng_host &host,
+ dng_negative &negative)
+ {
+
+ if (SkipIfPreview () && host.ForPreview ())
+ {
+
+ negative.SetIsPreview (true);
+
+ }
+
+ else if (MinVersion () > dngVersion_Current &&
+ WasReadFromStream ())
+ {
+
+ if (!Optional ())
+ {
+
+ // Somebody screwed up computing the DNGBackwardVersion...
+
+ ThrowBadFormat ();
+
+ }
+
+ }
+
+ else if (!IsValidForNegative (negative))
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ else if (!IsNOP ())
+ {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+dng_opcode_Unknown::dng_opcode_Unknown (dng_host &host,
+ uint32 opcodeID,
+ dng_stream &stream)
+
+ : dng_opcode (opcodeID,
+ stream,
+ NULL)
+
+ , fData ()
+
+ {
+
+ uint32 size = stream.Get_uint32 ();
+
+ if (size)
+ {
+
+ fData.Reset (host.Allocate (size));
+
+ stream.Get (fData->Buffer (),
+ fData->LogicalSize ());
+
+ #if qDNGValidate
+
+ if (gVerbose)
+ {
+
+ DumpHexAscii (fData->Buffer_uint8 (),
+ fData->LogicalSize ());
+
+ }
+
+ #endif
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_Unknown::PutData (dng_stream &stream) const
+ {
+
+ if (fData.Get ())
+ {
+
+ stream.Put_uint32 (fData->LogicalSize ());
+
+ stream.Put (fData->Buffer (),
+ fData->LogicalSize ());
+
+ }
+
+ else
+ {
+
+ stream.Put_uint32 (0);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_opcode_Unknown::Apply (dng_host & /* host */,
+ dng_negative & /* negative */,
+ AutoPtr<dng_image> & /* image */)
+ {
+
+ // We should never need to apply an unknown opcode.
+
+ if (!Optional ())
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+class dng_filter_opcode_task: public dng_filter_task
+ {
+
+ private:
+
+ dng_filter_opcode &fOpcode;
+
+ dng_negative &fNegative;
+
+ public:
+
+ dng_filter_opcode_task (dng_filter_opcode &opcode,
+ dng_negative &negative,
+ const dng_image &srcImage,
+ dng_image &dstImage)
+
+ : dng_filter_task (srcImage,
+ dstImage)
+
+ , fOpcode (opcode)
+ , fNegative (negative)
+
+ {
+
+ fSrcPixelType = fOpcode.BufferPixelType (srcImage.PixelType ());
+
+ fDstPixelType = fSrcPixelType;
+
+ fSrcRepeat = opcode.SrcRepeat ();
+
+ }
+
+ virtual dng_rect SrcArea (const dng_rect &dstArea)
+ {
+
+ return fOpcode.SrcArea (dstArea,
+ fDstImage.Bounds ());
+
+ }
+
+ virtual dng_point SrcTileSize (const dng_point &dstTileSize)
+ {
+
+ return fOpcode.SrcTileSize (dstTileSize,
+ fDstImage.Bounds ());
+
+ }
+
+ virtual void ProcessArea (uint32 threadIndex,
+ dng_pixel_buffer &srcBuffer,
+ dng_pixel_buffer &dstBuffer)
+ {
+
+ fOpcode.ProcessArea (fNegative,
+ threadIndex,
+ srcBuffer,
+ dstBuffer,
+ dstBuffer.Area (),
+ fDstImage.Bounds ());
+
+ }
+
+ virtual void Start (uint32 threadCount,
+ const dng_point &tileSize,
+ dng_memory_allocator *allocator,
+ dng_abort_sniffer *sniffer)
+ {
+
+ dng_filter_task::Start (threadCount,
+ tileSize,
+ allocator,
+ sniffer);
+
+ fOpcode.Prepare (fNegative,
+ threadCount,
+ tileSize,
+ fDstImage.Bounds (),
+ fDstImage.Planes (),
+ fDstPixelType,
+ *allocator);
+
+ }
+
+ };
+
+/*****************************************************************************/
+
+dng_filter_opcode::dng_filter_opcode (uint32 opcodeID,
+ uint32 minVersion,
+ uint32 flags)
+
+ : dng_opcode (opcodeID,
+ minVersion,
+ flags)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_filter_opcode::dng_filter_opcode (uint32 opcodeID,
+ dng_stream &stream,
+ const char *name)
+
+ : dng_opcode (opcodeID,
+ stream,
+ name)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_filter_opcode::Apply (dng_host &host,
+ dng_negative &negative,
+ AutoPtr<dng_image> &image)
+ {
+
+ dng_rect modifiedBounds = ModifiedBounds (image->Bounds ());
+
+ if (modifiedBounds.NotEmpty ())
+ {
+
+ // Allocate destination image.
+
+ AutoPtr<dng_image> dstImage;
+
+ // If we are processing the entire image, allocate an
+ // undefined image.
+
+ if (modifiedBounds == image->Bounds ())
+ {
+
+ dstImage.Reset (host.Make_dng_image (image->Bounds (),
+ image->Planes (),
+ image->PixelType ()));
+
+ }
+
+ // Else start with a clone of the existing image.
+
+ else
+ {
+
+ dstImage.Reset (image->Clone ());
+
+ }
+
+ // Filter the image.
+
+ dng_filter_opcode_task task (*this,
+ negative,
+ *image,
+ *dstImage);
+
+ host.PerformAreaTask (task,
+ modifiedBounds);
+
+ // Return the new image.
+
+ image.Reset (dstImage.Release ());
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+class dng_inplace_opcode_task: public dng_area_task
+ {
+
+ private:
+
+ dng_inplace_opcode &fOpcode;
+
+ dng_negative &fNegative;
+
+ dng_image &fImage;
+
+ uint32 fPixelType;
+
+ AutoPtr<dng_memory_block> fBuffer [kMaxMPThreads];
+
+ public:
+
+ dng_inplace_opcode_task (dng_inplace_opcode &opcode,
+ dng_negative &negative,
+ dng_image &image)
+
+ : dng_area_task ()
+
+ , fOpcode (opcode)
+ , fNegative (negative)
+ , fImage (image)
+ , fPixelType (opcode.BufferPixelType (image.PixelType ()))
+
+ {
+
+ }
+
+ virtual void Start (uint32 threadCount,
+ const dng_point &tileSize,
+ dng_memory_allocator *allocator,
+ dng_abort_sniffer * /* sniffer */)
+ {
+
+ uint32 bufferSize = ComputeBufferSize(fPixelType, tileSize,
+ fImage.Planes(), pad16Bytes);
+
+ for (uint32 threadIndex = 0; threadIndex < threadCount; threadIndex++)
+ {
+
+ fBuffer [threadIndex] . Reset (allocator->Allocate (bufferSize));
+
+ }
+
+ fOpcode.Prepare (fNegative,
+ threadCount,
+ tileSize,
+ fImage.Bounds (),
+ fImage.Planes (),
+ fPixelType,
+ *allocator);
+
+ }
+
+ virtual void Process (uint32 threadIndex,
+ const dng_rect &tile,
+ dng_abort_sniffer * /* sniffer */)
+ {
+
+ // Setup buffer.
+
+ dng_pixel_buffer buffer(tile, 0, fImage.Planes (), fPixelType,
+ pcRowInterleavedAlign16,
+ fBuffer [threadIndex]->Buffer ());
+
+ // Get source pixels.
+
+ fImage.Get (buffer);
+
+ // Process area.
+
+ fOpcode.ProcessArea (fNegative,
+ threadIndex,
+ buffer,
+ tile,
+ fImage.Bounds ());
+
+ // Save result pixels.
+
+ fImage.Put (buffer);
+
+ }
+
+ };
+
+/*****************************************************************************/
+
+dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID,
+ uint32 minVersion,
+ uint32 flags)
+
+ : dng_opcode (opcodeID,
+ minVersion,
+ flags)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_inplace_opcode::dng_inplace_opcode (uint32 opcodeID,
+ dng_stream &stream,
+ const char *name)
+
+ : dng_opcode (opcodeID,
+ stream,
+ name)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_inplace_opcode::Apply (dng_host &host,
+ dng_negative &negative,
+ AutoPtr<dng_image> &image)
+ {
+
+ dng_rect modifiedBounds = ModifiedBounds (image->Bounds ());
+
+ if (modifiedBounds.NotEmpty ())
+ {
+
+ dng_inplace_opcode_task task (*this,
+ negative,
+ *image);
+
+ host.PerformAreaTask (task,
+ modifiedBounds);
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_opcodes.h b/source/dng_opcodes.h
index b214540..b14a4a2 100644
--- a/source/dng_opcodes.h
+++ b/source/dng_opcodes.h
@@ -1,507 +1,507 @@
-/*****************************************************************************/
-// 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_opcodes.h#2 $ */
-/* $DateTime: 2012/08/02 06:09:06 $ */
-/* $Change: 841096 $ */
-/* $Author: erichan $ */
-
-/** \file
- * Base class and common data structures for opcodes (introduced in DNG 1.3).
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_opcodes__
-#define __dng_opcodes__
-
-/*****************************************************************************/
-
-#include "dng_auto_ptr.h"
-#include "dng_classes.h"
-#include "dng_rect.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// \brief List of supported opcodes (by ID).
-
-enum dng_opcode_id
- {
-
- // Internal use only opcode. Never written to DNGs.
-
- dngOpcode_Private = 0,
-
- // Warp image to correct distortion and lateral chromatic aberration for
- // rectilinear lenses.
-
- dngOpcode_WarpRectilinear = 1,
-
- // Warp image to correction distortion for fisheye lenses (i.e., map the
- // fisheye projection to a perspective projection).
-
- dngOpcode_WarpFisheye = 2,
-
- // Radial vignette correction.
-
- dngOpcode_FixVignetteRadial = 3,
-
- // Patch bad Bayer pixels which are marked with a special value in the image.
-
- dngOpcode_FixBadPixelsConstant = 4,
-
- // Patch bad Bayer pixels/rectangles at a list of specified coordinates.
-
- dngOpcode_FixBadPixelsList = 5,
-
- // Trim image to specified bounds.
-
- dngOpcode_TrimBounds = 6,
-
- // Map an area through a 16-bit LUT.
-
- dngOpcode_MapTable = 7,
-
- // Map an area using a polynomial function.
-
- dngOpcode_MapPolynomial = 8,
-
- // Apply a gain map to an area.
-
- dngOpcode_GainMap = 9,
-
- // Apply a per-row delta to an area.
-
- dngOpcode_DeltaPerRow = 10,
-
- // Apply a per-column delta to an area.
-
- dngOpcode_DeltaPerColumn = 11,
-
- // Apply a per-row scale to an area.
-
- dngOpcode_ScalePerRow = 12,
-
- // Apply a per-column scale to an area.
-
- dngOpcode_ScalePerColumn = 13
-
- };
-
-/*****************************************************************************/
-
-/// \brief Virtual base class for opcode.
-
-class dng_opcode
- {
-
- public:
-
- /// Opcode flags.
-
- enum
- {
- kFlag_None = 0, //!< No flag.
- kFlag_Optional = 1, //!< This opcode is optional.
- kFlag_SkipIfPreview = 2 //!< May skip opcode for preview images.
- };
-
- private:
-
- uint32 fOpcodeID;
-
- uint32 fMinVersion;
-
- uint32 fFlags;
-
- bool fWasReadFromStream;
-
- uint32 fStage;
-
- protected:
-
- dng_opcode (uint32 opcodeID,
- uint32 minVersion,
- uint32 flags);
-
- dng_opcode (uint32 opcodeID,
- dng_stream &stream,
- const char *name);
-
- public:
-
- virtual ~dng_opcode ();
-
- /// The ID of this opcode.
-
- uint32 OpcodeID () const
- {
- return fOpcodeID;
- }
-
- /// The first DNG version that supports this opcode.
-
- uint32 MinVersion () const
- {
- return fMinVersion;
- }
-
- /// The flags for this opcode.
-
- uint32 Flags () const
- {
- return fFlags;
- }
-
- /// Is this opcode optional?
-
- bool Optional () const
- {
- return (Flags () & kFlag_Optional) != 0;
- }
-
- /// Should the opcode be skipped when rendering preview images?
-
- bool SkipIfPreview () const
- {
- return (Flags () & kFlag_SkipIfPreview) != 0;
- }
-
- /// Was this opcode read from a data stream?
-
- bool WasReadFromStream () const
- {
- return fWasReadFromStream;
- }
-
- /// Which image processing stage (1, 2, 3) is associated with this
- /// opcode?
-
- uint32 Stage () const
- {
- return fStage;
- }
-
- /// Set the image processing stage (1, 2, 3) for this opcode. Stage 1 is
- /// the original image data, including masked areas. Stage 2 is
- /// linearized image data and trimmed to the active area. Stage 3 is
- /// demosaiced and trimmed to the active area.
-
- void SetStage (uint32 stage)
- {
- fStage = stage;
- }
-
- /// Is the opcode a NOP (i.e., does nothing)? An opcode could be a NOP
- /// for some specific parameters.
-
- virtual bool IsNOP () const
- {
- return false;
- }
-
- /// Is this opcode valid for the specified negative?
-
- virtual bool IsValidForNegative (const dng_negative & /* negative */) const
- {
- return true;
- }
-
- /// Write opcode to a stream.
- /// \param stream The stream to which to write the opcode data.
-
- virtual void PutData (dng_stream &stream) const;
-
- /// Perform error checking prior to applying this opcode to the
- /// specified negative. Returns true if this opcode should be applied to
- /// the negative, false otherwise.
-
- bool AboutToApply (dng_host &host,
- dng_negative &negative);
-
- /// Apply this opcode to the specified image with associated negative.
-
- virtual void Apply (dng_host &host,
- dng_negative &negative,
- AutoPtr<dng_image> &image) = 0;
-
- };
-
-/*****************************************************************************/
-
-/// \brief Class to represent unknown opcodes (e.g, opcodes defined in future
-/// DNG versions).
-
-class dng_opcode_Unknown: public dng_opcode
- {
-
- private:
-
- AutoPtr<dng_memory_block> fData;
-
- public:
-
- dng_opcode_Unknown (dng_host &host,
- uint32 opcodeID,
- dng_stream &stream);
-
- virtual void PutData (dng_stream &stream) const;
-
- virtual void Apply (dng_host &host,
- dng_negative &negative,
- AutoPtr<dng_image> &image);
-
- };
-
-/*****************************************************************************/
-
-/// \brief Class to represent a filter opcode, such as a convolution.
-
-class dng_filter_opcode: public dng_opcode
- {
-
- protected:
-
- dng_filter_opcode (uint32 opcodeID,
- uint32 minVersion,
- uint32 flags);
-
- dng_filter_opcode (uint32 opcodeID,
- dng_stream &stream,
- const char *name);
-
- public:
-
- /// The pixel data type of this opcode.
-
- virtual uint32 BufferPixelType (uint32 imagePixelType)
- {
- return imagePixelType;
- }
-
- /// The adjusted bounds (processing area) of this opcode. It is limited to
- /// the intersection of the specified image area and the GainMap area.
-
- virtual dng_rect ModifiedBounds (const dng_rect &imageBounds)
- {
- return imageBounds;
- }
-
- /// Returns the width and height (in pixels) of the repeating mosaic pattern.
-
- virtual dng_point SrcRepeat ()
- {
- return dng_point (1, 1);
- }
-
- /// Returns the source pixel area needed to process a destination pixel area
- /// that lies within the specified bounds.
- /// \param dstArea The destination pixel area to be computed.
- /// \param imageBounds The overall image area (dstArea will lie within these
- /// bounds).
- /// \retval The source pixel area needed to process the specified dstArea.
-
- virtual dng_rect SrcArea (const dng_rect &dstArea,
- const dng_rect & /* imageBounds */)
- {
- return dstArea;
- }
-
- /// Given a destination tile size, calculate input tile size. Simlar to
- /// SrcArea, and should seldom be overridden.
- ///
- /// \param dstTileSize The destination tile size that is targeted for output.
- ///
- /// \param imageBounds The image bounds (the destination tile will
- /// always lie within these bounds).
- ///
- /// \retval The source tile size needed to compute a tile of the destination
- /// size.
-
- virtual dng_point SrcTileSize (const dng_point &dstTileSize,
- const dng_rect &imageBounds)
- {
- return SrcArea (dng_rect (dstTileSize),
- imageBounds).Size ();
- }
-
- /// Startup method called before any processing is performed on pixel areas.
- /// It can be used to allocate (per-thread) memory and setup tasks.
- ///
- /// \param negative The negative object to be processed.
- ///
- /// \param threadCount The number of threads to be used to perform the
- /// processing.
- ///
- /// \param threadCount Total number of threads that will be used for
- /// processing. Less than or equal to MaxThreads.
- ///
- /// \param tileSize Size of source tiles which will be processed. (Not all
- /// tiles will be this size due to edge conditions.)
- ///
- /// \param imageBounds Total size of image to be processed.
- ///
- /// \param imagePlanes Number of planes in the image. Less than or equal to
- /// kMaxColorPlanes.
- ///
- /// \param bufferPixelType Pixel type of image buffer (see dng_tag_types.h).
- ///
- /// \param allocator dng_memory_allocator to use for allocating temporary
- /// buffers, etc.
-
- virtual void Prepare (dng_negative & /* negative */,
- uint32 /* threadCount */,
- const dng_point & /* tileSize */,
- const dng_rect & /* imageBounds */,
- uint32 /* imagePlanes */,
- uint32 /* bufferPixelType */,
- dng_memory_allocator & /* allocator */)
- {
- }
-
- /// Implements filtering operation from one buffer to another. Source
- /// and destination pixels are set up in member fields of this class.
- /// Ideally, no allocation should be done in this routine.
- ///
- /// \param negative The negative associated with the pixels to be
- /// processed.
- ///
- /// \param threadIndex The thread on which this routine is being called,
- /// between 0 and threadCount - 1 for the threadCount passed to Prepare
- /// method.
- ///
- /// \param srcBuffer Input area and source pixels.
- ///
- /// \param dstBuffer Destination pixels.
- ///
- /// \param dstArea Destination pixel processing area.
- ///
- /// \param imageBounds Total image area to be processed; dstArea will
- /// always lie within these bounds.
-
- virtual void ProcessArea (dng_negative &negative,
- uint32 threadIndex,
- dng_pixel_buffer &srcBuffer,
- dng_pixel_buffer &dstBuffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds) = 0;
-
- virtual void Apply (dng_host &host,
- dng_negative &negative,
- AutoPtr<dng_image> &image);
-
- };
-
-/*****************************************************************************/
-
-/// \brief Class to represent an in-place (i.e., pointwise, per-pixel) opcode,
-/// such as a global tone curve.
-
-class dng_inplace_opcode: public dng_opcode
- {
-
- protected:
-
- dng_inplace_opcode (uint32 opcodeID,
- uint32 minVersion,
- uint32 flags);
-
- dng_inplace_opcode (uint32 opcodeID,
- dng_stream &stream,
- const char *name);
-
- public:
-
- /// The pixel data type of this opcode.
-
- virtual uint32 BufferPixelType (uint32 imagePixelType)
- {
- return imagePixelType;
- }
-
- /// The adjusted bounds (processing area) of this opcode. It is limited to
- /// the intersection of the specified image area and the GainMap area.
-
- virtual dng_rect ModifiedBounds (const dng_rect &imageBounds)
- {
- return imageBounds;
- }
-
- /// Startup method called before any processing is performed on pixel areas.
- /// It can be used to allocate (per-thread) memory and setup tasks.
- ///
- /// \param negative The negative object to be processed.
- ///
- /// \param threadCount The number of threads to be used to perform the
- /// processing.
- ///
- /// \param threadCount Total number of threads that will be used for
- /// processing. Less than or equal to MaxThreads.
- ///
- /// \param tileSize Size of source tiles which will be processed. (Not all
- /// tiles will be this size due to edge conditions.)
- ///
- /// \param imageBounds Total size of image to be processed.
- ///
- /// \param imagePlanes Number of planes in the image. Less than or equal to
- /// kMaxColorPlanes.
- ///
- /// \param bufferPixelType Pixel type of image buffer (see dng_tag_types.h).
- ///
- /// \param allocator dng_memory_allocator to use for allocating temporary
- /// buffers, etc.
-
- virtual void Prepare (dng_negative & /* negative */,
- uint32 /* threadCount */,
- const dng_point & /* tileSize */,
- const dng_rect & /* imageBounds */,
- uint32 /* imagePlanes */,
- uint32 /* bufferPixelType */,
- dng_memory_allocator & /* allocator */)
- {
- }
-
- /// Implements image processing operation in a single buffer. The source
- /// pixels are provided as input to the buffer, and this routine
- /// calculates and writes the destination pixels to the same buffer.
- /// Ideally, no allocation should be done in this routine.
- ///
- /// \param negative The negative associated with the pixels to be
- /// processed.
- ///
- /// \param threadIndex The thread on which this routine is being called,
- /// between 0 and threadCount - 1 for the threadCount passed to Prepare
- /// method.
- ///
- /// \param srcBuffer Input area and source pixels.
- ///
- /// \param dstBuffer Destination pixels.
- ///
- /// \param dstArea Destination pixel processing area.
- ///
- /// \param imageBounds Total image area to be processed; dstArea will
- /// always lie within these bounds.
-
- virtual void ProcessArea (dng_negative &negative,
- uint32 threadIndex,
- dng_pixel_buffer &buffer,
- const dng_rect &dstArea,
- const dng_rect &imageBounds) = 0;
-
- virtual void Apply (dng_host &host,
- dng_negative &negative,
- AutoPtr<dng_image> &image);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// 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_opcodes.h#2 $ */
+/* $DateTime: 2012/08/02 06:09:06 $ */
+/* $Change: 841096 $ */
+/* $Author: erichan $ */
+
+/** \file
+ * Base class and common data structures for opcodes (introduced in DNG 1.3).
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_opcodes__
+#define __dng_opcodes__
+
+/*****************************************************************************/
+
+#include "dng_auto_ptr.h"
+#include "dng_classes.h"
+#include "dng_rect.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// \brief List of supported opcodes (by ID).
+
+enum dng_opcode_id
+ {
+
+ // Internal use only opcode. Never written to DNGs.
+
+ dngOpcode_Private = 0,
+
+ // Warp image to correct distortion and lateral chromatic aberration for
+ // rectilinear lenses.
+
+ dngOpcode_WarpRectilinear = 1,
+
+ // Warp image to correction distortion for fisheye lenses (i.e., map the
+ // fisheye projection to a perspective projection).
+
+ dngOpcode_WarpFisheye = 2,
+
+ // Radial vignette correction.
+
+ dngOpcode_FixVignetteRadial = 3,
+
+ // Patch bad Bayer pixels which are marked with a special value in the image.
+
+ dngOpcode_FixBadPixelsConstant = 4,
+
+ // Patch bad Bayer pixels/rectangles at a list of specified coordinates.
+
+ dngOpcode_FixBadPixelsList = 5,
+
+ // Trim image to specified bounds.
+
+ dngOpcode_TrimBounds = 6,
+
+ // Map an area through a 16-bit LUT.
+
+ dngOpcode_MapTable = 7,
+
+ // Map an area using a polynomial function.
+
+ dngOpcode_MapPolynomial = 8,
+
+ // Apply a gain map to an area.
+
+ dngOpcode_GainMap = 9,
+
+ // Apply a per-row delta to an area.
+
+ dngOpcode_DeltaPerRow = 10,
+
+ // Apply a per-column delta to an area.
+
+ dngOpcode_DeltaPerColumn = 11,
+
+ // Apply a per-row scale to an area.
+
+ dngOpcode_ScalePerRow = 12,
+
+ // Apply a per-column scale to an area.
+
+ dngOpcode_ScalePerColumn = 13
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Virtual base class for opcode.
+
+class dng_opcode
+ {
+
+ public:
+
+ /// Opcode flags.
+
+ enum
+ {
+ kFlag_None = 0, //!< No flag.
+ kFlag_Optional = 1, //!< This opcode is optional.
+ kFlag_SkipIfPreview = 2 //!< May skip opcode for preview images.
+ };
+
+ private:
+
+ uint32 fOpcodeID;
+
+ uint32 fMinVersion;
+
+ uint32 fFlags;
+
+ bool fWasReadFromStream;
+
+ uint32 fStage;
+
+ protected:
+
+ dng_opcode (uint32 opcodeID,
+ uint32 minVersion,
+ uint32 flags);
+
+ dng_opcode (uint32 opcodeID,
+ dng_stream &stream,
+ const char *name);
+
+ public:
+
+ virtual ~dng_opcode ();
+
+ /// The ID of this opcode.
+
+ uint32 OpcodeID () const
+ {
+ return fOpcodeID;
+ }
+
+ /// The first DNG version that supports this opcode.
+
+ uint32 MinVersion () const
+ {
+ return fMinVersion;
+ }
+
+ /// The flags for this opcode.
+
+ uint32 Flags () const
+ {
+ return fFlags;
+ }
+
+ /// Is this opcode optional?
+
+ bool Optional () const
+ {
+ return (Flags () & kFlag_Optional) != 0;
+ }
+
+ /// Should the opcode be skipped when rendering preview images?
+
+ bool SkipIfPreview () const
+ {
+ return (Flags () & kFlag_SkipIfPreview) != 0;
+ }
+
+ /// Was this opcode read from a data stream?
+
+ bool WasReadFromStream () const
+ {
+ return fWasReadFromStream;
+ }
+
+ /// Which image processing stage (1, 2, 3) is associated with this
+ /// opcode?
+
+ uint32 Stage () const
+ {
+ return fStage;
+ }
+
+ /// Set the image processing stage (1, 2, 3) for this opcode. Stage 1 is
+ /// the original image data, including masked areas. Stage 2 is
+ /// linearized image data and trimmed to the active area. Stage 3 is
+ /// demosaiced and trimmed to the active area.
+
+ void SetStage (uint32 stage)
+ {
+ fStage = stage;
+ }
+
+ /// Is the opcode a NOP (i.e., does nothing)? An opcode could be a NOP
+ /// for some specific parameters.
+
+ virtual bool IsNOP () const
+ {
+ return false;
+ }
+
+ /// Is this opcode valid for the specified negative?
+
+ virtual bool IsValidForNegative (const dng_negative & /* negative */) const
+ {
+ return true;
+ }
+
+ /// Write opcode to a stream.
+ /// \param stream The stream to which to write the opcode data.
+
+ virtual void PutData (dng_stream &stream) const;
+
+ /// Perform error checking prior to applying this opcode to the
+ /// specified negative. Returns true if this opcode should be applied to
+ /// the negative, false otherwise.
+
+ bool AboutToApply (dng_host &host,
+ dng_negative &negative);
+
+ /// Apply this opcode to the specified image with associated negative.
+
+ virtual void Apply (dng_host &host,
+ dng_negative &negative,
+ AutoPtr<dng_image> &image) = 0;
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Class to represent unknown opcodes (e.g, opcodes defined in future
+/// DNG versions).
+
+class dng_opcode_Unknown: public dng_opcode
+ {
+
+ private:
+
+ AutoPtr<dng_memory_block> fData;
+
+ public:
+
+ dng_opcode_Unknown (dng_host &host,
+ uint32 opcodeID,
+ dng_stream &stream);
+
+ virtual void PutData (dng_stream &stream) const;
+
+ virtual void Apply (dng_host &host,
+ dng_negative &negative,
+ AutoPtr<dng_image> &image);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Class to represent a filter opcode, such as a convolution.
+
+class dng_filter_opcode: public dng_opcode
+ {
+
+ protected:
+
+ dng_filter_opcode (uint32 opcodeID,
+ uint32 minVersion,
+ uint32 flags);
+
+ dng_filter_opcode (uint32 opcodeID,
+ dng_stream &stream,
+ const char *name);
+
+ public:
+
+ /// The pixel data type of this opcode.
+
+ virtual uint32 BufferPixelType (uint32 imagePixelType)
+ {
+ return imagePixelType;
+ }
+
+ /// The adjusted bounds (processing area) of this opcode. It is limited to
+ /// the intersection of the specified image area and the GainMap area.
+
+ virtual dng_rect ModifiedBounds (const dng_rect &imageBounds)
+ {
+ return imageBounds;
+ }
+
+ /// Returns the width and height (in pixels) of the repeating mosaic pattern.
+
+ virtual dng_point SrcRepeat ()
+ {
+ return dng_point (1, 1);
+ }
+
+ /// Returns the source pixel area needed to process a destination pixel area
+ /// that lies within the specified bounds.
+ /// \param dstArea The destination pixel area to be computed.
+ /// \param imageBounds The overall image area (dstArea will lie within these
+ /// bounds).
+ /// \retval The source pixel area needed to process the specified dstArea.
+
+ virtual dng_rect SrcArea (const dng_rect &dstArea,
+ const dng_rect & /* imageBounds */)
+ {
+ return dstArea;
+ }
+
+ /// Given a destination tile size, calculate input tile size. Simlar to
+ /// SrcArea, and should seldom be overridden.
+ ///
+ /// \param dstTileSize The destination tile size that is targeted for output.
+ ///
+ /// \param imageBounds The image bounds (the destination tile will
+ /// always lie within these bounds).
+ ///
+ /// \retval The source tile size needed to compute a tile of the destination
+ /// size.
+
+ virtual dng_point SrcTileSize (const dng_point &dstTileSize,
+ const dng_rect &imageBounds)
+ {
+ return SrcArea (dng_rect (dstTileSize),
+ imageBounds).Size ();
+ }
+
+ /// Startup method called before any processing is performed on pixel areas.
+ /// It can be used to allocate (per-thread) memory and setup tasks.
+ ///
+ /// \param negative The negative object to be processed.
+ ///
+ /// \param threadCount The number of threads to be used to perform the
+ /// processing.
+ ///
+ /// \param threadCount Total number of threads that will be used for
+ /// processing. Less than or equal to MaxThreads.
+ ///
+ /// \param tileSize Size of source tiles which will be processed. (Not all
+ /// tiles will be this size due to edge conditions.)
+ ///
+ /// \param imageBounds Total size of image to be processed.
+ ///
+ /// \param imagePlanes Number of planes in the image. Less than or equal to
+ /// kMaxColorPlanes.
+ ///
+ /// \param bufferPixelType Pixel type of image buffer (see dng_tag_types.h).
+ ///
+ /// \param allocator dng_memory_allocator to use for allocating temporary
+ /// buffers, etc.
+
+ virtual void Prepare (dng_negative & /* negative */,
+ uint32 /* threadCount */,
+ const dng_point & /* tileSize */,
+ const dng_rect & /* imageBounds */,
+ uint32 /* imagePlanes */,
+ uint32 /* bufferPixelType */,
+ dng_memory_allocator & /* allocator */)
+ {
+ }
+
+ /// Implements filtering operation from one buffer to another. Source
+ /// and destination pixels are set up in member fields of this class.
+ /// Ideally, no allocation should be done in this routine.
+ ///
+ /// \param negative The negative associated with the pixels to be
+ /// processed.
+ ///
+ /// \param threadIndex The thread on which this routine is being called,
+ /// between 0 and threadCount - 1 for the threadCount passed to Prepare
+ /// method.
+ ///
+ /// \param srcBuffer Input area and source pixels.
+ ///
+ /// \param dstBuffer Destination pixels.
+ ///
+ /// \param dstArea Destination pixel processing area.
+ ///
+ /// \param imageBounds Total image area to be processed; dstArea will
+ /// always lie within these bounds.
+
+ virtual void ProcessArea (dng_negative &negative,
+ uint32 threadIndex,
+ dng_pixel_buffer &srcBuffer,
+ dng_pixel_buffer &dstBuffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds) = 0;
+
+ virtual void Apply (dng_host &host,
+ dng_negative &negative,
+ AutoPtr<dng_image> &image);
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Class to represent an in-place (i.e., pointwise, per-pixel) opcode,
+/// such as a global tone curve.
+
+class dng_inplace_opcode: public dng_opcode
+ {
+
+ protected:
+
+ dng_inplace_opcode (uint32 opcodeID,
+ uint32 minVersion,
+ uint32 flags);
+
+ dng_inplace_opcode (uint32 opcodeID,
+ dng_stream &stream,
+ const char *name);
+
+ public:
+
+ /// The pixel data type of this opcode.
+
+ virtual uint32 BufferPixelType (uint32 imagePixelType)
+ {
+ return imagePixelType;
+ }
+
+ /// The adjusted bounds (processing area) of this opcode. It is limited to
+ /// the intersection of the specified image area and the GainMap area.
+
+ virtual dng_rect ModifiedBounds (const dng_rect &imageBounds)
+ {
+ return imageBounds;
+ }
+
+ /// Startup method called before any processing is performed on pixel areas.
+ /// It can be used to allocate (per-thread) memory and setup tasks.
+ ///
+ /// \param negative The negative object to be processed.
+ ///
+ /// \param threadCount The number of threads to be used to perform the
+ /// processing.
+ ///
+ /// \param threadCount Total number of threads that will be used for
+ /// processing. Less than or equal to MaxThreads.
+ ///
+ /// \param tileSize Size of source tiles which will be processed. (Not all
+ /// tiles will be this size due to edge conditions.)
+ ///
+ /// \param imageBounds Total size of image to be processed.
+ ///
+ /// \param imagePlanes Number of planes in the image. Less than or equal to
+ /// kMaxColorPlanes.
+ ///
+ /// \param bufferPixelType Pixel type of image buffer (see dng_tag_types.h).
+ ///
+ /// \param allocator dng_memory_allocator to use for allocating temporary
+ /// buffers, etc.
+
+ virtual void Prepare (dng_negative & /* negative */,
+ uint32 /* threadCount */,
+ const dng_point & /* tileSize */,
+ const dng_rect & /* imageBounds */,
+ uint32 /* imagePlanes */,
+ uint32 /* bufferPixelType */,
+ dng_memory_allocator & /* allocator */)
+ {
+ }
+
+ /// Implements image processing operation in a single buffer. The source
+ /// pixels are provided as input to the buffer, and this routine
+ /// calculates and writes the destination pixels to the same buffer.
+ /// Ideally, no allocation should be done in this routine.
+ ///
+ /// \param negative The negative associated with the pixels to be
+ /// processed.
+ ///
+ /// \param threadIndex The thread on which this routine is being called,
+ /// between 0 and threadCount - 1 for the threadCount passed to Prepare
+ /// method.
+ ///
+ /// \param srcBuffer Input area and source pixels.
+ ///
+ /// \param dstBuffer Destination pixels.
+ ///
+ /// \param dstArea Destination pixel processing area.
+ ///
+ /// \param imageBounds Total image area to be processed; dstArea will
+ /// always lie within these bounds.
+
+ virtual void ProcessArea (dng_negative &negative,
+ uint32 threadIndex,
+ dng_pixel_buffer &buffer,
+ const dng_rect &dstArea,
+ const dng_rect &imageBounds) = 0;
+
+ virtual void Apply (dng_host &host,
+ dng_negative &negative,
+ AutoPtr<dng_image> &image);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_orientation.cpp b/source/dng_orientation.cpp
index 820ca34..35b4118 100644
--- a/source/dng_orientation.cpp
+++ b/source/dng_orientation.cpp
@@ -1,233 +1,233 @@
-/*****************************************************************************/
-// Copyright 2006 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_orientation.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-#include "dng_orientation.h"
-
-/*****************************************************************************/
-
-void dng_orientation::SetTIFF (uint32 tiff)
- {
-
- switch (tiff)
- {
-
- case 1:
- {
- fAdobeOrientation = kNormal;
- break;
- }
-
- case 2:
- {
- fAdobeOrientation = kMirror;
- break;
- }
-
- case 3:
- {
- fAdobeOrientation = kRotate180;
- break;
- }
-
- case 4:
- {
- fAdobeOrientation = kMirror180;
- break;
- }
-
- case 5:
- {
- fAdobeOrientation = kMirror90CCW;
- break;
- }
-
- case 6:
- {
- fAdobeOrientation = kRotate90CW;
- break;
- }
-
- case 7:
- {
- fAdobeOrientation = kMirror90CW;
- break;
- }
-
- case 8:
- {
- fAdobeOrientation = kRotate90CCW;
- break;
- }
-
- case 9:
- {
- fAdobeOrientation = kUnknown;
- break;
- }
-
- default:
- {
- fAdobeOrientation = kNormal;
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_orientation::GetTIFF () const
- {
-
- switch (fAdobeOrientation)
- {
-
- case kNormal:
- {
- return 1;
- }
-
- case kMirror:
- {
- return 2;
- }
-
- case kRotate180:
- {
- return 3;
- }
-
- case kMirror180:
- {
- return 4;
- }
-
- case kMirror90CCW:
- {
- return 5;
- }
-
- case kRotate90CW:
- {
- return 6;
- }
-
- case kMirror90CW:
- {
- return 7;
- }
-
- case kRotate90CCW:
- {
- return 8;
- }
-
- case kUnknown:
- {
- return 9;
- }
-
- default:
- break;
-
- }
-
- return 1;
-
- }
-
-/*****************************************************************************/
-
-bool dng_orientation::FlipD () const
- {
-
- return (fAdobeOrientation & 1) != 0;
-
- }
-
-/*****************************************************************************/
-
-bool dng_orientation::FlipH () const
- {
-
- if (fAdobeOrientation & 4)
- return (fAdobeOrientation & 2) == 0;
-
- else
- return (fAdobeOrientation & 2) != 0;
-
- }
-
-/*****************************************************************************/
-
-bool dng_orientation::FlipV () const
- {
-
- if (fAdobeOrientation & 4)
- return FlipD () == FlipH ();
-
- else
- return FlipD () != FlipH ();
-
- }
-
-/*****************************************************************************/
-
-dng_orientation dng_orientation::operator- () const
- {
-
- uint32 x = GetAdobe ();
-
- if ((x & 5) == 5)
- {
-
- x ^= 2;
-
- }
-
- dng_orientation result;
-
- result.SetAdobe (((4 - x) & 3) | (x & 4));
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-dng_orientation dng_orientation::operator+ (const dng_orientation &b) const
- {
-
- uint32 x = GetAdobe ();
-
- uint32 y = b.GetAdobe ();
-
- if (y & 4)
- {
-
- if (x & 1)
- x ^= 6;
- else
- x ^= 4;
-
- }
-
- dng_orientation result;
-
- result.SetAdobe (((x + y) & 3) | (x & 4));
-
- return result;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_orientation.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+#include "dng_orientation.h"
+
+/*****************************************************************************/
+
+void dng_orientation::SetTIFF (uint32 tiff)
+ {
+
+ switch (tiff)
+ {
+
+ case 1:
+ {
+ fAdobeOrientation = kNormal;
+ break;
+ }
+
+ case 2:
+ {
+ fAdobeOrientation = kMirror;
+ break;
+ }
+
+ case 3:
+ {
+ fAdobeOrientation = kRotate180;
+ break;
+ }
+
+ case 4:
+ {
+ fAdobeOrientation = kMirror180;
+ break;
+ }
+
+ case 5:
+ {
+ fAdobeOrientation = kMirror90CCW;
+ break;
+ }
+
+ case 6:
+ {
+ fAdobeOrientation = kRotate90CW;
+ break;
+ }
+
+ case 7:
+ {
+ fAdobeOrientation = kMirror90CW;
+ break;
+ }
+
+ case 8:
+ {
+ fAdobeOrientation = kRotate90CCW;
+ break;
+ }
+
+ case 9:
+ {
+ fAdobeOrientation = kUnknown;
+ break;
+ }
+
+ default:
+ {
+ fAdobeOrientation = kNormal;
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_orientation::GetTIFF () const
+ {
+
+ switch (fAdobeOrientation)
+ {
+
+ case kNormal:
+ {
+ return 1;
+ }
+
+ case kMirror:
+ {
+ return 2;
+ }
+
+ case kRotate180:
+ {
+ return 3;
+ }
+
+ case kMirror180:
+ {
+ return 4;
+ }
+
+ case kMirror90CCW:
+ {
+ return 5;
+ }
+
+ case kRotate90CW:
+ {
+ return 6;
+ }
+
+ case kMirror90CW:
+ {
+ return 7;
+ }
+
+ case kRotate90CCW:
+ {
+ return 8;
+ }
+
+ case kUnknown:
+ {
+ return 9;
+ }
+
+ default:
+ break;
+
+ }
+
+ return 1;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_orientation::FlipD () const
+ {
+
+ return (fAdobeOrientation & 1) != 0;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_orientation::FlipH () const
+ {
+
+ if (fAdobeOrientation & 4)
+ return (fAdobeOrientation & 2) == 0;
+
+ else
+ return (fAdobeOrientation & 2) != 0;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_orientation::FlipV () const
+ {
+
+ if (fAdobeOrientation & 4)
+ return FlipD () == FlipH ();
+
+ else
+ return FlipD () != FlipH ();
+
+ }
+
+/*****************************************************************************/
+
+dng_orientation dng_orientation::operator- () const
+ {
+
+ uint32 x = GetAdobe ();
+
+ if ((x & 5) == 5)
+ {
+
+ x ^= 2;
+
+ }
+
+ dng_orientation result;
+
+ result.SetAdobe (((4 - x) & 3) | (x & 4));
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+dng_orientation dng_orientation::operator+ (const dng_orientation &b) const
+ {
+
+ uint32 x = GetAdobe ();
+
+ uint32 y = b.GetAdobe ();
+
+ if (y & 4)
+ {
+
+ if (x & 1)
+ x ^= 6;
+ else
+ x ^= 4;
+
+ }
+
+ dng_orientation result;
+
+ result.SetAdobe (((x + y) & 3) | (x & 4));
+
+ return result;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_orientation.h b/source/dng_orientation.h
index cb23adf..46fef02 100644
--- a/source/dng_orientation.h
+++ b/source/dng_orientation.h
@@ -1,189 +1,189 @@
-/*****************************************************************************/
-// Copyright 2006 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_orientation.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/******************************************************************************/
-
-#ifndef __dng_orientation__
-#define __dng_orientation__
-
-/******************************************************************************/
-
-#include "dng_types.h"
-
-/******************************************************************************/
-
-class dng_orientation
- {
-
- private:
-
- // We internally use an orientation encoding ("Adobe") that is
- // different than the TIFF orientation encoding ("TIFF").
-
- uint32 fAdobeOrientation;
-
- public:
- enum
- {
- kNormal = 0,
- kRotate90CW = 1,
- kRotate180 = 2,
- kRotate90CCW = 3,
- kMirror = 4,
- kMirror90CW = 5,
- kMirror180 = 6,
- kMirror90CCW = 7,
- kUnknown = 8
- };
-
-
- dng_orientation ()
-
- : fAdobeOrientation (kNormal)
-
- {
- }
-
- void SetAdobe (uint32 adobe)
- {
- fAdobeOrientation = adobe;
- }
-
- uint32 GetAdobe () const
- {
- return fAdobeOrientation;
- }
-
- void SetTIFF (uint32 tiff);
-
- uint32 GetTIFF () const;
-
- static dng_orientation AdobeToDNG (uint32 adobe)
- {
-
- dng_orientation result;
-
- result.SetAdobe (adobe);
-
- return result;
-
- }
-
- static dng_orientation TIFFtoDNG (uint32 tiff)
- {
-
- dng_orientation result;
-
- result.SetTIFF (tiff);
-
- return result;
-
- }
-
- static dng_orientation Normal ()
- {
- return AdobeToDNG (kNormal);
- }
-
- static dng_orientation Rotate90CW ()
- {
- return AdobeToDNG (kRotate90CW);
- }
-
- static dng_orientation Rotate180 ()
- {
- return AdobeToDNG (kRotate180);
- }
-
- static dng_orientation Rotate90CCW ()
- {
- return AdobeToDNG (kRotate90CCW);
- }
-
- static dng_orientation Mirror ()
- {
- return AdobeToDNG (kMirror);
- }
-
- static dng_orientation Mirror90CW ()
- {
- return AdobeToDNG (kMirror90CW);
- }
-
- static dng_orientation Mirror180 ()
- {
- return AdobeToDNG (kMirror180);
- }
-
- static dng_orientation Mirror90CCW ()
- {
- return AdobeToDNG (kMirror90CCW);
- }
-
- static dng_orientation Unknown ()
- {
- return AdobeToDNG (kUnknown);
- }
-
- bool IsValid () const
- {
- return fAdobeOrientation < kUnknown;
- }
-
- bool NotValid () const
- {
- return !IsValid ();
- }
-
- bool FlipD () const;
-
- bool FlipH () const;
-
- bool FlipV () const;
-
- bool operator== (const dng_orientation &b) const
- {
- return fAdobeOrientation == b.fAdobeOrientation;
- }
-
- bool operator!= (const dng_orientation &b) const
- {
- return !(*this == b);
- }
-
- dng_orientation operator- () const;
-
- dng_orientation operator+ (const dng_orientation &b) const;
-
- dng_orientation operator- (const dng_orientation &b) const
- {
- return (*this) + (-b);
- }
-
- void operator+= (const dng_orientation &b)
- {
- *this = *this + b;
- }
-
- void operator-= (const dng_orientation &b)
- {
- *this = *this - b;
- }
-
- };
-
-/******************************************************************************/
-
-#endif
-
-/******************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_orientation.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/******************************************************************************/
+
+#ifndef __dng_orientation__
+#define __dng_orientation__
+
+/******************************************************************************/
+
+#include "dng_types.h"
+
+/******************************************************************************/
+
+class dng_orientation
+ {
+
+ private:
+
+ // We internally use an orientation encoding ("Adobe") that is
+ // different than the TIFF orientation encoding ("TIFF").
+
+ uint32 fAdobeOrientation;
+
+ public:
+ enum
+ {
+ kNormal = 0,
+ kRotate90CW = 1,
+ kRotate180 = 2,
+ kRotate90CCW = 3,
+ kMirror = 4,
+ kMirror90CW = 5,
+ kMirror180 = 6,
+ kMirror90CCW = 7,
+ kUnknown = 8
+ };
+
+
+ dng_orientation ()
+
+ : fAdobeOrientation (kNormal)
+
+ {
+ }
+
+ void SetAdobe (uint32 adobe)
+ {
+ fAdobeOrientation = adobe;
+ }
+
+ uint32 GetAdobe () const
+ {
+ return fAdobeOrientation;
+ }
+
+ void SetTIFF (uint32 tiff);
+
+ uint32 GetTIFF () const;
+
+ static dng_orientation AdobeToDNG (uint32 adobe)
+ {
+
+ dng_orientation result;
+
+ result.SetAdobe (adobe);
+
+ return result;
+
+ }
+
+ static dng_orientation TIFFtoDNG (uint32 tiff)
+ {
+
+ dng_orientation result;
+
+ result.SetTIFF (tiff);
+
+ return result;
+
+ }
+
+ static dng_orientation Normal ()
+ {
+ return AdobeToDNG (kNormal);
+ }
+
+ static dng_orientation Rotate90CW ()
+ {
+ return AdobeToDNG (kRotate90CW);
+ }
+
+ static dng_orientation Rotate180 ()
+ {
+ return AdobeToDNG (kRotate180);
+ }
+
+ static dng_orientation Rotate90CCW ()
+ {
+ return AdobeToDNG (kRotate90CCW);
+ }
+
+ static dng_orientation Mirror ()
+ {
+ return AdobeToDNG (kMirror);
+ }
+
+ static dng_orientation Mirror90CW ()
+ {
+ return AdobeToDNG (kMirror90CW);
+ }
+
+ static dng_orientation Mirror180 ()
+ {
+ return AdobeToDNG (kMirror180);
+ }
+
+ static dng_orientation Mirror90CCW ()
+ {
+ return AdobeToDNG (kMirror90CCW);
+ }
+
+ static dng_orientation Unknown ()
+ {
+ return AdobeToDNG (kUnknown);
+ }
+
+ bool IsValid () const
+ {
+ return fAdobeOrientation < kUnknown;
+ }
+
+ bool NotValid () const
+ {
+ return !IsValid ();
+ }
+
+ bool FlipD () const;
+
+ bool FlipH () const;
+
+ bool FlipV () const;
+
+ bool operator== (const dng_orientation &b) const
+ {
+ return fAdobeOrientation == b.fAdobeOrientation;
+ }
+
+ bool operator!= (const dng_orientation &b) const
+ {
+ return !(*this == b);
+ }
+
+ dng_orientation operator- () const;
+
+ dng_orientation operator+ (const dng_orientation &b) const;
+
+ dng_orientation operator- (const dng_orientation &b) const
+ {
+ return (*this) + (-b);
+ }
+
+ void operator+= (const dng_orientation &b)
+ {
+ *this = *this + b;
+ }
+
+ void operator-= (const dng_orientation &b)
+ {
+ *this = *this - b;
+ }
+
+ };
+
+/******************************************************************************/
+
+#endif
+
+/******************************************************************************/
diff --git a/source/dng_parse_utils.cpp b/source/dng_parse_utils.cpp
index 879efbc..e16748a 100644
--- a/source/dng_parse_utils.cpp
+++ b/source/dng_parse_utils.cpp
@@ -1,3326 +1,3326 @@
-/*****************************************************************************/
-// Copyright 2006-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_parse_utils.cpp#3 $ */
-/* $DateTime: 2012/06/06 12:08:58 $ */
-/* $Change: 833617 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_parse_utils.h"
-
-#include "dng_date_time.h"
-#include "dng_globals.h"
-#include "dng_ifd.h"
-#include "dng_tag_codes.h"
-#include "dng_tag_types.h"
-#include "dng_tag_values.h"
-#include "dng_types.h"
-#include "dng_stream.h"
-#include "dng_exceptions.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-#if qDNGValidate
-
-/*****************************************************************************/
-
-struct dng_name_table
- {
- uint32 key;
- const char *name;
- };
-
-/*****************************************************************************/
-
-static const char * LookupName (uint32 key,
- const dng_name_table *table,
- uint32 table_entries)
- {
-
- for (uint32 index = 0; index < table_entries; index++)
- {
-
- if (key == table [index] . key)
- {
-
- return table [index] . name;
-
- }
-
- }
-
- return NULL;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupParentCode (uint32 parentCode)
- {
-
- const dng_name_table kParentCodeNames [] =
- {
- { 0, "IFD 0" },
- { tcExifIFD, "Exif IFD" },
- { tcGPSInfo, "GPS IFD" },
- { tcInteroperabilityIFD, "Interoperability IFD" },
- { tcKodakDCRPrivateIFD, "Kodak DCR Private IFD" },
- { tcKodakKDCPrivateIFD, "Kodak KDC Private IFD" },
- { tcCanonMakerNote, "Canon MakerNote" },
- { tcEpsonMakerNote, "Epson MakerNote" },
- { tcFujiMakerNote, "Fuji MakerNote" },
- { tcHasselbladMakerNote, "Hasselblad MakerNote" },
- { tcKodakMakerNote, "Kodak MakerNote" },
- { tcKodakMakerNote65280, "Kodak MakerNote 65280" },
- { tcLeicaMakerNote, "Leica MakerNote" },
- { tcMamiyaMakerNote, "Mamiya MakerNote" },
- { tcMinoltaMakerNote, "Minolta MakerNote" },
- { tcNikonMakerNote, "Nikon MakerNote" },
- { tcOlympusMakerNote, "Olympus MakerNote" },
- { tcOlympusMakerNote8208, "Olympus MakerNote 8208" },
- { tcOlympusMakerNote8224, "Olympus MakerNote 8224" },
- { tcOlympusMakerNote8240, "Olympus MakerNote 8240" },
- { tcOlympusMakerNote8256, "Olympus MakerNote 8256" },
- { tcOlympusMakerNote8272, "Olympus MakerNote 8272" },
- { tcOlympusMakerNote12288, "Olympus MakerNote 12288" },
- { tcPanasonicMakerNote, "Panasonic MakerNote" },
- { tcPentaxMakerNote, "Pentax MakerNote" },
- { tcPhaseOneMakerNote, "Phase One MakerNote" },
- { tcRicohMakerNote, "Ricoh MakerNote" },
- { tcRicohMakerNoteCameraInfo, "Ricoh MakerNote Camera Info" },
- { tcSonyMakerNote, "Sony MakerNote" },
- { tcSonyMakerNoteSubInfo, "Sony MakerNote SubInfo" },
- { tcSonyPrivateIFD1, "Sony Private IFD 1" },
- { tcSonyPrivateIFD2, "Sony Private IFD 2" },
- { tcSonyPrivateIFD3A, "Sony Private IFD 3A" },
- { tcSonyPrivateIFD3B, "Sony Private IFD 3B" },
- { tcSonyPrivateIFD3C, "Sony Private IFD 3C" },
- { tcCanonCRW, "Canon CRW" },
- { tcContaxRAW, "Contax RAW" },
- { tcFujiRAF, "Fuji RAF" },
- { tcLeafMOS, "Leaf MOS" },
- { tcMinoltaMRW, "Minolta MRW" },
- { tcPanasonicRAW, "Panasonic RAW" },
- { tcFoveonX3F, "Foveon X3F" },
- { tcJPEG, "JPEG" },
- { tcAdobePSD, "Adobe PSD" }
- };
-
- const char *name = LookupName (parentCode,
- kParentCodeNames,
- sizeof (kParentCodeNames ) /
- sizeof (kParentCodeNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- if (parentCode >= tcFirstSubIFD &&
- parentCode <= tcLastSubIFD)
- {
-
- sprintf (s, "SubIFD %u", (unsigned) (parentCode - tcFirstSubIFD + 1));
-
- }
-
- else if (parentCode >= tcFirstChainedIFD &&
- parentCode <= tcLastChainedIFD)
- {
-
- sprintf (s, "Chained IFD %u", (unsigned) (parentCode - tcFirstChainedIFD + 1));
-
- }
-
- else
- {
-
- sprintf (s, "ParentIFD %u", (unsigned) parentCode);
-
- }
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupTagCode (uint32 parentCode,
- uint32 tagCode)
- {
-
- const dng_name_table kTagNames [] =
- {
- { tcNewSubFileType, "NewSubFileType" },
- { tcSubFileType, "SubFileType" },
- { tcImageWidth, "ImageWidth" },
- { tcImageLength, "ImageLength" },
- { tcBitsPerSample, "BitsPerSample" },
- { tcCompression, "Compression" },
- { tcPhotometricInterpretation, "PhotometricInterpretation" },
- { tcThresholding, "Thresholding" },
- { tcCellWidth, "CellWidth" },
- { tcCellLength, "CellLength" },
- { tcFillOrder, "FillOrder" },
- { tcImageDescription, "ImageDescription" },
- { tcMake, "Make" },
- { tcModel, "Model" },
- { tcStripOffsets, "StripOffsets" },
- { tcOrientation, "Orientation" },
- { tcSamplesPerPixel, "SamplesPerPixel" },
- { tcRowsPerStrip, "RowsPerStrip" },
- { tcStripByteCounts, "StripByteCounts" },
- { tcMinSampleValue, "MinSampleValue" },
- { tcMaxSampleValue, "MaxSampleValue" },
- { tcXResolution, "XResolution" },
- { tcYResolution, "YResolution" },
- { tcPlanarConfiguration, "PlanarConfiguration" },
- { tcFreeOffsets, "FreeOffsets" },
- { tcFreeByteCounts, "FreeByteCounts" },
- { tcGrayResponseUnit, "GrayResponseUnit" },
- { tcGrayResponseCurve, "GrayResponseCurve" },
- { tcResolutionUnit, "ResolutionUnit" },
- { tcTransferFunction, "TransferFunction" },
- { tcSoftware, "Software" },
- { tcDateTime, "DateTime" },
- { tcArtist, "Artist" },
- { tcHostComputer, "HostComputer" },
- { tcWhitePoint, "WhitePoint" },
- { tcPrimaryChromaticities, "PrimaryChromaticities" },
- { tcColorMap, "ColorMap" },
- { tcTileWidth, "TileWidth" },
- { tcTileLength, "TileLength" },
- { tcTileOffsets, "TileOffsets" },
- { tcTileByteCounts, "TileByteCounts" },
- { tcSubIFDs, "SubIFDs" },
- { tcExtraSamples, "ExtraSamples" },
- { tcSampleFormat, "SampleFormat" },
- { tcJPEGTables, "JPEGTables" },
- { tcJPEGProc, "JPEGProc" },
- { tcJPEGInterchangeFormat, "JPEGInterchangeFormat" },
- { tcJPEGInterchangeFormatLength, "JPEGInterchangeFormatLength" },
- { tcYCbCrCoefficients, "YCbCrCoefficients" },
- { tcYCbCrSubSampling, "YCbCrSubSampling" },
- { tcYCbCrPositioning, "YCbCrPositioning" },
- { tcReferenceBlackWhite, "ReferenceBlackWhite" },
- { tcXMP, "XMP" },
- { tcKodakCameraSerialNumber, "KodakCameraSerialNumber" },
- { tcCFARepeatPatternDim, "CFARepeatPatternDim" },
- { tcCFAPattern, "CFAPattern" },
- { tcBatteryLevel, "BatteryLevel" },
- { tcKodakDCRPrivateIFD, "KodakDCRPrivateIFD" },
- { tcCopyright, "Copyright" },
- { tcExposureTime, "ExposureTime" },
- { tcFNumber, "FNumber" },
- { tcIPTC_NAA, "IPTC/NAA" },
- { tcLeafPKTS, "LeafPKTS" },
- { tcAdobeData, "AdobeData" },
- { tcExifIFD, "ExifIFD" },
- { tcICCProfile, "ICCProfile" },
- { tcExposureProgram, "ExposureProgram" },
- { tcSpectralSensitivity, "SpectralSensitivity" },
- { tcGPSInfo, "GPSInfo" },
- { tcISOSpeedRatings, "ISOSpeedRatings" },
- { tcOECF, "OECF" },
- { tcInterlace, "Interlace" },
- { tcTimeZoneOffset, "TimeZoneOffset" },
- { tcSelfTimerMode, "SelfTimerMode" },
- { tcSensitivityType, "SensitivityType" },
- { tcStandardOutputSensitivity, "StandardOutputSensitivity" },
- { tcRecommendedExposureIndex, "RecommendedExposureIndex" },
- { tcISOSpeed, "ISOSpeed" },
- { tcISOSpeedLatitudeyyy, "ISOSpeedLatitudeyyy" },
- { tcISOSpeedLatitudezzz, "ISOSpeedLatitudezzz" },
- { tcExifVersion, "ExifVersion" },
- { tcDateTimeOriginal, "DateTimeOriginal" },
- { tcDateTimeDigitized, "DateTimeDigitized" },
- { tcComponentsConfiguration, "ComponentsConfiguration" },
- { tcCompressedBitsPerPixel, "CompressedBitsPerPixel" },
- { tcShutterSpeedValue, "ShutterSpeedValue" },
- { tcApertureValue, "ApertureValue" },
- { tcBrightnessValue, "BrightnessValue" },
- { tcExposureBiasValue, "ExposureBiasValue" },
- { tcMaxApertureValue, "MaxApertureValue" },
- { tcSubjectDistance, "SubjectDistance" },
- { tcMeteringMode, "MeteringMode" },
- { tcLightSource, "LightSource" },
- { tcFlash, "Flash" },
- { tcFocalLength, "FocalLength" },
- { tcFlashEnergy, "FlashEnergy" },
- { tcSpatialFrequencyResponse, "SpatialFrequencyResponse" },
- { tcNoise, "Noise" },
- { tcFocalPlaneXResolution, "FocalPlaneXResolution" },
- { tcFocalPlaneYResolution, "FocalPlaneYResolution" },
- { tcFocalPlaneResolutionUnit, "FocalPlaneResolutionUnit" },
- { tcImageNumber, "ImageNumber" },
- { tcSecurityClassification, "SecurityClassification" },
- { tcImageHistory, "ImageHistory" },
- { tcSubjectArea, "SubjectArea" },
- { tcExposureIndex, "ExposureIndex" },
- { tcTIFF_EP_StandardID, "TIFF/EPStandardID" },
- { tcSensingMethod, "SensingMethod" },
- { tcMakerNote, "MakerNote" },
- { tcUserComment, "UserComment" },
- { tcSubsecTime, "SubsecTime" },
- { tcSubsecTimeOriginal, "SubsecTimeOriginal" },
- { tcSubsecTimeDigitized, "SubsecTimeDigitized" },
- { tcAdobeLayerData, "AdobeLayerData" },
- { tcFlashPixVersion, "FlashPixVersion" },
- { tcColorSpace, "ColorSpace" },
- { tcPixelXDimension, "PixelXDimension" },
- { tcPixelYDimension, "PixelYDimension" },
- { tcRelatedSoundFile, "RelatedSoundFile" },
- { tcInteroperabilityIFD, "InteroperabilityIFD" },
- { tcFlashEnergyExif, "FlashEnergyExif" },
- { tcSpatialFrequencyResponseExif, "SpatialFrequencyResponseExif" },
- { tcFocalPlaneXResolutionExif, "FocalPlaneXResolutionExif" },
- { tcFocalPlaneYResolutionExif, "FocalPlaneYResolutionExif" },
- { tcFocalPlaneResolutionUnitExif, "FocalPlaneResolutionUnitExif" },
- { tcSubjectLocation, "SubjectLocation" },
- { tcExposureIndexExif, "ExposureIndexExif" },
- { tcSensingMethodExif, "SensingMethodExif" },
- { tcFileSource, "FileSource" },
- { tcSceneType, "SceneType" },
- { tcCFAPatternExif, "CFAPatternExif" },
- { tcCustomRendered, "CustomRendered" },
- { tcExposureMode, "ExposureMode" },
- { tcWhiteBalance, "WhiteBalance" },
- { tcDigitalZoomRatio, "DigitalZoomRatio" },
- { tcFocalLengthIn35mmFilm, "FocalLengthIn35mmFilm" },
- { tcSceneCaptureType, "SceneCaptureType" },
- { tcGainControl, "GainControl" },
- { tcContrast, "Contrast" },
- { tcSaturation, "Saturation" },
- { tcSharpness, "Sharpness" },
- { tcDeviceSettingDescription, "DeviceSettingDescription" },
- { tcSubjectDistanceRange, "SubjectDistanceRange" },
- { tcImageUniqueID, "ImageUniqueID" },
- { tcCameraOwnerNameExif, "CameraOwnerNameExif" },
- { tcCameraSerialNumberExif, "CameraSerialNumberExif" },
- { tcLensSpecificationExif, "LensSpecificationExif" },
- { tcLensMakeExif, "LensMakeExif" },
- { tcLensModelExif, "LensModelExif" },
- { tcLensSerialNumberExif, "LensSerialNumberExif" },
- { tcGamma, "Gamma" },
- { tcPrintImageMatchingInfo, "PrintImageMatchingInfo" },
- { tcDNGVersion, "DNGVersion" },
- { tcDNGBackwardVersion, "DNGBackwardVersion" },
- { tcUniqueCameraModel, "UniqueCameraModel" },
- { tcLocalizedCameraModel, "LocalizedCameraModel" },
- { tcCFAPlaneColor, "CFAPlaneColor" },
- { tcCFALayout, "CFALayout" },
- { tcLinearizationTable, "LinearizationTable" },
- { tcBlackLevelRepeatDim, "BlackLevelRepeatDim" },
- { tcBlackLevel, "BlackLevel" },
- { tcBlackLevelDeltaH, "BlackLevelDeltaH" },
- { tcBlackLevelDeltaV, "BlackLevelDeltaV" },
- { tcWhiteLevel, "WhiteLevel" },
- { tcDefaultScale, "DefaultScale" },
- { tcDefaultCropOrigin, "DefaultCropOrigin" },
- { tcDefaultCropSize, "DefaultCropSize" },
- { tcDefaultUserCrop, "DefaultUserCrop" },
- { tcColorMatrix1, "ColorMatrix1" },
- { tcColorMatrix2, "ColorMatrix2" },
- { tcCameraCalibration1, "CameraCalibration1" },
- { tcCameraCalibration2, "CameraCalibration2" },
- { tcReductionMatrix1, "ReductionMatrix1" },
- { tcReductionMatrix2, "ReductionMatrix2" },
- { tcAnalogBalance, "AnalogBalance" },
- { tcAsShotNeutral, "AsShotNeutral" },
- { tcAsShotWhiteXY, "AsShotWhiteXY" },
- { tcBaselineExposure, "BaselineExposure" },
- { tcBaselineNoise, "BaselineNoise" },
- { tcBaselineSharpness, "BaselineSharpness" },
- { tcBayerGreenSplit, "BayerGreenSplit" },
- { tcLinearResponseLimit, "LinearResponseLimit" },
- { tcCameraSerialNumber, "CameraSerialNumber" },
- { tcLensInfo, "LensInfo" },
- { tcChromaBlurRadius, "ChromaBlurRadius" },
- { tcAntiAliasStrength, "AntiAliasStrength" },
- { tcShadowScale, "ShadowScale" },
- { tcDNGPrivateData, "DNGPrivateData" },
- { tcMakerNoteSafety, "MakerNoteSafety" },
- { tcCalibrationIlluminant1, "CalibrationIlluminant1" },
- { tcCalibrationIlluminant2, "CalibrationIlluminant2" },
- { tcBestQualityScale, "BestQualityScale" },
- { tcRawDataUniqueID, "RawDataUniqueID" },
- { tcOriginalRawFileName, "OriginalRawFileName" },
- { tcOriginalRawFileData, "OriginalRawFileData" },
- { tcActiveArea, "ActiveArea" },
- { tcMaskedAreas, "MaskedAreas" },
- { tcAsShotICCProfile, "AsShotICCProfile" },
- { tcAsShotPreProfileMatrix, "AsShotPreProfileMatrix" },
- { tcCurrentICCProfile, "CurrentICCProfile" },
- { tcCurrentPreProfileMatrix, "CurrentPreProfileMatrix" },
- { tcColorimetricReference, "ColorimetricReference" },
- { tcCameraCalibrationSignature, "CameraCalibrationSignature" },
- { tcProfileCalibrationSignature, "ProfileCalibrationSignature" },
- { tcExtraCameraProfiles, "ExtraCameraProfiles" },
- { tcAsShotProfileName, "AsShotProfileName" },
- { tcNoiseReductionApplied, "NoiseReductionApplied" },
- { tcProfileName, "ProfileName" },
- { tcProfileHueSatMapDims, "ProfileHueSatMapDims" },
- { tcProfileHueSatMapData1, "ProfileHueSatMapData1" },
- { tcProfileHueSatMapData2, "ProfileHueSatMapData2" },
- { tcProfileHueSatMapEncoding, "ProfileHueSatMapEncoding" },
- { tcProfileToneCurve, "ProfileToneCurve" },
- { tcProfileEmbedPolicy, "ProfileEmbedPolicy" },
- { tcProfileCopyright, "ProfileCopyright" },
- { tcForwardMatrix1, "ForwardMatrix1" },
- { tcForwardMatrix2, "ForwardMatrix2" },
- { tcPreviewApplicationName, "PreviewApplicationName" },
- { tcPreviewApplicationVersion, "PreviewApplicationVersion" },
- { tcPreviewSettingsName, "PreviewSettingsName" },
- { tcPreviewSettingsDigest, "PreviewSettingsDigest" },
- { tcPreviewColorSpace, "PreviewColorSpace" },
- { tcPreviewDateTime, "PreviewDateTime" },
- { tcRawImageDigest, "RawImageDigest" },
- { tcOriginalRawFileDigest, "OriginalRawFileDigest" },
- { tcSubTileBlockSize, "SubTileBlockSize" },
- { tcRowInterleaveFactor, "RowInterleaveFactor" },
- { tcProfileLookTableDims, "ProfileLookTableDims" },
- { tcProfileLookTableData, "ProfileLookTableData" },
- { tcProfileLookTableEncoding, "ProfileLookTableEncoding" },
- { tcBaselineExposureOffset, "BaselineExposureOffset" },
- { tcDefaultBlackRender, "DefaultBlackRender" },
- { tcOpcodeList1, "OpcodeList1" },
- { tcOpcodeList2, "OpcodeList2" },
- { tcOpcodeList3, "OpcodeList3" },
- { tcNoiseProfile, "NoiseProfile" },
- { tcOriginalDefaultFinalSize, "OriginalDefaultFinalSize" },
- { tcOriginalBestQualityFinalSize, "OriginalBestQualityFinalSize" },
- { tcOriginalDefaultCropSize, "OriginalDefaultCropSize" },
- { tcProfileHueSatMapEncoding, "ProfileHueSatMapEncoding" },
- { tcProfileLookTableEncoding, "ProfileLookTableEncoding" },
- { tcBaselineExposureOffset, "BaselineExposureOffset" },
- { tcDefaultBlackRender, "DefaultBlackRender" },
- { tcNewRawImageDigest, "NewRawImageDigest" },
- { tcRawToPreviewGain, "RawToPreviewGain" },
- { tcCacheBlob, "CacheBlob" },
- { tcKodakKDCPrivateIFD, "KodakKDCPrivateIFD" }
- };
-
- const dng_name_table kGPSTagNames [] =
- {
- { tcGPSVersionID, "GPSVersionID" },
- { tcGPSLatitudeRef, "GPSLatitudeRef" },
- { tcGPSLatitude, "GPSLatitude" },
- { tcGPSLongitudeRef, "GPSLongitudeRef" },
- { tcGPSLongitude, "GPSLongitude" },
- { tcGPSAltitudeRef, "GPSAltitudeRef" },
- { tcGPSAltitude, "GPSAltitude" },
- { tcGPSTimeStamp, "GPSTimeStamp" },
- { tcGPSSatellites, "GPSSatellites" },
- { tcGPSStatus, "GPSStatus" },
- { tcGPSMeasureMode, "GPSMeasureMode" },
- { tcGPSDOP, "GPSDOP" },
- { tcGPSSpeedRef, "GPSSpeedRef" },
- { tcGPSSpeed, "GPSSpeed" },
- { tcGPSTrackRef, "GPSTrackRef" },
- { tcGPSTrack, "GPSTrack" },
- { tcGPSImgDirectionRef, "GPSImgDirectionRef" },
- { tcGPSImgDirection, "GPSImgDirection" },
- { tcGPSMapDatum, "GPSMapDatum" },
- { tcGPSDestLatitudeRef, "GPSDestLatitudeRef" },
- { tcGPSDestLatitude, "GPSDestLatitude" },
- { tcGPSDestLongitudeRef, "GPSDestLongitudeRef" },
- { tcGPSDestLongitude, "GPSDestLongitude" },
- { tcGPSDestBearingRef, "GPSDestBearingRef" },
- { tcGPSDestBearing, "GPSDestBearing" },
- { tcGPSDestDistanceRef, "GPSDestDistanceRef" },
- { tcGPSDestDistance, "GPSDestDistance" },
- { tcGPSProcessingMethod, "GPSProcessingMethod" },
- { tcGPSAreaInformation, "GPSAreaInformation" },
- { tcGPSDateStamp, "GPSDateStamp" },
- { tcGPSDifferential, "GPSDifferential" },
- { tcGPSHPositioningError, "GPSHPositioningError" },
- };
-
- const dng_name_table kInteroperabilityTagNames [] =
- {
- { tcInteroperabilityIndex, "InteroperabilityIndex" },
- { tcInteroperabilityVersion, "InteroperabilityVersion" },
- { tcRelatedImageFileFormat, "RelatedImageFileFormat" },
- { tcRelatedImageWidth, "RelatedImageWidth" },
- { tcRelatedImageLength, "RelatedImageLength" }
- };
-
- const dng_name_table kFujiTagNames [] =
- {
- { tcFujiHeader, "FujiHeader" },
- { tcFujiRawInfo1, "FujiRawInfo1" },
- { tcFujiRawInfo2, "FujiRawInfo2" }
- };
-
- const dng_name_table kContaxTagNames [] =
- {
- { tcContaxHeader, "ContaxHeader" }
- };
-
- const char *name = NULL;
-
- if (parentCode == 0 ||
- parentCode == tcExifIFD ||
- parentCode == tcLeafMOS ||
- (parentCode >= tcFirstSubIFD && parentCode <= tcLastSubIFD) ||
- (parentCode >= tcFirstChainedIFD && parentCode <= tcLastChainedIFD))
- {
-
- name = LookupName (tagCode,
- kTagNames,
- sizeof (kTagNames ) /
- sizeof (kTagNames [0]));
-
- }
-
- else if (parentCode == tcGPSInfo)
- {
-
- name = LookupName (tagCode,
- kGPSTagNames,
- sizeof (kGPSTagNames ) /
- sizeof (kGPSTagNames [0]));
-
- }
-
- else if (parentCode == tcInteroperabilityIFD)
- {
-
- name = LookupName (tagCode,
- kInteroperabilityTagNames,
- sizeof (kInteroperabilityTagNames ) /
- sizeof (kInteroperabilityTagNames [0]));
-
- }
-
- else if (parentCode == tcFujiRAF)
- {
-
- name = LookupName (tagCode,
- kFujiTagNames,
- sizeof (kFujiTagNames ) /
- sizeof (kFujiTagNames [0]));
-
- }
-
- else if (parentCode == tcContaxRAW)
- {
-
- name = LookupName (tagCode,
- kContaxTagNames,
- sizeof (kContaxTagNames ) /
- sizeof (kContaxTagNames [0]));
-
- }
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- if (parentCode == tcCanonCRW)
- {
- sprintf (s, "CRW_%04X", (unsigned) tagCode);
- }
-
- else if (parentCode == tcMinoltaMRW)
- {
-
- char c1 = (char) ((tagCode >> 24) & 0xFF);
- char c2 = (char) ((tagCode >> 16) & 0xFF);
- char c3 = (char) ((tagCode >> 8) & 0xFF);
- char c4 = (char) ((tagCode ) & 0xFF);
-
- if (c1 < ' ') c1 = '_';
- if (c2 < ' ') c2 = '_';
- if (c3 < ' ') c3 = '_';
- if (c4 < ' ') c4 = '_';
-
- sprintf (s, "MRW%c%c%c%c", c1, c2, c3, c4);
-
- }
-
- else if (parentCode == tcFujiRawInfo1)
- {
- sprintf (s, "RAF1_%04X", (unsigned) tagCode);
- }
-
- else if (parentCode == tcFujiRawInfo2)
- {
- sprintf (s, "RAF2_%04X", (unsigned) tagCode);
- }
-
- else
- {
- sprintf (s, "Tag%u", (unsigned) tagCode);
- }
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupTagType (uint32 tagType)
- {
-
- const dng_name_table kTagTypeNames [] =
- {
- { ttByte, "Byte" },
- { ttAscii, "ASCII" },
- { ttShort, "Short" },
- { ttLong, "Long" },
- { ttRational, "Rational" },
- { ttSByte, "SByte" },
- { ttUndefined, "Undefined" },
- { ttSShort, "SShort" },
- { ttSLong, "SLong" },
- { ttSRational, "SRational" },
- { ttFloat, "Float" },
- { ttDouble, "Double" },
- { ttIFD, "IFD" },
- { ttUnicode, "Unicode" },
- { ttComplex, "Complex" }
- };
-
- const char *name = LookupName (tagType,
- kTagTypeNames,
- sizeof (kTagTypeNames ) /
- sizeof (kTagTypeNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "Type%u", (unsigned) tagType);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupNewSubFileType (uint32 key)
- {
-
- const dng_name_table kNewSubFileTypeNames [] =
- {
- { sfMainImage , "Main Image" },
- { sfPreviewImage , "Preview Image" },
- { sfTransparencyMask , "Transparency Mask" },
- { sfPreviewMask , "Preview Mask" },
- { sfAltPreviewImage , "Alt Preview Image" }
- };
-
- const char *name = LookupName (key,
- kNewSubFileTypeNames,
- sizeof (kNewSubFileTypeNames ) /
- sizeof (kNewSubFileTypeNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupCompression (uint32 key)
- {
-
- const dng_name_table kCompressionNames [] =
- {
- { ccUncompressed, "Uncompressed" },
- { ccLZW, "LZW" },
- { ccOldJPEG, "Old JPEG" },
- { ccJPEG, "JPEG" },
- { ccDeflate, "Deflate" },
- { ccPackBits, "PackBits" },
- { ccOldDeflate, "OldDeflate" },
- { ccLossyJPEG, "Lossy JPEG" }
- };
-
- const char *name = LookupName (key,
- kCompressionNames,
- sizeof (kCompressionNames ) /
- sizeof (kCompressionNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupPredictor (uint32 key)
- {
-
- const dng_name_table kPredictorNames [] =
- {
- { cpNullPredictor, "NullPredictor" },
- { cpHorizontalDifference, "HorizontalDifference" },
- { cpFloatingPoint, "FloatingPoint" },
- { cpHorizontalDifferenceX2, "HorizontalDifferenceX2" },
- { cpHorizontalDifferenceX4, "HorizontalDifferenceX4" },
- { cpFloatingPointX2, "FloatingPointX2" },
- { cpFloatingPointX4, "FloatingPointX4" }
- };
-
- const char *name = LookupName (key,
- kPredictorNames,
- sizeof (kPredictorNames ) /
- sizeof (kPredictorNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupSampleFormat (uint32 key)
- {
-
- const dng_name_table kSampleFormatNames [] =
- {
- { sfUnsignedInteger, "UnsignedInteger" },
- { sfSignedInteger, "SignedInteger" },
- { sfFloatingPoint, "FloatingPoint" },
- { sfUndefined, "Undefined" }
- };
-
- const char *name = LookupName (key,
- kSampleFormatNames,
- sizeof (kSampleFormatNames ) /
- sizeof (kSampleFormatNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupPhotometricInterpretation (uint32 key)
- {
-
- const dng_name_table kPhotometricInterpretationNames [] =
- {
- { piWhiteIsZero, "WhiteIsZero" },
- { piBlackIsZero, "BlackIsZero" },
- { piRGB, "RGB" },
- { piRGBPalette, "RGBPalette" },
- { piTransparencyMask, "TransparencyMask" },
- { piCMYK, "CMYK" },
- { piYCbCr, "YCbCr" },
- { piCIELab, "CIELab" },
- { piICCLab, "ICCLab" },
- { piCFA, "CFA" },
- { piLinearRaw, "LinearRaw" }
- };
-
- const char *name = LookupName (key,
- kPhotometricInterpretationNames,
- sizeof (kPhotometricInterpretationNames ) /
- sizeof (kPhotometricInterpretationNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupOrientation (uint32 key)
- {
-
- const dng_name_table kOrientationNames [] =
- {
- { 1, "1 - 0th row is top, 0th column is left" },
- { 2, "2 - 0th row is top, 0th column is right" },
- { 3, "3 - 0th row is bottom, 0th column is right" },
- { 4, "4 - 0th row is bottom, 0th column is left" },
- { 5, "5 - 0th row is left, 0th column is top" },
- { 6, "6 - 0th row is right, 0th column is top" },
- { 7, "7 - 0th row is right, 0th column is bottom" },
- { 8, "8 - 0th row is left, 0th column is bottom" },
- { 9, "9 - unknown" }
- };
-
- const char *name = LookupName (key,
- kOrientationNames,
- sizeof (kOrientationNames ) /
- sizeof (kOrientationNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupResolutionUnit (uint32 key)
- {
-
- const dng_name_table kResolutionUnitNames [] =
- {
- { ruNone, "None" },
- { ruInch, "Inch" },
- { ruCM, "cm" },
- { ruMM, "mm" },
- { ruMicroM, "Micrometer" }
- };
-
- const char *name = LookupName (key,
- kResolutionUnitNames,
- sizeof (kResolutionUnitNames ) /
- sizeof (kResolutionUnitNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupCFAColor (uint32 key)
- {
-
- const dng_name_table kCFAColorNames [] =
- {
- { 0, "Red" },
- { 1, "Green" },
- { 2, "Blue" },
- { 3, "Cyan" },
- { 4, "Magenta" },
- { 5, "Yellow" },
- { 6, "White" }
- };
-
- const char *name = LookupName (key,
- kCFAColorNames,
- sizeof (kCFAColorNames ) /
- sizeof (kCFAColorNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "Color%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupSensingMethod (uint32 key)
- {
-
- const dng_name_table kSensingMethodNames [] =
- {
- { 0, "Undefined" },
- { 1, "MonochromeArea" },
- { 2, "OneChipColorArea" },
- { 3, "TwoChipColorArea" },
- { 4, "ThreeChipColorArea" },
- { 5, "ColorSequentialArea" },
- { 6, "MonochromeLinear" },
- { 7, "TriLinear" },
- { 8, "ColorSequentialLinear" }
- };
-
- const char *name = LookupName (key,
- kSensingMethodNames,
- sizeof (kSensingMethodNames ) /
- sizeof (kSensingMethodNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupExposureProgram (uint32 key)
- {
-
- const dng_name_table kExposureProgramNames [] =
- {
- { epUnidentified, "Unidentified" },
- { epManual, "Manual" },
- { epProgramNormal, "Program Normal" },
- { epAperturePriority, "Aperture Priority" },
- { epShutterPriority, "Shutter Priority" },
- { epProgramCreative, "Program Creative" },
- { epProgramAction, "Program Action" },
- { epPortraitMode, "Portrait Mode" },
- { epLandscapeMode, "Landscape Mode" }
- };
-
- const char *name = LookupName (key,
- kExposureProgramNames,
- sizeof (kExposureProgramNames ) /
- sizeof (kExposureProgramNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupMeteringMode (uint32 key)
- {
-
- const dng_name_table kMeteringModeNames [] =
- {
- { mmUnidentified, "Unknown" },
- { mmAverage, "Average" },
- { mmCenterWeightedAverage, "CenterWeightedAverage" },
- { mmSpot, "Spot" },
- { mmMultiSpot, "MultiSpot" },
- { mmPattern, "Pattern" },
- { mmPartial, "Partial" },
- { mmOther, "Other" }
- };
-
- const char *name = LookupName (key,
- kMeteringModeNames,
- sizeof (kMeteringModeNames ) /
- sizeof (kMeteringModeNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupLightSource (uint32 key)
- {
-
- const dng_name_table kLightSourceNames [] =
- {
- { lsUnknown, "Unknown" },
- { lsDaylight, "Daylight" },
- { lsFluorescent, "Fluorescent" },
- { lsTungsten, "Tungsten (incandescent light)" },
- { lsFlash, "Flash" },
- { lsFineWeather, "Fine weather" },
- { lsCloudyWeather, "Cloudy weather" },
- { lsShade, "Shade" },
- { lsDaylightFluorescent, "Daylight fluorescent (D 5700 - 7100K)" },
- { lsDayWhiteFluorescent, "Day white fluorescent (N 4600 - 5500K)" },
- { lsCoolWhiteFluorescent, "Cool white fluorescent (W 3800 - 4500K)" },
- { lsWhiteFluorescent, "White fluorescent (WW 3250 - 3800K)" },
- { lsWarmWhiteFluorescent, "Warm white fluorescent (L 2600 - 3250K)" },
- { lsStandardLightA, "Standard light A" },
- { lsStandardLightB, "Standard light B" },
- { lsStandardLightC, "Standard light C" },
- { lsD55, "D55" },
- { lsD65, "D65" },
- { lsD75, "D75" },
- { lsD50, "D50" },
- { lsISOStudioTungsten, "ISO studio tungsten" },
- { lsOther, "Other" }
- };
-
- const char *name = LookupName (key,
- kLightSourceNames,
- sizeof (kLightSourceNames ) /
- sizeof (kLightSourceNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- if (key & 0x08000)
- {
-
- sprintf (s, "%uK", (unsigned) (key & 0x7FFF));
-
- }
-
- else
- {
-
- sprintf (s, "%u", (unsigned) key);
-
- }
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupColorSpace (uint32 key)
- {
-
- const dng_name_table kColorSpaceNames [] =
- {
- { 1, "sRGB" },
- { 0xFFFF, "Uncalibrated" }
- };
-
- const char *name = LookupName (key,
- kColorSpaceNames,
- sizeof (kColorSpaceNames ) /
- sizeof (kColorSpaceNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupFileSource (uint32 key)
- {
-
- const dng_name_table kFileSourceNames [] =
- {
- { 3, "DSC" }
- };
-
- const char *name = LookupName (key,
- kFileSourceNames,
- sizeof (kFileSourceNames ) /
- sizeof (kFileSourceNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupSceneType (uint32 key)
- {
-
- const dng_name_table kSceneTypeNames [] =
- {
- { 1, "A directly photographed image" }
- };
-
- const char *name = LookupName (key,
- kSceneTypeNames,
- sizeof (kSceneTypeNames ) /
- sizeof (kSceneTypeNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupCustomRendered (uint32 key)
- {
-
- const dng_name_table kCustomRenderedNames [] =
- {
- { 0, "Normal process" },
- { 1, "Custom process" }
- };
-
- const char *name = LookupName (key,
- kCustomRenderedNames,
- sizeof (kCustomRenderedNames ) /
- sizeof (kCustomRenderedNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupExposureMode (uint32 key)
- {
-
- const dng_name_table kExposureModeNames [] =
- {
- { 0, "Auto exposure" },
- { 1, "Manual exposure" },
- { 2, "Auto bracket" }
- };
-
- const char *name = LookupName (key,
- kExposureModeNames,
- sizeof (kExposureModeNames ) /
- sizeof (kExposureModeNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupWhiteBalance (uint32 key)
- {
-
- const dng_name_table kWhiteBalanceNames [] =
- {
- { 0, "Auto white balance" },
- { 1, "Manual white balance" }
- };
-
- const char *name = LookupName (key,
- kWhiteBalanceNames,
- sizeof (kWhiteBalanceNames ) /
- sizeof (kWhiteBalanceNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupSceneCaptureType (uint32 key)
- {
-
- const dng_name_table kSceneCaptureTypeNames [] =
- {
- { 0, "Standard" },
- { 1, "Landscape" },
- { 2, "Portrait" },
- { 3, "Night scene" }
- };
-
- const char *name = LookupName (key,
- kSceneCaptureTypeNames,
- sizeof (kSceneCaptureTypeNames ) /
- sizeof (kSceneCaptureTypeNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupGainControl (uint32 key)
- {
-
- const dng_name_table kGainControlNames [] =
- {
- { 0, "None" },
- { 1, "Low gain up" },
- { 2, "High gain up" },
- { 3, "Low gain down" },
- { 4, "High gain down" }
- };
-
- const char *name = LookupName (key,
- kGainControlNames,
- sizeof (kGainControlNames ) /
- sizeof (kGainControlNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupContrast (uint32 key)
- {
-
- const dng_name_table kContrastNames [] =
- {
- { 0, "Normal" },
- { 1, "Soft" },
- { 2, "Hard" }
- };
-
- const char *name = LookupName (key,
- kContrastNames,
- sizeof (kContrastNames ) /
- sizeof (kContrastNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupSaturation (uint32 key)
- {
-
- const dng_name_table kSaturationNames [] =
- {
- { 0, "Normal" },
- { 1, "Low saturation" },
- { 2, "High saturation" }
- };
-
- const char *name = LookupName (key,
- kSaturationNames,
- sizeof (kSaturationNames ) /
- sizeof (kSaturationNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupSharpness (uint32 key)
- {
-
- const dng_name_table kSharpnessNames [] =
- {
- { 0, "Normal" },
- { 1, "Soft" },
- { 2, "Hard" }
- };
-
- const char *name = LookupName (key,
- kSharpnessNames,
- sizeof (kSharpnessNames ) /
- sizeof (kSharpnessNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupSubjectDistanceRange (uint32 key)
- {
-
- const dng_name_table kSubjectDistanceRangeNames [] =
- {
- { 0, "Unknown" },
- { 1, "Macro" },
- { 2, "Close view" },
- { 3, "Distant view" }
- };
-
- const char *name = LookupName (key,
- kSubjectDistanceRangeNames,
- sizeof (kSubjectDistanceRangeNames ) /
- sizeof (kSubjectDistanceRangeNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupComponent (uint32 key)
- {
-
- const dng_name_table kComponentNames [] =
- {
- { 0, "-" },
- { 1, "Y" },
- { 2, "Cb" },
- { 3, "Cr" },
- { 4, "R" },
- { 5, "G" },
- { 6, "B" }
- };
-
- const char *name = LookupName (key,
- kComponentNames,
- sizeof (kComponentNames ) /
- sizeof (kComponentNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupCFALayout (uint32 key)
- {
-
- const dng_name_table kCFALayoutNames [] =
- {
- { 1, "Rectangular (or square) layout" },
- { 2, "Staggered layout A: even columns are offset down by 1/2 row" },
- { 3, "Staggered layout B: even columns are offset up by 1/2 row" },
- { 4, "Staggered layout C: even rows are offset right by 1/2 column" },
- { 5, "Staggered layout D: even rows are offset left by 1/2 column" },
- { 6, "Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column" },
- { 7, "Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column" },
- { 8, "Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column" },
- { 9, "Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column" }
- };
-
- const char *name = LookupName (key,
- kCFALayoutNames,
- sizeof (kCFALayoutNames ) /
- sizeof (kCFALayoutNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupMakerNoteSafety (uint32 key)
- {
-
- const dng_name_table kMakerNoteSafetyNames [] =
- {
- { 0, "Unsafe" },
- { 1, "Safe" }
- };
-
- const char *name = LookupName (key,
- kMakerNoteSafetyNames,
- sizeof (kMakerNoteSafetyNames ) /
- sizeof (kMakerNoteSafetyNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupColorimetricReference (uint32 key)
- {
-
- const dng_name_table kColorimetricReferenceNames [] =
- {
- { crSceneReferred, "Scene Referred" },
- { crICCProfilePCS, "ICC Profile PCS" }
- };
-
- const char *name = LookupName (key,
- kColorimetricReferenceNames,
- sizeof (kColorimetricReferenceNames ) /
- sizeof (kColorimetricReferenceNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupPreviewColorSpace (uint32 key)
- {
-
- const dng_name_table kPreviewColorSpaceNames [] =
- {
- { previewColorSpace_Unknown , "Unknown" },
- { previewColorSpace_GrayGamma22, "Gray Gamma 2.2" },
- { previewColorSpace_sRGB , "sRGB" },
- { previewColorSpace_AdobeRGB , "Adobe RGB (1998)" },
- { previewColorSpace_ProPhotoRGB, "Pro Photo RGB" }
- };
-
- const char *name = LookupName (key,
- kPreviewColorSpaceNames,
- sizeof (kPreviewColorSpaceNames ) /
- sizeof (kPreviewColorSpaceNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupJPEGMarker (uint32 key)
- {
-
- const dng_name_table kJPEGMarkerNames [] =
- {
- { M_TEM, "TEM" },
- { M_SOF0, "SOF0" },
- { M_SOF1, "SOF1" },
- { M_SOF2, "SOF2" },
- { M_SOF3, "SOF3" },
- { M_DHT, "DHT" },
- { M_SOF5, "SOF5" },
- { M_SOF6, "SOF6" },
- { M_SOF7, "SOF7" },
- { M_JPG, "JPG" },
- { M_SOF9, "SOF9" },
- { M_SOF10, "SOF10" },
- { M_SOF11, "SOF11" },
- { M_DAC, "DAC" },
- { M_SOF13, "SOF13" },
- { M_SOF14, "SOF14" },
- { M_SOF15, "SOF15" },
- { M_RST0, "RST0" },
- { M_RST1, "RST1" },
- { M_RST2, "RST2" },
- { M_RST3, "RST3" },
- { M_RST4, "RST4" },
- { M_RST5, "RST5" },
- { M_RST6, "RST6" },
- { M_RST7, "RST7" },
- { M_SOI, "SOI" },
- { M_EOI, "EOI" },
- { M_SOS, "SOS" },
- { M_DQT, "DQT" },
- { M_DNL, "DNL" },
- { M_DRI, "DRI" },
- { M_DHP, "DHP" },
- { M_EXP, "EXP" },
- { M_APP0, "APP0" },
- { M_APP1, "APP1" },
- { M_APP2, "APP2" },
- { M_APP3, "APP3" },
- { M_APP4, "APP4" },
- { M_APP5, "APP5" },
- { M_APP6, "APP6" },
- { M_APP7, "APP7" },
- { M_APP8, "APP8" },
- { M_APP9, "APP9" },
- { M_APP10, "APP10" },
- { M_APP11, "APP11" },
- { M_APP12, "APP12" },
- { M_APP13, "APP13" },
- { M_APP14, "APP14" },
- { M_APP15, "APP15" },
- { M_JPG0, "JPG0" },
- { M_JPG1, "JPG1" },
- { M_JPG2, "JPG2" },
- { M_JPG3, "JPG3" },
- { M_JPG4, "JPG4" },
- { M_JPG5, "JPG5" },
- { M_JPG6, "JPG6" },
- { M_JPG7, "JPG7" },
- { M_JPG8, "JPG8" },
- { M_JPG9, "JPG9" },
- { M_JPG10, "JPG10" },
- { M_JPG11, "JPG11" },
- { M_JPG12, "JPG12" },
- { M_JPG13, "JPG13" },
- { M_COM, "COM" },
- { M_ERROR, "ERROR" }
- };
-
- const char *name = LookupName (key,
- kJPEGMarkerNames,
- sizeof (kJPEGMarkerNames ) /
- sizeof (kJPEGMarkerNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "0x%02X", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-const char * LookupSensitivityType (uint32 key)
- {
-
- const dng_name_table kSensitivityTypeNames [] =
- {
- { stUnknown, "Unknown" },
- { stStandardOutputSensitivity, "Standard Output Sensitivity (SOS)" },
- { stRecommendedExposureIndex, "Recommended Exposure Index (REI)" },
- { stISOSpeed, "ISO Speed" },
- { stSOSandREI, "Standard Output Sensitivity (SOS) and Recommended Exposure Index (REI)" },
- { stSOSandISOSpeed, "Standard Output Sensitivity (SOS) and ISO Speed" },
- { stREIandISOSpeed, "Recommended Exposure Index (REI) and ISO Speed" },
- { stSOSandREIandISOSpeed, "Standard Output Sensitivity (SOS) and Recommended Exposure Index (REI) and ISO Speed" },
- };
-
- const char *name = LookupName (key,
- kSensitivityTypeNames,
- sizeof (kSensitivityTypeNames ) /
- sizeof (kSensitivityTypeNames [0]));
-
- if (name)
- {
- return name;
- }
-
- static char s [32];
-
- sprintf (s, "%u", (unsigned) key);
-
- return s;
-
- }
-
-/*****************************************************************************/
-
-void DumpHexAscii (dng_stream &stream,
- uint32 count)
- {
-
- uint32 rows = (count + 15) >> 4;
-
- if (rows > gDumpLineLimit)
- rows = gDumpLineLimit;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- printf (" ");
-
- uint32 col;
-
- uint32 cols = count - (row << 4);
-
- if (cols > 16)
- cols = 16;
-
- uint8 x [16];
-
- for (col = 0; col < 16; col++)
- {
-
- x [col] = ' ';
-
- if (col < cols)
- {
-
- x [col] = stream.Get_uint8 ();
-
- printf ("%02x ", x [col]);
-
- }
-
- else
- {
- printf (" ");
- }
-
- }
-
- printf (" ");
-
- for (col = 0; col < 16; col++)
- {
-
- if (x [col] >= (uint8) ' ' && x [col] <= (uint8) '~')
- {
- printf ("%c", x [col]);
- }
-
- else
- {
- printf (".");
- }
-
- }
-
- printf ("\n");
-
- }
-
- if (count > rows * 16)
- {
- printf (" ... %u more bytes\n", (unsigned) (count - rows * 16));
- }
-
- }
-
-/*****************************************************************************/
-
-void DumpHexAscii (const uint8 *buf,
- uint32 count)
- {
-
- uint32 rows = (count + 15) >> 4;
-
- if (rows > gDumpLineLimit)
- rows = gDumpLineLimit;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- printf (" ");
-
- uint32 col;
-
- uint32 cols = count - (row << 4);
-
- if (cols > 16)
- cols = 16;
-
- uint8 x [16];
-
- for (col = 0; col < 16; col++)
- {
-
- x [col] = ' ';
-
- if (col < cols)
- {
-
- x [col] = *(buf++);
-
- printf ("%02x ", x [col]);
-
- }
-
- else
- {
- printf (" ");
- }
-
- }
-
- printf (" ");
-
- for (col = 0; col < 16; col++)
- {
-
- if (x [col] >= (uint8) ' ' && x [col] <= (uint8) '~')
- {
- printf ("%c", x [col]);
- }
-
- else
- {
- printf (".");
- }
-
- }
-
- printf ("\n");
-
- }
-
- if (count > rows * 16)
- {
- printf (" ... %u more bytes\n", (unsigned) (count - rows * 16));
- }
-
- }
-
-/*****************************************************************************/
-
-void DumpXMP (dng_stream &stream,
- uint32 count)
- {
-
- uint32 lineLength = 0;
-
- while (count > 0)
- {
-
- uint32 x = stream.Get_uint8 ();
-
- if (x == 0) break;
-
- count--;
-
- if (lineLength == 0)
- {
-
- printf ("XMP: ");
-
- lineLength = 5;
-
- }
-
- if (x == '\n' ||
- x == '\r')
- {
-
- printf ("\n");
-
- lineLength = 0;
-
- }
-
- else
- {
-
- if (lineLength >= 128)
- {
-
- printf ("\nXMP: ");
-
- lineLength = 5;
-
- }
-
- if (x >= ' ' && x <= '~')
- {
-
- printf ("%c", (char) x);
-
- lineLength += 1;
-
- }
-
- else
- {
-
- printf ("\\%03o", (unsigned) x);
-
- lineLength += 4;
-
- }
-
- }
-
- }
-
- if (lineLength != 0)
- {
-
- printf ("\n");
-
- }
-
- }
-
-/*****************************************************************************/
-
-void DumpString (const dng_string &s)
- {
-
- const uint32 kMaxDumpString = gDumpLineLimit * 64;
-
- printf ("\"");
-
- const char *ss = s.Get ();
-
- uint32 total = 0;
-
- while (*ss != 0 && total++ < kMaxDumpString)
- {
-
- uint32 c = dng_string::DecodeUTF8 (ss);
-
- if (c >= ' ' && c <= '~')
- {
- printf ("%c", (char) c);
- }
-
- else switch (c)
- {
-
- case '\t':
- {
- printf ("\\t");
- break;
- }
-
- case '\n':
- {
- printf ("\\n");
- break;
- }
-
- case '\r':
- {
- printf ("\\r");
- break;
- }
-
- default:
- {
- printf ("[%X]", (unsigned) c);
- }
-
- }
-
- }
-
- uint32 extra = (uint32) strlen (ss);
-
- if (extra > 0)
- {
- printf ("...\" (%u more bytes)", (unsigned) extra);
- }
-
- else
- {
- printf ("\"");
- }
-
- }
-
-/*****************************************************************************/
-
-void DumpTagValues (dng_stream &stream,
- const char *entry_name,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- const char *tag_name)
- {
-
- const uint32 kMaxDumpSingleLine = 4;
-
- const uint32 kMaxDumpArray = Max_uint32 (gDumpLineLimit, kMaxDumpSingleLine);
-
- printf ("%s:", tag_name ? tag_name
- : LookupTagCode (parentCode, tagCode));
-
- switch (tagType)
- {
-
- case ttShort:
- case ttLong:
- case ttIFD:
- case ttSByte:
- case ttSShort:
- case ttSLong:
- case ttRational:
- case ttSRational:
- case ttFloat:
- case ttDouble:
- {
-
- if (tagCount > kMaxDumpSingleLine)
- {
-
- printf (" %u entries", (unsigned) tagCount);
-
- }
-
- for (uint32 j = 0; j < tagCount && j < kMaxDumpArray; j++)
- {
-
- if (tagCount <= kMaxDumpSingleLine)
- {
-
- if (j == 0)
- {
-
- printf (" %s =", entry_name);
-
- }
-
- printf (" ");
-
- }
-
- else
- {
-
- printf ("\n %s [%u] = ", entry_name, (unsigned) j);
-
- }
-
- switch (tagType)
- {
-
- case ttByte:
- case ttShort:
- case ttLong:
- case ttIFD:
- {
-
- uint32 x = stream.TagValue_uint32 (tagType);
-
- printf ("%u", (unsigned) x);
-
- break;
-
- }
-
- case ttSByte:
- case ttSShort:
- case ttSLong:
- {
-
- int32 x = stream.TagValue_int32 (tagType);
-
- printf ("%d", (int) x);
-
- break;
-
- }
-
- case ttRational:
- {
-
- dng_urational x = stream.TagValue_urational (tagType);
-
- printf ("%u/%u", (unsigned) x.n, (unsigned) x.d);
-
- break;
-
- }
-
- case ttSRational:
- {
-
- dng_srational x = stream.TagValue_srational (tagType);
-
- printf ("%d/%d", (int) x.n, (int) x.d);
-
- break;
-
- }
-
- default:
- {
-
- real64 x = stream.TagValue_real64 (tagType);
-
- printf ("%f", x);
-
- }
-
- }
-
- }
-
- printf ("\n");
-
- if (tagCount > kMaxDumpArray)
- {
-
- printf (" ... %u more entries\n", (unsigned) (tagCount - kMaxDumpArray));
-
- }
-
- break;
-
- }
-
- case ttAscii:
- {
-
- dng_string s;
-
- ParseStringTag (stream,
- parentCode,
- tagCode,
- tagCount,
- s,
- false);
-
- printf (" ");
-
- DumpString (s);
-
- printf ("\n");
-
- break;
-
- }
-
- default:
- {
-
- uint32 tagSize = tagCount * TagTypeSize (tagType);
-
- if (tagCount == 1 && (tagType == ttByte ||
- tagType == ttUndefined))
- {
-
- uint8 x = stream.Get_uint8 ();
-
- printf (" %s = %u\n", LookupTagType (tagType), x);
-
- }
-
- else
- {
-
- printf (" %s, size = %u\n", LookupTagType (tagType), (unsigned) tagSize);
-
- DumpHexAscii (stream, tagSize);
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void DumpMatrix (const dng_matrix &m)
- {
-
- for (uint32 row = 0; row < m.Rows (); row++)
- {
-
- for (uint32 col = 0; col < m.Cols (); col++)
- {
-
- if (col == 0)
- printf (" ");
- else
- printf (" ");
-
- printf ("%8.4f", m [row] [col]);
-
- }
-
- printf ("\n");
-
- }
-
- }
-
-/*****************************************************************************/
-
-void DumpVector (const dng_vector &v)
- {
-
- for (uint32 index = 0; index < v.Count (); index++)
- {
-
- printf (" %0.4f", v [index]);
-
- }
-
- printf ("\n");
-
- }
-
-/*****************************************************************************/
-
-void DumpDateTime (const dng_date_time &dt)
- {
-
- printf ("%04d:%02d:%02d %02d:%02d:%02d",
- (int) dt.fYear,
- (int) dt.fMonth,
- (int) dt.fDay,
- (int) dt.fHour,
- (int) dt.fMinute,
- (int) dt.fSecond);
-
- }
-
-/*****************************************************************************/
-
-void DumpExposureTime (real64 x)
- {
-
- if (x > 0.0)
- {
-
- if (x >= 0.25)
- {
- printf ("%0.2f sec", x);
- }
-
- else if (x >= 0.01)
- {
- printf ("1/%0.1f sec", 1.0 / x);
- }
-
- else
- {
- printf ("1/%0.0f sec", 1.0 / x);
- }
-
- }
-
- else
- {
-
- printf ("<invalid>");
-
- }
-
- }
-
-/*****************************************************************************/
-
-void DumpFingerprint (const dng_fingerprint &p)
- {
-
- printf ("<");
-
- for (uint32 j = 0; j < 16; j++)
- {
- printf ("%02x", p.data [j]);
- }
-
- printf (">");
-
- }
-
-/*****************************************************************************/
-
-void DumpHueSatMap (dng_stream &stream,
- uint32 hues,
- uint32 sats,
- uint32 vals,
- bool skipSat0)
- {
-
- uint32 doneLines = 0;
- uint32 skipLines = 0;
-
- for (uint32 v = 0; v < vals; v++)
- {
-
- for (uint32 h = 0; h < hues; h++)
- {
-
- for (uint32 s = skipSat0 ? 1 : 0; s < sats; s++)
- {
-
- real32 dh = stream.Get_real32 ();
- real32 ds = stream.Get_real32 ();
- real32 dv = stream.Get_real32 ();
-
- if (gDumpLineLimit == 0 ||
- gDumpLineLimit > doneLines)
- {
-
- doneLines++;
-
- if (vals == 1)
- {
-
- printf (" h [%2u] s [%2u]: h=%8.4f s=%6.4f v=%6.4f\n",
- (unsigned) h,
- (unsigned) s,
- (double) dh,
- (double) ds,
- (double) dv);
-
- }
-
- else
- {
-
- printf (" v [%2u] h [%2u] s [%2u]: h=%8.4f s=%6.4f v=%6.4f\n",
- (unsigned) v,
- (unsigned) h,
- (unsigned) s,
- (double) dh,
- (double) ds,
- (double) dv);
-
- }
-
- }
-
- else
- {
-
- skipLines++;
-
- }
-
- }
-
- }
-
- }
-
- if (skipLines > 0)
- {
-
- printf (" ... %u more entries\n", (unsigned) skipLines);
-
- }
-
- }
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
-
-bool CheckTagType (uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint16 validType0,
- uint16 validType1,
- uint16 validType2,
- uint16 validType3)
- {
-
- if (tagType != validType0 &&
- tagType != validType1 &&
- tagType != validType2 &&
- tagType != validType3)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s has unexpected type (%s)",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode),
- LookupTagType (tagType));
-
- ReportWarning (message);
-
- }
-
- #else
-
- (void) parentCode; // Unused
- (void) tagCode; // Unused
-
- #endif
-
- return false;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool CheckTagCount (uint32 parentCode,
- uint32 tagCode,
- uint32 tagCount,
- uint32 minCount,
- uint32 maxCount)
- {
-
- if (maxCount < minCount)
- maxCount = minCount;
-
- if (tagCount < minCount ||
- tagCount > maxCount)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s has unexpected count (%u)",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode),
- (unsigned) tagCount);
-
- ReportWarning (message);
-
- }
-
- #else
-
- (void) parentCode; // Unused
- (void) tagCode; // Unused
-
- #endif
-
- return false;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool CheckColorImage (uint32 parentCode,
- uint32 tagCode,
- uint32 colorPlanes)
- {
-
- if (colorPlanes == 0)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not allowed with unknown color plane count "
- " (missing ColorMatrix1 tag?)",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #else
-
- (void) parentCode; // Unused
- (void) tagCode; // Unused
-
- #endif
-
- return false;
-
- }
-
- if (colorPlanes == 1)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not allowed with monochrome images",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #endif
-
- return false;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool CheckMainIFD (uint32 parentCode,
- uint32 tagCode,
- uint32 newSubFileType)
- {
-
- if (newSubFileType != sfMainImage)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not allowed IFDs with NewSubFileType != 0",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #else
-
- (void) parentCode; // Unused
- (void) tagCode; // Unused
-
- #endif
-
- return false;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool CheckRawIFD (uint32 parentCode,
- uint32 tagCode,
- uint32 photometricInterpretation)
- {
-
- if (photometricInterpretation != piCFA &&
- photometricInterpretation != piLinearRaw)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not allowed in IFDs with a non-raw PhotometricInterpretation",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #else
-
- (void) parentCode; // Unused
- (void) tagCode; // Unused
-
- #endif
-
- return false;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool CheckCFA (uint32 parentCode,
- uint32 tagCode,
- uint32 photometricInterpretation)
- {
-
- if (photometricInterpretation != piCFA)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not allowed in IFDs with a non-CFA PhotometricInterpretation",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #else
-
- (void) parentCode; // Unused
- (void) tagCode; // Unused
-
- #endif
-
- return false;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-void ParseStringTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagCount,
- dng_string &s,
- bool trimBlanks)
- {
-
- if (tagCount == 0 ||
- tagCount == 0xFFFFFFFF)
- {
-
- s.Clear ();
-
- return;
-
- }
-
- dng_memory_data temp_buffer (tagCount + 1);
-
- char *buffer = temp_buffer.Buffer_char ();
-
- stream.Get (buffer, tagCount);
-
- // Make sure the string is null terminated.
-
- if (buffer [tagCount - 1] != 0)
- {
-
- buffer [tagCount] = 0;
-
- #if qDNGValidate
-
- {
-
- bool hasNull = false;
-
- for (uint32 j = 0; j < tagCount; j++)
- {
-
- if (buffer [j] == 0)
- {
-
- hasNull = true;
-
- break;
-
- }
-
- }
-
- if (!hasNull && parentCode < tcFirstMakerNoteIFD)
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not NULL terminated",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- }
-
- #else
-
- (void) parentCode; // Unused
- (void) tagCode; // Unused
-
- #endif
-
- }
-
- // Medata working group - Allow UTF-8
-
- s.Set_UTF8_or_System (buffer);
-
- if (trimBlanks)
- {
-
- s.TrimTrailingBlanks ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-void ParseDualStringTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagCount,
- dng_string &s1,
- dng_string &s2)
- {
-
- if (tagCount == 0 ||
- tagCount == 0xFFFFFFFF)
- {
-
- s1.Clear ();
- s2.Clear ();
-
- return;
-
- }
-
- dng_memory_data temp_buffer (tagCount + 1);
-
- char *buffer = temp_buffer.Buffer_char ();
-
- stream.Get (buffer, tagCount);
-
- // Make sure the string is null terminated.
-
- if (buffer [tagCount - 1] != 0)
- {
-
- buffer [tagCount] = 0;
-
- #if qDNGValidate
-
- {
-
- uint32 nullCount = 0;
-
- for (uint32 j = 0; j < tagCount; j++)
- {
-
- if (buffer [j] == 0)
- {
-
- nullCount++;
-
- }
-
- }
-
- if (nullCount < 2 && parentCode < tcFirstMakerNoteIFD)
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not NULL terminated",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- }
-
- #else
-
- (void) parentCode; // Unused
- (void) tagCode; // Unused
-
- #endif
-
- }
-
- // Medata working group - Allow UTF-8
-
- s1.Set_UTF8_or_System (buffer);
-
- s2.Set_ASCII (NULL);
-
- for (uint32 j = 1; j < tagCount - 1; j++)
- {
-
- if (buffer [j - 1] != 0 &&
- buffer [j ] == 0)
- {
-
- // Medata working group - Allow UTF-8
-
- s2.Set_UTF8_or_System (buffer + j + 1);
-
- break;
-
- }
-
- }
-
- s1.TrimTrailingBlanks ();
- s2.TrimTrailingBlanks ();
-
- }
-
-/*****************************************************************************/
-
-void ParseEncodedStringTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagCount,
- dng_string &s)
- {
-
- if (tagCount < 8)
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s has unexpected count (%u)",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode),
- (unsigned) tagCount);
-
- ReportWarning (message);
-
- }
-
- #else
-
- (void) parentCode; // Unused
- (void) tagCode; // Unused
-
- #endif
-
- s.Clear ();
-
- return;
-
- }
-
- char label [8];
-
- stream.Get (label, 8);
-
- // Sometimes lowercase is used by mistake. Accept this, but issue
- // warning.
-
- {
-
- bool hadLower = false;
-
- for (uint32 j = 0; j < 8; j++)
- {
-
- if (label [j] >= 'a' && label [j] <= 'z')
- {
-
- label [j] = 'A' + (label [j] - 'a');
-
- hadLower = true;
-
- }
-
- }
-
- #if qDNGValidate
-
- if (hadLower)
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s text encoding label not all uppercase",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #endif
-
- }
-
- if (memcmp (label, "UNICODE\000", 8) == 0)
- {
-
- uint32 uChars = (tagCount - 8) >> 1;
-
- dng_memory_data temp_buffer ((uChars + 1) * 2);
-
- uint16 *buffer = temp_buffer.Buffer_uint16 ();
-
- for (uint32 j = 0; j < uChars; j++)
- {
-
- buffer [j] = stream.Get_uint16 ();
-
- }
-
- buffer [uChars] = 0;
-
- #if qDNGValidate
-
- {
-
- // If the writer used UTF-8 rather than UTF-16, and padded
- // the string with blanks, then there will be lots of 0x2020
- // (unicode dagger symbol) characters in the string.
-
- uint32 count2020 = 0;
-
- for (uint32 k = 0; buffer [k] != 0; k++)
- {
-
- if (buffer [k] == 0x2020)
- {
-
- count2020++;
-
- }
-
- }
-
- if (count2020 > 1)
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s text appears to be UTF-8 rather than UTF-16",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- }
-
- #endif
-
- s.Set_UTF16 (buffer);
-
- }
-
- else
- {
-
- uint32 aChars = tagCount - 8;
-
- dng_memory_data temp_buffer (aChars + 1);
-
- char *buffer = temp_buffer.Buffer_char ();
-
- stream.Get (buffer, aChars);
-
- buffer [aChars] = 0;
-
- enum dng_encoding
- {
- dng_encoding_ascii,
- dng_encoding_jis_x208_1990,
- dng_encoding_unknown
- };
-
- dng_encoding encoding = dng_encoding_unknown;
-
- if (memcmp (label, "ASCII\000\000\000", 8) == 0)
- {
-
- encoding = dng_encoding_ascii;
-
- }
-
- else if (memcmp (label, "JIS\000\000\000\000\000\000", 8) == 0)
- {
-
- encoding = dng_encoding_jis_x208_1990;
-
- }
-
- else
- {
-
- // Some Nikon D1 files have UserComment tags with zero encoding bits and
- // garbage text values. So don't try to parse tags with unknown text
- // encoding unless all the characters are printing ASCII.
-
- #if qDNGValidate
-
- if (memcmp (label, "\000\000\000\000\000\000\000\000\000", 8) == 0)
- {
-
- // Many camera makes store null tags with all zero encoding, so
- // don't report a warning message for null strings.
-
- if (buffer [0] != 0)
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s has unknown encoding",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- }
-
- else
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s has unexpected text encoding",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #endif
-
- }
-
- // If text encoding was unknown, and the text is anything
- // other than pure ASCII, then ignore it.
-
- if (encoding == dng_encoding_unknown)
- {
-
- encoding = dng_encoding_ascii;
-
- for (uint32 i = 0; i < aChars && buffer [i] != 0; i++)
- {
-
- if (buffer [i] < ' ' ||
- buffer [i] > '~')
- {
-
- buffer [0] = 0;
-
- break;
-
- }
-
- }
-
- }
-
- switch (encoding)
- {
-
- case dng_encoding_ascii:
- {
-
- // Medata working group - allow UTF-8 for ASCII tags.
-
- s.Set_UTF8_or_System (buffer);
-
- break;
-
- }
-
- case dng_encoding_jis_x208_1990:
- {
- s.Set_JIS_X208_1990 (buffer);
- break;
- }
-
- case dng_encoding_unknown:
- {
- s.Set_SystemEncoding (buffer);
- break;
- }
-
- default:
- break;
-
- }
-
- #if qDNGValidate
-
- {
-
- if (encoding == dng_encoding_ascii && !s.IsASCII ())
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s has non-ASCII characters",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- }
-
- #endif
-
- }
-
- s.TrimTrailingBlanks ();
-
- }
-
-/*****************************************************************************/
-
-bool ParseMatrixTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint32 rows,
- uint32 cols,
- dng_matrix &m)
- {
-
- if (CheckTagCount (parentCode, tagCode, tagCount, rows * cols))
- {
-
- dng_matrix temp (rows, cols);
-
- for (uint32 row = 0; row < rows; row++)
- for (uint32 col = 0; col < cols; col++)
- {
-
- temp [row] [col] = stream.TagValue_real64 (tagType);
-
- }
-
- m = temp;
-
- return true;
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-bool ParseVectorTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint32 count,
- dng_vector &v)
- {
-
- if (CheckTagCount (parentCode, tagCode, tagCount, count))
- {
-
- dng_vector temp (count);
-
- for (uint32 index = 0; index < count; index++)
- {
-
- temp [index] = stream.TagValue_real64 (tagType);
-
- }
-
- v = temp;
-
- return true;
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-bool ParseDateTimeTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- dng_date_time &dt)
- {
-
- if (!CheckTagType (parentCode, tagCode, tagType, ttAscii))
- {
- return false;
- }
-
- // Kludge: Some versions of PaintShop Pro write these fields
- // with a length of 21 rather than 20. Otherwise they are
- // correctly formated. So relax this test and allow these
- // these longer than standard tags to be parsed.
-
- (void) CheckTagCount (parentCode, tagCode, tagCount, 20);
-
- if (tagCount < 20)
- {
- return false;
- }
-
- char s [21];
-
- stream.Get (s, 20);
-
- s [20] = 0;
-
- // See if this is a valid date/time string.
-
- if (dt.Parse (s))
- {
- return true;
- }
-
- // Accept strings that contain only blanks, colons, and zeros as
- // valid "null" dates.
-
- dt = dng_date_time ();
-
- for (uint32 index = 0; index < 21; index++)
- {
-
- char c = s [index];
-
- if (c == 0)
- {
- return true;
- }
-
- if (c != ' ' && c != ':' && c != '0')
- {
-
- #if qDNGValidate
-
- {
-
- char message [256];
-
- sprintf (message,
- "%s %s is not a valid date/time",
- LookupParentCode (parentCode),
- LookupTagCode (parentCode, tagCode));
-
- ReportWarning (message);
-
- }
-
- #endif
-
- return false;
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_parse_utils.cpp#3 $ */
+/* $DateTime: 2012/06/06 12:08:58 $ */
+/* $Change: 833617 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_parse_utils.h"
+
+#include "dng_date_time.h"
+#include "dng_globals.h"
+#include "dng_ifd.h"
+#include "dng_tag_codes.h"
+#include "dng_tag_types.h"
+#include "dng_tag_values.h"
+#include "dng_types.h"
+#include "dng_stream.h"
+#include "dng_exceptions.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+#if qDNGValidate
+
+/*****************************************************************************/
+
+struct dng_name_table
+ {
+ uint32 key;
+ const char *name;
+ };
+
+/*****************************************************************************/
+
+static const char * LookupName (uint32 key,
+ const dng_name_table *table,
+ uint32 table_entries)
+ {
+
+ for (uint32 index = 0; index < table_entries; index++)
+ {
+
+ if (key == table [index] . key)
+ {
+
+ return table [index] . name;
+
+ }
+
+ }
+
+ return NULL;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupParentCode (uint32 parentCode)
+ {
+
+ const dng_name_table kParentCodeNames [] =
+ {
+ { 0, "IFD 0" },
+ { tcExifIFD, "Exif IFD" },
+ { tcGPSInfo, "GPS IFD" },
+ { tcInteroperabilityIFD, "Interoperability IFD" },
+ { tcKodakDCRPrivateIFD, "Kodak DCR Private IFD" },
+ { tcKodakKDCPrivateIFD, "Kodak KDC Private IFD" },
+ { tcCanonMakerNote, "Canon MakerNote" },
+ { tcEpsonMakerNote, "Epson MakerNote" },
+ { tcFujiMakerNote, "Fuji MakerNote" },
+ { tcHasselbladMakerNote, "Hasselblad MakerNote" },
+ { tcKodakMakerNote, "Kodak MakerNote" },
+ { tcKodakMakerNote65280, "Kodak MakerNote 65280" },
+ { tcLeicaMakerNote, "Leica MakerNote" },
+ { tcMamiyaMakerNote, "Mamiya MakerNote" },
+ { tcMinoltaMakerNote, "Minolta MakerNote" },
+ { tcNikonMakerNote, "Nikon MakerNote" },
+ { tcOlympusMakerNote, "Olympus MakerNote" },
+ { tcOlympusMakerNote8208, "Olympus MakerNote 8208" },
+ { tcOlympusMakerNote8224, "Olympus MakerNote 8224" },
+ { tcOlympusMakerNote8240, "Olympus MakerNote 8240" },
+ { tcOlympusMakerNote8256, "Olympus MakerNote 8256" },
+ { tcOlympusMakerNote8272, "Olympus MakerNote 8272" },
+ { tcOlympusMakerNote12288, "Olympus MakerNote 12288" },
+ { tcPanasonicMakerNote, "Panasonic MakerNote" },
+ { tcPentaxMakerNote, "Pentax MakerNote" },
+ { tcPhaseOneMakerNote, "Phase One MakerNote" },
+ { tcRicohMakerNote, "Ricoh MakerNote" },
+ { tcRicohMakerNoteCameraInfo, "Ricoh MakerNote Camera Info" },
+ { tcSonyMakerNote, "Sony MakerNote" },
+ { tcSonyMakerNoteSubInfo, "Sony MakerNote SubInfo" },
+ { tcSonyPrivateIFD1, "Sony Private IFD 1" },
+ { tcSonyPrivateIFD2, "Sony Private IFD 2" },
+ { tcSonyPrivateIFD3A, "Sony Private IFD 3A" },
+ { tcSonyPrivateIFD3B, "Sony Private IFD 3B" },
+ { tcSonyPrivateIFD3C, "Sony Private IFD 3C" },
+ { tcCanonCRW, "Canon CRW" },
+ { tcContaxRAW, "Contax RAW" },
+ { tcFujiRAF, "Fuji RAF" },
+ { tcLeafMOS, "Leaf MOS" },
+ { tcMinoltaMRW, "Minolta MRW" },
+ { tcPanasonicRAW, "Panasonic RAW" },
+ { tcFoveonX3F, "Foveon X3F" },
+ { tcJPEG, "JPEG" },
+ { tcAdobePSD, "Adobe PSD" }
+ };
+
+ const char *name = LookupName (parentCode,
+ kParentCodeNames,
+ sizeof (kParentCodeNames ) /
+ sizeof (kParentCodeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ if (parentCode >= tcFirstSubIFD &&
+ parentCode <= tcLastSubIFD)
+ {
+
+ sprintf (s, "SubIFD %u", (unsigned) (parentCode - tcFirstSubIFD + 1));
+
+ }
+
+ else if (parentCode >= tcFirstChainedIFD &&
+ parentCode <= tcLastChainedIFD)
+ {
+
+ sprintf (s, "Chained IFD %u", (unsigned) (parentCode - tcFirstChainedIFD + 1));
+
+ }
+
+ else
+ {
+
+ sprintf (s, "ParentIFD %u", (unsigned) parentCode);
+
+ }
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupTagCode (uint32 parentCode,
+ uint32 tagCode)
+ {
+
+ const dng_name_table kTagNames [] =
+ {
+ { tcNewSubFileType, "NewSubFileType" },
+ { tcSubFileType, "SubFileType" },
+ { tcImageWidth, "ImageWidth" },
+ { tcImageLength, "ImageLength" },
+ { tcBitsPerSample, "BitsPerSample" },
+ { tcCompression, "Compression" },
+ { tcPhotometricInterpretation, "PhotometricInterpretation" },
+ { tcThresholding, "Thresholding" },
+ { tcCellWidth, "CellWidth" },
+ { tcCellLength, "CellLength" },
+ { tcFillOrder, "FillOrder" },
+ { tcImageDescription, "ImageDescription" },
+ { tcMake, "Make" },
+ { tcModel, "Model" },
+ { tcStripOffsets, "StripOffsets" },
+ { tcOrientation, "Orientation" },
+ { tcSamplesPerPixel, "SamplesPerPixel" },
+ { tcRowsPerStrip, "RowsPerStrip" },
+ { tcStripByteCounts, "StripByteCounts" },
+ { tcMinSampleValue, "MinSampleValue" },
+ { tcMaxSampleValue, "MaxSampleValue" },
+ { tcXResolution, "XResolution" },
+ { tcYResolution, "YResolution" },
+ { tcPlanarConfiguration, "PlanarConfiguration" },
+ { tcFreeOffsets, "FreeOffsets" },
+ { tcFreeByteCounts, "FreeByteCounts" },
+ { tcGrayResponseUnit, "GrayResponseUnit" },
+ { tcGrayResponseCurve, "GrayResponseCurve" },
+ { tcResolutionUnit, "ResolutionUnit" },
+ { tcTransferFunction, "TransferFunction" },
+ { tcSoftware, "Software" },
+ { tcDateTime, "DateTime" },
+ { tcArtist, "Artist" },
+ { tcHostComputer, "HostComputer" },
+ { tcWhitePoint, "WhitePoint" },
+ { tcPrimaryChromaticities, "PrimaryChromaticities" },
+ { tcColorMap, "ColorMap" },
+ { tcTileWidth, "TileWidth" },
+ { tcTileLength, "TileLength" },
+ { tcTileOffsets, "TileOffsets" },
+ { tcTileByteCounts, "TileByteCounts" },
+ { tcSubIFDs, "SubIFDs" },
+ { tcExtraSamples, "ExtraSamples" },
+ { tcSampleFormat, "SampleFormat" },
+ { tcJPEGTables, "JPEGTables" },
+ { tcJPEGProc, "JPEGProc" },
+ { tcJPEGInterchangeFormat, "JPEGInterchangeFormat" },
+ { tcJPEGInterchangeFormatLength, "JPEGInterchangeFormatLength" },
+ { tcYCbCrCoefficients, "YCbCrCoefficients" },
+ { tcYCbCrSubSampling, "YCbCrSubSampling" },
+ { tcYCbCrPositioning, "YCbCrPositioning" },
+ { tcReferenceBlackWhite, "ReferenceBlackWhite" },
+ { tcXMP, "XMP" },
+ { tcKodakCameraSerialNumber, "KodakCameraSerialNumber" },
+ { tcCFARepeatPatternDim, "CFARepeatPatternDim" },
+ { tcCFAPattern, "CFAPattern" },
+ { tcBatteryLevel, "BatteryLevel" },
+ { tcKodakDCRPrivateIFD, "KodakDCRPrivateIFD" },
+ { tcCopyright, "Copyright" },
+ { tcExposureTime, "ExposureTime" },
+ { tcFNumber, "FNumber" },
+ { tcIPTC_NAA, "IPTC/NAA" },
+ { tcLeafPKTS, "LeafPKTS" },
+ { tcAdobeData, "AdobeData" },
+ { tcExifIFD, "ExifIFD" },
+ { tcICCProfile, "ICCProfile" },
+ { tcExposureProgram, "ExposureProgram" },
+ { tcSpectralSensitivity, "SpectralSensitivity" },
+ { tcGPSInfo, "GPSInfo" },
+ { tcISOSpeedRatings, "ISOSpeedRatings" },
+ { tcOECF, "OECF" },
+ { tcInterlace, "Interlace" },
+ { tcTimeZoneOffset, "TimeZoneOffset" },
+ { tcSelfTimerMode, "SelfTimerMode" },
+ { tcSensitivityType, "SensitivityType" },
+ { tcStandardOutputSensitivity, "StandardOutputSensitivity" },
+ { tcRecommendedExposureIndex, "RecommendedExposureIndex" },
+ { tcISOSpeed, "ISOSpeed" },
+ { tcISOSpeedLatitudeyyy, "ISOSpeedLatitudeyyy" },
+ { tcISOSpeedLatitudezzz, "ISOSpeedLatitudezzz" },
+ { tcExifVersion, "ExifVersion" },
+ { tcDateTimeOriginal, "DateTimeOriginal" },
+ { tcDateTimeDigitized, "DateTimeDigitized" },
+ { tcComponentsConfiguration, "ComponentsConfiguration" },
+ { tcCompressedBitsPerPixel, "CompressedBitsPerPixel" },
+ { tcShutterSpeedValue, "ShutterSpeedValue" },
+ { tcApertureValue, "ApertureValue" },
+ { tcBrightnessValue, "BrightnessValue" },
+ { tcExposureBiasValue, "ExposureBiasValue" },
+ { tcMaxApertureValue, "MaxApertureValue" },
+ { tcSubjectDistance, "SubjectDistance" },
+ { tcMeteringMode, "MeteringMode" },
+ { tcLightSource, "LightSource" },
+ { tcFlash, "Flash" },
+ { tcFocalLength, "FocalLength" },
+ { tcFlashEnergy, "FlashEnergy" },
+ { tcSpatialFrequencyResponse, "SpatialFrequencyResponse" },
+ { tcNoise, "Noise" },
+ { tcFocalPlaneXResolution, "FocalPlaneXResolution" },
+ { tcFocalPlaneYResolution, "FocalPlaneYResolution" },
+ { tcFocalPlaneResolutionUnit, "FocalPlaneResolutionUnit" },
+ { tcImageNumber, "ImageNumber" },
+ { tcSecurityClassification, "SecurityClassification" },
+ { tcImageHistory, "ImageHistory" },
+ { tcSubjectArea, "SubjectArea" },
+ { tcExposureIndex, "ExposureIndex" },
+ { tcTIFF_EP_StandardID, "TIFF/EPStandardID" },
+ { tcSensingMethod, "SensingMethod" },
+ { tcMakerNote, "MakerNote" },
+ { tcUserComment, "UserComment" },
+ { tcSubsecTime, "SubsecTime" },
+ { tcSubsecTimeOriginal, "SubsecTimeOriginal" },
+ { tcSubsecTimeDigitized, "SubsecTimeDigitized" },
+ { tcAdobeLayerData, "AdobeLayerData" },
+ { tcFlashPixVersion, "FlashPixVersion" },
+ { tcColorSpace, "ColorSpace" },
+ { tcPixelXDimension, "PixelXDimension" },
+ { tcPixelYDimension, "PixelYDimension" },
+ { tcRelatedSoundFile, "RelatedSoundFile" },
+ { tcInteroperabilityIFD, "InteroperabilityIFD" },
+ { tcFlashEnergyExif, "FlashEnergyExif" },
+ { tcSpatialFrequencyResponseExif, "SpatialFrequencyResponseExif" },
+ { tcFocalPlaneXResolutionExif, "FocalPlaneXResolutionExif" },
+ { tcFocalPlaneYResolutionExif, "FocalPlaneYResolutionExif" },
+ { tcFocalPlaneResolutionUnitExif, "FocalPlaneResolutionUnitExif" },
+ { tcSubjectLocation, "SubjectLocation" },
+ { tcExposureIndexExif, "ExposureIndexExif" },
+ { tcSensingMethodExif, "SensingMethodExif" },
+ { tcFileSource, "FileSource" },
+ { tcSceneType, "SceneType" },
+ { tcCFAPatternExif, "CFAPatternExif" },
+ { tcCustomRendered, "CustomRendered" },
+ { tcExposureMode, "ExposureMode" },
+ { tcWhiteBalance, "WhiteBalance" },
+ { tcDigitalZoomRatio, "DigitalZoomRatio" },
+ { tcFocalLengthIn35mmFilm, "FocalLengthIn35mmFilm" },
+ { tcSceneCaptureType, "SceneCaptureType" },
+ { tcGainControl, "GainControl" },
+ { tcContrast, "Contrast" },
+ { tcSaturation, "Saturation" },
+ { tcSharpness, "Sharpness" },
+ { tcDeviceSettingDescription, "DeviceSettingDescription" },
+ { tcSubjectDistanceRange, "SubjectDistanceRange" },
+ { tcImageUniqueID, "ImageUniqueID" },
+ { tcCameraOwnerNameExif, "CameraOwnerNameExif" },
+ { tcCameraSerialNumberExif, "CameraSerialNumberExif" },
+ { tcLensSpecificationExif, "LensSpecificationExif" },
+ { tcLensMakeExif, "LensMakeExif" },
+ { tcLensModelExif, "LensModelExif" },
+ { tcLensSerialNumberExif, "LensSerialNumberExif" },
+ { tcGamma, "Gamma" },
+ { tcPrintImageMatchingInfo, "PrintImageMatchingInfo" },
+ { tcDNGVersion, "DNGVersion" },
+ { tcDNGBackwardVersion, "DNGBackwardVersion" },
+ { tcUniqueCameraModel, "UniqueCameraModel" },
+ { tcLocalizedCameraModel, "LocalizedCameraModel" },
+ { tcCFAPlaneColor, "CFAPlaneColor" },
+ { tcCFALayout, "CFALayout" },
+ { tcLinearizationTable, "LinearizationTable" },
+ { tcBlackLevelRepeatDim, "BlackLevelRepeatDim" },
+ { tcBlackLevel, "BlackLevel" },
+ { tcBlackLevelDeltaH, "BlackLevelDeltaH" },
+ { tcBlackLevelDeltaV, "BlackLevelDeltaV" },
+ { tcWhiteLevel, "WhiteLevel" },
+ { tcDefaultScale, "DefaultScale" },
+ { tcDefaultCropOrigin, "DefaultCropOrigin" },
+ { tcDefaultCropSize, "DefaultCropSize" },
+ { tcDefaultUserCrop, "DefaultUserCrop" },
+ { tcColorMatrix1, "ColorMatrix1" },
+ { tcColorMatrix2, "ColorMatrix2" },
+ { tcCameraCalibration1, "CameraCalibration1" },
+ { tcCameraCalibration2, "CameraCalibration2" },
+ { tcReductionMatrix1, "ReductionMatrix1" },
+ { tcReductionMatrix2, "ReductionMatrix2" },
+ { tcAnalogBalance, "AnalogBalance" },
+ { tcAsShotNeutral, "AsShotNeutral" },
+ { tcAsShotWhiteXY, "AsShotWhiteXY" },
+ { tcBaselineExposure, "BaselineExposure" },
+ { tcBaselineNoise, "BaselineNoise" },
+ { tcBaselineSharpness, "BaselineSharpness" },
+ { tcBayerGreenSplit, "BayerGreenSplit" },
+ { tcLinearResponseLimit, "LinearResponseLimit" },
+ { tcCameraSerialNumber, "CameraSerialNumber" },
+ { tcLensInfo, "LensInfo" },
+ { tcChromaBlurRadius, "ChromaBlurRadius" },
+ { tcAntiAliasStrength, "AntiAliasStrength" },
+ { tcShadowScale, "ShadowScale" },
+ { tcDNGPrivateData, "DNGPrivateData" },
+ { tcMakerNoteSafety, "MakerNoteSafety" },
+ { tcCalibrationIlluminant1, "CalibrationIlluminant1" },
+ { tcCalibrationIlluminant2, "CalibrationIlluminant2" },
+ { tcBestQualityScale, "BestQualityScale" },
+ { tcRawDataUniqueID, "RawDataUniqueID" },
+ { tcOriginalRawFileName, "OriginalRawFileName" },
+ { tcOriginalRawFileData, "OriginalRawFileData" },
+ { tcActiveArea, "ActiveArea" },
+ { tcMaskedAreas, "MaskedAreas" },
+ { tcAsShotICCProfile, "AsShotICCProfile" },
+ { tcAsShotPreProfileMatrix, "AsShotPreProfileMatrix" },
+ { tcCurrentICCProfile, "CurrentICCProfile" },
+ { tcCurrentPreProfileMatrix, "CurrentPreProfileMatrix" },
+ { tcColorimetricReference, "ColorimetricReference" },
+ { tcCameraCalibrationSignature, "CameraCalibrationSignature" },
+ { tcProfileCalibrationSignature, "ProfileCalibrationSignature" },
+ { tcExtraCameraProfiles, "ExtraCameraProfiles" },
+ { tcAsShotProfileName, "AsShotProfileName" },
+ { tcNoiseReductionApplied, "NoiseReductionApplied" },
+ { tcProfileName, "ProfileName" },
+ { tcProfileHueSatMapDims, "ProfileHueSatMapDims" },
+ { tcProfileHueSatMapData1, "ProfileHueSatMapData1" },
+ { tcProfileHueSatMapData2, "ProfileHueSatMapData2" },
+ { tcProfileHueSatMapEncoding, "ProfileHueSatMapEncoding" },
+ { tcProfileToneCurve, "ProfileToneCurve" },
+ { tcProfileEmbedPolicy, "ProfileEmbedPolicy" },
+ { tcProfileCopyright, "ProfileCopyright" },
+ { tcForwardMatrix1, "ForwardMatrix1" },
+ { tcForwardMatrix2, "ForwardMatrix2" },
+ { tcPreviewApplicationName, "PreviewApplicationName" },
+ { tcPreviewApplicationVersion, "PreviewApplicationVersion" },
+ { tcPreviewSettingsName, "PreviewSettingsName" },
+ { tcPreviewSettingsDigest, "PreviewSettingsDigest" },
+ { tcPreviewColorSpace, "PreviewColorSpace" },
+ { tcPreviewDateTime, "PreviewDateTime" },
+ { tcRawImageDigest, "RawImageDigest" },
+ { tcOriginalRawFileDigest, "OriginalRawFileDigest" },
+ { tcSubTileBlockSize, "SubTileBlockSize" },
+ { tcRowInterleaveFactor, "RowInterleaveFactor" },
+ { tcProfileLookTableDims, "ProfileLookTableDims" },
+ { tcProfileLookTableData, "ProfileLookTableData" },
+ { tcProfileLookTableEncoding, "ProfileLookTableEncoding" },
+ { tcBaselineExposureOffset, "BaselineExposureOffset" },
+ { tcDefaultBlackRender, "DefaultBlackRender" },
+ { tcOpcodeList1, "OpcodeList1" },
+ { tcOpcodeList2, "OpcodeList2" },
+ { tcOpcodeList3, "OpcodeList3" },
+ { tcNoiseProfile, "NoiseProfile" },
+ { tcOriginalDefaultFinalSize, "OriginalDefaultFinalSize" },
+ { tcOriginalBestQualityFinalSize, "OriginalBestQualityFinalSize" },
+ { tcOriginalDefaultCropSize, "OriginalDefaultCropSize" },
+ { tcProfileHueSatMapEncoding, "ProfileHueSatMapEncoding" },
+ { tcProfileLookTableEncoding, "ProfileLookTableEncoding" },
+ { tcBaselineExposureOffset, "BaselineExposureOffset" },
+ { tcDefaultBlackRender, "DefaultBlackRender" },
+ { tcNewRawImageDigest, "NewRawImageDigest" },
+ { tcRawToPreviewGain, "RawToPreviewGain" },
+ { tcCacheBlob, "CacheBlob" },
+ { tcKodakKDCPrivateIFD, "KodakKDCPrivateIFD" }
+ };
+
+ const dng_name_table kGPSTagNames [] =
+ {
+ { tcGPSVersionID, "GPSVersionID" },
+ { tcGPSLatitudeRef, "GPSLatitudeRef" },
+ { tcGPSLatitude, "GPSLatitude" },
+ { tcGPSLongitudeRef, "GPSLongitudeRef" },
+ { tcGPSLongitude, "GPSLongitude" },
+ { tcGPSAltitudeRef, "GPSAltitudeRef" },
+ { tcGPSAltitude, "GPSAltitude" },
+ { tcGPSTimeStamp, "GPSTimeStamp" },
+ { tcGPSSatellites, "GPSSatellites" },
+ { tcGPSStatus, "GPSStatus" },
+ { tcGPSMeasureMode, "GPSMeasureMode" },
+ { tcGPSDOP, "GPSDOP" },
+ { tcGPSSpeedRef, "GPSSpeedRef" },
+ { tcGPSSpeed, "GPSSpeed" },
+ { tcGPSTrackRef, "GPSTrackRef" },
+ { tcGPSTrack, "GPSTrack" },
+ { tcGPSImgDirectionRef, "GPSImgDirectionRef" },
+ { tcGPSImgDirection, "GPSImgDirection" },
+ { tcGPSMapDatum, "GPSMapDatum" },
+ { tcGPSDestLatitudeRef, "GPSDestLatitudeRef" },
+ { tcGPSDestLatitude, "GPSDestLatitude" },
+ { tcGPSDestLongitudeRef, "GPSDestLongitudeRef" },
+ { tcGPSDestLongitude, "GPSDestLongitude" },
+ { tcGPSDestBearingRef, "GPSDestBearingRef" },
+ { tcGPSDestBearing, "GPSDestBearing" },
+ { tcGPSDestDistanceRef, "GPSDestDistanceRef" },
+ { tcGPSDestDistance, "GPSDestDistance" },
+ { tcGPSProcessingMethod, "GPSProcessingMethod" },
+ { tcGPSAreaInformation, "GPSAreaInformation" },
+ { tcGPSDateStamp, "GPSDateStamp" },
+ { tcGPSDifferential, "GPSDifferential" },
+ { tcGPSHPositioningError, "GPSHPositioningError" },
+ };
+
+ const dng_name_table kInteroperabilityTagNames [] =
+ {
+ { tcInteroperabilityIndex, "InteroperabilityIndex" },
+ { tcInteroperabilityVersion, "InteroperabilityVersion" },
+ { tcRelatedImageFileFormat, "RelatedImageFileFormat" },
+ { tcRelatedImageWidth, "RelatedImageWidth" },
+ { tcRelatedImageLength, "RelatedImageLength" }
+ };
+
+ const dng_name_table kFujiTagNames [] =
+ {
+ { tcFujiHeader, "FujiHeader" },
+ { tcFujiRawInfo1, "FujiRawInfo1" },
+ { tcFujiRawInfo2, "FujiRawInfo2" }
+ };
+
+ const dng_name_table kContaxTagNames [] =
+ {
+ { tcContaxHeader, "ContaxHeader" }
+ };
+
+ const char *name = NULL;
+
+ if (parentCode == 0 ||
+ parentCode == tcExifIFD ||
+ parentCode == tcLeafMOS ||
+ (parentCode >= tcFirstSubIFD && parentCode <= tcLastSubIFD) ||
+ (parentCode >= tcFirstChainedIFD && parentCode <= tcLastChainedIFD))
+ {
+
+ name = LookupName (tagCode,
+ kTagNames,
+ sizeof (kTagNames ) /
+ sizeof (kTagNames [0]));
+
+ }
+
+ else if (parentCode == tcGPSInfo)
+ {
+
+ name = LookupName (tagCode,
+ kGPSTagNames,
+ sizeof (kGPSTagNames ) /
+ sizeof (kGPSTagNames [0]));
+
+ }
+
+ else if (parentCode == tcInteroperabilityIFD)
+ {
+
+ name = LookupName (tagCode,
+ kInteroperabilityTagNames,
+ sizeof (kInteroperabilityTagNames ) /
+ sizeof (kInteroperabilityTagNames [0]));
+
+ }
+
+ else if (parentCode == tcFujiRAF)
+ {
+
+ name = LookupName (tagCode,
+ kFujiTagNames,
+ sizeof (kFujiTagNames ) /
+ sizeof (kFujiTagNames [0]));
+
+ }
+
+ else if (parentCode == tcContaxRAW)
+ {
+
+ name = LookupName (tagCode,
+ kContaxTagNames,
+ sizeof (kContaxTagNames ) /
+ sizeof (kContaxTagNames [0]));
+
+ }
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ if (parentCode == tcCanonCRW)
+ {
+ sprintf (s, "CRW_%04X", (unsigned) tagCode);
+ }
+
+ else if (parentCode == tcMinoltaMRW)
+ {
+
+ char c1 = (char) ((tagCode >> 24) & 0xFF);
+ char c2 = (char) ((tagCode >> 16) & 0xFF);
+ char c3 = (char) ((tagCode >> 8) & 0xFF);
+ char c4 = (char) ((tagCode ) & 0xFF);
+
+ if (c1 < ' ') c1 = '_';
+ if (c2 < ' ') c2 = '_';
+ if (c3 < ' ') c3 = '_';
+ if (c4 < ' ') c4 = '_';
+
+ sprintf (s, "MRW%c%c%c%c", c1, c2, c3, c4);
+
+ }
+
+ else if (parentCode == tcFujiRawInfo1)
+ {
+ sprintf (s, "RAF1_%04X", (unsigned) tagCode);
+ }
+
+ else if (parentCode == tcFujiRawInfo2)
+ {
+ sprintf (s, "RAF2_%04X", (unsigned) tagCode);
+ }
+
+ else
+ {
+ sprintf (s, "Tag%u", (unsigned) tagCode);
+ }
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupTagType (uint32 tagType)
+ {
+
+ const dng_name_table kTagTypeNames [] =
+ {
+ { ttByte, "Byte" },
+ { ttAscii, "ASCII" },
+ { ttShort, "Short" },
+ { ttLong, "Long" },
+ { ttRational, "Rational" },
+ { ttSByte, "SByte" },
+ { ttUndefined, "Undefined" },
+ { ttSShort, "SShort" },
+ { ttSLong, "SLong" },
+ { ttSRational, "SRational" },
+ { ttFloat, "Float" },
+ { ttDouble, "Double" },
+ { ttIFD, "IFD" },
+ { ttUnicode, "Unicode" },
+ { ttComplex, "Complex" }
+ };
+
+ const char *name = LookupName (tagType,
+ kTagTypeNames,
+ sizeof (kTagTypeNames ) /
+ sizeof (kTagTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "Type%u", (unsigned) tagType);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupNewSubFileType (uint32 key)
+ {
+
+ const dng_name_table kNewSubFileTypeNames [] =
+ {
+ { sfMainImage , "Main Image" },
+ { sfPreviewImage , "Preview Image" },
+ { sfTransparencyMask , "Transparency Mask" },
+ { sfPreviewMask , "Preview Mask" },
+ { sfAltPreviewImage , "Alt Preview Image" }
+ };
+
+ const char *name = LookupName (key,
+ kNewSubFileTypeNames,
+ sizeof (kNewSubFileTypeNames ) /
+ sizeof (kNewSubFileTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupCompression (uint32 key)
+ {
+
+ const dng_name_table kCompressionNames [] =
+ {
+ { ccUncompressed, "Uncompressed" },
+ { ccLZW, "LZW" },
+ { ccOldJPEG, "Old JPEG" },
+ { ccJPEG, "JPEG" },
+ { ccDeflate, "Deflate" },
+ { ccPackBits, "PackBits" },
+ { ccOldDeflate, "OldDeflate" },
+ { ccLossyJPEG, "Lossy JPEG" }
+ };
+
+ const char *name = LookupName (key,
+ kCompressionNames,
+ sizeof (kCompressionNames ) /
+ sizeof (kCompressionNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupPredictor (uint32 key)
+ {
+
+ const dng_name_table kPredictorNames [] =
+ {
+ { cpNullPredictor, "NullPredictor" },
+ { cpHorizontalDifference, "HorizontalDifference" },
+ { cpFloatingPoint, "FloatingPoint" },
+ { cpHorizontalDifferenceX2, "HorizontalDifferenceX2" },
+ { cpHorizontalDifferenceX4, "HorizontalDifferenceX4" },
+ { cpFloatingPointX2, "FloatingPointX2" },
+ { cpFloatingPointX4, "FloatingPointX4" }
+ };
+
+ const char *name = LookupName (key,
+ kPredictorNames,
+ sizeof (kPredictorNames ) /
+ sizeof (kPredictorNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSampleFormat (uint32 key)
+ {
+
+ const dng_name_table kSampleFormatNames [] =
+ {
+ { sfUnsignedInteger, "UnsignedInteger" },
+ { sfSignedInteger, "SignedInteger" },
+ { sfFloatingPoint, "FloatingPoint" },
+ { sfUndefined, "Undefined" }
+ };
+
+ const char *name = LookupName (key,
+ kSampleFormatNames,
+ sizeof (kSampleFormatNames ) /
+ sizeof (kSampleFormatNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupPhotometricInterpretation (uint32 key)
+ {
+
+ const dng_name_table kPhotometricInterpretationNames [] =
+ {
+ { piWhiteIsZero, "WhiteIsZero" },
+ { piBlackIsZero, "BlackIsZero" },
+ { piRGB, "RGB" },
+ { piRGBPalette, "RGBPalette" },
+ { piTransparencyMask, "TransparencyMask" },
+ { piCMYK, "CMYK" },
+ { piYCbCr, "YCbCr" },
+ { piCIELab, "CIELab" },
+ { piICCLab, "ICCLab" },
+ { piCFA, "CFA" },
+ { piLinearRaw, "LinearRaw" }
+ };
+
+ const char *name = LookupName (key,
+ kPhotometricInterpretationNames,
+ sizeof (kPhotometricInterpretationNames ) /
+ sizeof (kPhotometricInterpretationNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupOrientation (uint32 key)
+ {
+
+ const dng_name_table kOrientationNames [] =
+ {
+ { 1, "1 - 0th row is top, 0th column is left" },
+ { 2, "2 - 0th row is top, 0th column is right" },
+ { 3, "3 - 0th row is bottom, 0th column is right" },
+ { 4, "4 - 0th row is bottom, 0th column is left" },
+ { 5, "5 - 0th row is left, 0th column is top" },
+ { 6, "6 - 0th row is right, 0th column is top" },
+ { 7, "7 - 0th row is right, 0th column is bottom" },
+ { 8, "8 - 0th row is left, 0th column is bottom" },
+ { 9, "9 - unknown" }
+ };
+
+ const char *name = LookupName (key,
+ kOrientationNames,
+ sizeof (kOrientationNames ) /
+ sizeof (kOrientationNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupResolutionUnit (uint32 key)
+ {
+
+ const dng_name_table kResolutionUnitNames [] =
+ {
+ { ruNone, "None" },
+ { ruInch, "Inch" },
+ { ruCM, "cm" },
+ { ruMM, "mm" },
+ { ruMicroM, "Micrometer" }
+ };
+
+ const char *name = LookupName (key,
+ kResolutionUnitNames,
+ sizeof (kResolutionUnitNames ) /
+ sizeof (kResolutionUnitNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupCFAColor (uint32 key)
+ {
+
+ const dng_name_table kCFAColorNames [] =
+ {
+ { 0, "Red" },
+ { 1, "Green" },
+ { 2, "Blue" },
+ { 3, "Cyan" },
+ { 4, "Magenta" },
+ { 5, "Yellow" },
+ { 6, "White" }
+ };
+
+ const char *name = LookupName (key,
+ kCFAColorNames,
+ sizeof (kCFAColorNames ) /
+ sizeof (kCFAColorNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "Color%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSensingMethod (uint32 key)
+ {
+
+ const dng_name_table kSensingMethodNames [] =
+ {
+ { 0, "Undefined" },
+ { 1, "MonochromeArea" },
+ { 2, "OneChipColorArea" },
+ { 3, "TwoChipColorArea" },
+ { 4, "ThreeChipColorArea" },
+ { 5, "ColorSequentialArea" },
+ { 6, "MonochromeLinear" },
+ { 7, "TriLinear" },
+ { 8, "ColorSequentialLinear" }
+ };
+
+ const char *name = LookupName (key,
+ kSensingMethodNames,
+ sizeof (kSensingMethodNames ) /
+ sizeof (kSensingMethodNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupExposureProgram (uint32 key)
+ {
+
+ const dng_name_table kExposureProgramNames [] =
+ {
+ { epUnidentified, "Unidentified" },
+ { epManual, "Manual" },
+ { epProgramNormal, "Program Normal" },
+ { epAperturePriority, "Aperture Priority" },
+ { epShutterPriority, "Shutter Priority" },
+ { epProgramCreative, "Program Creative" },
+ { epProgramAction, "Program Action" },
+ { epPortraitMode, "Portrait Mode" },
+ { epLandscapeMode, "Landscape Mode" }
+ };
+
+ const char *name = LookupName (key,
+ kExposureProgramNames,
+ sizeof (kExposureProgramNames ) /
+ sizeof (kExposureProgramNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupMeteringMode (uint32 key)
+ {
+
+ const dng_name_table kMeteringModeNames [] =
+ {
+ { mmUnidentified, "Unknown" },
+ { mmAverage, "Average" },
+ { mmCenterWeightedAverage, "CenterWeightedAverage" },
+ { mmSpot, "Spot" },
+ { mmMultiSpot, "MultiSpot" },
+ { mmPattern, "Pattern" },
+ { mmPartial, "Partial" },
+ { mmOther, "Other" }
+ };
+
+ const char *name = LookupName (key,
+ kMeteringModeNames,
+ sizeof (kMeteringModeNames ) /
+ sizeof (kMeteringModeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupLightSource (uint32 key)
+ {
+
+ const dng_name_table kLightSourceNames [] =
+ {
+ { lsUnknown, "Unknown" },
+ { lsDaylight, "Daylight" },
+ { lsFluorescent, "Fluorescent" },
+ { lsTungsten, "Tungsten (incandescent light)" },
+ { lsFlash, "Flash" },
+ { lsFineWeather, "Fine weather" },
+ { lsCloudyWeather, "Cloudy weather" },
+ { lsShade, "Shade" },
+ { lsDaylightFluorescent, "Daylight fluorescent (D 5700 - 7100K)" },
+ { lsDayWhiteFluorescent, "Day white fluorescent (N 4600 - 5500K)" },
+ { lsCoolWhiteFluorescent, "Cool white fluorescent (W 3800 - 4500K)" },
+ { lsWhiteFluorescent, "White fluorescent (WW 3250 - 3800K)" },
+ { lsWarmWhiteFluorescent, "Warm white fluorescent (L 2600 - 3250K)" },
+ { lsStandardLightA, "Standard light A" },
+ { lsStandardLightB, "Standard light B" },
+ { lsStandardLightC, "Standard light C" },
+ { lsD55, "D55" },
+ { lsD65, "D65" },
+ { lsD75, "D75" },
+ { lsD50, "D50" },
+ { lsISOStudioTungsten, "ISO studio tungsten" },
+ { lsOther, "Other" }
+ };
+
+ const char *name = LookupName (key,
+ kLightSourceNames,
+ sizeof (kLightSourceNames ) /
+ sizeof (kLightSourceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ if (key & 0x08000)
+ {
+
+ sprintf (s, "%uK", (unsigned) (key & 0x7FFF));
+
+ }
+
+ else
+ {
+
+ sprintf (s, "%u", (unsigned) key);
+
+ }
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupColorSpace (uint32 key)
+ {
+
+ const dng_name_table kColorSpaceNames [] =
+ {
+ { 1, "sRGB" },
+ { 0xFFFF, "Uncalibrated" }
+ };
+
+ const char *name = LookupName (key,
+ kColorSpaceNames,
+ sizeof (kColorSpaceNames ) /
+ sizeof (kColorSpaceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupFileSource (uint32 key)
+ {
+
+ const dng_name_table kFileSourceNames [] =
+ {
+ { 3, "DSC" }
+ };
+
+ const char *name = LookupName (key,
+ kFileSourceNames,
+ sizeof (kFileSourceNames ) /
+ sizeof (kFileSourceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSceneType (uint32 key)
+ {
+
+ const dng_name_table kSceneTypeNames [] =
+ {
+ { 1, "A directly photographed image" }
+ };
+
+ const char *name = LookupName (key,
+ kSceneTypeNames,
+ sizeof (kSceneTypeNames ) /
+ sizeof (kSceneTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupCustomRendered (uint32 key)
+ {
+
+ const dng_name_table kCustomRenderedNames [] =
+ {
+ { 0, "Normal process" },
+ { 1, "Custom process" }
+ };
+
+ const char *name = LookupName (key,
+ kCustomRenderedNames,
+ sizeof (kCustomRenderedNames ) /
+ sizeof (kCustomRenderedNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupExposureMode (uint32 key)
+ {
+
+ const dng_name_table kExposureModeNames [] =
+ {
+ { 0, "Auto exposure" },
+ { 1, "Manual exposure" },
+ { 2, "Auto bracket" }
+ };
+
+ const char *name = LookupName (key,
+ kExposureModeNames,
+ sizeof (kExposureModeNames ) /
+ sizeof (kExposureModeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupWhiteBalance (uint32 key)
+ {
+
+ const dng_name_table kWhiteBalanceNames [] =
+ {
+ { 0, "Auto white balance" },
+ { 1, "Manual white balance" }
+ };
+
+ const char *name = LookupName (key,
+ kWhiteBalanceNames,
+ sizeof (kWhiteBalanceNames ) /
+ sizeof (kWhiteBalanceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSceneCaptureType (uint32 key)
+ {
+
+ const dng_name_table kSceneCaptureTypeNames [] =
+ {
+ { 0, "Standard" },
+ { 1, "Landscape" },
+ { 2, "Portrait" },
+ { 3, "Night scene" }
+ };
+
+ const char *name = LookupName (key,
+ kSceneCaptureTypeNames,
+ sizeof (kSceneCaptureTypeNames ) /
+ sizeof (kSceneCaptureTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupGainControl (uint32 key)
+ {
+
+ const dng_name_table kGainControlNames [] =
+ {
+ { 0, "None" },
+ { 1, "Low gain up" },
+ { 2, "High gain up" },
+ { 3, "Low gain down" },
+ { 4, "High gain down" }
+ };
+
+ const char *name = LookupName (key,
+ kGainControlNames,
+ sizeof (kGainControlNames ) /
+ sizeof (kGainControlNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupContrast (uint32 key)
+ {
+
+ const dng_name_table kContrastNames [] =
+ {
+ { 0, "Normal" },
+ { 1, "Soft" },
+ { 2, "Hard" }
+ };
+
+ const char *name = LookupName (key,
+ kContrastNames,
+ sizeof (kContrastNames ) /
+ sizeof (kContrastNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSaturation (uint32 key)
+ {
+
+ const dng_name_table kSaturationNames [] =
+ {
+ { 0, "Normal" },
+ { 1, "Low saturation" },
+ { 2, "High saturation" }
+ };
+
+ const char *name = LookupName (key,
+ kSaturationNames,
+ sizeof (kSaturationNames ) /
+ sizeof (kSaturationNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSharpness (uint32 key)
+ {
+
+ const dng_name_table kSharpnessNames [] =
+ {
+ { 0, "Normal" },
+ { 1, "Soft" },
+ { 2, "Hard" }
+ };
+
+ const char *name = LookupName (key,
+ kSharpnessNames,
+ sizeof (kSharpnessNames ) /
+ sizeof (kSharpnessNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSubjectDistanceRange (uint32 key)
+ {
+
+ const dng_name_table kSubjectDistanceRangeNames [] =
+ {
+ { 0, "Unknown" },
+ { 1, "Macro" },
+ { 2, "Close view" },
+ { 3, "Distant view" }
+ };
+
+ const char *name = LookupName (key,
+ kSubjectDistanceRangeNames,
+ sizeof (kSubjectDistanceRangeNames ) /
+ sizeof (kSubjectDistanceRangeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupComponent (uint32 key)
+ {
+
+ const dng_name_table kComponentNames [] =
+ {
+ { 0, "-" },
+ { 1, "Y" },
+ { 2, "Cb" },
+ { 3, "Cr" },
+ { 4, "R" },
+ { 5, "G" },
+ { 6, "B" }
+ };
+
+ const char *name = LookupName (key,
+ kComponentNames,
+ sizeof (kComponentNames ) /
+ sizeof (kComponentNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupCFALayout (uint32 key)
+ {
+
+ const dng_name_table kCFALayoutNames [] =
+ {
+ { 1, "Rectangular (or square) layout" },
+ { 2, "Staggered layout A: even columns are offset down by 1/2 row" },
+ { 3, "Staggered layout B: even columns are offset up by 1/2 row" },
+ { 4, "Staggered layout C: even rows are offset right by 1/2 column" },
+ { 5, "Staggered layout D: even rows are offset left by 1/2 column" },
+ { 6, "Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column" },
+ { 7, "Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column" },
+ { 8, "Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column" },
+ { 9, "Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column" }
+ };
+
+ const char *name = LookupName (key,
+ kCFALayoutNames,
+ sizeof (kCFALayoutNames ) /
+ sizeof (kCFALayoutNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupMakerNoteSafety (uint32 key)
+ {
+
+ const dng_name_table kMakerNoteSafetyNames [] =
+ {
+ { 0, "Unsafe" },
+ { 1, "Safe" }
+ };
+
+ const char *name = LookupName (key,
+ kMakerNoteSafetyNames,
+ sizeof (kMakerNoteSafetyNames ) /
+ sizeof (kMakerNoteSafetyNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupColorimetricReference (uint32 key)
+ {
+
+ const dng_name_table kColorimetricReferenceNames [] =
+ {
+ { crSceneReferred, "Scene Referred" },
+ { crICCProfilePCS, "ICC Profile PCS" }
+ };
+
+ const char *name = LookupName (key,
+ kColorimetricReferenceNames,
+ sizeof (kColorimetricReferenceNames ) /
+ sizeof (kColorimetricReferenceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupPreviewColorSpace (uint32 key)
+ {
+
+ const dng_name_table kPreviewColorSpaceNames [] =
+ {
+ { previewColorSpace_Unknown , "Unknown" },
+ { previewColorSpace_GrayGamma22, "Gray Gamma 2.2" },
+ { previewColorSpace_sRGB , "sRGB" },
+ { previewColorSpace_AdobeRGB , "Adobe RGB (1998)" },
+ { previewColorSpace_ProPhotoRGB, "Pro Photo RGB" }
+ };
+
+ const char *name = LookupName (key,
+ kPreviewColorSpaceNames,
+ sizeof (kPreviewColorSpaceNames ) /
+ sizeof (kPreviewColorSpaceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupJPEGMarker (uint32 key)
+ {
+
+ const dng_name_table kJPEGMarkerNames [] =
+ {
+ { M_TEM, "TEM" },
+ { M_SOF0, "SOF0" },
+ { M_SOF1, "SOF1" },
+ { M_SOF2, "SOF2" },
+ { M_SOF3, "SOF3" },
+ { M_DHT, "DHT" },
+ { M_SOF5, "SOF5" },
+ { M_SOF6, "SOF6" },
+ { M_SOF7, "SOF7" },
+ { M_JPG, "JPG" },
+ { M_SOF9, "SOF9" },
+ { M_SOF10, "SOF10" },
+ { M_SOF11, "SOF11" },
+ { M_DAC, "DAC" },
+ { M_SOF13, "SOF13" },
+ { M_SOF14, "SOF14" },
+ { M_SOF15, "SOF15" },
+ { M_RST0, "RST0" },
+ { M_RST1, "RST1" },
+ { M_RST2, "RST2" },
+ { M_RST3, "RST3" },
+ { M_RST4, "RST4" },
+ { M_RST5, "RST5" },
+ { M_RST6, "RST6" },
+ { M_RST7, "RST7" },
+ { M_SOI, "SOI" },
+ { M_EOI, "EOI" },
+ { M_SOS, "SOS" },
+ { M_DQT, "DQT" },
+ { M_DNL, "DNL" },
+ { M_DRI, "DRI" },
+ { M_DHP, "DHP" },
+ { M_EXP, "EXP" },
+ { M_APP0, "APP0" },
+ { M_APP1, "APP1" },
+ { M_APP2, "APP2" },
+ { M_APP3, "APP3" },
+ { M_APP4, "APP4" },
+ { M_APP5, "APP5" },
+ { M_APP6, "APP6" },
+ { M_APP7, "APP7" },
+ { M_APP8, "APP8" },
+ { M_APP9, "APP9" },
+ { M_APP10, "APP10" },
+ { M_APP11, "APP11" },
+ { M_APP12, "APP12" },
+ { M_APP13, "APP13" },
+ { M_APP14, "APP14" },
+ { M_APP15, "APP15" },
+ { M_JPG0, "JPG0" },
+ { M_JPG1, "JPG1" },
+ { M_JPG2, "JPG2" },
+ { M_JPG3, "JPG3" },
+ { M_JPG4, "JPG4" },
+ { M_JPG5, "JPG5" },
+ { M_JPG6, "JPG6" },
+ { M_JPG7, "JPG7" },
+ { M_JPG8, "JPG8" },
+ { M_JPG9, "JPG9" },
+ { M_JPG10, "JPG10" },
+ { M_JPG11, "JPG11" },
+ { M_JPG12, "JPG12" },
+ { M_JPG13, "JPG13" },
+ { M_COM, "COM" },
+ { M_ERROR, "ERROR" }
+ };
+
+ const char *name = LookupName (key,
+ kJPEGMarkerNames,
+ sizeof (kJPEGMarkerNames ) /
+ sizeof (kJPEGMarkerNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "0x%02X", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSensitivityType (uint32 key)
+ {
+
+ const dng_name_table kSensitivityTypeNames [] =
+ {
+ { stUnknown, "Unknown" },
+ { stStandardOutputSensitivity, "Standard Output Sensitivity (SOS)" },
+ { stRecommendedExposureIndex, "Recommended Exposure Index (REI)" },
+ { stISOSpeed, "ISO Speed" },
+ { stSOSandREI, "Standard Output Sensitivity (SOS) and Recommended Exposure Index (REI)" },
+ { stSOSandISOSpeed, "Standard Output Sensitivity (SOS) and ISO Speed" },
+ { stREIandISOSpeed, "Recommended Exposure Index (REI) and ISO Speed" },
+ { stSOSandREIandISOSpeed, "Standard Output Sensitivity (SOS) and Recommended Exposure Index (REI) and ISO Speed" },
+ };
+
+ const char *name = LookupName (key,
+ kSensitivityTypeNames,
+ sizeof (kSensitivityTypeNames ) /
+ sizeof (kSensitivityTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+void DumpHexAscii (dng_stream &stream,
+ uint32 count)
+ {
+
+ uint32 rows = (count + 15) >> 4;
+
+ if (rows > gDumpLineLimit)
+ rows = gDumpLineLimit;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ printf (" ");
+
+ uint32 col;
+
+ uint32 cols = count - (row << 4);
+
+ if (cols > 16)
+ cols = 16;
+
+ uint8 x [16];
+
+ for (col = 0; col < 16; col++)
+ {
+
+ x [col] = ' ';
+
+ if (col < cols)
+ {
+
+ x [col] = stream.Get_uint8 ();
+
+ printf ("%02x ", x [col]);
+
+ }
+
+ else
+ {
+ printf (" ");
+ }
+
+ }
+
+ printf (" ");
+
+ for (col = 0; col < 16; col++)
+ {
+
+ if (x [col] >= (uint8) ' ' && x [col] <= (uint8) '~')
+ {
+ printf ("%c", x [col]);
+ }
+
+ else
+ {
+ printf (".");
+ }
+
+ }
+
+ printf ("\n");
+
+ }
+
+ if (count > rows * 16)
+ {
+ printf (" ... %u more bytes\n", (unsigned) (count - rows * 16));
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpHexAscii (const uint8 *buf,
+ uint32 count)
+ {
+
+ uint32 rows = (count + 15) >> 4;
+
+ if (rows > gDumpLineLimit)
+ rows = gDumpLineLimit;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ printf (" ");
+
+ uint32 col;
+
+ uint32 cols = count - (row << 4);
+
+ if (cols > 16)
+ cols = 16;
+
+ uint8 x [16];
+
+ for (col = 0; col < 16; col++)
+ {
+
+ x [col] = ' ';
+
+ if (col < cols)
+ {
+
+ x [col] = *(buf++);
+
+ printf ("%02x ", x [col]);
+
+ }
+
+ else
+ {
+ printf (" ");
+ }
+
+ }
+
+ printf (" ");
+
+ for (col = 0; col < 16; col++)
+ {
+
+ if (x [col] >= (uint8) ' ' && x [col] <= (uint8) '~')
+ {
+ printf ("%c", x [col]);
+ }
+
+ else
+ {
+ printf (".");
+ }
+
+ }
+
+ printf ("\n");
+
+ }
+
+ if (count > rows * 16)
+ {
+ printf (" ... %u more bytes\n", (unsigned) (count - rows * 16));
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpXMP (dng_stream &stream,
+ uint32 count)
+ {
+
+ uint32 lineLength = 0;
+
+ while (count > 0)
+ {
+
+ uint32 x = stream.Get_uint8 ();
+
+ if (x == 0) break;
+
+ count--;
+
+ if (lineLength == 0)
+ {
+
+ printf ("XMP: ");
+
+ lineLength = 5;
+
+ }
+
+ if (x == '\n' ||
+ x == '\r')
+ {
+
+ printf ("\n");
+
+ lineLength = 0;
+
+ }
+
+ else
+ {
+
+ if (lineLength >= 128)
+ {
+
+ printf ("\nXMP: ");
+
+ lineLength = 5;
+
+ }
+
+ if (x >= ' ' && x <= '~')
+ {
+
+ printf ("%c", (char) x);
+
+ lineLength += 1;
+
+ }
+
+ else
+ {
+
+ printf ("\\%03o", (unsigned) x);
+
+ lineLength += 4;
+
+ }
+
+ }
+
+ }
+
+ if (lineLength != 0)
+ {
+
+ printf ("\n");
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpString (const dng_string &s)
+ {
+
+ const uint32 kMaxDumpString = gDumpLineLimit * 64;
+
+ printf ("\"");
+
+ const char *ss = s.Get ();
+
+ uint32 total = 0;
+
+ while (*ss != 0 && total++ < kMaxDumpString)
+ {
+
+ uint32 c = dng_string::DecodeUTF8 (ss);
+
+ if (c >= ' ' && c <= '~')
+ {
+ printf ("%c", (char) c);
+ }
+
+ else switch (c)
+ {
+
+ case '\t':
+ {
+ printf ("\\t");
+ break;
+ }
+
+ case '\n':
+ {
+ printf ("\\n");
+ break;
+ }
+
+ case '\r':
+ {
+ printf ("\\r");
+ break;
+ }
+
+ default:
+ {
+ printf ("[%X]", (unsigned) c);
+ }
+
+ }
+
+ }
+
+ uint32 extra = (uint32) strlen (ss);
+
+ if (extra > 0)
+ {
+ printf ("...\" (%u more bytes)", (unsigned) extra);
+ }
+
+ else
+ {
+ printf ("\"");
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpTagValues (dng_stream &stream,
+ const char *entry_name,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ const char *tag_name)
+ {
+
+ const uint32 kMaxDumpSingleLine = 4;
+
+ const uint32 kMaxDumpArray = Max_uint32 (gDumpLineLimit, kMaxDumpSingleLine);
+
+ printf ("%s:", tag_name ? tag_name
+ : LookupTagCode (parentCode, tagCode));
+
+ switch (tagType)
+ {
+
+ case ttShort:
+ case ttLong:
+ case ttIFD:
+ case ttSByte:
+ case ttSShort:
+ case ttSLong:
+ case ttRational:
+ case ttSRational:
+ case ttFloat:
+ case ttDouble:
+ {
+
+ if (tagCount > kMaxDumpSingleLine)
+ {
+
+ printf (" %u entries", (unsigned) tagCount);
+
+ }
+
+ for (uint32 j = 0; j < tagCount && j < kMaxDumpArray; j++)
+ {
+
+ if (tagCount <= kMaxDumpSingleLine)
+ {
+
+ if (j == 0)
+ {
+
+ printf (" %s =", entry_name);
+
+ }
+
+ printf (" ");
+
+ }
+
+ else
+ {
+
+ printf ("\n %s [%u] = ", entry_name, (unsigned) j);
+
+ }
+
+ switch (tagType)
+ {
+
+ case ttByte:
+ case ttShort:
+ case ttLong:
+ case ttIFD:
+ {
+
+ uint32 x = stream.TagValue_uint32 (tagType);
+
+ printf ("%u", (unsigned) x);
+
+ break;
+
+ }
+
+ case ttSByte:
+ case ttSShort:
+ case ttSLong:
+ {
+
+ int32 x = stream.TagValue_int32 (tagType);
+
+ printf ("%d", (int) x);
+
+ break;
+
+ }
+
+ case ttRational:
+ {
+
+ dng_urational x = stream.TagValue_urational (tagType);
+
+ printf ("%u/%u", (unsigned) x.n, (unsigned) x.d);
+
+ break;
+
+ }
+
+ case ttSRational:
+ {
+
+ dng_srational x = stream.TagValue_srational (tagType);
+
+ printf ("%d/%d", (int) x.n, (int) x.d);
+
+ break;
+
+ }
+
+ default:
+ {
+
+ real64 x = stream.TagValue_real64 (tagType);
+
+ printf ("%f", x);
+
+ }
+
+ }
+
+ }
+
+ printf ("\n");
+
+ if (tagCount > kMaxDumpArray)
+ {
+
+ printf (" ... %u more entries\n", (unsigned) (tagCount - kMaxDumpArray));
+
+ }
+
+ break;
+
+ }
+
+ case ttAscii:
+ {
+
+ dng_string s;
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ s,
+ false);
+
+ printf (" ");
+
+ DumpString (s);
+
+ printf ("\n");
+
+ break;
+
+ }
+
+ default:
+ {
+
+ uint32 tagSize = tagCount * TagTypeSize (tagType);
+
+ if (tagCount == 1 && (tagType == ttByte ||
+ tagType == ttUndefined))
+ {
+
+ uint8 x = stream.Get_uint8 ();
+
+ printf (" %s = %u\n", LookupTagType (tagType), x);
+
+ }
+
+ else
+ {
+
+ printf (" %s, size = %u\n", LookupTagType (tagType), (unsigned) tagSize);
+
+ DumpHexAscii (stream, tagSize);
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpMatrix (const dng_matrix &m)
+ {
+
+ for (uint32 row = 0; row < m.Rows (); row++)
+ {
+
+ for (uint32 col = 0; col < m.Cols (); col++)
+ {
+
+ if (col == 0)
+ printf (" ");
+ else
+ printf (" ");
+
+ printf ("%8.4f", m [row] [col]);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpVector (const dng_vector &v)
+ {
+
+ for (uint32 index = 0; index < v.Count (); index++)
+ {
+
+ printf (" %0.4f", v [index]);
+
+ }
+
+ printf ("\n");
+
+ }
+
+/*****************************************************************************/
+
+void DumpDateTime (const dng_date_time &dt)
+ {
+
+ printf ("%04d:%02d:%02d %02d:%02d:%02d",
+ (int) dt.fYear,
+ (int) dt.fMonth,
+ (int) dt.fDay,
+ (int) dt.fHour,
+ (int) dt.fMinute,
+ (int) dt.fSecond);
+
+ }
+
+/*****************************************************************************/
+
+void DumpExposureTime (real64 x)
+ {
+
+ if (x > 0.0)
+ {
+
+ if (x >= 0.25)
+ {
+ printf ("%0.2f sec", x);
+ }
+
+ else if (x >= 0.01)
+ {
+ printf ("1/%0.1f sec", 1.0 / x);
+ }
+
+ else
+ {
+ printf ("1/%0.0f sec", 1.0 / x);
+ }
+
+ }
+
+ else
+ {
+
+ printf ("<invalid>");
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpFingerprint (const dng_fingerprint &p)
+ {
+
+ printf ("<");
+
+ for (uint32 j = 0; j < 16; j++)
+ {
+ printf ("%02x", p.data [j]);
+ }
+
+ printf (">");
+
+ }
+
+/*****************************************************************************/
+
+void DumpHueSatMap (dng_stream &stream,
+ uint32 hues,
+ uint32 sats,
+ uint32 vals,
+ bool skipSat0)
+ {
+
+ uint32 doneLines = 0;
+ uint32 skipLines = 0;
+
+ for (uint32 v = 0; v < vals; v++)
+ {
+
+ for (uint32 h = 0; h < hues; h++)
+ {
+
+ for (uint32 s = skipSat0 ? 1 : 0; s < sats; s++)
+ {
+
+ real32 dh = stream.Get_real32 ();
+ real32 ds = stream.Get_real32 ();
+ real32 dv = stream.Get_real32 ();
+
+ if (gDumpLineLimit == 0 ||
+ gDumpLineLimit > doneLines)
+ {
+
+ doneLines++;
+
+ if (vals == 1)
+ {
+
+ printf (" h [%2u] s [%2u]: h=%8.4f s=%6.4f v=%6.4f\n",
+ (unsigned) h,
+ (unsigned) s,
+ (double) dh,
+ (double) ds,
+ (double) dv);
+
+ }
+
+ else
+ {
+
+ printf (" v [%2u] h [%2u] s [%2u]: h=%8.4f s=%6.4f v=%6.4f\n",
+ (unsigned) v,
+ (unsigned) h,
+ (unsigned) s,
+ (double) dh,
+ (double) ds,
+ (double) dv);
+
+ }
+
+ }
+
+ else
+ {
+
+ skipLines++;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ if (skipLines > 0)
+ {
+
+ printf (" ... %u more entries\n", (unsigned) skipLines);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
+
+bool CheckTagType (uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint16 validType0,
+ uint16 validType1,
+ uint16 validType2,
+ uint16 validType3)
+ {
+
+ if (tagType != validType0 &&
+ tagType != validType1 &&
+ tagType != validType2 &&
+ tagType != validType3)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unexpected type (%s)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode),
+ LookupTagType (tagType));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckTagCount (uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ uint32 minCount,
+ uint32 maxCount)
+ {
+
+ if (maxCount < minCount)
+ maxCount = minCount;
+
+ if (tagCount < minCount ||
+ tagCount > maxCount)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unexpected count (%u)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode),
+ (unsigned) tagCount);
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckColorImage (uint32 parentCode,
+ uint32 tagCode,
+ uint32 colorPlanes)
+ {
+
+ if (colorPlanes == 0)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed with unknown color plane count "
+ " (missing ColorMatrix1 tag?)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ if (colorPlanes == 1)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed with monochrome images",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckMainIFD (uint32 parentCode,
+ uint32 tagCode,
+ uint32 newSubFileType)
+ {
+
+ if (newSubFileType != sfMainImage)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed IFDs with NewSubFileType != 0",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckRawIFD (uint32 parentCode,
+ uint32 tagCode,
+ uint32 photometricInterpretation)
+ {
+
+ if (photometricInterpretation != piCFA &&
+ photometricInterpretation != piLinearRaw)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed in IFDs with a non-raw PhotometricInterpretation",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckCFA (uint32 parentCode,
+ uint32 tagCode,
+ uint32 photometricInterpretation)
+ {
+
+ if (photometricInterpretation != piCFA)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed in IFDs with a non-CFA PhotometricInterpretation",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+void ParseStringTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ dng_string &s,
+ bool trimBlanks)
+ {
+
+ if (tagCount == 0 ||
+ tagCount == 0xFFFFFFFF)
+ {
+
+ s.Clear ();
+
+ return;
+
+ }
+
+ dng_memory_data temp_buffer (tagCount + 1);
+
+ char *buffer = temp_buffer.Buffer_char ();
+
+ stream.Get (buffer, tagCount);
+
+ // Make sure the string is null terminated.
+
+ if (buffer [tagCount - 1] != 0)
+ {
+
+ buffer [tagCount] = 0;
+
+ #if qDNGValidate
+
+ {
+
+ bool hasNull = false;
+
+ for (uint32 j = 0; j < tagCount; j++)
+ {
+
+ if (buffer [j] == 0)
+ {
+
+ hasNull = true;
+
+ break;
+
+ }
+
+ }
+
+ if (!hasNull && parentCode < tcFirstMakerNoteIFD)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not NULL terminated",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ }
+
+ // Medata working group - Allow UTF-8
+
+ s.Set_UTF8_or_System (buffer);
+
+ if (trimBlanks)
+ {
+
+ s.TrimTrailingBlanks ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void ParseDualStringTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ dng_string &s1,
+ dng_string &s2)
+ {
+
+ if (tagCount == 0 ||
+ tagCount == 0xFFFFFFFF)
+ {
+
+ s1.Clear ();
+ s2.Clear ();
+
+ return;
+
+ }
+
+ dng_memory_data temp_buffer (tagCount + 1);
+
+ char *buffer = temp_buffer.Buffer_char ();
+
+ stream.Get (buffer, tagCount);
+
+ // Make sure the string is null terminated.
+
+ if (buffer [tagCount - 1] != 0)
+ {
+
+ buffer [tagCount] = 0;
+
+ #if qDNGValidate
+
+ {
+
+ uint32 nullCount = 0;
+
+ for (uint32 j = 0; j < tagCount; j++)
+ {
+
+ if (buffer [j] == 0)
+ {
+
+ nullCount++;
+
+ }
+
+ }
+
+ if (nullCount < 2 && parentCode < tcFirstMakerNoteIFD)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not NULL terminated",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ }
+
+ // Medata working group - Allow UTF-8
+
+ s1.Set_UTF8_or_System (buffer);
+
+ s2.Set_ASCII (NULL);
+
+ for (uint32 j = 1; j < tagCount - 1; j++)
+ {
+
+ if (buffer [j - 1] != 0 &&
+ buffer [j ] == 0)
+ {
+
+ // Medata working group - Allow UTF-8
+
+ s2.Set_UTF8_or_System (buffer + j + 1);
+
+ break;
+
+ }
+
+ }
+
+ s1.TrimTrailingBlanks ();
+ s2.TrimTrailingBlanks ();
+
+ }
+
+/*****************************************************************************/
+
+void ParseEncodedStringTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ dng_string &s)
+ {
+
+ if (tagCount < 8)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unexpected count (%u)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode),
+ (unsigned) tagCount);
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ s.Clear ();
+
+ return;
+
+ }
+
+ char label [8];
+
+ stream.Get (label, 8);
+
+ // Sometimes lowercase is used by mistake. Accept this, but issue
+ // warning.
+
+ {
+
+ bool hadLower = false;
+
+ for (uint32 j = 0; j < 8; j++)
+ {
+
+ if (label [j] >= 'a' && label [j] <= 'z')
+ {
+
+ label [j] = 'A' + (label [j] - 'a');
+
+ hadLower = true;
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (hadLower)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s text encoding label not all uppercase",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ }
+
+ if (memcmp (label, "UNICODE\000", 8) == 0)
+ {
+
+ uint32 uChars = (tagCount - 8) >> 1;
+
+ dng_memory_data temp_buffer ((uChars + 1) * 2);
+
+ uint16 *buffer = temp_buffer.Buffer_uint16 ();
+
+ for (uint32 j = 0; j < uChars; j++)
+ {
+
+ buffer [j] = stream.Get_uint16 ();
+
+ }
+
+ buffer [uChars] = 0;
+
+ #if qDNGValidate
+
+ {
+
+ // If the writer used UTF-8 rather than UTF-16, and padded
+ // the string with blanks, then there will be lots of 0x2020
+ // (unicode dagger symbol) characters in the string.
+
+ uint32 count2020 = 0;
+
+ for (uint32 k = 0; buffer [k] != 0; k++)
+ {
+
+ if (buffer [k] == 0x2020)
+ {
+
+ count2020++;
+
+ }
+
+ }
+
+ if (count2020 > 1)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s text appears to be UTF-8 rather than UTF-16",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #endif
+
+ s.Set_UTF16 (buffer);
+
+ }
+
+ else
+ {
+
+ uint32 aChars = tagCount - 8;
+
+ dng_memory_data temp_buffer (aChars + 1);
+
+ char *buffer = temp_buffer.Buffer_char ();
+
+ stream.Get (buffer, aChars);
+
+ buffer [aChars] = 0;
+
+ enum dng_encoding
+ {
+ dng_encoding_ascii,
+ dng_encoding_jis_x208_1990,
+ dng_encoding_unknown
+ };
+
+ dng_encoding encoding = dng_encoding_unknown;
+
+ if (memcmp (label, "ASCII\000\000\000", 8) == 0)
+ {
+
+ encoding = dng_encoding_ascii;
+
+ }
+
+ else if (memcmp (label, "JIS\000\000\000\000\000\000", 8) == 0)
+ {
+
+ encoding = dng_encoding_jis_x208_1990;
+
+ }
+
+ else
+ {
+
+ // Some Nikon D1 files have UserComment tags with zero encoding bits and
+ // garbage text values. So don't try to parse tags with unknown text
+ // encoding unless all the characters are printing ASCII.
+
+ #if qDNGValidate
+
+ if (memcmp (label, "\000\000\000\000\000\000\000\000\000", 8) == 0)
+ {
+
+ // Many camera makes store null tags with all zero encoding, so
+ // don't report a warning message for null strings.
+
+ if (buffer [0] != 0)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unknown encoding",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ else
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unexpected text encoding",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ }
+
+ // If text encoding was unknown, and the text is anything
+ // other than pure ASCII, then ignore it.
+
+ if (encoding == dng_encoding_unknown)
+ {
+
+ encoding = dng_encoding_ascii;
+
+ for (uint32 i = 0; i < aChars && buffer [i] != 0; i++)
+ {
+
+ if (buffer [i] < ' ' ||
+ buffer [i] > '~')
+ {
+
+ buffer [0] = 0;
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ switch (encoding)
+ {
+
+ case dng_encoding_ascii:
+ {
+
+ // Medata working group - allow UTF-8 for ASCII tags.
+
+ s.Set_UTF8_or_System (buffer);
+
+ break;
+
+ }
+
+ case dng_encoding_jis_x208_1990:
+ {
+ s.Set_JIS_X208_1990 (buffer);
+ break;
+ }
+
+ case dng_encoding_unknown:
+ {
+ s.Set_SystemEncoding (buffer);
+ break;
+ }
+
+ default:
+ break;
+
+ }
+
+ #if qDNGValidate
+
+ {
+
+ if (encoding == dng_encoding_ascii && !s.IsASCII ())
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has non-ASCII characters",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #endif
+
+ }
+
+ s.TrimTrailingBlanks ();
+
+ }
+
+/*****************************************************************************/
+
+bool ParseMatrixTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint32 rows,
+ uint32 cols,
+ dng_matrix &m)
+ {
+
+ if (CheckTagCount (parentCode, tagCode, tagCount, rows * cols))
+ {
+
+ dng_matrix temp (rows, cols);
+
+ for (uint32 row = 0; row < rows; row++)
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ temp [row] [col] = stream.TagValue_real64 (tagType);
+
+ }
+
+ m = temp;
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+bool ParseVectorTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint32 count,
+ dng_vector &v)
+ {
+
+ if (CheckTagCount (parentCode, tagCode, tagCount, count))
+ {
+
+ dng_vector temp (count);
+
+ for (uint32 index = 0; index < count; index++)
+ {
+
+ temp [index] = stream.TagValue_real64 (tagType);
+
+ }
+
+ v = temp;
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+bool ParseDateTimeTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ dng_date_time &dt)
+ {
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttAscii))
+ {
+ return false;
+ }
+
+ // Kludge: Some versions of PaintShop Pro write these fields
+ // with a length of 21 rather than 20. Otherwise they are
+ // correctly formated. So relax this test and allow these
+ // these longer than standard tags to be parsed.
+
+ (void) CheckTagCount (parentCode, tagCode, tagCount, 20);
+
+ if (tagCount < 20)
+ {
+ return false;
+ }
+
+ char s [21];
+
+ stream.Get (s, 20);
+
+ s [20] = 0;
+
+ // See if this is a valid date/time string.
+
+ if (dt.Parse (s))
+ {
+ return true;
+ }
+
+ // Accept strings that contain only blanks, colons, and zeros as
+ // valid "null" dates.
+
+ dt = dng_date_time ();
+
+ for (uint32 index = 0; index < 21; index++)
+ {
+
+ char c = s [index];
+
+ if (c == 0)
+ {
+ return true;
+ }
+
+ if (c != ' ' && c != ':' && c != '0')
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not a valid date/time",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_parse_utils.h b/source/dng_parse_utils.h
index 89a082f..39ef37a 100644
--- a/source/dng_parse_utils.h
+++ b/source/dng_parse_utils.h
@@ -1,232 +1,232 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_parse_utils.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_parse_utils__
-#define __dng_parse_utils__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_flags.h"
-#include "dng_types.h"
-#include "dng_stream.h"
-#include "dng_string.h"
-#include "dng_matrix.h"
-
-/*****************************************************************************/
-
-#if qDNGValidate
-
-/*****************************************************************************/
-
-const char * LookupParentCode (uint32 parentCode);
-
-/*****************************************************************************/
-
-const char * LookupTagCode (uint32 parentCode,
- uint32 tagCode);
-
-/*****************************************************************************/
-
-const char * LookupTagType (uint32 tagType);
-
-/*****************************************************************************/
-
-const char * LookupNewSubFileType (uint32 key);
-
-const char * LookupCompression (uint32 key);
-
-const char * LookupPredictor (uint32 key);
-
-const char * LookupSampleFormat (uint32 key);
-
-const char * LookupPhotometricInterpretation (uint32 key);
-
-const char * LookupOrientation (uint32 key);
-
-const char * LookupResolutionUnit (uint32 key);
-
-const char * LookupCFAColor (uint32 key);
-
-const char * LookupSensingMethod (uint32 key);
-
-const char * LookupExposureProgram (uint32 key);
-
-const char * LookupMeteringMode (uint32 key);
-
-const char * LookupLightSource (uint32 key);
-
-const char * LookupColorSpace (uint32 key);
-
-const char * LookupFileSource (uint32 key);
-
-const char * LookupSceneType (uint32 key);
-
-const char * LookupCustomRendered (uint32 key);
-
-const char * LookupExposureMode (uint32 key);
-
-const char * LookupWhiteBalance (uint32 key);
-
-const char * LookupSceneCaptureType (uint32 key);
-
-const char * LookupGainControl (uint32 key);
-
-const char * LookupContrast (uint32 key);
-
-const char * LookupSaturation (uint32 key);
-
-const char * LookupSharpness (uint32 key);
-
-const char * LookupSubjectDistanceRange (uint32 key);
-
-const char * LookupComponent (uint32 key);
-
-const char * LookupCFALayout (uint32 key);
-
-const char * LookupMakerNoteSafety (uint32 key);
-
-const char * LookupColorimetricReference (uint32 key);
-
-const char * LookupPreviewColorSpace (uint32 key);
-
-const char * LookupJPEGMarker (uint32 key);
-
-const char * LookupSensitivityType (uint32 key);
-
-/*****************************************************************************/
-
-void DumpHexAscii (dng_stream &stream,
- uint32 count);
-
-void DumpHexAscii (const uint8 *buf,
- uint32 count);
-
-void DumpXMP (dng_stream &stream,
- uint32 count);
-
-void DumpString (const dng_string &s);
-
-void DumpTagValues (dng_stream &stream,
- const char *entry_name,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- const char *tag_name = NULL);
-
-void DumpMatrix (const dng_matrix &m);
-
-void DumpVector (const dng_vector &v);
-
-void DumpDateTime (const dng_date_time &dt);
-
-void DumpExposureTime (real64 x);
-
-void DumpFingerprint (const dng_fingerprint &p);
-
-void DumpHueSatMap (dng_stream &stream,
- uint32 hues,
- uint32 sats,
- uint32 vals,
- bool skipSat0);
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
-
-bool CheckTagType (uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint16 validType0,
- uint16 validType1 = 0,
- uint16 validType2 = 0,
- uint16 validType3 = 0);
-
-bool CheckTagCount (uint32 parentCode,
- uint32 tagCode,
- uint32 tagCount,
- uint32 minCount,
- uint32 maxCount = 0);
-
-bool CheckColorImage (uint32 parentCode,
- uint32 tagCode,
- uint32 colorPlanes);
-
-bool CheckMainIFD (uint32 parentCode,
- uint32 tagCode,
- uint32 newSubFileType);
-
-bool CheckRawIFD (uint32 parentCode,
- uint32 tagCode,
- uint32 photometricInterpretation);
-
-bool CheckCFA (uint32 parentCode,
- uint32 tagCode,
- uint32 photometricInterpretation);
-
-/*****************************************************************************/
-
-void ParseStringTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagCount,
- dng_string &s,
- bool trimBlanks = true);
-
-void ParseDualStringTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagCount,
- dng_string &s1,
- dng_string &s2);
-
-void ParseEncodedStringTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagCount,
- dng_string &s);
-
-bool ParseMatrixTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint32 rows,
- uint32 cols,
- dng_matrix &m);
-
-bool ParseVectorTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint32 count,
- dng_vector &v);
-
-bool ParseDateTimeTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- dng_date_time &dt);
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_parse_utils.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_parse_utils__
+#define __dng_parse_utils__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_flags.h"
+#include "dng_types.h"
+#include "dng_stream.h"
+#include "dng_string.h"
+#include "dng_matrix.h"
+
+/*****************************************************************************/
+
+#if qDNGValidate
+
+/*****************************************************************************/
+
+const char * LookupParentCode (uint32 parentCode);
+
+/*****************************************************************************/
+
+const char * LookupTagCode (uint32 parentCode,
+ uint32 tagCode);
+
+/*****************************************************************************/
+
+const char * LookupTagType (uint32 tagType);
+
+/*****************************************************************************/
+
+const char * LookupNewSubFileType (uint32 key);
+
+const char * LookupCompression (uint32 key);
+
+const char * LookupPredictor (uint32 key);
+
+const char * LookupSampleFormat (uint32 key);
+
+const char * LookupPhotometricInterpretation (uint32 key);
+
+const char * LookupOrientation (uint32 key);
+
+const char * LookupResolutionUnit (uint32 key);
+
+const char * LookupCFAColor (uint32 key);
+
+const char * LookupSensingMethod (uint32 key);
+
+const char * LookupExposureProgram (uint32 key);
+
+const char * LookupMeteringMode (uint32 key);
+
+const char * LookupLightSource (uint32 key);
+
+const char * LookupColorSpace (uint32 key);
+
+const char * LookupFileSource (uint32 key);
+
+const char * LookupSceneType (uint32 key);
+
+const char * LookupCustomRendered (uint32 key);
+
+const char * LookupExposureMode (uint32 key);
+
+const char * LookupWhiteBalance (uint32 key);
+
+const char * LookupSceneCaptureType (uint32 key);
+
+const char * LookupGainControl (uint32 key);
+
+const char * LookupContrast (uint32 key);
+
+const char * LookupSaturation (uint32 key);
+
+const char * LookupSharpness (uint32 key);
+
+const char * LookupSubjectDistanceRange (uint32 key);
+
+const char * LookupComponent (uint32 key);
+
+const char * LookupCFALayout (uint32 key);
+
+const char * LookupMakerNoteSafety (uint32 key);
+
+const char * LookupColorimetricReference (uint32 key);
+
+const char * LookupPreviewColorSpace (uint32 key);
+
+const char * LookupJPEGMarker (uint32 key);
+
+const char * LookupSensitivityType (uint32 key);
+
+/*****************************************************************************/
+
+void DumpHexAscii (dng_stream &stream,
+ uint32 count);
+
+void DumpHexAscii (const uint8 *buf,
+ uint32 count);
+
+void DumpXMP (dng_stream &stream,
+ uint32 count);
+
+void DumpString (const dng_string &s);
+
+void DumpTagValues (dng_stream &stream,
+ const char *entry_name,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ const char *tag_name = NULL);
+
+void DumpMatrix (const dng_matrix &m);
+
+void DumpVector (const dng_vector &v);
+
+void DumpDateTime (const dng_date_time &dt);
+
+void DumpExposureTime (real64 x);
+
+void DumpFingerprint (const dng_fingerprint &p);
+
+void DumpHueSatMap (dng_stream &stream,
+ uint32 hues,
+ uint32 sats,
+ uint32 vals,
+ bool skipSat0);
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
+
+bool CheckTagType (uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint16 validType0,
+ uint16 validType1 = 0,
+ uint16 validType2 = 0,
+ uint16 validType3 = 0);
+
+bool CheckTagCount (uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ uint32 minCount,
+ uint32 maxCount = 0);
+
+bool CheckColorImage (uint32 parentCode,
+ uint32 tagCode,
+ uint32 colorPlanes);
+
+bool CheckMainIFD (uint32 parentCode,
+ uint32 tagCode,
+ uint32 newSubFileType);
+
+bool CheckRawIFD (uint32 parentCode,
+ uint32 tagCode,
+ uint32 photometricInterpretation);
+
+bool CheckCFA (uint32 parentCode,
+ uint32 tagCode,
+ uint32 photometricInterpretation);
+
+/*****************************************************************************/
+
+void ParseStringTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ dng_string &s,
+ bool trimBlanks = true);
+
+void ParseDualStringTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ dng_string &s1,
+ dng_string &s2);
+
+void ParseEncodedStringTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ dng_string &s);
+
+bool ParseMatrixTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint32 rows,
+ uint32 cols,
+ dng_matrix &m);
+
+bool ParseVectorTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint32 count,
+ dng_vector &v);
+
+bool ParseDateTimeTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ dng_date_time &dt);
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_point.cpp b/source/dng_point.cpp
index abfd7dd..2b61e92 100644
--- a/source/dng_point.cpp
+++ b/source/dng_point.cpp
@@ -1,22 +1,22 @@
-/*****************************************************************************/
-// Copyright 2006 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_point.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_point.h"
-
-/*****************************************************************************/
-
-// Currently all inlined.
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_point.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_point.h"
+
+/*****************************************************************************/
+
+// Currently all inlined.
+
+/*****************************************************************************/
diff --git a/source/dng_point.h b/source/dng_point.h
index e92e93a..c6070b9 100644
--- a/source/dng_point.h
+++ b/source/dng_point.h
@@ -1,199 +1,199 @@
-/*****************************************************************************/
-// Copyright 2006 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_point.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_point__
-#define __dng_point__
-
-/*****************************************************************************/
-
-#include "dng_types.h"
-#include "dng_safe_arithmetic.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-class dng_point
- {
-
- public:
-
- int32 v;
- int32 h;
-
- public:
-
- dng_point ()
- : v (0)
- , h (0)
- {
- }
-
- dng_point (int32 vv, int32 hh)
- : v (vv)
- , h (hh)
- {
- }
-
- bool operator== (const dng_point &pt) const
- {
- return (v == pt.v) &&
- (h == pt.h);
- }
-
- bool operator!= (const dng_point &pt) const
- {
- return !(*this == pt);
- }
-
- };
-
-/*****************************************************************************/
-
-class dng_point_real64
- {
-
- public:
-
- real64 v;
- real64 h;
-
- public:
-
- dng_point_real64 ()
- : v (0.0)
- , h (0.0)
- {
- }
-
- dng_point_real64 (real64 vv, real64 hh)
- : v (vv)
- , h (hh)
- {
- }
-
- dng_point_real64 (const dng_point &pt)
- : v ((real64) pt.v)
- , h ((real64) pt.h)
- {
- }
-
- bool operator== (const dng_point_real64 &pt) const
- {
- return (v == pt.v) &&
- (h == pt.h);
- }
-
- bool operator!= (const dng_point_real64 &pt) const
- {
- return !(*this == pt);
- }
-
- dng_point Round () const
- {
- return dng_point (Round_int32 (v),
- Round_int32 (h));
- }
-
- };
-
-/*****************************************************************************/
-
-inline dng_point operator+ (const dng_point &a,
- const dng_point &b)
-
-
- {
-
- return dng_point (SafeInt32Add(a.v, b.v),
- SafeInt32Add(a.h, b.h));
-
- }
-
-/*****************************************************************************/
-
-inline dng_point_real64 operator+ (const dng_point_real64 &a,
- const dng_point_real64 &b)
-
-
- {
-
- return dng_point_real64 (a.v + b.v,
- a.h + b.h);
-
- }
-
-/*****************************************************************************/
-
-inline dng_point operator- (const dng_point &a,
- const dng_point &b)
-
-
- {
-
- return dng_point (SafeInt32Sub(a.v, b.v),
- SafeInt32Sub(a.h, b.h));
-
- }
-
-/*****************************************************************************/
-
-inline dng_point_real64 operator- (const dng_point_real64 &a,
- const dng_point_real64 &b)
-
-
- {
-
- return dng_point_real64 (a.v - b.v,
- a.h - b.h);
-
- }
-
-/*****************************************************************************/
-
-inline real64 DistanceSquared (const dng_point_real64 &a,
- const dng_point_real64 &b)
-
-
- {
-
- dng_point_real64 diff = a - b;
-
- return (diff.v * diff.v) + (diff.h * diff.h);
-
- }
-
-/*****************************************************************************/
-
-inline dng_point Transpose (const dng_point &a)
- {
-
- return dng_point (a.h, a.v);
-
- }
-
-/*****************************************************************************/
-
-inline dng_point_real64 Transpose (const dng_point_real64 &a)
- {
-
- return dng_point_real64 (a.h, a.v);
-
- }
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_point.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_point__
+#define __dng_point__
+
+/*****************************************************************************/
+
+#include "dng_types.h"
+#include "dng_safe_arithmetic.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+class dng_point
+ {
+
+ public:
+
+ int32 v;
+ int32 h;
+
+ public:
+
+ dng_point ()
+ : v (0)
+ , h (0)
+ {
+ }
+
+ dng_point (int32 vv, int32 hh)
+ : v (vv)
+ , h (hh)
+ {
+ }
+
+ bool operator== (const dng_point &pt) const
+ {
+ return (v == pt.v) &&
+ (h == pt.h);
+ }
+
+ bool operator!= (const dng_point &pt) const
+ {
+ return !(*this == pt);
+ }
+
+ };
+
+/*****************************************************************************/
+
+class dng_point_real64
+ {
+
+ public:
+
+ real64 v;
+ real64 h;
+
+ public:
+
+ dng_point_real64 ()
+ : v (0.0)
+ , h (0.0)
+ {
+ }
+
+ dng_point_real64 (real64 vv, real64 hh)
+ : v (vv)
+ , h (hh)
+ {
+ }
+
+ dng_point_real64 (const dng_point &pt)
+ : v ((real64) pt.v)
+ , h ((real64) pt.h)
+ {
+ }
+
+ bool operator== (const dng_point_real64 &pt) const
+ {
+ return (v == pt.v) &&
+ (h == pt.h);
+ }
+
+ bool operator!= (const dng_point_real64 &pt) const
+ {
+ return !(*this == pt);
+ }
+
+ dng_point Round () const
+ {
+ return dng_point (Round_int32 (v),
+ Round_int32 (h));
+ }
+
+ };
+
+/*****************************************************************************/
+
+inline dng_point operator+ (const dng_point &a,
+ const dng_point &b)
+
+
+ {
+
+ return dng_point (SafeInt32Add(a.v, b.v),
+ SafeInt32Add(a.h, b.h));
+
+ }
+
+/*****************************************************************************/
+
+inline dng_point_real64 operator+ (const dng_point_real64 &a,
+ const dng_point_real64 &b)
+
+
+ {
+
+ return dng_point_real64 (a.v + b.v,
+ a.h + b.h);
+
+ }
+
+/*****************************************************************************/
+
+inline dng_point operator- (const dng_point &a,
+ const dng_point &b)
+
+
+ {
+
+ return dng_point (SafeInt32Sub(a.v, b.v),
+ SafeInt32Sub(a.h, b.h));
+
+ }
+
+/*****************************************************************************/
+
+inline dng_point_real64 operator- (const dng_point_real64 &a,
+ const dng_point_real64 &b)
+
+
+ {
+
+ return dng_point_real64 (a.v - b.v,
+ a.h - b.h);
+
+ }
+
+/*****************************************************************************/
+
+inline real64 DistanceSquared (const dng_point_real64 &a,
+ const dng_point_real64 &b)
+
+
+ {
+
+ dng_point_real64 diff = a - b;
+
+ return (diff.v * diff.v) + (diff.h * diff.h);
+
+ }
+
+/*****************************************************************************/
+
+inline dng_point Transpose (const dng_point &a)
+ {
+
+ return dng_point (a.h, a.v);
+
+ }
+
+/*****************************************************************************/
+
+inline dng_point_real64 Transpose (const dng_point_real64 &a)
+ {
+
+ return dng_point_real64 (a.h, a.v);
+
+ }
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_preview.cpp b/source/dng_preview.cpp
index 1a65cb0..6fbeb20 100644
--- a/source/dng_preview.cpp
+++ b/source/dng_preview.cpp
@@ -1,709 +1,709 @@
-/*****************************************************************************/
-// Copyright 2007-2011 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_preview.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_preview.h"
-
-#include "dng_assertions.h"
-#include "dng_image.h"
-#include "dng_image_writer.h"
-#include "dng_memory.h"
-#include "dng_stream.h"
-#include "dng_tag_codes.h"
-#include "dng_tag_values.h"
-
-/*****************************************************************************/
-
-class dng_preview_tag_set: public dng_basic_tag_set
- {
-
- private:
-
- tag_string fApplicationNameTag;
-
- tag_string fApplicationVersionTag;
-
- tag_string fSettingsNameTag;
-
- dng_fingerprint fSettingsDigest;
-
- tag_uint8_ptr fSettingsDigestTag;
-
- tag_uint32 fColorSpaceTag;
-
- tag_string fDateTimeTag;
-
- tag_real64 fRawToPreviewGainTag;
-
- tag_uint32 fCacheVersionTag;
-
- public:
-
- dng_preview_tag_set (dng_tiff_directory &directory,
- const dng_preview &preview,
- const dng_ifd &ifd);
-
- virtual ~dng_preview_tag_set ();
-
- };
-
-/*****************************************************************************/
-
-dng_preview_tag_set::dng_preview_tag_set (dng_tiff_directory &directory,
- const dng_preview &preview,
- const dng_ifd &ifd)
-
- : dng_basic_tag_set (directory, ifd)
-
- , fApplicationNameTag (tcPreviewApplicationName,
- preview.fInfo.fApplicationName,
- false)
-
- , fApplicationVersionTag (tcPreviewApplicationVersion,
- preview.fInfo.fApplicationVersion,
- false)
-
- , fSettingsNameTag (tcPreviewSettingsName,
- preview.fInfo.fSettingsName,
- false)
-
- , fSettingsDigest (preview.fInfo.fSettingsDigest)
-
- , fSettingsDigestTag (tcPreviewSettingsDigest,
- fSettingsDigest.data,
- 16)
-
- , fColorSpaceTag (tcPreviewColorSpace,
- preview.fInfo.fColorSpace)
-
- , fDateTimeTag (tcPreviewDateTime,
- preview.fInfo.fDateTime,
- true)
-
- , fRawToPreviewGainTag (tcRawToPreviewGain,
- preview.fInfo.fRawToPreviewGain)
-
- , fCacheVersionTag (tcCacheVersion,
- preview.fInfo.fCacheVersion)
-
- {
-
- if (preview.fInfo.fApplicationName.NotEmpty ())
- {
-
- directory.Add (&fApplicationNameTag);
-
- }
-
- if (preview.fInfo.fApplicationVersion.NotEmpty ())
- {
-
- directory.Add (&fApplicationVersionTag);
-
- }
-
- if (preview.fInfo.fSettingsName.NotEmpty ())
- {
-
- directory.Add (&fSettingsNameTag);
-
- }
-
- if (preview.fInfo.fSettingsDigest.IsValid ())
- {
-
- directory.Add (&fSettingsDigestTag);
-
- }
-
- if (preview.fInfo.fColorSpace != previewColorSpace_MaxEnum)
- {
-
- directory.Add (&fColorSpaceTag);
-
- }
-
- if (preview.fInfo.fDateTime.NotEmpty ())
- {
-
- directory.Add (&fDateTimeTag);
-
- }
-
- if (preview.fInfo.fRawToPreviewGain != 1.0)
- {
-
- directory.Add (&fRawToPreviewGainTag);
-
- }
-
- if (preview.fInfo.fCacheVersion != 0)
- {
-
- directory.Add (&fCacheVersionTag);
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_preview_tag_set::~dng_preview_tag_set ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_preview::dng_preview ()
-
- : fInfo ()
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_preview::~dng_preview ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_image_preview::dng_image_preview ()
-
- : fImage ()
- , fIFD ()
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_image_preview::~dng_image_preview ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_basic_tag_set * dng_image_preview::AddTagSet (dng_tiff_directory &directory) const
- {
-
- fIFD.fNewSubFileType = fInfo.fIsPrimary ? sfPreviewImage
- : sfAltPreviewImage;
-
- fIFD.fImageWidth = fImage->Width ();
- fIFD.fImageLength = fImage->Height ();
-
- fIFD.fSamplesPerPixel = fImage->Planes ();
-
- fIFD.fPhotometricInterpretation = fIFD.fSamplesPerPixel == 1 ? piBlackIsZero
- : piRGB;
-
- fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
-
- for (uint32 j = 1; j < fIFD.fSamplesPerPixel; j++)
- {
- fIFD.fBitsPerSample [j] = fIFD.fBitsPerSample [0];
- }
-
- fIFD.SetSingleStrip ();
-
- return new dng_preview_tag_set (directory, *this, fIFD);
-
- }
-
-/*****************************************************************************/
-
-void dng_image_preview::WriteData (dng_host &host,
- dng_image_writer &writer,
- dng_basic_tag_set &basic,
- dng_stream &stream) const
- {
-
- writer.WriteImage (host,
- fIFD,
- basic,
- stream,
- *fImage.Get ());
-
- }
-
-/*****************************************************************************/
-
-class dng_jpeg_preview_tag_set: public dng_preview_tag_set
- {
-
- private:
-
- dng_urational fCoefficientsData [3];
-
- tag_urational_ptr fCoefficientsTag;
-
- uint16 fSubSamplingData [2];
-
- tag_uint16_ptr fSubSamplingTag;
-
- tag_uint16 fPositioningTag;
-
- dng_urational fReferenceData [6];
-
- tag_urational_ptr fReferenceTag;
-
- public:
-
- dng_jpeg_preview_tag_set (dng_tiff_directory &directory,
- const dng_jpeg_preview &preview,
- const dng_ifd &ifd);
-
- virtual ~dng_jpeg_preview_tag_set ();
-
- };
-
-/******************************************************************************/
-
-dng_jpeg_preview_tag_set::dng_jpeg_preview_tag_set (dng_tiff_directory &directory,
- const dng_jpeg_preview &preview,
- const dng_ifd &ifd)
-
- : dng_preview_tag_set (directory, preview, ifd)
-
- , fCoefficientsTag (tcYCbCrCoefficients, fCoefficientsData, 3)
-
- , fSubSamplingTag (tcYCbCrSubSampling, fSubSamplingData, 2)
-
- , fPositioningTag (tcYCbCrPositioning, preview.fYCbCrPositioning)
-
- , fReferenceTag (tcReferenceBlackWhite, fReferenceData, 6)
-
- {
-
- if (preview.fPhotometricInterpretation == piYCbCr)
- {
-
- fCoefficientsData [0] = dng_urational (299, 1000);
- fCoefficientsData [1] = dng_urational (587, 1000);
- fCoefficientsData [2] = dng_urational (114, 1000);
-
- directory.Add (&fCoefficientsTag);
-
- fSubSamplingData [0] = (uint16) preview.fYCbCrSubSampling.h;
- fSubSamplingData [1] = (uint16) preview.fYCbCrSubSampling.v;
-
- directory.Add (&fSubSamplingTag);
-
- directory.Add (&fPositioningTag);
-
- fReferenceData [0] = dng_urational ( 0, 1);
- fReferenceData [1] = dng_urational (255, 1);
- fReferenceData [2] = dng_urational (128, 1);
- fReferenceData [3] = dng_urational (255, 1);
- fReferenceData [4] = dng_urational (128, 1);
- fReferenceData [5] = dng_urational (255, 1);
-
- directory.Add (&fReferenceTag);
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_jpeg_preview_tag_set::~dng_jpeg_preview_tag_set ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_jpeg_preview::dng_jpeg_preview ()
-
- : fPreviewSize ()
- , fPhotometricInterpretation (piYCbCr)
- , fYCbCrSubSampling (1, 1)
- , fYCbCrPositioning (2)
- , fCompressedData ()
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_jpeg_preview::~dng_jpeg_preview ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_basic_tag_set * dng_jpeg_preview::AddTagSet (dng_tiff_directory &directory) const
- {
-
- dng_ifd ifd;
-
- ifd.fNewSubFileType = fInfo.fIsPrimary ? sfPreviewImage
- : sfAltPreviewImage;
-
- ifd.fImageWidth = fPreviewSize.h;
- ifd.fImageLength = fPreviewSize.v;
-
- ifd.fPhotometricInterpretation = fPhotometricInterpretation;
-
- ifd.fBitsPerSample [0] = 8;
- ifd.fBitsPerSample [1] = 8;
- ifd.fBitsPerSample [2] = 8;
-
- ifd.fSamplesPerPixel = (fPhotometricInterpretation == piBlackIsZero ? 1 : 3);
-
- ifd.fCompression = ccJPEG;
- ifd.fPredictor = cpNullPredictor;
-
- ifd.SetSingleStrip ();
-
- return new dng_jpeg_preview_tag_set (directory, *this, ifd);
-
- }
-
-/*****************************************************************************/
-
-void dng_jpeg_preview::WriteData (dng_host & /* host */,
- dng_image_writer & /* writer */,
- dng_basic_tag_set &basic,
- dng_stream &stream) const
- {
-
- basic.SetTileOffset (0, (uint32) stream.Position ());
-
- basic.SetTileByteCount (0, fCompressedData->LogicalSize ());
-
- stream.Put (fCompressedData->Buffer (),
- fCompressedData->LogicalSize ());
-
- if (fCompressedData->LogicalSize () & 1)
- {
- stream.Put_uint8 (0);
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_jpeg_preview::SpoolAdobeThumbnail (dng_stream &stream) const
- {
-
- DNG_ASSERT (fCompressedData.Get (),
- "SpoolAdobeThumbnail: no data");
-
- DNG_ASSERT (fPhotometricInterpretation == piYCbCr,
- "SpoolAdobeThumbnail: Non-YCbCr");
-
- uint32 compressedSize = fCompressedData->LogicalSize ();
-
- stream.Put_uint32 (DNG_CHAR4 ('8','B','I','M'));
- stream.Put_uint16 (1036);
- stream.Put_uint16 (0);
-
- stream.Put_uint32 (compressedSize + 28);
-
- uint32 widthBytes = (fPreviewSize.h * 24 + 31) / 32 * 4;
-
- stream.Put_uint32 (1);
- stream.Put_uint32 (fPreviewSize.h);
- stream.Put_uint32 (fPreviewSize.v);
- stream.Put_uint32 (widthBytes);
- stream.Put_uint32 (widthBytes * fPreviewSize.v);
- stream.Put_uint32 (compressedSize);
- stream.Put_uint16 (24);
- stream.Put_uint16 (1);
-
- stream.Put (fCompressedData->Buffer (),
- compressedSize);
-
- if (compressedSize & 1)
- {
- stream.Put_uint8 (0);
- }
-
- }
-
-/*****************************************************************************/
-
-class dng_raw_preview_tag_set: public dng_preview_tag_set
- {
-
- private:
-
- tag_data_ptr fOpcodeList2Tag;
-
- tag_uint32_ptr fWhiteLevelTag;
-
- uint32 fWhiteLevelData [kMaxColorPlanes];
-
- public:
-
- dng_raw_preview_tag_set (dng_tiff_directory &directory,
- const dng_raw_preview &preview,
- const dng_ifd &ifd);
-
- virtual ~dng_raw_preview_tag_set ();
-
- };
-
-/*****************************************************************************/
-
-dng_raw_preview_tag_set::dng_raw_preview_tag_set (dng_tiff_directory &directory,
- const dng_raw_preview &preview,
- const dng_ifd &ifd)
-
- : dng_preview_tag_set (directory, preview, ifd)
-
- , fOpcodeList2Tag (tcOpcodeList2,
- ttUndefined,
- 0,
- NULL)
-
- , fWhiteLevelTag (tcWhiteLevel,
- fWhiteLevelData,
- preview.fImage->Planes ())
-
- {
-
- if (preview.fOpcodeList2Data.Get ())
- {
-
- fOpcodeList2Tag.SetData (preview.fOpcodeList2Data->Buffer ());
- fOpcodeList2Tag.SetCount (preview.fOpcodeList2Data->LogicalSize ());
-
- directory.Add (&fOpcodeList2Tag);
-
- }
-
- if (preview.fImage->PixelType () == ttFloat)
- {
-
- for (uint32 j = 0; j < kMaxColorPlanes; j++)
- {
- fWhiteLevelData [j] = 32768;
- }
-
- directory.Add (&fWhiteLevelTag);
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_raw_preview_tag_set::~dng_raw_preview_tag_set ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_raw_preview::dng_raw_preview ()
-
- : fImage ()
- , fOpcodeList2Data ()
- , fCompressionQuality (-1)
- , fIFD ()
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_raw_preview::~dng_raw_preview ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_basic_tag_set * dng_raw_preview::AddTagSet (dng_tiff_directory &directory) const
- {
-
- fIFD.fNewSubFileType = sfPreviewImage;
-
- fIFD.fImageWidth = fImage->Width ();
- fIFD.fImageLength = fImage->Height ();
-
- fIFD.fSamplesPerPixel = fImage->Planes ();
-
- fIFD.fPhotometricInterpretation = piLinearRaw;
-
- if (fImage->PixelType () == ttFloat)
- {
-
- fIFD.fCompression = ccDeflate;
-
- fIFD.fCompressionQuality = fCompressionQuality;
-
- fIFD.fPredictor = cpFloatingPoint;
-
- for (uint32 j = 0; j < fIFD.fSamplesPerPixel; j++)
- {
- fIFD.fBitsPerSample [j] = 16;
- fIFD.fSampleFormat [j] = sfFloatingPoint;
- }
-
- fIFD.FindTileSize (512 * 1024);
-
- }
-
- else
- {
-
- fIFD.fCompression = ccLossyJPEG;
-
- fIFD.fCompressionQuality = fCompressionQuality;
-
- fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
-
- for (uint32 j = 1; j < fIFD.fSamplesPerPixel; j++)
- {
- fIFD.fBitsPerSample [j] = fIFD.fBitsPerSample [0];
- }
-
- fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel);
-
- }
-
- return new dng_raw_preview_tag_set (directory, *this, fIFD);
-
- }
-
-/*****************************************************************************/
-
-void dng_raw_preview::WriteData (dng_host &host,
- dng_image_writer &writer,
- dng_basic_tag_set &basic,
- dng_stream &stream) const
- {
-
- writer.WriteImage (host,
- fIFD,
- basic,
- stream,
- *fImage.Get ());
-
- }
-
-/*****************************************************************************/
-
-dng_mask_preview::dng_mask_preview ()
-
- : fImage ()
- , fCompressionQuality (-1)
- , fIFD ()
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_mask_preview::~dng_mask_preview ()
- {
-
- }
-
-/*****************************************************************************/
-
-dng_basic_tag_set * dng_mask_preview::AddTagSet (dng_tiff_directory &directory) const
- {
-
- fIFD.fNewSubFileType = sfPreviewMask;
-
- fIFD.fImageWidth = fImage->Width ();
- fIFD.fImageLength = fImage->Height ();
-
- fIFD.fSamplesPerPixel = 1;
-
- fIFD.fPhotometricInterpretation = piTransparencyMask;
-
- fIFD.fCompression = ccDeflate;
- fIFD.fPredictor = cpHorizontalDifference;
-
- fIFD.fCompressionQuality = fCompressionQuality;
-
- fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
-
- fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel);
-
- return new dng_basic_tag_set (directory, fIFD);
-
- }
-
-/*****************************************************************************/
-
-void dng_mask_preview::WriteData (dng_host &host,
- dng_image_writer &writer,
- dng_basic_tag_set &basic,
- dng_stream &stream) const
- {
-
- writer.WriteImage (host,
- fIFD,
- basic,
- stream,
- *fImage.Get ());
-
- }
-
-/*****************************************************************************/
-
-dng_preview_list::dng_preview_list ()
-
- : fCount (0)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_preview_list::~dng_preview_list ()
- {
-
- }
-
-/*****************************************************************************/
-
-void dng_preview_list::Append (AutoPtr<dng_preview> &preview)
- {
-
- if (preview.Get ())
- {
-
- DNG_ASSERT (fCount < kMaxDNGPreviews, "DNG preview list overflow");
-
- if (fCount < kMaxDNGPreviews)
- {
-
- fPreview [fCount++] . Reset (preview.Release ());
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2007-2011 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_preview.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_preview.h"
+
+#include "dng_assertions.h"
+#include "dng_image.h"
+#include "dng_image_writer.h"
+#include "dng_memory.h"
+#include "dng_stream.h"
+#include "dng_tag_codes.h"
+#include "dng_tag_values.h"
+
+/*****************************************************************************/
+
+class dng_preview_tag_set: public dng_basic_tag_set
+ {
+
+ private:
+
+ tag_string fApplicationNameTag;
+
+ tag_string fApplicationVersionTag;
+
+ tag_string fSettingsNameTag;
+
+ dng_fingerprint fSettingsDigest;
+
+ tag_uint8_ptr fSettingsDigestTag;
+
+ tag_uint32 fColorSpaceTag;
+
+ tag_string fDateTimeTag;
+
+ tag_real64 fRawToPreviewGainTag;
+
+ tag_uint32 fCacheVersionTag;
+
+ public:
+
+ dng_preview_tag_set (dng_tiff_directory &directory,
+ const dng_preview &preview,
+ const dng_ifd &ifd);
+
+ virtual ~dng_preview_tag_set ();
+
+ };
+
+/*****************************************************************************/
+
+dng_preview_tag_set::dng_preview_tag_set (dng_tiff_directory &directory,
+ const dng_preview &preview,
+ const dng_ifd &ifd)
+
+ : dng_basic_tag_set (directory, ifd)
+
+ , fApplicationNameTag (tcPreviewApplicationName,
+ preview.fInfo.fApplicationName,
+ false)
+
+ , fApplicationVersionTag (tcPreviewApplicationVersion,
+ preview.fInfo.fApplicationVersion,
+ false)
+
+ , fSettingsNameTag (tcPreviewSettingsName,
+ preview.fInfo.fSettingsName,
+ false)
+
+ , fSettingsDigest (preview.fInfo.fSettingsDigest)
+
+ , fSettingsDigestTag (tcPreviewSettingsDigest,
+ fSettingsDigest.data,
+ 16)
+
+ , fColorSpaceTag (tcPreviewColorSpace,
+ preview.fInfo.fColorSpace)
+
+ , fDateTimeTag (tcPreviewDateTime,
+ preview.fInfo.fDateTime,
+ true)
+
+ , fRawToPreviewGainTag (tcRawToPreviewGain,
+ preview.fInfo.fRawToPreviewGain)
+
+ , fCacheVersionTag (tcCacheVersion,
+ preview.fInfo.fCacheVersion)
+
+ {
+
+ if (preview.fInfo.fApplicationName.NotEmpty ())
+ {
+
+ directory.Add (&fApplicationNameTag);
+
+ }
+
+ if (preview.fInfo.fApplicationVersion.NotEmpty ())
+ {
+
+ directory.Add (&fApplicationVersionTag);
+
+ }
+
+ if (preview.fInfo.fSettingsName.NotEmpty ())
+ {
+
+ directory.Add (&fSettingsNameTag);
+
+ }
+
+ if (preview.fInfo.fSettingsDigest.IsValid ())
+ {
+
+ directory.Add (&fSettingsDigestTag);
+
+ }
+
+ if (preview.fInfo.fColorSpace != previewColorSpace_MaxEnum)
+ {
+
+ directory.Add (&fColorSpaceTag);
+
+ }
+
+ if (preview.fInfo.fDateTime.NotEmpty ())
+ {
+
+ directory.Add (&fDateTimeTag);
+
+ }
+
+ if (preview.fInfo.fRawToPreviewGain != 1.0)
+ {
+
+ directory.Add (&fRawToPreviewGainTag);
+
+ }
+
+ if (preview.fInfo.fCacheVersion != 0)
+ {
+
+ directory.Add (&fCacheVersionTag);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_preview_tag_set::~dng_preview_tag_set ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_preview::dng_preview ()
+
+ : fInfo ()
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_preview::~dng_preview ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_image_preview::dng_image_preview ()
+
+ : fImage ()
+ , fIFD ()
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_image_preview::~dng_image_preview ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_basic_tag_set * dng_image_preview::AddTagSet (dng_tiff_directory &directory) const
+ {
+
+ fIFD.fNewSubFileType = fInfo.fIsPrimary ? sfPreviewImage
+ : sfAltPreviewImage;
+
+ fIFD.fImageWidth = fImage->Width ();
+ fIFD.fImageLength = fImage->Height ();
+
+ fIFD.fSamplesPerPixel = fImage->Planes ();
+
+ fIFD.fPhotometricInterpretation = fIFD.fSamplesPerPixel == 1 ? piBlackIsZero
+ : piRGB;
+
+ fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
+
+ for (uint32 j = 1; j < fIFD.fSamplesPerPixel; j++)
+ {
+ fIFD.fBitsPerSample [j] = fIFD.fBitsPerSample [0];
+ }
+
+ fIFD.SetSingleStrip ();
+
+ return new dng_preview_tag_set (directory, *this, fIFD);
+
+ }
+
+/*****************************************************************************/
+
+void dng_image_preview::WriteData (dng_host &host,
+ dng_image_writer &writer,
+ dng_basic_tag_set &basic,
+ dng_stream &stream) const
+ {
+
+ writer.WriteImage (host,
+ fIFD,
+ basic,
+ stream,
+ *fImage.Get ());
+
+ }
+
+/*****************************************************************************/
+
+class dng_jpeg_preview_tag_set: public dng_preview_tag_set
+ {
+
+ private:
+
+ dng_urational fCoefficientsData [3];
+
+ tag_urational_ptr fCoefficientsTag;
+
+ uint16 fSubSamplingData [2];
+
+ tag_uint16_ptr fSubSamplingTag;
+
+ tag_uint16 fPositioningTag;
+
+ dng_urational fReferenceData [6];
+
+ tag_urational_ptr fReferenceTag;
+
+ public:
+
+ dng_jpeg_preview_tag_set (dng_tiff_directory &directory,
+ const dng_jpeg_preview &preview,
+ const dng_ifd &ifd);
+
+ virtual ~dng_jpeg_preview_tag_set ();
+
+ };
+
+/******************************************************************************/
+
+dng_jpeg_preview_tag_set::dng_jpeg_preview_tag_set (dng_tiff_directory &directory,
+ const dng_jpeg_preview &preview,
+ const dng_ifd &ifd)
+
+ : dng_preview_tag_set (directory, preview, ifd)
+
+ , fCoefficientsTag (tcYCbCrCoefficients, fCoefficientsData, 3)
+
+ , fSubSamplingTag (tcYCbCrSubSampling, fSubSamplingData, 2)
+
+ , fPositioningTag (tcYCbCrPositioning, preview.fYCbCrPositioning)
+
+ , fReferenceTag (tcReferenceBlackWhite, fReferenceData, 6)
+
+ {
+
+ if (preview.fPhotometricInterpretation == piYCbCr)
+ {
+
+ fCoefficientsData [0] = dng_urational (299, 1000);
+ fCoefficientsData [1] = dng_urational (587, 1000);
+ fCoefficientsData [2] = dng_urational (114, 1000);
+
+ directory.Add (&fCoefficientsTag);
+
+ fSubSamplingData [0] = (uint16) preview.fYCbCrSubSampling.h;
+ fSubSamplingData [1] = (uint16) preview.fYCbCrSubSampling.v;
+
+ directory.Add (&fSubSamplingTag);
+
+ directory.Add (&fPositioningTag);
+
+ fReferenceData [0] = dng_urational ( 0, 1);
+ fReferenceData [1] = dng_urational (255, 1);
+ fReferenceData [2] = dng_urational (128, 1);
+ fReferenceData [3] = dng_urational (255, 1);
+ fReferenceData [4] = dng_urational (128, 1);
+ fReferenceData [5] = dng_urational (255, 1);
+
+ directory.Add (&fReferenceTag);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_jpeg_preview_tag_set::~dng_jpeg_preview_tag_set ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_jpeg_preview::dng_jpeg_preview ()
+
+ : fPreviewSize ()
+ , fPhotometricInterpretation (piYCbCr)
+ , fYCbCrSubSampling (1, 1)
+ , fYCbCrPositioning (2)
+ , fCompressedData ()
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_jpeg_preview::~dng_jpeg_preview ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_basic_tag_set * dng_jpeg_preview::AddTagSet (dng_tiff_directory &directory) const
+ {
+
+ dng_ifd ifd;
+
+ ifd.fNewSubFileType = fInfo.fIsPrimary ? sfPreviewImage
+ : sfAltPreviewImage;
+
+ ifd.fImageWidth = fPreviewSize.h;
+ ifd.fImageLength = fPreviewSize.v;
+
+ ifd.fPhotometricInterpretation = fPhotometricInterpretation;
+
+ ifd.fBitsPerSample [0] = 8;
+ ifd.fBitsPerSample [1] = 8;
+ ifd.fBitsPerSample [2] = 8;
+
+ ifd.fSamplesPerPixel = (fPhotometricInterpretation == piBlackIsZero ? 1 : 3);
+
+ ifd.fCompression = ccJPEG;
+ ifd.fPredictor = cpNullPredictor;
+
+ ifd.SetSingleStrip ();
+
+ return new dng_jpeg_preview_tag_set (directory, *this, ifd);
+
+ }
+
+/*****************************************************************************/
+
+void dng_jpeg_preview::WriteData (dng_host & /* host */,
+ dng_image_writer & /* writer */,
+ dng_basic_tag_set &basic,
+ dng_stream &stream) const
+ {
+
+ basic.SetTileOffset (0, (uint32) stream.Position ());
+
+ basic.SetTileByteCount (0, fCompressedData->LogicalSize ());
+
+ stream.Put (fCompressedData->Buffer (),
+ fCompressedData->LogicalSize ());
+
+ if (fCompressedData->LogicalSize () & 1)
+ {
+ stream.Put_uint8 (0);
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_jpeg_preview::SpoolAdobeThumbnail (dng_stream &stream) const
+ {
+
+ DNG_ASSERT (fCompressedData.Get (),
+ "SpoolAdobeThumbnail: no data");
+
+ DNG_ASSERT (fPhotometricInterpretation == piYCbCr,
+ "SpoolAdobeThumbnail: Non-YCbCr");
+
+ uint32 compressedSize = fCompressedData->LogicalSize ();
+
+ stream.Put_uint32 (DNG_CHAR4 ('8','B','I','M'));
+ stream.Put_uint16 (1036);
+ stream.Put_uint16 (0);
+
+ stream.Put_uint32 (compressedSize + 28);
+
+ uint32 widthBytes = (fPreviewSize.h * 24 + 31) / 32 * 4;
+
+ stream.Put_uint32 (1);
+ stream.Put_uint32 (fPreviewSize.h);
+ stream.Put_uint32 (fPreviewSize.v);
+ stream.Put_uint32 (widthBytes);
+ stream.Put_uint32 (widthBytes * fPreviewSize.v);
+ stream.Put_uint32 (compressedSize);
+ stream.Put_uint16 (24);
+ stream.Put_uint16 (1);
+
+ stream.Put (fCompressedData->Buffer (),
+ compressedSize);
+
+ if (compressedSize & 1)
+ {
+ stream.Put_uint8 (0);
+ }
+
+ }
+
+/*****************************************************************************/
+
+class dng_raw_preview_tag_set: public dng_preview_tag_set
+ {
+
+ private:
+
+ tag_data_ptr fOpcodeList2Tag;
+
+ tag_uint32_ptr fWhiteLevelTag;
+
+ uint32 fWhiteLevelData [kMaxColorPlanes];
+
+ public:
+
+ dng_raw_preview_tag_set (dng_tiff_directory &directory,
+ const dng_raw_preview &preview,
+ const dng_ifd &ifd);
+
+ virtual ~dng_raw_preview_tag_set ();
+
+ };
+
+/*****************************************************************************/
+
+dng_raw_preview_tag_set::dng_raw_preview_tag_set (dng_tiff_directory &directory,
+ const dng_raw_preview &preview,
+ const dng_ifd &ifd)
+
+ : dng_preview_tag_set (directory, preview, ifd)
+
+ , fOpcodeList2Tag (tcOpcodeList2,
+ ttUndefined,
+ 0,
+ NULL)
+
+ , fWhiteLevelTag (tcWhiteLevel,
+ fWhiteLevelData,
+ preview.fImage->Planes ())
+
+ {
+
+ if (preview.fOpcodeList2Data.Get ())
+ {
+
+ fOpcodeList2Tag.SetData (preview.fOpcodeList2Data->Buffer ());
+ fOpcodeList2Tag.SetCount (preview.fOpcodeList2Data->LogicalSize ());
+
+ directory.Add (&fOpcodeList2Tag);
+
+ }
+
+ if (preview.fImage->PixelType () == ttFloat)
+ {
+
+ for (uint32 j = 0; j < kMaxColorPlanes; j++)
+ {
+ fWhiteLevelData [j] = 32768;
+ }
+
+ directory.Add (&fWhiteLevelTag);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_raw_preview_tag_set::~dng_raw_preview_tag_set ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_raw_preview::dng_raw_preview ()
+
+ : fImage ()
+ , fOpcodeList2Data ()
+ , fCompressionQuality (-1)
+ , fIFD ()
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_raw_preview::~dng_raw_preview ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_basic_tag_set * dng_raw_preview::AddTagSet (dng_tiff_directory &directory) const
+ {
+
+ fIFD.fNewSubFileType = sfPreviewImage;
+
+ fIFD.fImageWidth = fImage->Width ();
+ fIFD.fImageLength = fImage->Height ();
+
+ fIFD.fSamplesPerPixel = fImage->Planes ();
+
+ fIFD.fPhotometricInterpretation = piLinearRaw;
+
+ if (fImage->PixelType () == ttFloat)
+ {
+
+ fIFD.fCompression = ccDeflate;
+
+ fIFD.fCompressionQuality = fCompressionQuality;
+
+ fIFD.fPredictor = cpFloatingPoint;
+
+ for (uint32 j = 0; j < fIFD.fSamplesPerPixel; j++)
+ {
+ fIFD.fBitsPerSample [j] = 16;
+ fIFD.fSampleFormat [j] = sfFloatingPoint;
+ }
+
+ fIFD.FindTileSize (512 * 1024);
+
+ }
+
+ else
+ {
+
+ fIFD.fCompression = ccLossyJPEG;
+
+ fIFD.fCompressionQuality = fCompressionQuality;
+
+ fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
+
+ for (uint32 j = 1; j < fIFD.fSamplesPerPixel; j++)
+ {
+ fIFD.fBitsPerSample [j] = fIFD.fBitsPerSample [0];
+ }
+
+ fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel);
+
+ }
+
+ return new dng_raw_preview_tag_set (directory, *this, fIFD);
+
+ }
+
+/*****************************************************************************/
+
+void dng_raw_preview::WriteData (dng_host &host,
+ dng_image_writer &writer,
+ dng_basic_tag_set &basic,
+ dng_stream &stream) const
+ {
+
+ writer.WriteImage (host,
+ fIFD,
+ basic,
+ stream,
+ *fImage.Get ());
+
+ }
+
+/*****************************************************************************/
+
+dng_mask_preview::dng_mask_preview ()
+
+ : fImage ()
+ , fCompressionQuality (-1)
+ , fIFD ()
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_mask_preview::~dng_mask_preview ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_basic_tag_set * dng_mask_preview::AddTagSet (dng_tiff_directory &directory) const
+ {
+
+ fIFD.fNewSubFileType = sfPreviewMask;
+
+ fIFD.fImageWidth = fImage->Width ();
+ fIFD.fImageLength = fImage->Height ();
+
+ fIFD.fSamplesPerPixel = 1;
+
+ fIFD.fPhotometricInterpretation = piTransparencyMask;
+
+ fIFD.fCompression = ccDeflate;
+ fIFD.fPredictor = cpHorizontalDifference;
+
+ fIFD.fCompressionQuality = fCompressionQuality;
+
+ fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
+
+ fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel);
+
+ return new dng_basic_tag_set (directory, fIFD);
+
+ }
+
+/*****************************************************************************/
+
+void dng_mask_preview::WriteData (dng_host &host,
+ dng_image_writer &writer,
+ dng_basic_tag_set &basic,
+ dng_stream &stream) const
+ {
+
+ writer.WriteImage (host,
+ fIFD,
+ basic,
+ stream,
+ *fImage.Get ());
+
+ }
+
+/*****************************************************************************/
+
+dng_preview_list::dng_preview_list ()
+
+ : fCount (0)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_preview_list::~dng_preview_list ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+void dng_preview_list::Append (AutoPtr<dng_preview> &preview)
+ {
+
+ if (preview.Get ())
+ {
+
+ DNG_ASSERT (fCount < kMaxDNGPreviews, "DNG preview list overflow");
+
+ if (fCount < kMaxDNGPreviews)
+ {
+
+ fPreview [fCount++] . Reset (preview.Release ());
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_preview.h b/source/dng_preview.h
index 2b616e3..30b61d7 100644
--- a/source/dng_preview.h
+++ b/source/dng_preview.h
@@ -1,245 +1,245 @@
-/*****************************************************************************/
-// Copyright 2007-2011 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_preview.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_preview__
-#define __dng_preview__
-
-/*****************************************************************************/
-
-#include "dng_auto_ptr.h"
-#include "dng_classes.h"
-#include "dng_ifd.h"
-#include "dng_opcode_list.h"
-#include "dng_point.h"
-#include "dng_sdk_limits.h"
-
-/*****************************************************************************/
-
-class dng_preview
- {
-
- public:
-
- dng_preview_info fInfo;
-
- protected:
-
- dng_preview ();
-
- public:
-
- virtual ~dng_preview ();
-
- virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const = 0;
-
- virtual void WriteData (dng_host &host,
- dng_image_writer &writer,
- dng_basic_tag_set &basic,
- dng_stream &stream) const = 0;
-
- };
-
-/*****************************************************************************/
-
-class dng_image_preview: public dng_preview
- {
-
- public:
-
- AutoPtr<dng_image> fImage;
-
- private:
-
- mutable dng_ifd fIFD;
-
- public:
-
- dng_image_preview ();
-
- virtual ~dng_image_preview ();
-
- virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
-
- virtual void WriteData (dng_host &host,
- dng_image_writer &writer,
- dng_basic_tag_set &basic,
- dng_stream &stream) const;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_image_preview (const dng_image_preview &preview);
-
- dng_image_preview & operator= (const dng_image_preview &preview);
-
- };
-
-/*****************************************************************************/
-
-class dng_jpeg_preview: public dng_preview
- {
-
- public:
-
- dng_point fPreviewSize;
-
- uint16 fPhotometricInterpretation;
-
- dng_point fYCbCrSubSampling;
-
- uint16 fYCbCrPositioning;
-
- AutoPtr<dng_memory_block> fCompressedData;
-
- public:
-
- dng_jpeg_preview ();
-
- virtual ~dng_jpeg_preview ();
-
- virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
-
- virtual void WriteData (dng_host &host,
- dng_image_writer &writer,
- dng_basic_tag_set &basic,
- dng_stream &stream) const;
-
- void SpoolAdobeThumbnail (dng_stream &stream) const;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_jpeg_preview (const dng_jpeg_preview &preview);
-
- dng_jpeg_preview & operator= (const dng_jpeg_preview &preview);
-
- };
-
-/*****************************************************************************/
-
-class dng_raw_preview: public dng_preview
- {
-
- public:
-
- AutoPtr<dng_image> fImage;
-
- AutoPtr<dng_memory_block> fOpcodeList2Data;
-
- int32 fCompressionQuality;
-
- private:
-
- mutable dng_ifd fIFD;
-
- public:
-
- dng_raw_preview ();
-
- virtual ~dng_raw_preview ();
-
- virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
-
- virtual void WriteData (dng_host &host,
- dng_image_writer &writer,
- dng_basic_tag_set &basic,
- dng_stream &stream) const;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_raw_preview (const dng_raw_preview &preview);
-
- dng_raw_preview & operator= (const dng_raw_preview &preview);
-
- };
-
-/*****************************************************************************/
-
-class dng_mask_preview: public dng_preview
- {
-
- public:
-
- AutoPtr<dng_image> fImage;
-
- int32 fCompressionQuality;
-
- private:
-
- mutable dng_ifd fIFD;
-
- public:
-
- dng_mask_preview ();
-
- virtual ~dng_mask_preview ();
-
- virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
-
- virtual void WriteData (dng_host &host,
- dng_image_writer &writer,
- dng_basic_tag_set &basic,
- dng_stream &stream) const;
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_mask_preview (const dng_mask_preview &preview);
-
- dng_mask_preview & operator= (const dng_mask_preview &preview);
-
- };
-
-/*****************************************************************************/
-
-class dng_preview_list
- {
-
- private:
-
- uint32 fCount;
-
- AutoPtr<dng_preview> fPreview [kMaxDNGPreviews];
-
- public:
-
- dng_preview_list ();
-
- ~dng_preview_list ();
-
- uint32 Count () const
- {
- return fCount;
- }
-
- const dng_preview & Preview (uint32 index) const
- {
- return *(fPreview [index]);
- }
-
- void Append (AutoPtr<dng_preview> &preview);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2007-2011 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_preview.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_preview__
+#define __dng_preview__
+
+/*****************************************************************************/
+
+#include "dng_auto_ptr.h"
+#include "dng_classes.h"
+#include "dng_ifd.h"
+#include "dng_opcode_list.h"
+#include "dng_point.h"
+#include "dng_sdk_limits.h"
+
+/*****************************************************************************/
+
+class dng_preview
+ {
+
+ public:
+
+ dng_preview_info fInfo;
+
+ protected:
+
+ dng_preview ();
+
+ public:
+
+ virtual ~dng_preview ();
+
+ virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const = 0;
+
+ virtual void WriteData (dng_host &host,
+ dng_image_writer &writer,
+ dng_basic_tag_set &basic,
+ dng_stream &stream) const = 0;
+
+ };
+
+/*****************************************************************************/
+
+class dng_image_preview: public dng_preview
+ {
+
+ public:
+
+ AutoPtr<dng_image> fImage;
+
+ private:
+
+ mutable dng_ifd fIFD;
+
+ public:
+
+ dng_image_preview ();
+
+ virtual ~dng_image_preview ();
+
+ virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
+
+ virtual void WriteData (dng_host &host,
+ dng_image_writer &writer,
+ dng_basic_tag_set &basic,
+ dng_stream &stream) const;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_image_preview (const dng_image_preview &preview);
+
+ dng_image_preview & operator= (const dng_image_preview &preview);
+
+ };
+
+/*****************************************************************************/
+
+class dng_jpeg_preview: public dng_preview
+ {
+
+ public:
+
+ dng_point fPreviewSize;
+
+ uint16 fPhotometricInterpretation;
+
+ dng_point fYCbCrSubSampling;
+
+ uint16 fYCbCrPositioning;
+
+ AutoPtr<dng_memory_block> fCompressedData;
+
+ public:
+
+ dng_jpeg_preview ();
+
+ virtual ~dng_jpeg_preview ();
+
+ virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
+
+ virtual void WriteData (dng_host &host,
+ dng_image_writer &writer,
+ dng_basic_tag_set &basic,
+ dng_stream &stream) const;
+
+ void SpoolAdobeThumbnail (dng_stream &stream) const;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_jpeg_preview (const dng_jpeg_preview &preview);
+
+ dng_jpeg_preview & operator= (const dng_jpeg_preview &preview);
+
+ };
+
+/*****************************************************************************/
+
+class dng_raw_preview: public dng_preview
+ {
+
+ public:
+
+ AutoPtr<dng_image> fImage;
+
+ AutoPtr<dng_memory_block> fOpcodeList2Data;
+
+ int32 fCompressionQuality;
+
+ private:
+
+ mutable dng_ifd fIFD;
+
+ public:
+
+ dng_raw_preview ();
+
+ virtual ~dng_raw_preview ();
+
+ virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
+
+ virtual void WriteData (dng_host &host,
+ dng_image_writer &writer,
+ dng_basic_tag_set &basic,
+ dng_stream &stream) const;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_raw_preview (const dng_raw_preview &preview);
+
+ dng_raw_preview & operator= (const dng_raw_preview &preview);
+
+ };
+
+/*****************************************************************************/
+
+class dng_mask_preview: public dng_preview
+ {
+
+ public:
+
+ AutoPtr<dng_image> fImage;
+
+ int32 fCompressionQuality;
+
+ private:
+
+ mutable dng_ifd fIFD;
+
+ public:
+
+ dng_mask_preview ();
+
+ virtual ~dng_mask_preview ();
+
+ virtual dng_basic_tag_set * AddTagSet (dng_tiff_directory &directory) const;
+
+ virtual void WriteData (dng_host &host,
+ dng_image_writer &writer,
+ dng_basic_tag_set &basic,
+ dng_stream &stream) const;
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_mask_preview (const dng_mask_preview &preview);
+
+ dng_mask_preview & operator= (const dng_mask_preview &preview);
+
+ };
+
+/*****************************************************************************/
+
+class dng_preview_list
+ {
+
+ private:
+
+ uint32 fCount;
+
+ AutoPtr<dng_preview> fPreview [kMaxDNGPreviews];
+
+ public:
+
+ dng_preview_list ();
+
+ ~dng_preview_list ();
+
+ uint32 Count () const
+ {
+ return fCount;
+ }
+
+ const dng_preview & Preview (uint32 index) const
+ {
+ return *(fPreview [index]);
+ }
+
+ void Append (AutoPtr<dng_preview> &preview);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_pthread.cpp b/source/dng_pthread.cpp
index 2fffa07..0347856 100644
--- a/source/dng_pthread.cpp
+++ b/source/dng_pthread.cpp
@@ -1,1141 +1,1141 @@
-/*****************************************************************************/
-// Copyright 2002-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_pthread.cpp#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-#include "dng_pthread.h"
-
-/*****************************************************************************/
-
-#if qDNGThreadSafe
-
-/*****************************************************************************/
-
-#include "dng_assertions.h"
-
-/*****************************************************************************/
-
-#if qWinOS
-
-#pragma warning(disable : 4786)
-
-// Nothing in this file requires Unicode,
-// However, CreateSemaphore has a path parameter
-// (which is NULL always in this code) and thus
-// does not work on Win98 if UNICODE is defined.
-// So we force it off here.
-
-#undef UNICODE
-#undef _UNICODE
-
-#include <windows.h>
-#include <process.h>
-#include <errno.h>
-#include <memory>
-#include <new>
-#include <map>
-
-#else
-
-#include <sys/time.h>
-
-#endif
-
-/*****************************************************************************/
-
-#if qWinOS
-
-/*****************************************************************************/
-
-namespace {
- struct waiter {
- struct waiter *prev;
- struct waiter *next;
- HANDLE semaphore;
- bool chosen_by_signal;
- };
-}
-
-/*****************************************************************************/
-
-struct dng_pthread_mutex_impl
-{
- CRITICAL_SECTION lock;
-
- dng_pthread_mutex_impl() { ::InitializeCriticalSection(&lock); }
- ~dng_pthread_mutex_impl() { ::DeleteCriticalSection(&lock); }
- void Lock() { ::EnterCriticalSection(&lock); }
- void Unlock() { ::LeaveCriticalSection(&lock); }
-private:
- dng_pthread_mutex_impl &operator=(const dng_pthread_mutex_impl &) { }
- dng_pthread_mutex_impl(const dng_pthread_mutex_impl &) { }
-};
-
-/*****************************************************************************/
-
-struct dng_pthread_cond_impl
-{
- dng_pthread_mutex_impl lock; // Mutual exclusion on next two variables
- waiter *head_waiter; // List of threads waiting on this condition
- waiter *tail_waiter; // Used to get FIFO, rather than LIFO, behavior for pthread_cond_signal
- unsigned int broadcast_generation; // Used as sort of a separator on broadcasts
- // saves having to walk the waiters list setting
- // each one's "chosen_by_signal" flag while the condition is locked
-
- dng_pthread_cond_impl() : head_waiter(NULL), tail_waiter(NULL), broadcast_generation(0) { }
- ~dng_pthread_cond_impl() { } ;
-
-// Non copyable
-private:
- dng_pthread_cond_impl &operator=(const dng_pthread_cond_impl &) { }
- dng_pthread_cond_impl(const dng_pthread_cond_impl &) { }
-
-};
-
-/*****************************************************************************/
-
-namespace
-{
-
- struct ScopedLock
- {
- dng_pthread_mutex_impl *mutex;
-
- ScopedLock(dng_pthread_mutex_impl *arg) : mutex(arg)
- {
- mutex->Lock();
- }
- ScopedLock(dng_pthread_mutex_impl &arg) : mutex(&arg)
- {
- mutex->Lock();
- }
- ~ScopedLock()
- {
- mutex->Unlock();
- }
- private:
- ScopedLock &operator=(const ScopedLock &) { }
- ScopedLock(const ScopedLock &) { }
- };
-
- dng_pthread_mutex_impl validationLock;
-
- void ValidateMutex(dng_pthread_mutex_t *mutex)
- {
- if (*mutex != DNG_PTHREAD_MUTEX_INITIALIZER)
- return;
-
- ScopedLock lock(validationLock);
-
- if (*mutex == DNG_PTHREAD_MUTEX_INITIALIZER)
- dng_pthread_mutex_init(mutex, NULL);
- }
-
- void ValidateCond(dng_pthread_cond_t *cond)
- {
- if (*cond != DNG_PTHREAD_COND_INITIALIZER)
- return;
-
- ScopedLock lock(validationLock);
-
- if (*cond == DNG_PTHREAD_COND_INITIALIZER)
- dng_pthread_cond_init(cond, NULL);
- }
-
- DWORD thread_wait_sema_TLS_index;
- bool thread_wait_sema_inited = false;
- dng_pthread_once_t once_thread_TLS = DNG_PTHREAD_ONCE_INIT;
-
- void init_thread_TLS()
- {
- thread_wait_sema_TLS_index = ::TlsAlloc();
- thread_wait_sema_inited = true;
- }
-
- void finalize_thread_TLS()
- {
- if (thread_wait_sema_inited)
- {
- ::TlsFree(thread_wait_sema_TLS_index);
- thread_wait_sema_inited = false;
- }
- }
-
- dng_pthread_mutex_impl primaryHandleMapLock;
-
- typedef std::map<DWORD, std::pair<HANDLE, void **> > ThreadMapType;
-
- // A map to make sure handles are freed and to allow returning a pointer sized result
- // even on 64-bit Windows.
- ThreadMapType primaryHandleMap;
-
- HANDLE GetThreadSemaphore()
- {
- dng_pthread_once(&once_thread_TLS, init_thread_TLS);
-
- HANDLE semaphore = ::TlsGetValue(thread_wait_sema_TLS_index);
- if (semaphore == NULL)
- {
- semaphore = ::CreateSemaphore(NULL, 0, 1, NULL);
- ::TlsSetValue(thread_wait_sema_TLS_index, semaphore);
- }
-
- return semaphore;
- }
-
- void FreeThreadSemaphore()
- {
- if (thread_wait_sema_inited)
- {
- HANDLE semaphore = (HANDLE)::TlsGetValue(thread_wait_sema_TLS_index);
-
- if (semaphore != NULL)
- {
- ::TlsSetValue(thread_wait_sema_TLS_index, NULL);
- ::CloseHandle(semaphore);
- }
- }
- }
-
- struct trampoline_args
- {
- void *(*func)(void *);
- void *arg;
- };
-
- // This trampoline takes care of the return type being different
- // between pthreads thread funcs and Windows C lib thread funcs
- unsigned __stdcall trampoline(void *arg_arg)
- {
- trampoline_args *args_ptr = (trampoline_args *)arg_arg;
- trampoline_args args = *args_ptr;
-
- delete args_ptr;
-
- GetThreadSemaphore();
-
- void *result = args.func(args.arg);
-
- {
- ScopedLock lockMap(primaryHandleMapLock);
-
- ThreadMapType::iterator iter = primaryHandleMap.find(pthread_self());
- if (iter != primaryHandleMap.end())
- *iter->second.second = result;
- }
-
- FreeThreadSemaphore();
-
- return S_OK;
- }
-
-}
-
-/*****************************************************************************/
-
-extern "C" {
-
-/*****************************************************************************/
-
-struct dng_pthread_attr_impl
- {
- size_t stacksize;
- };
-
-/*****************************************************************************/
-
-int dng_pthread_attr_init(pthread_attr_t *attr)
- {
- dng_pthread_attr_impl *newAttrs;
-
- newAttrs = new (std::nothrow) dng_pthread_attr_impl;
- if (newAttrs == NULL)
- return -1; // ENOMEM;
-
- newAttrs->stacksize = 0;
-
- *attr = newAttrs;
-
- return 0;
- }
-
-/*****************************************************************************/
-
-int dng_pthread_attr_destroy(pthread_attr_t *attr)
- {
- if (*attr == NULL)
- return -1; // EINVAL
-
- delete *attr;
-
- *attr = NULL;
-
- return 0;
- }
-
-/*****************************************************************************/
-
-int dng_pthread_attr_setstacksize(dng_pthread_attr_t *attr, size_t stacksize)
- {
- if (attr == NULL || (*attr) == NULL)
- return -1; // EINVAL
-
- (*attr)->stacksize = stacksize;
-
- return 0;
- }
-
-/*****************************************************************************/
-
-int dng_pthread_attr_getstacksize(const dng_pthread_attr_t *attr, size_t *stacksize)
- {
- if (attr == NULL || (*attr) == NULL || stacksize == NULL)
- return -1; // EINVAL
-
- *stacksize = (*attr)->stacksize;
-
- return 0;
- }
-
-/*****************************************************************************/
-
-int dng_pthread_create(dng_pthread_t *thread, const pthread_attr_t *attrs, void * (*func)(void *), void *arg)
-{
- try
- {
- uintptr_t result;
- unsigned threadID;
- std::auto_ptr<trampoline_args> args(new (std::nothrow) trampoline_args);
- std::auto_ptr<void *> resultHolder(new (std::nothrow) (void *));
-
- if (args.get() == NULL || resultHolder.get () == NULL)
- return -1; // ENOMEM
-
- args->func = func;
- args->arg = arg;
-
- size_t stacksize = 0;
-
- if (attrs != NULL)
- dng_pthread_attr_getstacksize (attrs, &stacksize);
-
- {
- ScopedLock lockMap(primaryHandleMapLock);
-
- result = _beginthreadex(NULL, (unsigned)stacksize, trampoline, args.get(), 0, &threadID);
- if (result == NULL)
- return -1; // ENOMEM
- args.release();
-
- std::pair<DWORD, std::pair<HANDLE, void **> > newMapEntry(threadID,
- std::pair<HANDLE, void **>((HANDLE)result, resultHolder.get ()));
- std::pair<ThreadMapType::iterator, bool> insertion = primaryHandleMap.insert(newMapEntry);
-
- // If there is a handle open on the thread, its ID should not be reused so assert that an insertion was made.
- DNG_ASSERT(insertion.second, "pthread emulation logic error");
- }
-
-
- resultHolder.release ();
-
- *thread = (dng_pthread_t)threadID;
- return 0;
- }
- catch (const std::bad_alloc &)
- {
- return -1;
- }
-}
-
-/*****************************************************************************/
-
-int dng_pthread_detach(dng_pthread_t thread)
-{
- HANDLE primaryHandle;
- void **resultHolder = NULL;
-
- {
- ScopedLock lockMap(primaryHandleMapLock);
-
- ThreadMapType::iterator iter = primaryHandleMap.find(thread);
- if (iter == primaryHandleMap.end())
- return -1;
-
- primaryHandle = iter->second.first;
-
- // A join is waiting on the thread.
- if (primaryHandle == NULL)
- return -1;
-
- resultHolder = iter->second.second;
-
- primaryHandleMap.erase(iter);
- }
-
- delete resultHolder;
-
- if (!::CloseHandle(primaryHandle))
- return -1;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_join(dng_pthread_t thread, void **result)
-{
- bool found = false;
- HANDLE primaryHandle = NULL;
- void **resultHolder = NULL;
-
- ThreadMapType::iterator iter;
-
- {
- ScopedLock lockMap(primaryHandleMapLock);
-
- iter = primaryHandleMap.find(thread);
- found = iter != primaryHandleMap.end();
- if (found)
- {
- primaryHandle = iter->second.first;
- resultHolder = iter->second.second;
-
- // Set HANDLE to NULL to force any later join or detach to fail.
- iter->second.first = NULL;
- }
- }
-
- // This case can happens when joining a thread not created with pthread_create,
- // which is a bad idea, but it gets mapped to doing the join, but always returns NULL.
- if (!found)
- primaryHandle = ::OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION, FALSE, thread);
-
- if (primaryHandle == NULL)
- return -1;
-
- DWORD err;
- if (::WaitForSingleObject(primaryHandle, INFINITE) != WAIT_OBJECT_0)
- {
- err = ::GetLastError();
- return -1;
- }
-
- {
- ScopedLock lockMap(primaryHandleMapLock);
-
- if (iter != primaryHandleMap.end())
- primaryHandleMap.erase(iter);
- }
-
- ::CloseHandle(primaryHandle);
- if (result != NULL && resultHolder != NULL)
- *result = *resultHolder;
-
- delete resultHolder;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-dng_pthread_t dng_pthread_self()
-{
- return (dng_pthread_t)::GetCurrentThreadId();
-}
-
-/*****************************************************************************/
-
-void dng_pthread_exit(void *result)
-{
- {
- ScopedLock lockMap(primaryHandleMapLock);
-
- ThreadMapType::iterator iter = primaryHandleMap.find(pthread_self());
- if (iter != primaryHandleMap.end())
- *iter->second.second = result;
- }
-
- FreeThreadSemaphore();
-
- _endthreadex(S_OK);
-}
-
-/*****************************************************************************/
-
-int dng_pthread_mutex_init(dng_pthread_mutex_t *mutex, void * /* attrs */)
-{
- dng_pthread_mutex_t result;
- try {
- result = new(dng_pthread_mutex_impl);
- } catch (const std::bad_alloc &)
- {
- return -1;
- }
-
- if (result == NULL)
- return -1;
- *mutex = result;
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_mutex_destroy(dng_pthread_mutex_t *mutex)
-{
- if (*mutex == DNG_PTHREAD_MUTEX_INITIALIZER)
- {
- *mutex = NULL;
- return 0;
- }
-
- delete *mutex;
- *mutex = NULL;
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_cond_init(dng_pthread_cond_t *cond, void * /* attrs */)
-{
- dng_pthread_cond_t result;
- try {
- result = new(dng_pthread_cond_impl);
- } catch (const std::bad_alloc &)
- {
- return -1;
- }
-
- if (result == NULL)
- return -1;
- *cond = result;
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_cond_destroy(dng_pthread_cond_t *cond)
-{
- if (*cond == DNG_PTHREAD_COND_INITIALIZER)
- {
- *cond = NULL;
- return 0;
- }
-
- delete *cond;
- *cond = NULL;
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_mutexattr_init(dng_pthread_mutexattr_t* mutexattr)
-{
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_mutexattr_settype(dng_pthread_mutexattr_t* mutexattr, int type)
-{
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_mutex_lock(dng_pthread_mutex_t *mutex)
-{
- ValidateMutex(mutex);
- (*mutex)->Lock();
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_mutex_unlock(dng_pthread_mutex_t *mutex)
-{
- ValidateMutex(mutex);
- (*mutex)->Unlock();
- return 0;
-}
-
-/*****************************************************************************/
-
-static int cond_wait_internal(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex, int timeout_milliseconds)
-{
- dng_pthread_cond_impl &real_cond = **cond;
- dng_pthread_mutex_impl &real_mutex = **mutex;
-
- waiter this_wait;
- HANDLE semaphore = GetThreadSemaphore();
- int my_generation; // The broadcast generation this waiter is in
-
- {
- this_wait.next = NULL;
- this_wait.semaphore = semaphore;
- this_wait.chosen_by_signal = 0;
-
- ScopedLock lock1(real_cond.lock);
-
- // Add this waiter to the end of the list.
- this_wait.prev = real_cond.tail_waiter;
- if (real_cond.tail_waiter != NULL)
- real_cond.tail_waiter->next = &this_wait;
- real_cond.tail_waiter = &this_wait;
-
- // If the list was empty, set the head of the list to this waiter.
- if (real_cond.head_waiter == NULL)
- real_cond.head_waiter = &this_wait;
-
- // Note which broadcast generation this waiter belongs to.
- my_generation = real_cond.broadcast_generation;
- }
-
- real_mutex.Unlock();
-
- DWORD result = ::WaitForSingleObject(semaphore, timeout_milliseconds);
-
- if (result == WAIT_TIMEOUT)
- {
- // If the wait timed out, this thread is likely still on the waiters list
- // of the condition. However, there is a race in that the thread may have been
- // signaled or broadcast between when WaitForSingleObject decided
- // we had timed out and this code running.
-
- bool mustConsumeSemaphore = false;
- {
- ScopedLock lock2(real_cond.lock);
-
- bool chosen_by_signal = this_wait.chosen_by_signal;
- bool chosen_by_broadcast = my_generation != real_cond.broadcast_generation;
-
- if (chosen_by_signal || chosen_by_broadcast)
- mustConsumeSemaphore = true;
- else
- {
- // Still on waiters list. Remove this waiter from list.
- if (this_wait.next != NULL)
- this_wait.next->prev = this_wait.prev;
- else
- real_cond.tail_waiter = this_wait.prev;
-
- if (this_wait.prev != NULL)
- this_wait.prev->next = this_wait.next;
- else
- real_cond.head_waiter = this_wait.next;
- }
- }
-
- if (mustConsumeSemaphore)
- {
- ::WaitForSingleObject(semaphore, INFINITE);
- result = WAIT_OBJECT_0;
- }
- }
- else
- DNG_ASSERT (result == WAIT_OBJECT_0, "pthread emulation logic error");
-
- // reacquire the mutex
- real_mutex.Lock();
-
- return (result == WAIT_TIMEOUT) ? DNG_ETIMEDOUT : 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_cond_wait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex)
-{
- ValidateCond(cond);
-
- return cond_wait_internal(cond, mutex, INFINITE);
-}
-
-/*****************************************************************************/
-
-int dng_pthread_cond_timedwait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex, struct dng_timespec *latest_time)
-{
- ValidateCond(cond);
-
- struct dng_timespec sys_timespec;
-
- dng_pthread_now (&sys_timespec);
-
- __int64 sys_time = (__int64)sys_timespec.tv_sec * 1000000000 + sys_timespec.tv_nsec;
- __int64 lock_time = (__int64)latest_time->tv_sec * 1000000000 + latest_time->tv_nsec;
-
- int wait_millisecs = (int)((lock_time - sys_time + 500000) / 1000000);
-
- if (wait_millisecs < 0)
- wait_millisecs = 0;
-
- return cond_wait_internal(cond, mutex, wait_millisecs);
-}
-
-/*****************************************************************************/
-
-int dng_pthread_cond_signal(dng_pthread_cond_t *cond)
-{
- ValidateCond(cond);
-
- waiter *first;
- dng_pthread_cond_impl &real_cond = **cond;
-
- {
- ScopedLock lock(real_cond.lock);
-
- first = real_cond.head_waiter;
- if (first != NULL)
- {
- if (first->next != NULL)
- first->next->prev = NULL;
- else
- real_cond.tail_waiter = NULL; // Or first->prev, which is always NULL in this case
-
- first->chosen_by_signal = true;
-
- real_cond.head_waiter = first->next;
- }
- }
-
- if (first != NULL)
- ::ReleaseSemaphore(first->semaphore, 1, NULL);
-
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_cond_broadcast(dng_pthread_cond_t *cond)
-{
- ValidateCond(cond);
-
- waiter *first;
- dng_pthread_cond_impl &real_cond = **cond;
-
- {
- ScopedLock lock(real_cond.lock);
-
- first = real_cond.head_waiter;
- real_cond.head_waiter = NULL;
- real_cond.tail_waiter = NULL;
-
- real_cond.broadcast_generation++;
- }
-
- while (first != NULL)
- {
- waiter *next = first->next;
- ::ReleaseSemaphore(first->semaphore, 1, NULL);
- first = next;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_once(dng_pthread_once_t *once, void (*init_func)())
-{
- if (once == NULL || init_func == NULL)
- return EINVAL;
-
- if (once->inited)
- return 0;
-
- if (::InterlockedIncrement(&once->semaphore) == 0)
- {
- init_func();
- once->inited = 1;
- }
- else
- {
- while (!once->inited)
- Sleep(0);
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_key_create(dng_pthread_key_t * key, void (*destructor) (void *))
-{
- if (destructor != NULL)
- return -1;
-
- DWORD result = ::TlsAlloc();
- if (result == TLS_OUT_OF_INDEXES)
- return -1;
- *key = (unsigned long)result;
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_key_delete(dng_pthread_key_t key)
-{
- if (::TlsFree((DWORD)key))
- return 0;
- return -1;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_setspecific(dng_pthread_key_t key, const void *value)
-{
- if (::TlsSetValue((DWORD)key, const_cast<void *>(value)))
- return 0;
- return -1;
-}
-
-/*****************************************************************************/
-
-void *dng_pthread_getspecific(dng_pthread_key_t key)
-{
- return ::TlsGetValue((DWORD)key);
-}
-
-/*****************************************************************************/
-
-namespace {
- struct rw_waiter {
- struct rw_waiter *prev;
- struct rw_waiter *next;
- HANDLE semaphore;
- bool is_writer;
- };
-}
-
-struct dng_pthread_rwlock_impl
-{
- dng_pthread_mutex_impl mutex;
-
- rw_waiter *head_waiter;
- rw_waiter *tail_waiter;
-
- unsigned long readers_active;
- unsigned long writers_waiting;
- bool writer_active;
-
- dng_pthread_cond_impl read_wait;
- dng_pthread_cond_impl write_wait;
-
- dng_pthread_rwlock_impl ()
- : mutex ()
- , head_waiter (NULL)
- , tail_waiter (NULL)
- , readers_active (0)
- , writers_waiting (0)
- , read_wait ()
- , write_wait ()
- , writer_active (false)
- {
- }
-
- ~dng_pthread_rwlock_impl ()
- {
- }
-
- void WakeHeadWaiter ()
- {
- HANDLE semaphore = head_waiter->semaphore;
-
- head_waiter = head_waiter->next;
- if (head_waiter == NULL)
- tail_waiter = NULL;
-
- ::ReleaseSemaphore(semaphore, 1, NULL);
- }
-
-};
-
-/*****************************************************************************/
-
-int dng_pthread_rwlock_init(dng_pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attrs)
-{
- dng_pthread_rwlock_impl *newRWLock;
-
- newRWLock = new (std::nothrow) dng_pthread_rwlock_impl;
- if (newRWLock == NULL)
- return -1; // ENOMEM;
-
- *rwlock = newRWLock;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_rwlock_destroy(dng_pthread_rwlock_t *rwlock)
-{
- dng_pthread_rwlock_impl &real_rwlock = **rwlock;
-
- {
- ScopedLock lock (real_rwlock.mutex);
-
- if (real_rwlock.head_waiter != NULL ||
- real_rwlock.readers_active != 0 ||
- real_rwlock.writers_waiting != 0 ||
- real_rwlock.writer_active)
- return -1; // EBUSY
- }
-
- delete *rwlock;
- *rwlock = NULL;
- return 0;
-}
-
-/*****************************************************************************/
-
-#define CHECK_RWLOCK_STATE(real_rwlock) \
- DNG_ASSERT (!real_rwlock.writer_active || real_rwlock.readers_active == 0, "dng_pthread_rwlock_t logic error")
-
-/*****************************************************************************/
-
-int dng_pthread_rwlock_rdlock(dng_pthread_rwlock_t *rwlock)
-{
- dng_pthread_rwlock_impl &real_rwlock = **rwlock;
-
- struct rw_waiter this_wait;
- bool doWait = false;;
- int result = 0;
- HANDLE semaphore=NULL;
-
- {
-
- ScopedLock lock (real_rwlock.mutex);
-
- CHECK_RWLOCK_STATE (real_rwlock);
-
- if (real_rwlock.writers_waiting > 0 || real_rwlock.writer_active)
- {
- semaphore = GetThreadSemaphore();
-
- this_wait.next = NULL;
- this_wait.semaphore = semaphore;
- this_wait.is_writer = false;
-
- // Add this waiter to the end of the list.
- this_wait.prev = real_rwlock.tail_waiter;
- if (real_rwlock.tail_waiter != NULL)
- real_rwlock.tail_waiter->next = &this_wait;
- real_rwlock.tail_waiter = &this_wait;
-
- // If the list was empty, set the head of the list to this waiter.
- if (real_rwlock.head_waiter == NULL)
- real_rwlock.head_waiter = &this_wait;
-
- doWait = true;
- }
- else
- real_rwlock.readers_active++;
- }
-
- if (result == 0 && doWait)
- result = (WaitForSingleObject(semaphore, INFINITE) == WAIT_OBJECT_0) ? 0 : -1;
-
- return result;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_rwlock_tryrdlock(dng_pthread_rwlock_t *rwlock)
-{
- dng_pthread_rwlock_impl &real_rwlock = **rwlock;
-
- ScopedLock lock (real_rwlock.mutex);
-
- CHECK_RWLOCK_STATE (real_rwlock);
-
- if (real_rwlock.writers_waiting == 0 && !real_rwlock.writer_active)
- {
- real_rwlock.readers_active++;
- return 0;
- }
-
- return -1;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_rwlock_trywrlock(dng_pthread_rwlock_t *rwlock)
-{
- dng_pthread_rwlock_impl &real_rwlock = **rwlock;
-
- ScopedLock lock (real_rwlock.mutex);
-
- CHECK_RWLOCK_STATE (real_rwlock);
-
- if (real_rwlock.readers_active == 0 &&
- real_rwlock.writers_waiting == 0 &&
- !real_rwlock.writer_active)
- {
- real_rwlock.writer_active = true;
- return 0;
- }
-
- return -1;
-}
-
-/*****************************************************************************/
-
-int dng_pthread_rwlock_unlock(dng_pthread_rwlock_t *rwlock)
- {
- dng_pthread_rwlock_impl &real_rwlock = **rwlock;
-
- int result = 0;
-
- ScopedLock lock (real_rwlock.mutex);
-
- CHECK_RWLOCK_STATE (real_rwlock);
-
- if (real_rwlock.readers_active > 0)
- --real_rwlock.readers_active;
- else
- real_rwlock.writer_active = false;
-
- while (real_rwlock.head_waiter != NULL)
- {
- if (real_rwlock.head_waiter->is_writer)
- {
- if (real_rwlock.readers_active == 0)
- {
- real_rwlock.writers_waiting--;
- real_rwlock.writer_active = true;
- real_rwlock.WakeHeadWaiter ();
- }
-
- break;
- }
- else
- {
- ++real_rwlock.readers_active;
- real_rwlock.WakeHeadWaiter ();
- }
- }
-
- return result;
- }
-
-/*****************************************************************************/
-
-int dng_pthread_rwlock_wrlock(dng_pthread_rwlock_t *rwlock)
- {
- dng_pthread_rwlock_impl &real_rwlock = **rwlock;
-
- int result = 0;
- struct rw_waiter this_wait;
- HANDLE semaphore=NULL;
- bool doWait = false;
-
- {
- ScopedLock lock (real_rwlock.mutex);
-
- CHECK_RWLOCK_STATE (real_rwlock);
-
- if (real_rwlock.readers_active ||
- real_rwlock.writers_waiting ||
- real_rwlock.writer_active)
- {
- semaphore = GetThreadSemaphore();
-
- this_wait.next = NULL;
- this_wait.semaphore = semaphore;
- this_wait.is_writer = true;
-
- // Add this waiter to the end of the list.
- this_wait.prev = real_rwlock.tail_waiter;
- if (real_rwlock.tail_waiter != NULL)
- real_rwlock.tail_waiter->next = &this_wait;
- real_rwlock.tail_waiter = &this_wait;
-
- // If the list was empty, set the head of the list to this waiter.
- if (real_rwlock.head_waiter == NULL)
- real_rwlock.head_waiter = &this_wait;
-
- real_rwlock.writers_waiting++;
-
- doWait = true;
- }
- else
- real_rwlock.writer_active = true;
- }
-
- if (result == 0 && doWait)
- result = (WaitForSingleObject(semaphore, INFINITE) == WAIT_OBJECT_0) ? 0 : -1;
-
- return result;
- }
-
-/*****************************************************************************/
-
-void dng_pthread_disassociate()
-{
- FreeThreadSemaphore();
-}
-
-void dng_pthread_terminate()
- {
- finalize_thread_TLS();
- }
-
-/*****************************************************************************/
-
-} // extern "C"
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
-
-int dng_pthread_now (struct timespec *now)
- {
-
- if (now == NULL)
- return -1; // EINVAL
-
- #if qWinOS
-
- FILETIME ft;
- ::GetSystemTimeAsFileTime(&ft);
-
- __int64 sys_time = ((__int64)ft.dwHighDateTime << 32) + ft.dwLowDateTime;
-
- #define SecsFrom1601To1970 11644473600
-
- sys_time -= SecsFrom1601To1970 * 10000000LL;
-
- sys_time *= 100; // Convert from 100ns to 1ns units
-
- now->tv_sec = (long)(sys_time / 1000000000);
- now->tv_nsec = (long)(sys_time % 1000000000);
-
- #else
-
- struct timeval tv;
-
- if (gettimeofday (&tv, NULL) != 0)
- return errno;
-
- now->tv_sec = tv.tv_sec;
- now->tv_nsec = tv.tv_usec * 1000;
-
- #endif
-
- return 0;
-
- }
-
-/*****************************************************************************/
-
-#endif // qDNGThreadSafe
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2002-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_pthread.cpp#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+#include "dng_pthread.h"
+
+/*****************************************************************************/
+
+#if qDNGThreadSafe
+
+/*****************************************************************************/
+
+#include "dng_assertions.h"
+
+/*****************************************************************************/
+
+#if qWinOS
+
+#pragma warning(disable : 4786)
+
+// Nothing in this file requires Unicode,
+// However, CreateSemaphore has a path parameter
+// (which is NULL always in this code) and thus
+// does not work on Win98 if UNICODE is defined.
+// So we force it off here.
+
+#undef UNICODE
+#undef _UNICODE
+
+#include <windows.h>
+#include <process.h>
+#include <errno.h>
+#include <memory>
+#include <new>
+#include <map>
+
+#else
+
+#include <sys/time.h>
+
+#endif
+
+/*****************************************************************************/
+
+#if qWinOS
+
+/*****************************************************************************/
+
+namespace {
+ struct waiter {
+ struct waiter *prev;
+ struct waiter *next;
+ HANDLE semaphore;
+ bool chosen_by_signal;
+ };
+}
+
+/*****************************************************************************/
+
+struct dng_pthread_mutex_impl
+{
+ CRITICAL_SECTION lock;
+
+ dng_pthread_mutex_impl() { ::InitializeCriticalSection(&lock); }
+ ~dng_pthread_mutex_impl() { ::DeleteCriticalSection(&lock); }
+ void Lock() { ::EnterCriticalSection(&lock); }
+ void Unlock() { ::LeaveCriticalSection(&lock); }
+private:
+ dng_pthread_mutex_impl &operator=(const dng_pthread_mutex_impl &) { }
+ dng_pthread_mutex_impl(const dng_pthread_mutex_impl &) { }
+};
+
+/*****************************************************************************/
+
+struct dng_pthread_cond_impl
+{
+ dng_pthread_mutex_impl lock; // Mutual exclusion on next two variables
+ waiter *head_waiter; // List of threads waiting on this condition
+ waiter *tail_waiter; // Used to get FIFO, rather than LIFO, behavior for pthread_cond_signal
+ unsigned int broadcast_generation; // Used as sort of a separator on broadcasts
+ // saves having to walk the waiters list setting
+ // each one's "chosen_by_signal" flag while the condition is locked
+
+ dng_pthread_cond_impl() : head_waiter(NULL), tail_waiter(NULL), broadcast_generation(0) { }
+ ~dng_pthread_cond_impl() { } ;
+
+// Non copyable
+private:
+ dng_pthread_cond_impl &operator=(const dng_pthread_cond_impl &) { }
+ dng_pthread_cond_impl(const dng_pthread_cond_impl &) { }
+
+};
+
+/*****************************************************************************/
+
+namespace
+{
+
+ struct ScopedLock
+ {
+ dng_pthread_mutex_impl *mutex;
+
+ ScopedLock(dng_pthread_mutex_impl *arg) : mutex(arg)
+ {
+ mutex->Lock();
+ }
+ ScopedLock(dng_pthread_mutex_impl &arg) : mutex(&arg)
+ {
+ mutex->Lock();
+ }
+ ~ScopedLock()
+ {
+ mutex->Unlock();
+ }
+ private:
+ ScopedLock &operator=(const ScopedLock &) { }
+ ScopedLock(const ScopedLock &) { }
+ };
+
+ dng_pthread_mutex_impl validationLock;
+
+ void ValidateMutex(dng_pthread_mutex_t *mutex)
+ {
+ if (*mutex != DNG_PTHREAD_MUTEX_INITIALIZER)
+ return;
+
+ ScopedLock lock(validationLock);
+
+ if (*mutex == DNG_PTHREAD_MUTEX_INITIALIZER)
+ dng_pthread_mutex_init(mutex, NULL);
+ }
+
+ void ValidateCond(dng_pthread_cond_t *cond)
+ {
+ if (*cond != DNG_PTHREAD_COND_INITIALIZER)
+ return;
+
+ ScopedLock lock(validationLock);
+
+ if (*cond == DNG_PTHREAD_COND_INITIALIZER)
+ dng_pthread_cond_init(cond, NULL);
+ }
+
+ DWORD thread_wait_sema_TLS_index;
+ bool thread_wait_sema_inited = false;
+ dng_pthread_once_t once_thread_TLS = DNG_PTHREAD_ONCE_INIT;
+
+ void init_thread_TLS()
+ {
+ thread_wait_sema_TLS_index = ::TlsAlloc();
+ thread_wait_sema_inited = true;
+ }
+
+ void finalize_thread_TLS()
+ {
+ if (thread_wait_sema_inited)
+ {
+ ::TlsFree(thread_wait_sema_TLS_index);
+ thread_wait_sema_inited = false;
+ }
+ }
+
+ dng_pthread_mutex_impl primaryHandleMapLock;
+
+ typedef std::map<DWORD, std::pair<HANDLE, void **> > ThreadMapType;
+
+ // A map to make sure handles are freed and to allow returning a pointer sized result
+ // even on 64-bit Windows.
+ ThreadMapType primaryHandleMap;
+
+ HANDLE GetThreadSemaphore()
+ {
+ dng_pthread_once(&once_thread_TLS, init_thread_TLS);
+
+ HANDLE semaphore = ::TlsGetValue(thread_wait_sema_TLS_index);
+ if (semaphore == NULL)
+ {
+ semaphore = ::CreateSemaphore(NULL, 0, 1, NULL);
+ ::TlsSetValue(thread_wait_sema_TLS_index, semaphore);
+ }
+
+ return semaphore;
+ }
+
+ void FreeThreadSemaphore()
+ {
+ if (thread_wait_sema_inited)
+ {
+ HANDLE semaphore = (HANDLE)::TlsGetValue(thread_wait_sema_TLS_index);
+
+ if (semaphore != NULL)
+ {
+ ::TlsSetValue(thread_wait_sema_TLS_index, NULL);
+ ::CloseHandle(semaphore);
+ }
+ }
+ }
+
+ struct trampoline_args
+ {
+ void *(*func)(void *);
+ void *arg;
+ };
+
+ // This trampoline takes care of the return type being different
+ // between pthreads thread funcs and Windows C lib thread funcs
+ unsigned __stdcall trampoline(void *arg_arg)
+ {
+ trampoline_args *args_ptr = (trampoline_args *)arg_arg;
+ trampoline_args args = *args_ptr;
+
+ delete args_ptr;
+
+ GetThreadSemaphore();
+
+ void *result = args.func(args.arg);
+
+ {
+ ScopedLock lockMap(primaryHandleMapLock);
+
+ ThreadMapType::iterator iter = primaryHandleMap.find(pthread_self());
+ if (iter != primaryHandleMap.end())
+ *iter->second.second = result;
+ }
+
+ FreeThreadSemaphore();
+
+ return S_OK;
+ }
+
+}
+
+/*****************************************************************************/
+
+extern "C" {
+
+/*****************************************************************************/
+
+struct dng_pthread_attr_impl
+ {
+ size_t stacksize;
+ };
+
+/*****************************************************************************/
+
+int dng_pthread_attr_init(pthread_attr_t *attr)
+ {
+ dng_pthread_attr_impl *newAttrs;
+
+ newAttrs = new (std::nothrow) dng_pthread_attr_impl;
+ if (newAttrs == NULL)
+ return -1; // ENOMEM;
+
+ newAttrs->stacksize = 0;
+
+ *attr = newAttrs;
+
+ return 0;
+ }
+
+/*****************************************************************************/
+
+int dng_pthread_attr_destroy(pthread_attr_t *attr)
+ {
+ if (*attr == NULL)
+ return -1; // EINVAL
+
+ delete *attr;
+
+ *attr = NULL;
+
+ return 0;
+ }
+
+/*****************************************************************************/
+
+int dng_pthread_attr_setstacksize(dng_pthread_attr_t *attr, size_t stacksize)
+ {
+ if (attr == NULL || (*attr) == NULL)
+ return -1; // EINVAL
+
+ (*attr)->stacksize = stacksize;
+
+ return 0;
+ }
+
+/*****************************************************************************/
+
+int dng_pthread_attr_getstacksize(const dng_pthread_attr_t *attr, size_t *stacksize)
+ {
+ if (attr == NULL || (*attr) == NULL || stacksize == NULL)
+ return -1; // EINVAL
+
+ *stacksize = (*attr)->stacksize;
+
+ return 0;
+ }
+
+/*****************************************************************************/
+
+int dng_pthread_create(dng_pthread_t *thread, const pthread_attr_t *attrs, void * (*func)(void *), void *arg)
+{
+ try
+ {
+ uintptr_t result;
+ unsigned threadID;
+ std::auto_ptr<trampoline_args> args(new (std::nothrow) trampoline_args);
+ std::auto_ptr<void *> resultHolder(new (std::nothrow) (void *));
+
+ if (args.get() == NULL || resultHolder.get () == NULL)
+ return -1; // ENOMEM
+
+ args->func = func;
+ args->arg = arg;
+
+ size_t stacksize = 0;
+
+ if (attrs != NULL)
+ dng_pthread_attr_getstacksize (attrs, &stacksize);
+
+ {
+ ScopedLock lockMap(primaryHandleMapLock);
+
+ result = _beginthreadex(NULL, (unsigned)stacksize, trampoline, args.get(), 0, &threadID);
+ if (result == NULL)
+ return -1; // ENOMEM
+ args.release();
+
+ std::pair<DWORD, std::pair<HANDLE, void **> > newMapEntry(threadID,
+ std::pair<HANDLE, void **>((HANDLE)result, resultHolder.get ()));
+ std::pair<ThreadMapType::iterator, bool> insertion = primaryHandleMap.insert(newMapEntry);
+
+ // If there is a handle open on the thread, its ID should not be reused so assert that an insertion was made.
+ DNG_ASSERT(insertion.second, "pthread emulation logic error");
+ }
+
+
+ resultHolder.release ();
+
+ *thread = (dng_pthread_t)threadID;
+ return 0;
+ }
+ catch (const std::bad_alloc &)
+ {
+ return -1;
+ }
+}
+
+/*****************************************************************************/
+
+int dng_pthread_detach(dng_pthread_t thread)
+{
+ HANDLE primaryHandle;
+ void **resultHolder = NULL;
+
+ {
+ ScopedLock lockMap(primaryHandleMapLock);
+
+ ThreadMapType::iterator iter = primaryHandleMap.find(thread);
+ if (iter == primaryHandleMap.end())
+ return -1;
+
+ primaryHandle = iter->second.first;
+
+ // A join is waiting on the thread.
+ if (primaryHandle == NULL)
+ return -1;
+
+ resultHolder = iter->second.second;
+
+ primaryHandleMap.erase(iter);
+ }
+
+ delete resultHolder;
+
+ if (!::CloseHandle(primaryHandle))
+ return -1;
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_join(dng_pthread_t thread, void **result)
+{
+ bool found = false;
+ HANDLE primaryHandle = NULL;
+ void **resultHolder = NULL;
+
+ ThreadMapType::iterator iter;
+
+ {
+ ScopedLock lockMap(primaryHandleMapLock);
+
+ iter = primaryHandleMap.find(thread);
+ found = iter != primaryHandleMap.end();
+ if (found)
+ {
+ primaryHandle = iter->second.first;
+ resultHolder = iter->second.second;
+
+ // Set HANDLE to NULL to force any later join or detach to fail.
+ iter->second.first = NULL;
+ }
+ }
+
+ // This case can happens when joining a thread not created with pthread_create,
+ // which is a bad idea, but it gets mapped to doing the join, but always returns NULL.
+ if (!found)
+ primaryHandle = ::OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION, FALSE, thread);
+
+ if (primaryHandle == NULL)
+ return -1;
+
+ DWORD err;
+ if (::WaitForSingleObject(primaryHandle, INFINITE) != WAIT_OBJECT_0)
+ {
+ err = ::GetLastError();
+ return -1;
+ }
+
+ {
+ ScopedLock lockMap(primaryHandleMapLock);
+
+ if (iter != primaryHandleMap.end())
+ primaryHandleMap.erase(iter);
+ }
+
+ ::CloseHandle(primaryHandle);
+ if (result != NULL && resultHolder != NULL)
+ *result = *resultHolder;
+
+ delete resultHolder;
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+dng_pthread_t dng_pthread_self()
+{
+ return (dng_pthread_t)::GetCurrentThreadId();
+}
+
+/*****************************************************************************/
+
+void dng_pthread_exit(void *result)
+{
+ {
+ ScopedLock lockMap(primaryHandleMapLock);
+
+ ThreadMapType::iterator iter = primaryHandleMap.find(pthread_self());
+ if (iter != primaryHandleMap.end())
+ *iter->second.second = result;
+ }
+
+ FreeThreadSemaphore();
+
+ _endthreadex(S_OK);
+}
+
+/*****************************************************************************/
+
+int dng_pthread_mutex_init(dng_pthread_mutex_t *mutex, void * /* attrs */)
+{
+ dng_pthread_mutex_t result;
+ try {
+ result = new(dng_pthread_mutex_impl);
+ } catch (const std::bad_alloc &)
+ {
+ return -1;
+ }
+
+ if (result == NULL)
+ return -1;
+ *mutex = result;
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_mutex_destroy(dng_pthread_mutex_t *mutex)
+{
+ if (*mutex == DNG_PTHREAD_MUTEX_INITIALIZER)
+ {
+ *mutex = NULL;
+ return 0;
+ }
+
+ delete *mutex;
+ *mutex = NULL;
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_cond_init(dng_pthread_cond_t *cond, void * /* attrs */)
+{
+ dng_pthread_cond_t result;
+ try {
+ result = new(dng_pthread_cond_impl);
+ } catch (const std::bad_alloc &)
+ {
+ return -1;
+ }
+
+ if (result == NULL)
+ return -1;
+ *cond = result;
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_cond_destroy(dng_pthread_cond_t *cond)
+{
+ if (*cond == DNG_PTHREAD_COND_INITIALIZER)
+ {
+ *cond = NULL;
+ return 0;
+ }
+
+ delete *cond;
+ *cond = NULL;
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_mutexattr_init(dng_pthread_mutexattr_t* mutexattr)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_mutexattr_settype(dng_pthread_mutexattr_t* mutexattr, int type)
+{
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_mutex_lock(dng_pthread_mutex_t *mutex)
+{
+ ValidateMutex(mutex);
+ (*mutex)->Lock();
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_mutex_unlock(dng_pthread_mutex_t *mutex)
+{
+ ValidateMutex(mutex);
+ (*mutex)->Unlock();
+ return 0;
+}
+
+/*****************************************************************************/
+
+static int cond_wait_internal(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex, int timeout_milliseconds)
+{
+ dng_pthread_cond_impl &real_cond = **cond;
+ dng_pthread_mutex_impl &real_mutex = **mutex;
+
+ waiter this_wait;
+ HANDLE semaphore = GetThreadSemaphore();
+ int my_generation; // The broadcast generation this waiter is in
+
+ {
+ this_wait.next = NULL;
+ this_wait.semaphore = semaphore;
+ this_wait.chosen_by_signal = 0;
+
+ ScopedLock lock1(real_cond.lock);
+
+ // Add this waiter to the end of the list.
+ this_wait.prev = real_cond.tail_waiter;
+ if (real_cond.tail_waiter != NULL)
+ real_cond.tail_waiter->next = &this_wait;
+ real_cond.tail_waiter = &this_wait;
+
+ // If the list was empty, set the head of the list to this waiter.
+ if (real_cond.head_waiter == NULL)
+ real_cond.head_waiter = &this_wait;
+
+ // Note which broadcast generation this waiter belongs to.
+ my_generation = real_cond.broadcast_generation;
+ }
+
+ real_mutex.Unlock();
+
+ DWORD result = ::WaitForSingleObject(semaphore, timeout_milliseconds);
+
+ if (result == WAIT_TIMEOUT)
+ {
+ // If the wait timed out, this thread is likely still on the waiters list
+ // of the condition. However, there is a race in that the thread may have been
+ // signaled or broadcast between when WaitForSingleObject decided
+ // we had timed out and this code running.
+
+ bool mustConsumeSemaphore = false;
+ {
+ ScopedLock lock2(real_cond.lock);
+
+ bool chosen_by_signal = this_wait.chosen_by_signal;
+ bool chosen_by_broadcast = my_generation != real_cond.broadcast_generation;
+
+ if (chosen_by_signal || chosen_by_broadcast)
+ mustConsumeSemaphore = true;
+ else
+ {
+ // Still on waiters list. Remove this waiter from list.
+ if (this_wait.next != NULL)
+ this_wait.next->prev = this_wait.prev;
+ else
+ real_cond.tail_waiter = this_wait.prev;
+
+ if (this_wait.prev != NULL)
+ this_wait.prev->next = this_wait.next;
+ else
+ real_cond.head_waiter = this_wait.next;
+ }
+ }
+
+ if (mustConsumeSemaphore)
+ {
+ ::WaitForSingleObject(semaphore, INFINITE);
+ result = WAIT_OBJECT_0;
+ }
+ }
+ else
+ DNG_ASSERT (result == WAIT_OBJECT_0, "pthread emulation logic error");
+
+ // reacquire the mutex
+ real_mutex.Lock();
+
+ return (result == WAIT_TIMEOUT) ? DNG_ETIMEDOUT : 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_cond_wait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex)
+{
+ ValidateCond(cond);
+
+ return cond_wait_internal(cond, mutex, INFINITE);
+}
+
+/*****************************************************************************/
+
+int dng_pthread_cond_timedwait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex, struct dng_timespec *latest_time)
+{
+ ValidateCond(cond);
+
+ struct dng_timespec sys_timespec;
+
+ dng_pthread_now (&sys_timespec);
+
+ __int64 sys_time = (__int64)sys_timespec.tv_sec * 1000000000 + sys_timespec.tv_nsec;
+ __int64 lock_time = (__int64)latest_time->tv_sec * 1000000000 + latest_time->tv_nsec;
+
+ int wait_millisecs = (int)((lock_time - sys_time + 500000) / 1000000);
+
+ if (wait_millisecs < 0)
+ wait_millisecs = 0;
+
+ return cond_wait_internal(cond, mutex, wait_millisecs);
+}
+
+/*****************************************************************************/
+
+int dng_pthread_cond_signal(dng_pthread_cond_t *cond)
+{
+ ValidateCond(cond);
+
+ waiter *first;
+ dng_pthread_cond_impl &real_cond = **cond;
+
+ {
+ ScopedLock lock(real_cond.lock);
+
+ first = real_cond.head_waiter;
+ if (first != NULL)
+ {
+ if (first->next != NULL)
+ first->next->prev = NULL;
+ else
+ real_cond.tail_waiter = NULL; // Or first->prev, which is always NULL in this case
+
+ first->chosen_by_signal = true;
+
+ real_cond.head_waiter = first->next;
+ }
+ }
+
+ if (first != NULL)
+ ::ReleaseSemaphore(first->semaphore, 1, NULL);
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_cond_broadcast(dng_pthread_cond_t *cond)
+{
+ ValidateCond(cond);
+
+ waiter *first;
+ dng_pthread_cond_impl &real_cond = **cond;
+
+ {
+ ScopedLock lock(real_cond.lock);
+
+ first = real_cond.head_waiter;
+ real_cond.head_waiter = NULL;
+ real_cond.tail_waiter = NULL;
+
+ real_cond.broadcast_generation++;
+ }
+
+ while (first != NULL)
+ {
+ waiter *next = first->next;
+ ::ReleaseSemaphore(first->semaphore, 1, NULL);
+ first = next;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_once(dng_pthread_once_t *once, void (*init_func)())
+{
+ if (once == NULL || init_func == NULL)
+ return EINVAL;
+
+ if (once->inited)
+ return 0;
+
+ if (::InterlockedIncrement(&once->semaphore) == 0)
+ {
+ init_func();
+ once->inited = 1;
+ }
+ else
+ {
+ while (!once->inited)
+ Sleep(0);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_key_create(dng_pthread_key_t * key, void (*destructor) (void *))
+{
+ if (destructor != NULL)
+ return -1;
+
+ DWORD result = ::TlsAlloc();
+ if (result == TLS_OUT_OF_INDEXES)
+ return -1;
+ *key = (unsigned long)result;
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_key_delete(dng_pthread_key_t key)
+{
+ if (::TlsFree((DWORD)key))
+ return 0;
+ return -1;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_setspecific(dng_pthread_key_t key, const void *value)
+{
+ if (::TlsSetValue((DWORD)key, const_cast<void *>(value)))
+ return 0;
+ return -1;
+}
+
+/*****************************************************************************/
+
+void *dng_pthread_getspecific(dng_pthread_key_t key)
+{
+ return ::TlsGetValue((DWORD)key);
+}
+
+/*****************************************************************************/
+
+namespace {
+ struct rw_waiter {
+ struct rw_waiter *prev;
+ struct rw_waiter *next;
+ HANDLE semaphore;
+ bool is_writer;
+ };
+}
+
+struct dng_pthread_rwlock_impl
+{
+ dng_pthread_mutex_impl mutex;
+
+ rw_waiter *head_waiter;
+ rw_waiter *tail_waiter;
+
+ unsigned long readers_active;
+ unsigned long writers_waiting;
+ bool writer_active;
+
+ dng_pthread_cond_impl read_wait;
+ dng_pthread_cond_impl write_wait;
+
+ dng_pthread_rwlock_impl ()
+ : mutex ()
+ , head_waiter (NULL)
+ , tail_waiter (NULL)
+ , readers_active (0)
+ , writers_waiting (0)
+ , read_wait ()
+ , write_wait ()
+ , writer_active (false)
+ {
+ }
+
+ ~dng_pthread_rwlock_impl ()
+ {
+ }
+
+ void WakeHeadWaiter ()
+ {
+ HANDLE semaphore = head_waiter->semaphore;
+
+ head_waiter = head_waiter->next;
+ if (head_waiter == NULL)
+ tail_waiter = NULL;
+
+ ::ReleaseSemaphore(semaphore, 1, NULL);
+ }
+
+};
+
+/*****************************************************************************/
+
+int dng_pthread_rwlock_init(dng_pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attrs)
+{
+ dng_pthread_rwlock_impl *newRWLock;
+
+ newRWLock = new (std::nothrow) dng_pthread_rwlock_impl;
+ if (newRWLock == NULL)
+ return -1; // ENOMEM;
+
+ *rwlock = newRWLock;
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_rwlock_destroy(dng_pthread_rwlock_t *rwlock)
+{
+ dng_pthread_rwlock_impl &real_rwlock = **rwlock;
+
+ {
+ ScopedLock lock (real_rwlock.mutex);
+
+ if (real_rwlock.head_waiter != NULL ||
+ real_rwlock.readers_active != 0 ||
+ real_rwlock.writers_waiting != 0 ||
+ real_rwlock.writer_active)
+ return -1; // EBUSY
+ }
+
+ delete *rwlock;
+ *rwlock = NULL;
+ return 0;
+}
+
+/*****************************************************************************/
+
+#define CHECK_RWLOCK_STATE(real_rwlock) \
+ DNG_ASSERT (!real_rwlock.writer_active || real_rwlock.readers_active == 0, "dng_pthread_rwlock_t logic error")
+
+/*****************************************************************************/
+
+int dng_pthread_rwlock_rdlock(dng_pthread_rwlock_t *rwlock)
+{
+ dng_pthread_rwlock_impl &real_rwlock = **rwlock;
+
+ struct rw_waiter this_wait;
+ bool doWait = false;;
+ int result = 0;
+ HANDLE semaphore=NULL;
+
+ {
+
+ ScopedLock lock (real_rwlock.mutex);
+
+ CHECK_RWLOCK_STATE (real_rwlock);
+
+ if (real_rwlock.writers_waiting > 0 || real_rwlock.writer_active)
+ {
+ semaphore = GetThreadSemaphore();
+
+ this_wait.next = NULL;
+ this_wait.semaphore = semaphore;
+ this_wait.is_writer = false;
+
+ // Add this waiter to the end of the list.
+ this_wait.prev = real_rwlock.tail_waiter;
+ if (real_rwlock.tail_waiter != NULL)
+ real_rwlock.tail_waiter->next = &this_wait;
+ real_rwlock.tail_waiter = &this_wait;
+
+ // If the list was empty, set the head of the list to this waiter.
+ if (real_rwlock.head_waiter == NULL)
+ real_rwlock.head_waiter = &this_wait;
+
+ doWait = true;
+ }
+ else
+ real_rwlock.readers_active++;
+ }
+
+ if (result == 0 && doWait)
+ result = (WaitForSingleObject(semaphore, INFINITE) == WAIT_OBJECT_0) ? 0 : -1;
+
+ return result;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_rwlock_tryrdlock(dng_pthread_rwlock_t *rwlock)
+{
+ dng_pthread_rwlock_impl &real_rwlock = **rwlock;
+
+ ScopedLock lock (real_rwlock.mutex);
+
+ CHECK_RWLOCK_STATE (real_rwlock);
+
+ if (real_rwlock.writers_waiting == 0 && !real_rwlock.writer_active)
+ {
+ real_rwlock.readers_active++;
+ return 0;
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_rwlock_trywrlock(dng_pthread_rwlock_t *rwlock)
+{
+ dng_pthread_rwlock_impl &real_rwlock = **rwlock;
+
+ ScopedLock lock (real_rwlock.mutex);
+
+ CHECK_RWLOCK_STATE (real_rwlock);
+
+ if (real_rwlock.readers_active == 0 &&
+ real_rwlock.writers_waiting == 0 &&
+ !real_rwlock.writer_active)
+ {
+ real_rwlock.writer_active = true;
+ return 0;
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+int dng_pthread_rwlock_unlock(dng_pthread_rwlock_t *rwlock)
+ {
+ dng_pthread_rwlock_impl &real_rwlock = **rwlock;
+
+ int result = 0;
+
+ ScopedLock lock (real_rwlock.mutex);
+
+ CHECK_RWLOCK_STATE (real_rwlock);
+
+ if (real_rwlock.readers_active > 0)
+ --real_rwlock.readers_active;
+ else
+ real_rwlock.writer_active = false;
+
+ while (real_rwlock.head_waiter != NULL)
+ {
+ if (real_rwlock.head_waiter->is_writer)
+ {
+ if (real_rwlock.readers_active == 0)
+ {
+ real_rwlock.writers_waiting--;
+ real_rwlock.writer_active = true;
+ real_rwlock.WakeHeadWaiter ();
+ }
+
+ break;
+ }
+ else
+ {
+ ++real_rwlock.readers_active;
+ real_rwlock.WakeHeadWaiter ();
+ }
+ }
+
+ return result;
+ }
+
+/*****************************************************************************/
+
+int dng_pthread_rwlock_wrlock(dng_pthread_rwlock_t *rwlock)
+ {
+ dng_pthread_rwlock_impl &real_rwlock = **rwlock;
+
+ int result = 0;
+ struct rw_waiter this_wait;
+ HANDLE semaphore=NULL;
+ bool doWait = false;
+
+ {
+ ScopedLock lock (real_rwlock.mutex);
+
+ CHECK_RWLOCK_STATE (real_rwlock);
+
+ if (real_rwlock.readers_active ||
+ real_rwlock.writers_waiting ||
+ real_rwlock.writer_active)
+ {
+ semaphore = GetThreadSemaphore();
+
+ this_wait.next = NULL;
+ this_wait.semaphore = semaphore;
+ this_wait.is_writer = true;
+
+ // Add this waiter to the end of the list.
+ this_wait.prev = real_rwlock.tail_waiter;
+ if (real_rwlock.tail_waiter != NULL)
+ real_rwlock.tail_waiter->next = &this_wait;
+ real_rwlock.tail_waiter = &this_wait;
+
+ // If the list was empty, set the head of the list to this waiter.
+ if (real_rwlock.head_waiter == NULL)
+ real_rwlock.head_waiter = &this_wait;
+
+ real_rwlock.writers_waiting++;
+
+ doWait = true;
+ }
+ else
+ real_rwlock.writer_active = true;
+ }
+
+ if (result == 0 && doWait)
+ result = (WaitForSingleObject(semaphore, INFINITE) == WAIT_OBJECT_0) ? 0 : -1;
+
+ return result;
+ }
+
+/*****************************************************************************/
+
+void dng_pthread_disassociate()
+{
+ FreeThreadSemaphore();
+}
+
+void dng_pthread_terminate()
+ {
+ finalize_thread_TLS();
+ }
+
+/*****************************************************************************/
+
+} // extern "C"
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
+
+int dng_pthread_now (struct timespec *now)
+ {
+
+ if (now == NULL)
+ return -1; // EINVAL
+
+ #if qWinOS
+
+ FILETIME ft;
+ ::GetSystemTimeAsFileTime(&ft);
+
+ __int64 sys_time = ((__int64)ft.dwHighDateTime << 32) + ft.dwLowDateTime;
+
+ #define SecsFrom1601To1970 11644473600
+
+ sys_time -= SecsFrom1601To1970 * 10000000LL;
+
+ sys_time *= 100; // Convert from 100ns to 1ns units
+
+ now->tv_sec = (long)(sys_time / 1000000000);
+ now->tv_nsec = (long)(sys_time % 1000000000);
+
+ #else
+
+ struct timeval tv;
+
+ if (gettimeofday (&tv, NULL) != 0)
+ return errno;
+
+ now->tv_sec = tv.tv_sec;
+ now->tv_nsec = tv.tv_usec * 1000;
+
+ #endif
+
+ return 0;
+
+ }
+
+/*****************************************************************************/
+
+#endif // qDNGThreadSafe
+
+/*****************************************************************************/
diff --git a/source/dng_pthread.h b/source/dng_pthread.h
index 7ff34f7..0a28a1b 100644
--- a/source/dng_pthread.h
+++ b/source/dng_pthread.h
@@ -1,266 +1,266 @@
-/*****************************************************************************/
-// Copyright 2002-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_pthread.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_pthread__
-#define __dng_pthread__
-
-/*****************************************************************************/
-
-#include "dng_flags.h"
-
-/*****************************************************************************/
-
-#if qDNGThreadSafe
-
-/*****************************************************************************/
-
-#if !qWinOS
-
-/*****************************************************************************/
-
-/* Try generic POSIX compile */
-
-#include <errno.h>
-#include <pthread.h>
-
-#define dng_pthread_disassociate()
-#define dng_pthread_terminate()
-
-/*****************************************************************************/
-
-#else
-
-/*****************************************************************************/
-
-#include <stdlib.h>
-
-#if _MSC_VER >= 1600
-
-// Get this included so ETIMEDOUT is predefined.
-#include <errno.h>
-
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/*****************************************************************************/
-
-#define DNG_ETIMEDOUT 60 /* Operation timed out */
-
-struct dng_timespec {
- long tv_sec;
- long tv_nsec;
-};
-
-
-typedef unsigned long dng_pthread_t;
-
-typedef struct dng_pthread_mutex_impl *dng_pthread_mutex_t;
-typedef struct dng_pthread_cond_impl *dng_pthread_cond_t;
-typedef unsigned long dng_pthread_key_t;
-
-
-#define DNG_PTHREAD_MUTEX_INITIALIZER ((struct dng_pthread_mutex_impl *)-1)
-#define DNG_PTHREAD_COND_INITIALIZER ((struct dng_pthread_cond_impl *)-1)
-
-struct _dng_pthread_once_t {
- int inited;
- long semaphore;
-};
-
-typedef struct _dng_pthread_once_t dng_pthread_once_t;
-#define DNG_PTHREAD_ONCE_INIT { 0, -1 }
-
-#define dng_pthread_equal(t1, t2) ((t1) == (t2))
-
-typedef struct dng_pthread_attr_impl *dng_pthread_attr_t;
-
-int dng_pthread_attr_init(dng_pthread_attr_t *attr);
-int dng_pthread_attr_destroy(dng_pthread_attr_t *attr);
-
-int dng_pthread_attr_setstacksize(dng_pthread_attr_t *attr, size_t stacksize);
-int dng_pthread_attr_getstacksize(const dng_pthread_attr_t *attr, size_t *stacksize);
-
-int dng_pthread_create(dng_pthread_t *thread, const dng_pthread_attr_t * /* attrs */, void * (*func)(void *), void *arg);
-int dng_pthread_detach(dng_pthread_t thread);
-int dng_pthread_join(dng_pthread_t thread, void **result);
-dng_pthread_t dng_pthread_self();
-void dng_pthread_exit(void *result);
-
-#define DNG_PTHREAD_MUTEX_RECURSIVE 0
-typedef unsigned long dng_pthread_mutexattr_t;
-
-int dng_pthread_mutexattr_init(dng_pthread_mutexattr_t *mutexattr);
-int dng_pthread_mutexattr_settype(dng_pthread_mutexattr_t *mutexattr, int /*the options*/);
-
-int dng_pthread_mutex_init(dng_pthread_mutex_t *mutex, void * /* attrs */);
-int dng_pthread_mutex_destroy(dng_pthread_mutex_t *mutex);
-int dng_pthread_mutex_lock(dng_pthread_mutex_t *mutex);
-int dng_pthread_mutex_unlock(dng_pthread_mutex_t *mutex);
-
-int dng_pthread_cond_init(dng_pthread_cond_t *cond, void * /* attrs */);
-int dng_pthread_cond_destroy(dng_pthread_cond_t *cond);
-int dng_pthread_cond_wait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex);
-int dng_pthread_cond_timedwait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex, struct dng_timespec *latest_time);
-int dng_pthread_cond_signal(dng_pthread_cond_t *cond);
-int dng_pthread_cond_broadcast(dng_pthread_cond_t *cond);
-
-int dng_pthread_once(dng_pthread_once_t *once, void (*init_func)());
-
-int dng_pthread_key_create(dng_pthread_key_t * key, void (*destructor) (void *));
-int dng_pthread_key_delete(dng_pthread_key_t key);
-int dng_pthread_setspecific(dng_pthread_key_t key, const void *value);
-void *dng_pthread_getspecific(dng_pthread_key_t key);
-
-typedef struct dng_pthread_rwlock_impl *dng_pthread_rwlock_t;
-typedef void *pthread_rwlockattr_t;
-
-int dng_pthread_rwlock_destroy(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_init(dng_pthread_rwlock_t * rwlock, const pthread_rwlockattr_t * attrs);
-int dng_pthread_rwlock_rdlock(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_tryrdlock(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_trywrlock(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_unlock(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_wrlock(dng_pthread_rwlock_t * rwlock);
-
-typedef struct dng_pthread_rwlock_impl *dng_pthread_rwlock_t;
-typedef void *pthread_rwlockattr_t;
-
-int dng_pthread_rwlock_destroy(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_init(dng_pthread_rwlock_t * rwlock, const pthread_rwlockattr_t * attrs);
-int dng_pthread_rwlock_rdlock(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_tryrdlock(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_trywrlock(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_unlock(dng_pthread_rwlock_t * rwlock);
-int dng_pthread_rwlock_wrlock(dng_pthread_rwlock_t * rwlock);
-
-// dng_pthread may maintain per-thread global state. This routine frees that global state.
-// there is no need to call this for threads created by dng_pthread and one can call
-// dng_pthread routines of a thread after dng_pthread_disassociate as the global state will
-// be recreated as necessary. However dng_pthread_disassociate will need to be called again
-// and there is a slight performance cost. Do not call this routine while holding a mutex, etc.
-void dng_pthread_disassociate();
-
-void dng_pthread_terminate();
-
-/*****************************************************************************/
-
-// Map symbols back to plain pthread names. This whole mechanism is so the DNG pthreads library
-// symbols do not collide with another pthread emulation library
-// that may be in use in the same linked entity. However if that is the case, it would be far better
-// to have the DNG code use the same pthread library as the rest of the code.
-
-#define pthread_t dng_pthread_t
-#define pthread_mutex_t dng_pthread_mutex_t
-#define pthread_cond_t dng_pthread_cond_t
-#define pthread_once_t dng_pthread_once_t
-#define pthread_key_t dng_pthread_key_t
-
-#undef PTHREAD_MUTEX_INITIALIZER
-#define PTHREAD_MUTEX_INITIALIZER DNG_PTHREAD_MUTEX_INITIALIZER
-#undef PTHREAD_COND_INITIALIZER
-#define PTHREAD_COND_INITIALIZER DNG_PTHREAD_COND_INITIALIZER
-
-#undef PTHREAD_ONCE_INIT
-#define PTHREAD_ONCE_INIT DNG_PTHREAD_ONCE_INIT
-
-#define timespec dng_timespec
-
-/* If it is defined on Windows, it probably has the wrong value... */
-#if defined(WIN32) || !defined(ETIMEDOUT)
-#undef ETIMEDOUT
-#define ETIMEDOUT DNG_ETIMEDOUT
-#endif
-
-#define pthread_equal dng_pthread_equal
-
-#define pthread_attr_t dng_pthread_attr_t
-
-#define pthread_attr_init dng_pthread_attr_init
-#define pthread_attr_destroy dng_pthread_attr_destroy
-
-#define pthread_attr_setstacksize dng_pthread_attr_setstacksize
-#define pthread_attr_getstacksize dng_pthread_attr_getstacksize
-
-#define pthread_create dng_pthread_create
-#define pthread_detach dng_pthread_detach
-#define pthread_join dng_pthread_join
-#define pthread_self dng_pthread_self
-#define pthread_exit dng_pthread_exit
-
-#define pthread_mutex_init dng_pthread_mutex_init
-#define pthread_mutex_destroy dng_pthread_mutex_destroy
-#define pthread_mutex_lock dng_pthread_mutex_lock
-#define pthread_mutex_unlock dng_pthread_mutex_unlock
-
-#define pthread_cond_init dng_pthread_cond_init
-#define pthread_cond_destroy dng_pthread_cond_destroy
-#define pthread_cond_wait dng_pthread_cond_wait
-#define pthread_cond_timedwait dng_pthread_cond_timedwait
-#define pthread_cond_signal dng_pthread_cond_signal
-#define pthread_cond_broadcast dng_pthread_cond_broadcast
-
-#define pthread_once dng_pthread_once
-
-#define pthread_key_create dng_pthread_key_create
-#define pthread_key_delete dng_pthread_key_delete
-#define pthread_setspecific dng_pthread_setspecific
-#define pthread_getspecific dng_pthread_getspecific
-
-#define pthread_rwlock_t dng_pthread_rwlock_t
-
-#define pthread_rwlock_destroy dng_pthread_rwlock_destroy
-#define pthread_rwlock_init dng_pthread_rwlock_init
-#define pthread_rwlock_rdlock dng_pthread_rwlock_rdlock
-#define pthread_rwlock_tryrdlock dng_pthread_rwlock_tryrdlock
-#define pthread_rwlock_trywrlock dng_pthread_rwlock_trywrlock
-#define pthread_rwlock_unlock dng_pthread_rwlock_unlock
-#define pthread_rwlock_wrlock dng_pthread_rwlock_wrlock
-
-/*****************************************************************************/
-
-#ifdef __cplusplus
-}
-#endif
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-int dng_pthread_now (struct timespec *now);
-
-#ifdef __cplusplus
-}
-#endif
-
-/*****************************************************************************/
-
-#endif // qDNGThreadSafe
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2002-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_pthread.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_pthread__
+#define __dng_pthread__
+
+/*****************************************************************************/
+
+#include "dng_flags.h"
+
+/*****************************************************************************/
+
+#if qDNGThreadSafe
+
+/*****************************************************************************/
+
+#if !qWinOS
+
+/*****************************************************************************/
+
+/* Try generic POSIX compile */
+
+#include <errno.h>
+#include <pthread.h>
+
+#define dng_pthread_disassociate()
+#define dng_pthread_terminate()
+
+/*****************************************************************************/
+
+#else
+
+/*****************************************************************************/
+
+#include <stdlib.h>
+
+#if _MSC_VER >= 1600
+
+// Get this included so ETIMEDOUT is predefined.
+#include <errno.h>
+
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************/
+
+#define DNG_ETIMEDOUT 60 /* Operation timed out */
+
+struct dng_timespec {
+ long tv_sec;
+ long tv_nsec;
+};
+
+
+typedef unsigned long dng_pthread_t;
+
+typedef struct dng_pthread_mutex_impl *dng_pthread_mutex_t;
+typedef struct dng_pthread_cond_impl *dng_pthread_cond_t;
+typedef unsigned long dng_pthread_key_t;
+
+
+#define DNG_PTHREAD_MUTEX_INITIALIZER ((struct dng_pthread_mutex_impl *)-1)
+#define DNG_PTHREAD_COND_INITIALIZER ((struct dng_pthread_cond_impl *)-1)
+
+struct _dng_pthread_once_t {
+ int inited;
+ long semaphore;
+};
+
+typedef struct _dng_pthread_once_t dng_pthread_once_t;
+#define DNG_PTHREAD_ONCE_INIT { 0, -1 }
+
+#define dng_pthread_equal(t1, t2) ((t1) == (t2))
+
+typedef struct dng_pthread_attr_impl *dng_pthread_attr_t;
+
+int dng_pthread_attr_init(dng_pthread_attr_t *attr);
+int dng_pthread_attr_destroy(dng_pthread_attr_t *attr);
+
+int dng_pthread_attr_setstacksize(dng_pthread_attr_t *attr, size_t stacksize);
+int dng_pthread_attr_getstacksize(const dng_pthread_attr_t *attr, size_t *stacksize);
+
+int dng_pthread_create(dng_pthread_t *thread, const dng_pthread_attr_t * /* attrs */, void * (*func)(void *), void *arg);
+int dng_pthread_detach(dng_pthread_t thread);
+int dng_pthread_join(dng_pthread_t thread, void **result);
+dng_pthread_t dng_pthread_self();
+void dng_pthread_exit(void *result);
+
+#define DNG_PTHREAD_MUTEX_RECURSIVE 0
+typedef unsigned long dng_pthread_mutexattr_t;
+
+int dng_pthread_mutexattr_init(dng_pthread_mutexattr_t *mutexattr);
+int dng_pthread_mutexattr_settype(dng_pthread_mutexattr_t *mutexattr, int /*the options*/);
+
+int dng_pthread_mutex_init(dng_pthread_mutex_t *mutex, void * /* attrs */);
+int dng_pthread_mutex_destroy(dng_pthread_mutex_t *mutex);
+int dng_pthread_mutex_lock(dng_pthread_mutex_t *mutex);
+int dng_pthread_mutex_unlock(dng_pthread_mutex_t *mutex);
+
+int dng_pthread_cond_init(dng_pthread_cond_t *cond, void * /* attrs */);
+int dng_pthread_cond_destroy(dng_pthread_cond_t *cond);
+int dng_pthread_cond_wait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex);
+int dng_pthread_cond_timedwait(dng_pthread_cond_t *cond, dng_pthread_mutex_t *mutex, struct dng_timespec *latest_time);
+int dng_pthread_cond_signal(dng_pthread_cond_t *cond);
+int dng_pthread_cond_broadcast(dng_pthread_cond_t *cond);
+
+int dng_pthread_once(dng_pthread_once_t *once, void (*init_func)());
+
+int dng_pthread_key_create(dng_pthread_key_t * key, void (*destructor) (void *));
+int dng_pthread_key_delete(dng_pthread_key_t key);
+int dng_pthread_setspecific(dng_pthread_key_t key, const void *value);
+void *dng_pthread_getspecific(dng_pthread_key_t key);
+
+typedef struct dng_pthread_rwlock_impl *dng_pthread_rwlock_t;
+typedef void *pthread_rwlockattr_t;
+
+int dng_pthread_rwlock_destroy(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_init(dng_pthread_rwlock_t * rwlock, const pthread_rwlockattr_t * attrs);
+int dng_pthread_rwlock_rdlock(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_tryrdlock(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_trywrlock(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_unlock(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_wrlock(dng_pthread_rwlock_t * rwlock);
+
+typedef struct dng_pthread_rwlock_impl *dng_pthread_rwlock_t;
+typedef void *pthread_rwlockattr_t;
+
+int dng_pthread_rwlock_destroy(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_init(dng_pthread_rwlock_t * rwlock, const pthread_rwlockattr_t * attrs);
+int dng_pthread_rwlock_rdlock(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_tryrdlock(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_trywrlock(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_unlock(dng_pthread_rwlock_t * rwlock);
+int dng_pthread_rwlock_wrlock(dng_pthread_rwlock_t * rwlock);
+
+// dng_pthread may maintain per-thread global state. This routine frees that global state.
+// there is no need to call this for threads created by dng_pthread and one can call
+// dng_pthread routines of a thread after dng_pthread_disassociate as the global state will
+// be recreated as necessary. However dng_pthread_disassociate will need to be called again
+// and there is a slight performance cost. Do not call this routine while holding a mutex, etc.
+void dng_pthread_disassociate();
+
+void dng_pthread_terminate();
+
+/*****************************************************************************/
+
+// Map symbols back to plain pthread names. This whole mechanism is so the DNG pthreads library
+// symbols do not collide with another pthread emulation library
+// that may be in use in the same linked entity. However if that is the case, it would be far better
+// to have the DNG code use the same pthread library as the rest of the code.
+
+#define pthread_t dng_pthread_t
+#define pthread_mutex_t dng_pthread_mutex_t
+#define pthread_cond_t dng_pthread_cond_t
+#define pthread_once_t dng_pthread_once_t
+#define pthread_key_t dng_pthread_key_t
+
+#undef PTHREAD_MUTEX_INITIALIZER
+#define PTHREAD_MUTEX_INITIALIZER DNG_PTHREAD_MUTEX_INITIALIZER
+#undef PTHREAD_COND_INITIALIZER
+#define PTHREAD_COND_INITIALIZER DNG_PTHREAD_COND_INITIALIZER
+
+#undef PTHREAD_ONCE_INIT
+#define PTHREAD_ONCE_INIT DNG_PTHREAD_ONCE_INIT
+
+#define timespec dng_timespec
+
+/* If it is defined on Windows, it probably has the wrong value... */
+#if defined(WIN32) || !defined(ETIMEDOUT)
+#undef ETIMEDOUT
+#define ETIMEDOUT DNG_ETIMEDOUT
+#endif
+
+#define pthread_equal dng_pthread_equal
+
+#define pthread_attr_t dng_pthread_attr_t
+
+#define pthread_attr_init dng_pthread_attr_init
+#define pthread_attr_destroy dng_pthread_attr_destroy
+
+#define pthread_attr_setstacksize dng_pthread_attr_setstacksize
+#define pthread_attr_getstacksize dng_pthread_attr_getstacksize
+
+#define pthread_create dng_pthread_create
+#define pthread_detach dng_pthread_detach
+#define pthread_join dng_pthread_join
+#define pthread_self dng_pthread_self
+#define pthread_exit dng_pthread_exit
+
+#define pthread_mutex_init dng_pthread_mutex_init
+#define pthread_mutex_destroy dng_pthread_mutex_destroy
+#define pthread_mutex_lock dng_pthread_mutex_lock
+#define pthread_mutex_unlock dng_pthread_mutex_unlock
+
+#define pthread_cond_init dng_pthread_cond_init
+#define pthread_cond_destroy dng_pthread_cond_destroy
+#define pthread_cond_wait dng_pthread_cond_wait
+#define pthread_cond_timedwait dng_pthread_cond_timedwait
+#define pthread_cond_signal dng_pthread_cond_signal
+#define pthread_cond_broadcast dng_pthread_cond_broadcast
+
+#define pthread_once dng_pthread_once
+
+#define pthread_key_create dng_pthread_key_create
+#define pthread_key_delete dng_pthread_key_delete
+#define pthread_setspecific dng_pthread_setspecific
+#define pthread_getspecific dng_pthread_getspecific
+
+#define pthread_rwlock_t dng_pthread_rwlock_t
+
+#define pthread_rwlock_destroy dng_pthread_rwlock_destroy
+#define pthread_rwlock_init dng_pthread_rwlock_init
+#define pthread_rwlock_rdlock dng_pthread_rwlock_rdlock
+#define pthread_rwlock_tryrdlock dng_pthread_rwlock_tryrdlock
+#define pthread_rwlock_trywrlock dng_pthread_rwlock_trywrlock
+#define pthread_rwlock_unlock dng_pthread_rwlock_unlock
+#define pthread_rwlock_wrlock dng_pthread_rwlock_wrlock
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int dng_pthread_now (struct timespec *now);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*****************************************************************************/
+
+#endif // qDNGThreadSafe
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_rational.cpp b/source/dng_rational.cpp
index c366b46..9cddf5b 100644
--- a/source/dng_rational.cpp
+++ b/source/dng_rational.cpp
@@ -1,150 +1,150 @@
-/*****************************************************************************/
-// Copyright 2006 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_rational.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_rational.h"
-
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-real64 dng_srational::As_real64 () const
- {
-
- if (d)
- return (real64) n / (real64) d;
-
- else
- return 0.0;
-
- }
-
-/*****************************************************************************/
-
-void dng_srational::Set_real64 (real64 x, int32 dd)
- {
-
- if (x == 0.0)
- {
-
- *this = dng_srational (0, 1);
-
- }
-
- if (dd == 0)
- {
-
- real64 y = Abs_real64 (x);
-
- if (y >= 32768.0)
- {
- dd = 1;
- }
-
- else if (y >= 1.0)
- {
- dd = 32768;
- }
-
- else
- {
- dd = 32768 * 32768;
- }
-
- }
-
- *this = dng_srational (Round_int32 (x * dd), dd);
-
- }
-
-/*****************************************************************************/
-
-void dng_srational::ReduceByFactor (int32 factor)
- {
-
- while (n % factor == 0 &&
- d % factor == 0 &&
- d >= factor)
- {
- n /= factor;
- d /= factor;
- }
-
- }
-
-/*****************************************************************************/
-
-real64 dng_urational::As_real64 () const
- {
-
- if (d)
- return (real64) n / (real64) d;
-
- else
- return 0.0;
-
- }
-
-/*****************************************************************************/
-
-void dng_urational::Set_real64 (real64 x, uint32 dd)
- {
-
- if (x <= 0.0)
- {
-
- *this = dng_urational (0, 1);
-
- }
-
- if (dd == 0)
- {
-
- if (x >= 32768.0)
- {
- dd = 1;
- }
-
- else if (x >= 1.0)
- {
- dd = 32768;
- }
-
- else
- {
- dd = 32768 * 32768;
- }
-
- }
-
- *this = dng_urational (Round_uint32 (x * dd), dd);
-
- }
-
-/*****************************************************************************/
-
-void dng_urational::ReduceByFactor (uint32 factor)
- {
-
- while (n % factor == 0 &&
- d % factor == 0 &&
- d >= factor)
- {
- n /= factor;
- d /= factor;
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_rational.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_rational.h"
+
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+real64 dng_srational::As_real64 () const
+ {
+
+ if (d)
+ return (real64) n / (real64) d;
+
+ else
+ return 0.0;
+
+ }
+
+/*****************************************************************************/
+
+void dng_srational::Set_real64 (real64 x, int32 dd)
+ {
+
+ if (x == 0.0)
+ {
+
+ *this = dng_srational (0, 1);
+
+ }
+
+ if (dd == 0)
+ {
+
+ real64 y = Abs_real64 (x);
+
+ if (y >= 32768.0)
+ {
+ dd = 1;
+ }
+
+ else if (y >= 1.0)
+ {
+ dd = 32768;
+ }
+
+ else
+ {
+ dd = 32768 * 32768;
+ }
+
+ }
+
+ *this = dng_srational (Round_int32 (x * dd), dd);
+
+ }
+
+/*****************************************************************************/
+
+void dng_srational::ReduceByFactor (int32 factor)
+ {
+
+ while (n % factor == 0 &&
+ d % factor == 0 &&
+ d >= factor)
+ {
+ n /= factor;
+ d /= factor;
+ }
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_urational::As_real64 () const
+ {
+
+ if (d)
+ return (real64) n / (real64) d;
+
+ else
+ return 0.0;
+
+ }
+
+/*****************************************************************************/
+
+void dng_urational::Set_real64 (real64 x, uint32 dd)
+ {
+
+ if (x <= 0.0)
+ {
+
+ *this = dng_urational (0, 1);
+
+ }
+
+ if (dd == 0)
+ {
+
+ if (x >= 32768.0)
+ {
+ dd = 1;
+ }
+
+ else if (x >= 1.0)
+ {
+ dd = 32768;
+ }
+
+ else
+ {
+ dd = 32768 * 32768;
+ }
+
+ }
+
+ *this = dng_urational (Round_uint32 (x * dd), dd);
+
+ }
+
+/*****************************************************************************/
+
+void dng_urational::ReduceByFactor (uint32 factor)
+ {
+
+ while (n % factor == 0 &&
+ d % factor == 0 &&
+ d >= factor)
+ {
+ n /= factor;
+ d /= factor;
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_rational.h b/source/dng_rational.h
index 9080a63..f466062 100644
--- a/source/dng_rational.h
+++ b/source/dng_rational.h
@@ -1,149 +1,149 @@
-/*****************************************************************************/
-// Copyright 2006 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_rational.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Signed and unsigned rational data types.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_rational__
-#define __dng_rational__
-
-/*****************************************************************************/
-
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-class dng_srational
- {
-
- public:
-
- int32 n; // Numerator
- int32 d; // Denominator
-
- public:
-
- dng_srational ()
- : n (0)
- , d (0)
- {
- }
-
- dng_srational (int32 nn, int32 dd)
- : n (nn)
- , d (dd)
- {
- }
-
- void Clear ()
- {
- n = 0;
- d = 0;
- }
-
- bool IsValid () const
- {
- return d != 0;
- }
-
- bool NotValid () const
- {
- return !IsValid ();
- }
-
- bool operator== (const dng_srational &r) const
- {
- return (n == r.n) &&
- (d == r.d);
- }
-
- bool operator!= (const dng_srational &r) const
- {
- return !(*this == r);
- }
-
- real64 As_real64 () const;
-
- void Set_real64 (real64 x, int32 dd = 0);
-
- void ReduceByFactor (int32 factor);
-
- };
-
-/*****************************************************************************/
-
-class dng_urational
- {
-
- public:
-
- uint32 n; // Numerator
- uint32 d; // Denominator
-
- public:
-
- dng_urational ()
- : n (0)
- , d (0)
- {
- }
-
- dng_urational (uint32 nn, uint32 dd)
- : n (nn)
- , d (dd)
- {
- }
-
- void Clear ()
- {
- n = 0;
- d = 0;
- }
-
- bool IsValid () const
- {
- return d != 0;
- }
-
- bool NotValid () const
- {
- return !IsValid ();
- }
-
- bool operator== (const dng_urational &r) const
- {
- return (n == r.n) &&
- (d == r.d);
- }
-
- bool operator!= (const dng_urational &r) const
- {
- return !(*this == r);
- }
-
- real64 As_real64 () const;
-
- void Set_real64 (real64 x, uint32 dd = 0);
-
- void ReduceByFactor (uint32 factor);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_rational.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Signed and unsigned rational data types.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_rational__
+#define __dng_rational__
+
+/*****************************************************************************/
+
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+class dng_srational
+ {
+
+ public:
+
+ int32 n; // Numerator
+ int32 d; // Denominator
+
+ public:
+
+ dng_srational ()
+ : n (0)
+ , d (0)
+ {
+ }
+
+ dng_srational (int32 nn, int32 dd)
+ : n (nn)
+ , d (dd)
+ {
+ }
+
+ void Clear ()
+ {
+ n = 0;
+ d = 0;
+ }
+
+ bool IsValid () const
+ {
+ return d != 0;
+ }
+
+ bool NotValid () const
+ {
+ return !IsValid ();
+ }
+
+ bool operator== (const dng_srational &r) const
+ {
+ return (n == r.n) &&
+ (d == r.d);
+ }
+
+ bool operator!= (const dng_srational &r) const
+ {
+ return !(*this == r);
+ }
+
+ real64 As_real64 () const;
+
+ void Set_real64 (real64 x, int32 dd = 0);
+
+ void ReduceByFactor (int32 factor);
+
+ };
+
+/*****************************************************************************/
+
+class dng_urational
+ {
+
+ public:
+
+ uint32 n; // Numerator
+ uint32 d; // Denominator
+
+ public:
+
+ dng_urational ()
+ : n (0)
+ , d (0)
+ {
+ }
+
+ dng_urational (uint32 nn, uint32 dd)
+ : n (nn)
+ , d (dd)
+ {
+ }
+
+ void Clear ()
+ {
+ n = 0;
+ d = 0;
+ }
+
+ bool IsValid () const
+ {
+ return d != 0;
+ }
+
+ bool NotValid () const
+ {
+ return !IsValid ();
+ }
+
+ bool operator== (const dng_urational &r) const
+ {
+ return (n == r.n) &&
+ (d == r.d);
+ }
+
+ bool operator!= (const dng_urational &r) const
+ {
+ return !(*this == r);
+ }
+
+ real64 As_real64 () const;
+
+ void Set_real64 (real64 x, uint32 dd = 0);
+
+ void ReduceByFactor (uint32 factor);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_read_image.h b/source/dng_read_image.h
index bd79e55..99951af 100644
--- a/source/dng_read_image.h
+++ b/source/dng_read_image.h
@@ -1,182 +1,182 @@
-/*****************************************************************************/
-// Copyright 2006-2012 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_read_image.h#2 $ */
-/* $DateTime: 2012/06/05 11:05:39 $ */
-/* $Change: 833352 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Support for DNG image reading.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_read_image__
-#define __dng_read_image__
-
-/*****************************************************************************/
-
-#include "dng_auto_ptr.h"
-#include "dng_classes.h"
-#include "dng_image.h"
-#include "dng_memory.h"
-#include "dng_types.h"
-
-/******************************************************************************/
-
-bool DecodePackBits (dng_stream &stream,
- uint8 *dPtr,
- int32 dstCount);
-
-/*****************************************************************************/
-
-class dng_row_interleaved_image: public dng_image
- {
-
- private:
-
- dng_image &fImage;
-
- uint32 fFactor;
-
- public:
-
- dng_row_interleaved_image (dng_image &image,
- uint32 factor);
-
- virtual void DoGet (dng_pixel_buffer &buffer) const;
-
- virtual void DoPut (const dng_pixel_buffer &buffer);
-
- private:
-
- int32 MapRow (int32 row) const;
-
- };
-
-/*****************************************************************************/
-
-/// \brief
-///
-///
-
-class dng_read_image
- {
-
- friend class dng_read_tiles_task;
-
- protected:
-
- enum
- {
-
- // Target size for buffer used to copy data to the image.
-
- kImageBufferSize = 128 * 1024
-
- };
-
- AutoPtr<dng_memory_block> fJPEGTables;
-
- public:
-
- dng_read_image ();
-
- virtual ~dng_read_image ();
-
- ///
- /// \param
-
- virtual bool CanRead (const dng_ifd &ifd);
-
- ///
- /// \param host Host used for memory allocation, progress updating, and abort testing.
- /// \param ifd
- /// \param stream Stream to read image data from.
- /// \param image Result image to populate.
-
- virtual void Read (dng_host &host,
- const dng_ifd &ifd,
- dng_stream &stream,
- dng_image &image,
- dng_jpeg_image *jpegImage,
- dng_fingerprint *jpegDigest);
-
- protected:
-
- virtual bool ReadUncompressed (dng_host &host,
- const dng_ifd &ifd,
- dng_stream &stream,
- dng_image &image,
- const dng_rect &tileArea,
- uint32 plane,
- uint32 planes,
- AutoPtr<dng_memory_block> &uncompressedBuffer,
- AutoPtr<dng_memory_block> &subTileBlockBuffer);
-
- virtual void DecodeLossyJPEG (dng_host &host,
- dng_image &image,
- const dng_rect &tileArea,
- uint32 plane,
- uint32 planes,
- uint32 photometricInterpretation,
- uint32 jpegDataSize,
- uint8 *jpegDataInMemory);
-
- virtual bool ReadBaselineJPEG (dng_host &host,
- const dng_ifd &ifd,
- dng_stream &stream,
- dng_image &image,
- const dng_rect &tileArea,
- uint32 plane,
- uint32 planes,
- uint32 tileByteCount,
- uint8 *jpegDataInMemory);
-
- virtual bool ReadLosslessJPEG (dng_host &host,
- const dng_ifd &ifd,
- dng_stream &stream,
- dng_image &image,
- const dng_rect &tileArea,
- uint32 plane,
- uint32 planes,
- uint32 tileByteCount,
- AutoPtr<dng_memory_block> &uncompressedBuffer,
- AutoPtr<dng_memory_block> &subTileBlockBuffer);
-
- virtual bool CanReadTile (const dng_ifd &ifd);
-
- virtual bool NeedsCompressedBuffer (const dng_ifd &ifd);
-
- virtual void ByteSwapBuffer (dng_host &host,
- dng_pixel_buffer &buffer);
-
- virtual void DecodePredictor (dng_host &host,
- const dng_ifd &ifd,
- dng_pixel_buffer &buffer);
-
- virtual void ReadTile (dng_host &host,
- const dng_ifd &ifd,
- dng_stream &stream,
- dng_image &image,
- const dng_rect &tileArea,
- uint32 plane,
- uint32 planes,
- uint32 tileByteCount,
- AutoPtr<dng_memory_block> &compressedBuffer,
- AutoPtr<dng_memory_block> &uncompressedBuffer,
- AutoPtr<dng_memory_block> &subTileBlockBuffer);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2012 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_read_image.h#2 $ */
+/* $DateTime: 2012/06/05 11:05:39 $ */
+/* $Change: 833352 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Support for DNG image reading.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_read_image__
+#define __dng_read_image__
+
+/*****************************************************************************/
+
+#include "dng_auto_ptr.h"
+#include "dng_classes.h"
+#include "dng_image.h"
+#include "dng_memory.h"
+#include "dng_types.h"
+
+/******************************************************************************/
+
+bool DecodePackBits (dng_stream &stream,
+ uint8 *dPtr,
+ int32 dstCount);
+
+/*****************************************************************************/
+
+class dng_row_interleaved_image: public dng_image
+ {
+
+ private:
+
+ dng_image &fImage;
+
+ uint32 fFactor;
+
+ public:
+
+ dng_row_interleaved_image (dng_image &image,
+ uint32 factor);
+
+ virtual void DoGet (dng_pixel_buffer &buffer) const;
+
+ virtual void DoPut (const dng_pixel_buffer &buffer);
+
+ private:
+
+ int32 MapRow (int32 row) const;
+
+ };
+
+/*****************************************************************************/
+
+/// \brief
+///
+///
+
+class dng_read_image
+ {
+
+ friend class dng_read_tiles_task;
+
+ protected:
+
+ enum
+ {
+
+ // Target size for buffer used to copy data to the image.
+
+ kImageBufferSize = 128 * 1024
+
+ };
+
+ AutoPtr<dng_memory_block> fJPEGTables;
+
+ public:
+
+ dng_read_image ();
+
+ virtual ~dng_read_image ();
+
+ ///
+ /// \param
+
+ virtual bool CanRead (const dng_ifd &ifd);
+
+ ///
+ /// \param host Host used for memory allocation, progress updating, and abort testing.
+ /// \param ifd
+ /// \param stream Stream to read image data from.
+ /// \param image Result image to populate.
+
+ virtual void Read (dng_host &host,
+ const dng_ifd &ifd,
+ dng_stream &stream,
+ dng_image &image,
+ dng_jpeg_image *jpegImage,
+ dng_fingerprint *jpegDigest);
+
+ protected:
+
+ virtual bool ReadUncompressed (dng_host &host,
+ const dng_ifd &ifd,
+ dng_stream &stream,
+ dng_image &image,
+ const dng_rect &tileArea,
+ uint32 plane,
+ uint32 planes,
+ AutoPtr<dng_memory_block> &uncompressedBuffer,
+ AutoPtr<dng_memory_block> &subTileBlockBuffer);
+
+ virtual void DecodeLossyJPEG (dng_host &host,
+ dng_image &image,
+ const dng_rect &tileArea,
+ uint32 plane,
+ uint32 planes,
+ uint32 photometricInterpretation,
+ uint32 jpegDataSize,
+ uint8 *jpegDataInMemory);
+
+ virtual bool ReadBaselineJPEG (dng_host &host,
+ const dng_ifd &ifd,
+ dng_stream &stream,
+ dng_image &image,
+ const dng_rect &tileArea,
+ uint32 plane,
+ uint32 planes,
+ uint32 tileByteCount,
+ uint8 *jpegDataInMemory);
+
+ virtual bool ReadLosslessJPEG (dng_host &host,
+ const dng_ifd &ifd,
+ dng_stream &stream,
+ dng_image &image,
+ const dng_rect &tileArea,
+ uint32 plane,
+ uint32 planes,
+ uint32 tileByteCount,
+ AutoPtr<dng_memory_block> &uncompressedBuffer,
+ AutoPtr<dng_memory_block> &subTileBlockBuffer);
+
+ virtual bool CanReadTile (const dng_ifd &ifd);
+
+ virtual bool NeedsCompressedBuffer (const dng_ifd &ifd);
+
+ virtual void ByteSwapBuffer (dng_host &host,
+ dng_pixel_buffer &buffer);
+
+ virtual void DecodePredictor (dng_host &host,
+ const dng_ifd &ifd,
+ dng_pixel_buffer &buffer);
+
+ virtual void ReadTile (dng_host &host,
+ const dng_ifd &ifd,
+ dng_stream &stream,
+ dng_image &image,
+ const dng_rect &tileArea,
+ uint32 plane,
+ uint32 planes,
+ uint32 tileByteCount,
+ AutoPtr<dng_memory_block> &compressedBuffer,
+ AutoPtr<dng_memory_block> &uncompressedBuffer,
+ AutoPtr<dng_memory_block> &subTileBlockBuffer);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_rect.cpp b/source/dng_rect.cpp
index c45e03f..e873df2 100644
--- a/source/dng_rect.cpp
+++ b/source/dng_rect.cpp
@@ -1,168 +1,168 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_rect.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_rect.h"
-
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-bool dng_rect::operator== (const dng_rect &rect) const
- {
-
- return (rect.t == t) &&
- (rect.l == l) &&
- (rect.b == b) &&
- (rect.r == r);
-
- }
-
-/*****************************************************************************/
-
-bool dng_rect::IsZero () const
- {
-
- return (t == 0) && (l == 0) && (b == 0) && (r == 0);
-
- }
-
-/*****************************************************************************/
-
-bool dng_rect_real64::operator== (const dng_rect_real64 &rect) const
- {
-
- return (rect.t == t) &&
- (rect.l == l) &&
- (rect.b == b) &&
- (rect.r == r);
-
- }
-
-/*****************************************************************************/
-
-bool dng_rect_real64::IsZero () const
- {
-
- return (t == 0.0) && (l == 0.0) && (b == 0.0) && (r == 0.0);
-
- }
-
-/*****************************************************************************/
-
-dng_rect operator& (const dng_rect &a,
- const dng_rect &b)
- {
-
- dng_rect c;
-
- c.t = Max_int32 (a.t, b.t);
- c.l = Max_int32 (a.l, b.l);
-
- c.b = Min_int32 (a.b, b.b);
- c.r = Min_int32 (a.r, b.r);
-
- if (c.IsEmpty ())
- {
-
- c = dng_rect ();
-
- }
-
- return c;
-
- }
-
-/*****************************************************************************/
-
-dng_rect operator| (const dng_rect &a,
- const dng_rect &b)
- {
-
- if (a.IsEmpty ())
- {
- return b;
- }
-
- if (b.IsEmpty ())
- {
- return a;
- }
-
- dng_rect c;
-
- c.t = Min_int32 (a.t, b.t);
- c.l = Min_int32 (a.l, b.l);
-
- c.b = Max_int32 (a.b, b.b);
- c.r = Max_int32 (a.r, b.r);
-
- return c;
-
- }
-
-/*****************************************************************************/
-
-dng_rect_real64 operator& (const dng_rect_real64 &a,
- const dng_rect_real64 &b)
- {
-
- dng_rect_real64 c;
-
- c.t = Max_real64 (a.t, b.t);
- c.l = Max_real64 (a.l, b.l);
-
- c.b = Min_real64 (a.b, b.b);
- c.r = Min_real64 (a.r, b.r);
-
- if (c.IsEmpty ())
- {
-
- c = dng_rect_real64 ();
-
- }
-
- return c;
-
- }
-
-/*****************************************************************************/
-
-dng_rect_real64 operator| (const dng_rect_real64 &a,
- const dng_rect_real64 &b)
- {
-
- if (a.IsEmpty ())
- {
- return b;
- }
-
- if (b.IsEmpty ())
- {
- return a;
- }
-
- dng_rect_real64 c;
-
- c.t = Min_real64 (a.t, b.t);
- c.l = Min_real64 (a.l, b.l);
-
- c.b = Max_real64 (a.b, b.b);
- c.r = Max_real64 (a.r, b.r);
-
- return c;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_rect.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_rect.h"
+
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+bool dng_rect::operator== (const dng_rect &rect) const
+ {
+
+ return (rect.t == t) &&
+ (rect.l == l) &&
+ (rect.b == b) &&
+ (rect.r == r);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_rect::IsZero () const
+ {
+
+ return (t == 0) && (l == 0) && (b == 0) && (r == 0);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_rect_real64::operator== (const dng_rect_real64 &rect) const
+ {
+
+ return (rect.t == t) &&
+ (rect.l == l) &&
+ (rect.b == b) &&
+ (rect.r == r);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_rect_real64::IsZero () const
+ {
+
+ return (t == 0.0) && (l == 0.0) && (b == 0.0) && (r == 0.0);
+
+ }
+
+/*****************************************************************************/
+
+dng_rect operator& (const dng_rect &a,
+ const dng_rect &b)
+ {
+
+ dng_rect c;
+
+ c.t = Max_int32 (a.t, b.t);
+ c.l = Max_int32 (a.l, b.l);
+
+ c.b = Min_int32 (a.b, b.b);
+ c.r = Min_int32 (a.r, b.r);
+
+ if (c.IsEmpty ())
+ {
+
+ c = dng_rect ();
+
+ }
+
+ return c;
+
+ }
+
+/*****************************************************************************/
+
+dng_rect operator| (const dng_rect &a,
+ const dng_rect &b)
+ {
+
+ if (a.IsEmpty ())
+ {
+ return b;
+ }
+
+ if (b.IsEmpty ())
+ {
+ return a;
+ }
+
+ dng_rect c;
+
+ c.t = Min_int32 (a.t, b.t);
+ c.l = Min_int32 (a.l, b.l);
+
+ c.b = Max_int32 (a.b, b.b);
+ c.r = Max_int32 (a.r, b.r);
+
+ return c;
+
+ }
+
+/*****************************************************************************/
+
+dng_rect_real64 operator& (const dng_rect_real64 &a,
+ const dng_rect_real64 &b)
+ {
+
+ dng_rect_real64 c;
+
+ c.t = Max_real64 (a.t, b.t);
+ c.l = Max_real64 (a.l, b.l);
+
+ c.b = Min_real64 (a.b, b.b);
+ c.r = Min_real64 (a.r, b.r);
+
+ if (c.IsEmpty ())
+ {
+
+ c = dng_rect_real64 ();
+
+ }
+
+ return c;
+
+ }
+
+/*****************************************************************************/
+
+dng_rect_real64 operator| (const dng_rect_real64 &a,
+ const dng_rect_real64 &b)
+ {
+
+ if (a.IsEmpty ())
+ {
+ return b;
+ }
+
+ if (b.IsEmpty ())
+ {
+ return a;
+ }
+
+ dng_rect_real64 c;
+
+ c.t = Min_real64 (a.t, b.t);
+ c.l = Min_real64 (a.l, b.l);
+
+ c.b = Max_real64 (a.b, b.b);
+ c.r = Max_real64 (a.r, b.r);
+
+ return c;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_ref_counted_block.cpp b/source/dng_ref_counted_block.cpp
index d3e027b..0bd03ca 100644
--- a/source/dng_ref_counted_block.cpp
+++ b/source/dng_ref_counted_block.cpp
@@ -1,187 +1,187 @@
-/*****************************************************************************/
-// Copyright 2006 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_ref_counted_block.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include <new>
-
-#include "dng_ref_counted_block.h"
-
-#include "dng_exceptions.h"
-
-/*****************************************************************************/
-
-dng_ref_counted_block::dng_ref_counted_block ()
-
- : fBuffer (NULL)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_ref_counted_block::dng_ref_counted_block (uint32 size)
-
- : fBuffer (NULL)
-
- {
-
- Allocate (size);
-
- }
-
-/*****************************************************************************/
-
-dng_ref_counted_block::~dng_ref_counted_block ()
- {
-
- Clear ();
-
- }
-
-/*****************************************************************************/
-
-void dng_ref_counted_block::Allocate (uint32 size)
- {
-
- Clear ();
-
- if (size)
- {
-
- fBuffer = malloc (size + sizeof (header));
-
- if (!fBuffer)
- {
-
- ThrowMemoryFull ();
-
- }
-
- new (fBuffer) header (size);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_ref_counted_block::Clear ()
- {
-
- if (fBuffer)
- {
-
-
- bool doFree = false;
-
- header *blockHeader = (struct header *)fBuffer;
-
- {
-
- dng_lock_mutex lock (&blockHeader->fMutex);
-
- if (--blockHeader->fRefCount == 0)
- doFree = true;
- }
-
- if (doFree)
- {
-
- blockHeader->~header ();
-
- free (fBuffer);
-
- }
-
- fBuffer = NULL;
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_ref_counted_block::dng_ref_counted_block (const dng_ref_counted_block &data)
- : fBuffer (NULL)
- {
-
- header *blockHeader = (struct header *)data.fBuffer;
-
- dng_lock_mutex lock (&blockHeader->fMutex);
-
- blockHeader->fRefCount++;
-
- fBuffer = blockHeader;
-
- }
-
-/*****************************************************************************/
-
-dng_ref_counted_block & dng_ref_counted_block::operator= (const dng_ref_counted_block &data)
- {
-
- if (this != &data)
- {
- Clear ();
-
- header *blockHeader = (struct header *)data.fBuffer;
-
- dng_lock_mutex lock (&blockHeader->fMutex);
-
- blockHeader->fRefCount++;
-
- fBuffer = blockHeader;
-
- }
-
- return *this;
-
- }
-
-/*****************************************************************************/
-
-void dng_ref_counted_block::EnsureWriteable ()
- {
-
- if (fBuffer)
- {
-
- header *possiblySharedHeader = (header *)fBuffer;
-
- {
-
- dng_lock_mutex lock (&possiblySharedHeader->fMutex);
-
- if (possiblySharedHeader->fRefCount > 1)
- {
-
- fBuffer = NULL;
-
- Allocate ((uint32)possiblySharedHeader->fSize);
-
- memcpy (Buffer (),
- ((char *)possiblySharedHeader) + sizeof (struct header), // could just do + 1 w/o cast, but this makes the type mixing more explicit
- possiblySharedHeader->fSize);
-
- possiblySharedHeader->fRefCount--;
-
- }
-
- }
-
- }
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_ref_counted_block.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include <new>
+
+#include "dng_ref_counted_block.h"
+
+#include "dng_exceptions.h"
+
+/*****************************************************************************/
+
+dng_ref_counted_block::dng_ref_counted_block ()
+
+ : fBuffer (NULL)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_ref_counted_block::dng_ref_counted_block (uint32 size)
+
+ : fBuffer (NULL)
+
+ {
+
+ Allocate (size);
+
+ }
+
+/*****************************************************************************/
+
+dng_ref_counted_block::~dng_ref_counted_block ()
+ {
+
+ Clear ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_ref_counted_block::Allocate (uint32 size)
+ {
+
+ Clear ();
+
+ if (size)
+ {
+
+ fBuffer = malloc (size + sizeof (header));
+
+ if (!fBuffer)
+ {
+
+ ThrowMemoryFull ();
+
+ }
+
+ new (fBuffer) header (size);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_ref_counted_block::Clear ()
+ {
+
+ if (fBuffer)
+ {
+
+
+ bool doFree = false;
+
+ header *blockHeader = (struct header *)fBuffer;
+
+ {
+
+ dng_lock_mutex lock (&blockHeader->fMutex);
+
+ if (--blockHeader->fRefCount == 0)
+ doFree = true;
+ }
+
+ if (doFree)
+ {
+
+ blockHeader->~header ();
+
+ free (fBuffer);
+
+ }
+
+ fBuffer = NULL;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_ref_counted_block::dng_ref_counted_block (const dng_ref_counted_block &data)
+ : fBuffer (NULL)
+ {
+
+ header *blockHeader = (struct header *)data.fBuffer;
+
+ dng_lock_mutex lock (&blockHeader->fMutex);
+
+ blockHeader->fRefCount++;
+
+ fBuffer = blockHeader;
+
+ }
+
+/*****************************************************************************/
+
+dng_ref_counted_block & dng_ref_counted_block::operator= (const dng_ref_counted_block &data)
+ {
+
+ if (this != &data)
+ {
+ Clear ();
+
+ header *blockHeader = (struct header *)data.fBuffer;
+
+ dng_lock_mutex lock (&blockHeader->fMutex);
+
+ blockHeader->fRefCount++;
+
+ fBuffer = blockHeader;
+
+ }
+
+ return *this;
+
+ }
+
+/*****************************************************************************/
+
+void dng_ref_counted_block::EnsureWriteable ()
+ {
+
+ if (fBuffer)
+ {
+
+ header *possiblySharedHeader = (header *)fBuffer;
+
+ {
+
+ dng_lock_mutex lock (&possiblySharedHeader->fMutex);
+
+ if (possiblySharedHeader->fRefCount > 1)
+ {
+
+ fBuffer = NULL;
+
+ Allocate ((uint32)possiblySharedHeader->fSize);
+
+ memcpy (Buffer (),
+ ((char *)possiblySharedHeader) + sizeof (struct header), // could just do + 1 w/o cast, but this makes the type mixing more explicit
+ possiblySharedHeader->fSize);
+
+ possiblySharedHeader->fRefCount--;
+
+ }
+
+ }
+
+ }
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_ref_counted_block.h b/source/dng_ref_counted_block.h
index cdda745..819bf81 100644
--- a/source/dng_ref_counted_block.h
+++ b/source/dng_ref_counted_block.h
@@ -1,291 +1,291 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_ref_counted_block.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** Support for a refcounted block, with optional copy-on-write
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_ref_counted_block__
-#define __dng_ref_counted_block__
-
-/*****************************************************************************/
-
-#include "dng_types.h"
-#include "dng_mutex.h"
-
-/*****************************************************************************/
-
-/// \brief Class to provide resource acquisition is instantiation discipline
-/// for small memory allocations.
-///
-/// This class does not use dng_memory_allocator for memory allocation.
-
-class dng_ref_counted_block
- {
-
- private:
-
- struct header
- {
-
- dng_mutex fMutex;
-
- uint32 fRefCount;
-
- uint32 fSize;
-
- header (uint32 size)
- : fMutex ("dng_ref_counted_block")
- , fRefCount (1)
- , fSize (size)
- {
- }
-
- ~header ()
- {
- }
-
- };
-
- void *fBuffer;
-
- public:
-
-
- /// Construct an empty memory buffer using malloc.
- /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
-
- dng_ref_counted_block ();
-
- /// Construct memory buffer of size bytes using malloc.
- /// \param size Number of bytes of memory needed.
- /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
-
- dng_ref_counted_block (uint32 size);
-
- /// Release memory buffer using free.
-
- ~dng_ref_counted_block ();
-
- /// Copy constructore, which takes a reference to data and does not copy the block.
-
- dng_ref_counted_block (const dng_ref_counted_block &data);
-
- /// Assignment operatore takes a reference to right hand side and does not copy the data.
-
- dng_ref_counted_block & operator= (const dng_ref_counted_block &data);
-
- /// Clear existing memory buffer and allocate new memory of size bytes.
- /// \param size Number of bytes of memory needed.
- /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
-
- void Allocate (uint32 size);
-
- /// Release any allocated memory using free. Object is still valid and
- /// Allocate can be called again.
-
- void Clear ();
-
- /// If there is only one reference, do nothing, otherwise copy the data into a new block and return an object with that block as the data.
-
- void EnsureWriteable ();
-
- /// Return pointer to allocated memory as a void *..
- /// \retval void * valid for as many bytes as were allocated.
-
- uint32 LogicalSize ()
- {
- return ((header *)fBuffer)->fSize;
- }
-
- void * Buffer ()
- {
- return (void *)((char *)fBuffer + sizeof (header));
- }
-
- /// Return pointer to allocated memory as a const void *.
- /// \retval const void * valid for as many bytes as were allocated.
-
- const void * Buffer () const
- {
- return (const void *)((char *)fBuffer + sizeof (header));
- }
-
- /// Return pointer to allocated memory as a char *.
- /// \retval char * valid for as many bytes as were allocated.
-
- char * Buffer_char ()
- {
- return (char *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const char *.
- /// \retval const char * valid for as many bytes as were allocated.
-
- const char * Buffer_char () const
- {
- return (const char *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a uint8 *.
- /// \retval uint8 * valid for as many bytes as were allocated.
-
- uint8 * Buffer_uint8 ()
- {
- return (uint8 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const uint8 *.
- /// \retval const uint8 * valid for as many bytes as were allocated.
-
- const uint8 * Buffer_uint8 () const
- {
- return (const uint8 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a uint16 *.
- /// \retval uint16 * valid for as many bytes as were allocated.
-
- uint16 * Buffer_uint16 ()
- {
- return (uint16 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const uint16 *.
- /// \retval const uint16 * valid for as many bytes as were allocated.
-
- const uint16 * Buffer_uint16 () const
- {
- return (const uint16 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a int16 *.
- /// \retval int16 * valid for as many bytes as were allocated.
-
- int16 * Buffer_int16 ()
- {
- return (int16 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const int16 *.
- /// \retval const int16 * valid for as many bytes as were allocated.
-
- const int16 * Buffer_int16 () const
- {
- return (const int16 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a uint32 *.
- /// \retval uint32 * valid for as many bytes as were allocated.
-
- uint32 * Buffer_uint32 ()
- {
- return (uint32 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a uint32 *.
- /// \retval uint32 * valid for as many bytes as were allocated.
-
- const uint32 * Buffer_uint32 () const
- {
- return (const uint32 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const int32 *.
- /// \retval const int32 * valid for as many bytes as were allocated.
-
- int32 * Buffer_int32 ()
- {
- return (int32 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const int32 *.
- /// \retval const int32 * valid for as many bytes as were allocated.
-
- const int32 * Buffer_int32 () const
- {
- return (const int32 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a uint64 *.
- /// \retval uint64 * valid for as many bytes as were allocated.
-
- uint64 * Buffer_uint64 ()
- {
- return (uint64 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a uint64 *.
- /// \retval uint64 * valid for as many bytes as were allocated.
-
- const uint64 * Buffer_uint64 () const
- {
- return (const uint64 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const int64 *.
- /// \retval const int64 * valid for as many bytes as were allocated.
-
- int64 * Buffer_int64 ()
- {
- return (int64 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const int64 *.
- /// \retval const int64 * valid for as many bytes as were allocated.
-
- const int64 * Buffer_int64 () const
- {
- return (const int64 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a real32 *.
- /// \retval real32 * valid for as many bytes as were allocated.
-
- real32 * Buffer_real32 ()
- {
- return (real32 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const real32 *.
- /// \retval const real32 * valid for as many bytes as were allocated.
-
- const real32 * Buffer_real32 () const
- {
- return (const real32 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a real64 *.
- /// \retval real64 * valid for as many bytes as were allocated.
-
- real64 * Buffer_real64 ()
- {
- return (real64 *) Buffer ();
- }
-
- /// Return pointer to allocated memory as a const real64 *.
- /// \retval const real64 * valid for as many bytes as were allocated.
-
- const real64 * Buffer_real64 () const
- {
- return (const real64 *) Buffer ();
- }
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_ref_counted_block.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** Support for a refcounted block, with optional copy-on-write
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_ref_counted_block__
+#define __dng_ref_counted_block__
+
+/*****************************************************************************/
+
+#include "dng_types.h"
+#include "dng_mutex.h"
+
+/*****************************************************************************/
+
+/// \brief Class to provide resource acquisition is instantiation discipline
+/// for small memory allocations.
+///
+/// This class does not use dng_memory_allocator for memory allocation.
+
+class dng_ref_counted_block
+ {
+
+ private:
+
+ struct header
+ {
+
+ dng_mutex fMutex;
+
+ uint32 fRefCount;
+
+ uint32 fSize;
+
+ header (uint32 size)
+ : fMutex ("dng_ref_counted_block")
+ , fRefCount (1)
+ , fSize (size)
+ {
+ }
+
+ ~header ()
+ {
+ }
+
+ };
+
+ void *fBuffer;
+
+ public:
+
+
+ /// Construct an empty memory buffer using malloc.
+ /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
+
+ dng_ref_counted_block ();
+
+ /// Construct memory buffer of size bytes using malloc.
+ /// \param size Number of bytes of memory needed.
+ /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
+
+ dng_ref_counted_block (uint32 size);
+
+ /// Release memory buffer using free.
+
+ ~dng_ref_counted_block ();
+
+ /// Copy constructore, which takes a reference to data and does not copy the block.
+
+ dng_ref_counted_block (const dng_ref_counted_block &data);
+
+ /// Assignment operatore takes a reference to right hand side and does not copy the data.
+
+ dng_ref_counted_block & operator= (const dng_ref_counted_block &data);
+
+ /// Clear existing memory buffer and allocate new memory of size bytes.
+ /// \param size Number of bytes of memory needed.
+ /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
+
+ void Allocate (uint32 size);
+
+ /// Release any allocated memory using free. Object is still valid and
+ /// Allocate can be called again.
+
+ void Clear ();
+
+ /// If there is only one reference, do nothing, otherwise copy the data into a new block and return an object with that block as the data.
+
+ void EnsureWriteable ();
+
+ /// Return pointer to allocated memory as a void *..
+ /// \retval void * valid for as many bytes as were allocated.
+
+ uint32 LogicalSize ()
+ {
+ return ((header *)fBuffer)->fSize;
+ }
+
+ void * Buffer ()
+ {
+ return (void *)((char *)fBuffer + sizeof (header));
+ }
+
+ /// Return pointer to allocated memory as a const void *.
+ /// \retval const void * valid for as many bytes as were allocated.
+
+ const void * Buffer () const
+ {
+ return (const void *)((char *)fBuffer + sizeof (header));
+ }
+
+ /// Return pointer to allocated memory as a char *.
+ /// \retval char * valid for as many bytes as were allocated.
+
+ char * Buffer_char ()
+ {
+ return (char *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const char *.
+ /// \retval const char * valid for as many bytes as were allocated.
+
+ const char * Buffer_char () const
+ {
+ return (const char *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a uint8 *.
+ /// \retval uint8 * valid for as many bytes as were allocated.
+
+ uint8 * Buffer_uint8 ()
+ {
+ return (uint8 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const uint8 *.
+ /// \retval const uint8 * valid for as many bytes as were allocated.
+
+ const uint8 * Buffer_uint8 () const
+ {
+ return (const uint8 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a uint16 *.
+ /// \retval uint16 * valid for as many bytes as were allocated.
+
+ uint16 * Buffer_uint16 ()
+ {
+ return (uint16 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const uint16 *.
+ /// \retval const uint16 * valid for as many bytes as were allocated.
+
+ const uint16 * Buffer_uint16 () const
+ {
+ return (const uint16 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a int16 *.
+ /// \retval int16 * valid for as many bytes as were allocated.
+
+ int16 * Buffer_int16 ()
+ {
+ return (int16 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const int16 *.
+ /// \retval const int16 * valid for as many bytes as were allocated.
+
+ const int16 * Buffer_int16 () const
+ {
+ return (const int16 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a uint32 *.
+ /// \retval uint32 * valid for as many bytes as were allocated.
+
+ uint32 * Buffer_uint32 ()
+ {
+ return (uint32 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a uint32 *.
+ /// \retval uint32 * valid for as many bytes as were allocated.
+
+ const uint32 * Buffer_uint32 () const
+ {
+ return (const uint32 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const int32 *.
+ /// \retval const int32 * valid for as many bytes as were allocated.
+
+ int32 * Buffer_int32 ()
+ {
+ return (int32 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const int32 *.
+ /// \retval const int32 * valid for as many bytes as were allocated.
+
+ const int32 * Buffer_int32 () const
+ {
+ return (const int32 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a uint64 *.
+ /// \retval uint64 * valid for as many bytes as were allocated.
+
+ uint64 * Buffer_uint64 ()
+ {
+ return (uint64 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a uint64 *.
+ /// \retval uint64 * valid for as many bytes as were allocated.
+
+ const uint64 * Buffer_uint64 () const
+ {
+ return (const uint64 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const int64 *.
+ /// \retval const int64 * valid for as many bytes as were allocated.
+
+ int64 * Buffer_int64 ()
+ {
+ return (int64 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const int64 *.
+ /// \retval const int64 * valid for as many bytes as were allocated.
+
+ const int64 * Buffer_int64 () const
+ {
+ return (const int64 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a real32 *.
+ /// \retval real32 * valid for as many bytes as were allocated.
+
+ real32 * Buffer_real32 ()
+ {
+ return (real32 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const real32 *.
+ /// \retval const real32 * valid for as many bytes as were allocated.
+
+ const real32 * Buffer_real32 () const
+ {
+ return (const real32 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a real64 *.
+ /// \retval real64 * valid for as many bytes as were allocated.
+
+ real64 * Buffer_real64 ()
+ {
+ return (real64 *) Buffer ();
+ }
+
+ /// Return pointer to allocated memory as a const real64 *.
+ /// \retval const real64 * valid for as many bytes as were allocated.
+
+ const real64 * Buffer_real64 () const
+ {
+ return (const real64 *) Buffer ();
+ }
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_reference.cpp b/source/dng_reference.cpp
index 156726d..2d47021 100644
--- a/source/dng_reference.cpp
+++ b/source/dng_reference.cpp
@@ -1,2781 +1,2781 @@
-/*****************************************************************************/
-// Copyright 2006-2009 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_reference.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_reference.h"
-
-#include "dng_1d_table.h"
-#include "dng_hue_sat_map.h"
-#include "dng_matrix.h"
-#include "dng_resample.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-// This module contains routines that should be as fast as possible, even
-// at the expense of slight code size increases.
-
-#include "dng_fast_module.h"
-
-/*****************************************************************************/
-
-void RefZeroBytes (void *dPtr,
- uint32 count)
- {
-
- memset (dPtr, 0, count);
-
- }
-
-/*****************************************************************************/
-
-void RefCopyBytes (const void *sPtr,
- void *dPtr,
- uint32 count)
- {
-
- memcpy (dPtr, sPtr, count);
-
- }
-
-/*****************************************************************************/
-
-void RefSwapBytes16 (uint16 *dPtr,
- uint32 count)
- {
-
- for (uint32 j = 0; j < count; j++)
- {
-
- dPtr [j] = SwapBytes16 (dPtr [j]);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefSwapBytes32 (uint32 *dPtr,
- uint32 count)
- {
-
- for (uint32 j = 0; j < count; j++)
- {
-
- dPtr [j] = SwapBytes32 (dPtr [j]);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefSetArea8 (uint8 *dPtr,
- uint8 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- uint8 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- uint8 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = value;
-
- dPtr2 += planeStep;
-
- }
-
- dPtr1 += colStep;
-
- }
-
- dPtr += rowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefSetArea16 (uint16 *dPtr,
- uint16 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- uint16 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- uint16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = value;
-
- dPtr2 += planeStep;
-
- }
-
- dPtr1 += colStep;
-
- }
-
- dPtr += rowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefSetArea32 (uint32 *dPtr,
- uint32 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- uint32 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- uint32 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = value;
-
- dPtr2 += planeStep;
-
- }
-
- dPtr1 += colStep;
-
- }
-
- dPtr += rowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea8 (const uint8 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint8 *sPtr1 = sPtr;
- uint8 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint8 *sPtr2 = sPtr1;
- uint8 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint16 *sPtr1 = sPtr;
- uint16 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint16 *sPtr2 = sPtr1;
- uint16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea32 (const uint32 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint32 *sPtr1 = sPtr;
- uint32 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint32 *sPtr2 = sPtr1;
- uint32 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea8_16 (const uint8 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint8 *sPtr1 = sPtr;
- uint16 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint8 *sPtr2 = sPtr1;
- uint16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea8_S16 (const uint8 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint8 *sPtr1 = sPtr;
- int16 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint8 *sPtr2 = sPtr1;
- int16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- int16 x = *sPtr;
-
- *dPtr2 = x ^ 0x8000;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea8_32 (const uint8 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint8 *sPtr1 = sPtr;
- uint32 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint8 *sPtr2 = sPtr1;
- uint32 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea16_S16 (const uint16 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint16 *sPtr1 = sPtr;
- int16 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint16 *sPtr2 = sPtr1;
- int16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2 ^ 0x8000;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea16_32 (const uint16 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint16 *sPtr1 = sPtr;
- uint32 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint16 *sPtr2 = sPtr1;
- uint32 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea8_R32 (const uint8 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- real32 scale = 1.0f / (real32) pixelRange;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint8 *sPtr1 = sPtr;
- real32 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint8 *sPtr2 = sPtr1;
- real32 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = scale * (real32) *sPtr2;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyArea16_R32 (const uint16 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- real32 scale = 1.0f / (real32) pixelRange;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint16 *sPtr1 = sPtr;
- real32 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint16 *sPtr2 = sPtr1;
- real32 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = scale * (real32) *sPtr2;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyAreaS16_R32 (const int16 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- real32 scale = 1.0f / (real32) pixelRange;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const int16 *sPtr1 = sPtr;
- real32 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const int16 *sPtr2 = sPtr1;
- real32 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- int32 x = (*sPtr ^ 0x8000);
-
- *dPtr2 = scale * (real32) x;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyAreaR32_8 (const real32 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- real32 scale = (real32) pixelRange;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const real32 *sPtr1 = sPtr;
- uint8 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const real32 *sPtr2 = sPtr1;
- uint8 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = (uint8) (Pin_Overrange (*sPtr2) * scale + 0.5f);
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyAreaR32_16 (const real32 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- real32 scale = (real32) pixelRange;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const real32 *sPtr1 = sPtr;
- uint16 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const real32 *sPtr2 = sPtr1;
- uint16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = (uint16) (Pin_Overrange (*sPtr2) * scale + 0.5f);
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefCopyAreaR32_S16 (const real32 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange)
- {
-
- real32 scale = (real32) pixelRange;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const real32 *sPtr1 = sPtr;
- int16 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const real32 *sPtr2 = sPtr1;
- int16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- int32 x = (int32) (Pin_Overrange (*sPtr2) * scale + 0.5f);
-
- *dPtr2 = (int16) (x ^ 0x8000);
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefRepeatArea8 (const uint8 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH)
- {
-
- const uint8 *sPtr0 = sPtr + phaseV * rowStep +
- phaseH * colStep;
-
- int32 backStepV = (repeatV - 1) * rowStep;
- int32 backStepH = (repeatH - 1) * colStep;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint8 *sPtr1 = sPtr0;
- uint8 *dPtr1 = dPtr;
-
- uint32 colPhase = phaseH;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint8 *sPtr2 = sPtr1;
- uint8 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2;
-
- sPtr2 += planeStep;
- dPtr2 += planeStep;
-
- }
-
- if (++colPhase == repeatH)
- {
- colPhase = 0;
- sPtr1 -= backStepH;
- }
- else
- {
- sPtr1 += colStep;
- }
-
- dPtr1 += colStep;
-
- }
-
- if (++phaseV == repeatV)
- {
- phaseV = 0;
- sPtr0 -= backStepV;
- }
- else
- {
- sPtr0 += rowStep;
- }
-
- dPtr += rowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefRepeatArea16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH)
- {
-
- const uint16 *sPtr0 = sPtr + phaseV * rowStep +
- phaseH * colStep;
-
- int32 backStepV = (repeatV - 1) * rowStep;
- int32 backStepH = (repeatH - 1) * colStep;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint16 *sPtr1 = sPtr0;
- uint16 *dPtr1 = dPtr;
-
- uint32 colPhase = phaseH;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint16 *sPtr2 = sPtr1;
- uint16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2;
-
- sPtr2 += planeStep;
- dPtr2 += planeStep;
-
- }
-
- if (++colPhase == repeatH)
- {
- colPhase = 0;
- sPtr1 -= backStepH;
- }
- else
- {
- sPtr1 += colStep;
- }
-
- dPtr1 += colStep;
-
- }
-
- if (++phaseV == repeatV)
- {
- phaseV = 0;
- sPtr0 -= backStepV;
- }
- else
- {
- sPtr0 += rowStep;
- }
-
- dPtr += rowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefRepeatArea32 (const uint32 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH)
- {
-
- const uint32 *sPtr0 = sPtr + phaseV * rowStep +
- phaseH * colStep;
-
- int32 backStepV = (repeatV - 1) * rowStep;
- int32 backStepH = (repeatH - 1) * colStep;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint32 *sPtr1 = sPtr0;
- uint32 *dPtr1 = dPtr;
-
- uint32 colPhase = phaseH;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint32 *sPtr2 = sPtr1;
- uint32 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 = *sPtr2;
-
- sPtr2 += planeStep;
- dPtr2 += planeStep;
-
- }
-
- if (++colPhase == repeatH)
- {
- colPhase = 0;
- sPtr1 -= backStepH;
- }
- else
- {
- sPtr1 += colStep;
- }
-
- dPtr1 += colStep;
-
- }
-
- if (++phaseV == repeatV)
- {
- phaseV = 0;
- sPtr0 -= backStepV;
- }
- else
- {
- sPtr0 += rowStep;
- }
-
- dPtr += rowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefShiftRight16 (uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 shift)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- uint16 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- uint16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- *dPtr2 >>= shift;
-
- dPtr2 += planeStep;
-
- }
-
- dPtr1 += colStep;
-
- }
-
- dPtr += rowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefBilinearRow16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 cols,
- uint32 patPhase,
- uint32 patCount,
- const uint32 * kernCounts,
- const int32 * const * kernOffsets,
- const uint16 * const * kernWeights,
- uint32 sShift)
- {
-
- for (uint32 j = 0; j < cols; j++)
- {
-
- const uint16 *p = sPtr + (j >> sShift);
-
- uint32 count = kernCounts [patPhase];
-
- const int32 *offsets = kernOffsets [patPhase];
- const uint16 *weights = kernWeights [patPhase];
-
- if (++patPhase == patCount)
- {
- patPhase = 0;
- }
-
- uint32 total = 128;
-
- for (uint32 k = 0; k < count; k++)
- {
-
- int32 offset = offsets [k];
- uint32 weight = weights [k];
-
- uint32 pixel = p [offset];
-
- total += pixel * weight;
-
- }
-
- dPtr [j] = (uint16) (total >> 8);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefBilinearRow32 (const real32 *sPtr,
- real32 *dPtr,
- uint32 cols,
- uint32 patPhase,
- uint32 patCount,
- const uint32 * kernCounts,
- const int32 * const * kernOffsets,
- const real32 * const * kernWeights,
- uint32 sShift)
- {
-
- for (uint32 j = 0; j < cols; j++)
- {
-
- const real32 *p = sPtr + (j >> sShift);
-
- uint32 count = kernCounts [patPhase];
-
- const int32 *offsets = kernOffsets [patPhase];
- const real32 *weights = kernWeights [patPhase];
-
- if (++patPhase == patCount)
- {
- patPhase = 0;
- }
-
- real32 total = 0.0f;
-
- for (uint32 k = 0; k < count; k++)
- {
-
- int32 offset = offsets [k];
- real32 weight = weights [k];
-
- real32 pixel = p [offset];
-
- total += pixel * weight;
-
- }
-
- dPtr [j] = total;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefBaselineABCtoRGB (const real32 *sPtrA,
- const real32 *sPtrB,
- const real32 *sPtrC,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_vector &cameraWhite,
- const dng_matrix &cameraToRGB)
- {
-
- real32 clipA = (real32) cameraWhite [0];
- real32 clipB = (real32) cameraWhite [1];
- real32 clipC = (real32) cameraWhite [2];
-
- real32 m00 = (real32) cameraToRGB [0] [0];
- real32 m01 = (real32) cameraToRGB [0] [1];
- real32 m02 = (real32) cameraToRGB [0] [2];
-
- real32 m10 = (real32) cameraToRGB [1] [0];
- real32 m11 = (real32) cameraToRGB [1] [1];
- real32 m12 = (real32) cameraToRGB [1] [2];
-
- real32 m20 = (real32) cameraToRGB [2] [0];
- real32 m21 = (real32) cameraToRGB [2] [1];
- real32 m22 = (real32) cameraToRGB [2] [2];
-
- for (uint32 col = 0; col < count; col++)
- {
-
- real32 A = sPtrA [col];
- real32 B = sPtrB [col];
- real32 C = sPtrC [col];
-
- A = Min_real32 (A, clipA);
- B = Min_real32 (B, clipB);
- C = Min_real32 (C, clipC);
-
- real32 r = m00 * A + m01 * B + m02 * C;
- real32 g = m10 * A + m11 * B + m12 * C;
- real32 b = m20 * A + m21 * B + m22 * C;
-
- r = Pin_real32 (0.0f, r, 1.0f);
- g = Pin_real32 (0.0f, g, 1.0f);
- b = Pin_real32 (0.0f, b, 1.0f);
-
- dPtrR [col] = r;
- dPtrG [col] = g;
- dPtrB [col] = b;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefBaselineABCDtoRGB (const real32 *sPtrA,
- const real32 *sPtrB,
- const real32 *sPtrC,
- const real32 *sPtrD,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_vector &cameraWhite,
- const dng_matrix &cameraToRGB)
- {
-
- real32 clipA = (real32) cameraWhite [0];
- real32 clipB = (real32) cameraWhite [1];
- real32 clipC = (real32) cameraWhite [2];
- real32 clipD = (real32) cameraWhite [3];
-
- real32 m00 = (real32) cameraToRGB [0] [0];
- real32 m01 = (real32) cameraToRGB [0] [1];
- real32 m02 = (real32) cameraToRGB [0] [2];
- real32 m03 = (real32) cameraToRGB [0] [3];
-
- real32 m10 = (real32) cameraToRGB [1] [0];
- real32 m11 = (real32) cameraToRGB [1] [1];
- real32 m12 = (real32) cameraToRGB [1] [2];
- real32 m13 = (real32) cameraToRGB [1] [3];
-
- real32 m20 = (real32) cameraToRGB [2] [0];
- real32 m21 = (real32) cameraToRGB [2] [1];
- real32 m22 = (real32) cameraToRGB [2] [2];
- real32 m23 = (real32) cameraToRGB [2] [3];
-
- for (uint32 col = 0; col < count; col++)
- {
-
- real32 A = sPtrA [col];
- real32 B = sPtrB [col];
- real32 C = sPtrC [col];
- real32 D = sPtrD [col];
-
- A = Min_real32 (A, clipA);
- B = Min_real32 (B, clipB);
- C = Min_real32 (C, clipC);
- D = Min_real32 (D, clipD);
-
- real32 r = m00 * A + m01 * B + m02 * C + m03 * D;
- real32 g = m10 * A + m11 * B + m12 * C + m13 * D;
- real32 b = m20 * A + m21 * B + m22 * C + m23 * D;
-
- r = Pin_real32 (0.0f, r, 1.0f);
- g = Pin_real32 (0.0f, g, 1.0f);
- b = Pin_real32 (0.0f, b, 1.0f);
-
- dPtrR [col] = r;
- dPtrG [col] = g;
- dPtrB [col] = b;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefBaselineHueSatMap (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_hue_sat_map &lut,
- const dng_1d_table *encodeTable,
- const dng_1d_table *decodeTable)
- {
-
- uint32 hueDivisions;
- uint32 satDivisions;
- uint32 valDivisions;
-
- lut.GetDivisions (hueDivisions,
- satDivisions,
- valDivisions);
-
- real32 hScale = (hueDivisions < 2) ? 0.0f : (hueDivisions * (1.0f / 6.0f));
- real32 sScale = (real32) ((int32) satDivisions - 1);
- real32 vScale = (real32) ((int32) valDivisions - 1);
-
- int32 maxHueIndex0 = (int32) hueDivisions - 1;
- int32 maxSatIndex0 = (int32) satDivisions - 2;
- int32 maxValIndex0 = (int32) valDivisions - 2;
-
- const bool hasEncodeTable = ((encodeTable != NULL) && (encodeTable->Table () != NULL));
- const bool hasDecodeTable = ((decodeTable != NULL) && (decodeTable->Table () != NULL));
-
- const bool hasTable = hasEncodeTable && hasDecodeTable;
-
- const dng_hue_sat_map::HSBModify *tableBase = lut.GetConstDeltas ();
-
- int32 hueStep = satDivisions;
- int32 valStep = hueDivisions * hueStep;
-
- #if 0 // Not required with "2.5D" table optimization.
-
- if (valDivisions < 2)
- {
- valStep = 0;
- maxValIndex0 = 0;
- }
-
- #endif
-
- for (uint32 j = 0; j < count; j++)
- {
-
- real32 r = sPtrR [j];
- real32 g = sPtrG [j];
- real32 b = sPtrB [j];
-
- real32 h, s, v;
-
- DNG_RGBtoHSV (r, g, b, h, s, v);
-
- real32 vEncoded = v;
-
- real32 hueShift;
- real32 satScale;
- real32 valScale;
-
- if (valDivisions < 2) // Optimize most common case of "2.5D" table.
- {
-
- real32 hScaled = h * hScale;
- real32 sScaled = s * sScale;
-
- int32 hIndex0 = (int32) hScaled;
- int32 sIndex0 = (int32) sScaled;
-
- sIndex0 = Min_int32 (sIndex0, maxSatIndex0);
-
- int32 hIndex1 = hIndex0 + 1;
-
- if (hIndex0 >= maxHueIndex0)
- {
- hIndex0 = maxHueIndex0;
- hIndex1 = 0;
- }
-
- real32 hFract1 = hScaled - (real32) hIndex0;
- real32 sFract1 = sScaled - (real32) sIndex0;
-
- real32 hFract0 = 1.0f - hFract1;
- real32 sFract0 = 1.0f - sFract1;
-
- const dng_hue_sat_map::HSBModify *entry00 = tableBase + hIndex0 * hueStep +
- sIndex0;
-
- const dng_hue_sat_map::HSBModify *entry01 = entry00 + (hIndex1 - hIndex0) * hueStep;
-
- real32 hueShift0 = hFract0 * entry00->fHueShift +
- hFract1 * entry01->fHueShift;
-
- real32 satScale0 = hFract0 * entry00->fSatScale +
- hFract1 * entry01->fSatScale;
-
- real32 valScale0 = hFract0 * entry00->fValScale +
- hFract1 * entry01->fValScale;
-
- entry00++;
- entry01++;
-
- real32 hueShift1 = hFract0 * entry00->fHueShift +
- hFract1 * entry01->fHueShift;
-
- real32 satScale1 = hFract0 * entry00->fSatScale +
- hFract1 * entry01->fSatScale;
-
- real32 valScale1 = hFract0 * entry00->fValScale +
- hFract1 * entry01->fValScale;
-
- hueShift = sFract0 * hueShift0 + sFract1 * hueShift1;
- satScale = sFract0 * satScale0 + sFract1 * satScale1;
- valScale = sFract0 * valScale0 + sFract1 * valScale1;
-
- }
-
- else
- {
-
- if (hasTable)
- {
- vEncoded = encodeTable->Interpolate (Pin_real32 (v));
- }
-
- real32 hScaled = h * hScale;
- real32 sScaled = s * sScale;
- real32 vScaled = vEncoded * vScale;
-
- int32 hIndex0 = (int32) hScaled;
- int32 sIndex0 = (int32) sScaled;
- int32 vIndex0 = (int32) vScaled;
-
- sIndex0 = Min_int32 (sIndex0, maxSatIndex0);
- vIndex0 = Min_int32 (vIndex0, maxValIndex0);
-
- int32 hIndex1 = hIndex0 + 1;
-
- if (hIndex0 >= maxHueIndex0)
- {
- hIndex0 = maxHueIndex0;
- hIndex1 = 0;
- }
-
- real32 hFract1 = hScaled - (real32) hIndex0;
- real32 sFract1 = sScaled - (real32) sIndex0;
- real32 vFract1 = vScaled - (real32) vIndex0;
-
- real32 hFract0 = 1.0f - hFract1;
- real32 sFract0 = 1.0f - sFract1;
- real32 vFract0 = 1.0f - vFract1;
-
- const dng_hue_sat_map::HSBModify *entry00 = tableBase + vIndex0 * valStep +
- hIndex0 * hueStep +
- sIndex0;
-
- const dng_hue_sat_map::HSBModify *entry01 = entry00 + (hIndex1 - hIndex0) * hueStep;
-
- const dng_hue_sat_map::HSBModify *entry10 = entry00 + valStep;
- const dng_hue_sat_map::HSBModify *entry11 = entry01 + valStep;
-
- real32 hueShift0 = vFract0 * (hFract0 * entry00->fHueShift +
- hFract1 * entry01->fHueShift) +
- vFract1 * (hFract0 * entry10->fHueShift +
- hFract1 * entry11->fHueShift);
-
- real32 satScale0 = vFract0 * (hFract0 * entry00->fSatScale +
- hFract1 * entry01->fSatScale) +
- vFract1 * (hFract0 * entry10->fSatScale +
- hFract1 * entry11->fSatScale);
-
- real32 valScale0 = vFract0 * (hFract0 * entry00->fValScale +
- hFract1 * entry01->fValScale) +
- vFract1 * (hFract0 * entry10->fValScale +
- hFract1 * entry11->fValScale);
-
- entry00++;
- entry01++;
- entry10++;
- entry11++;
-
- real32 hueShift1 = vFract0 * (hFract0 * entry00->fHueShift +
- hFract1 * entry01->fHueShift) +
- vFract1 * (hFract0 * entry10->fHueShift +
- hFract1 * entry11->fHueShift);
-
- real32 satScale1 = vFract0 * (hFract0 * entry00->fSatScale +
- hFract1 * entry01->fSatScale) +
- vFract1 * (hFract0 * entry10->fSatScale +
- hFract1 * entry11->fSatScale);
-
- real32 valScale1 = vFract0 * (hFract0 * entry00->fValScale +
- hFract1 * entry01->fValScale) +
- vFract1 * (hFract0 * entry10->fValScale +
- hFract1 * entry11->fValScale);
-
- hueShift = sFract0 * hueShift0 + sFract1 * hueShift1;
- satScale = sFract0 * satScale0 + sFract1 * satScale1;
- valScale = sFract0 * valScale0 + sFract1 * valScale1;
-
- }
-
- hueShift *= (6.0f / 360.0f); // Convert to internal hue range.
-
- h += hueShift;
-
- s = Min_real32 (s * satScale, 1.0f);
-
- vEncoded = Pin_real32 (vEncoded * valScale);
-
- v = hasTable ? decodeTable->Interpolate (vEncoded) : vEncoded;
-
- DNG_HSVtoRGB (h, s, v, r, g, b);
-
- dPtrR [j] = r;
- dPtrG [j] = g;
- dPtrB [j] = b;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefBaselineRGBtoGray (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrG,
- uint32 count,
- const dng_matrix &matrix)
- {
-
- real32 m00 = (real32) matrix [0] [0];
- real32 m01 = (real32) matrix [0] [1];
- real32 m02 = (real32) matrix [0] [2];
-
- for (uint32 col = 0; col < count; col++)
- {
-
- real32 R = sPtrR [col];
- real32 G = sPtrG [col];
- real32 B = sPtrB [col];
-
- real32 g = m00 * R + m01 * G + m02 * B;
-
- g = Pin_real32 (0.0f, g, 1.0f);
-
- dPtrG [col] = g;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefBaselineRGBtoRGB (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_matrix &matrix)
- {
-
- real32 m00 = (real32) matrix [0] [0];
- real32 m01 = (real32) matrix [0] [1];
- real32 m02 = (real32) matrix [0] [2];
-
- real32 m10 = (real32) matrix [1] [0];
- real32 m11 = (real32) matrix [1] [1];
- real32 m12 = (real32) matrix [1] [2];
-
- real32 m20 = (real32) matrix [2] [0];
- real32 m21 = (real32) matrix [2] [1];
- real32 m22 = (real32) matrix [2] [2];
-
- for (uint32 col = 0; col < count; col++)
- {
-
- real32 R = sPtrR [col];
- real32 G = sPtrG [col];
- real32 B = sPtrB [col];
-
- real32 r = m00 * R + m01 * G + m02 * B;
- real32 g = m10 * R + m11 * G + m12 * B;
- real32 b = m20 * R + m21 * G + m22 * B;
-
- r = Pin_real32 (0.0f, r, 1.0f);
- g = Pin_real32 (0.0f, g, 1.0f);
- b = Pin_real32 (0.0f, b, 1.0f);
-
- dPtrR [col] = r;
- dPtrG [col] = g;
- dPtrB [col] = b;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefBaseline1DTable (const real32 *sPtr,
- real32 *dPtr,
- uint32 count,
- const dng_1d_table &table)
- {
-
- for (uint32 col = 0; col < count; col++)
- {
-
- real32 x = sPtr [col];
-
- real32 y = table.Interpolate (x);
-
- dPtr [col] = y;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefBaselineRGBTone (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_1d_table &table)
- {
-
- for (uint32 col = 0; col < count; col++)
- {
-
- real32 r = sPtrR [col];
- real32 g = sPtrG [col];
- real32 b = sPtrB [col];
-
- real32 rr;
- real32 gg;
- real32 bb;
-
- #define RGBTone(r, g, b, rr, gg, bb)\
- {\
- \
- DNG_ASSERT (r >= g && g >= b && r > b, "Logic Error RGBTone");\
- \
- rr = table.Interpolate (r);\
- bb = table.Interpolate (b);\
- \
- gg = bb + ((rr - bb) * (g - b) / (r - b));\
- \
- }
-
- if (r >= g)
- {
-
- if (g > b)
- {
-
- // Case 1: r >= g > b
-
- RGBTone (r, g, b, rr, gg, bb);
-
- }
-
- else if (b > r)
- {
-
- // Case 2: b > r >= g
-
- RGBTone (b, r, g, bb, rr, gg);
-
- }
-
- else if (b > g)
- {
-
- // Case 3: r >= b > g
-
- RGBTone (r, b, g, rr, bb, gg);
-
- }
-
- else
- {
-
- // Case 4: r >= g == b
-
- DNG_ASSERT (r >= g && g == b, "Logic Error 2");
-
- rr = table.Interpolate (r);
- gg = table.Interpolate (g);
- bb = gg;
-
- }
-
- }
-
- else
- {
-
- if (r >= b)
- {
-
- // Case 5: g > r >= b
-
- RGBTone (g, r, b, gg, rr, bb);
-
- }
-
- else if (b > g)
- {
-
- // Case 6: b > g > r
-
- RGBTone (b, g, r, bb, gg, rr);
-
- }
-
- else
- {
-
- // Case 7: g >= b > r
-
- RGBTone (g, b, r, gg, bb, rr);
-
- }
-
- }
-
- #undef RGBTone
-
- dPtrR [col] = rr;
- dPtrG [col] = gg;
- dPtrB [col] = bb;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefResampleDown16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 sCount,
- int32 sRowStep,
- const int16 *wPtr,
- uint32 wCount,
- uint32 pixelRange)
- {
-
- for (uint32 j = 0; j < sCount; j++)
- {
-
- int32 total = 8192;
-
- const uint16 *s = sPtr + j;
-
- for (uint32 k = 0; k < wCount; k++)
- {
-
- total += wPtr [k] * (int32) s [0];
-
- s += sRowStep;
-
- }
-
- dPtr [j] = (uint16) Pin_int32 (0,
- total >> 14,
- pixelRange);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefResampleDown32 (const real32 *sPtr,
- real32 *dPtr,
- uint32 sCount,
- int32 sRowStep,
- const real32 *wPtr,
- uint32 wCount)
- {
-
- uint32 col;
-
- // Process first row.
-
- real32 w = wPtr [0];
-
- for (col = 0; col < sCount; col++)
- {
-
- dPtr [col] = w * sPtr [col];
-
- }
-
- sPtr += sRowStep;
-
- // Process middle rows.
-
- for (uint32 j = 1; j < wCount - 1; j++)
- {
-
- w = wPtr [j];
-
- for (col = 0; col < sCount; col++)
- {
-
- dPtr [col] += w * sPtr [col];
-
- }
-
- sPtr += sRowStep;
-
- }
-
- // Process last row.
-
- w = wPtr [wCount - 1];
-
- for (col = 0; col < sCount; col++)
- {
-
- dPtr [col] = Pin_real32 (0.0f,
- dPtr [col] + w * sPtr [col],
- 1.0f);
-
- }
-
- }
-
-/******************************************************************************/
-
-void RefResampleAcross16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 dCount,
- const int32 *coord,
- const int16 *wPtr,
- uint32 wCount,
- uint32 wStep,
- uint32 pixelRange)
- {
-
- for (uint32 j = 0; j < dCount; j++)
- {
-
- int32 sCoord = coord [j];
-
- int32 sFract = sCoord & kResampleSubsampleMask;
- int32 sPixel = sCoord >> kResampleSubsampleBits;
-
- const int16 *w = wPtr + sFract * wStep;
- const uint16 *s = sPtr + sPixel;
-
- int32 total = w [0] * (int32) s [0];
-
- for (uint32 k = 1; k < wCount; k++)
- {
-
- total += w [k] * (int32) s [k];
-
- }
-
- dPtr [j] = (uint16) Pin_int32 (0,
- (total + 8192) >> 14,
- pixelRange);
-
- }
-
- }
-
-/******************************************************************************/
-
-void RefResampleAcross32 (const real32 *sPtr,
- real32 *dPtr,
- uint32 dCount,
- const int32 *coord,
- const real32 *wPtr,
- uint32 wCount,
- uint32 wStep)
- {
-
- for (uint32 j = 0; j < dCount; j++)
- {
-
- int32 sCoord = coord [j];
-
- int32 sFract = sCoord & kResampleSubsampleMask;
- int32 sPixel = sCoord >> kResampleSubsampleBits;
-
- const real32 *w = wPtr + sFract * wStep;
- const real32 *s = sPtr + sPixel;
-
- real32 total = w [0] * s [0];
-
- for (uint32 k = 1; k < wCount; k++)
- {
-
- total += w [k] * s [k];
-
- }
-
- dPtr [j] = Pin_real32 (0.0f, total, 1.0f);
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool RefEqualBytes (const void *sPtr,
- const void *dPtr,
- uint32 count)
- {
-
- return memcmp (dPtr, sPtr, count) == 0;
-
- }
-
-/*****************************************************************************/
-
-bool RefEqualArea8 (const uint8 *sPtr,
- const uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint8 *sPtr1 = sPtr;
- const uint8 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint8 *sPtr2 = sPtr1;
- const uint8 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- if (*dPtr2 != *sPtr2)
- return false;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool RefEqualArea16 (const uint16 *sPtr,
- const uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint16 *sPtr1 = sPtr;
- const uint16 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint16 *sPtr2 = sPtr1;
- const uint16 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- if (*dPtr2 != *sPtr2)
- return false;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-bool RefEqualArea32 (const uint32 *sPtr,
- const uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep)
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- const uint32 *sPtr1 = sPtr;
- const uint32 *dPtr1 = dPtr;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- const uint32 *sPtr2 = sPtr1;
- const uint32 *dPtr2 = dPtr1;
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- if (*dPtr2 != *sPtr2)
- return false;
-
- sPtr2 += sPlaneStep;
- dPtr2 += dPlaneStep;
-
- }
-
- sPtr1 += sColStep;
- dPtr1 += dColStep;
-
- }
-
- sPtr += sRowStep;
- dPtr += dRowStep;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-void RefVignetteMask16 (uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- int32 rowStep,
- int64 offsetH,
- int64 offsetV,
- int64 stepH,
- int64 stepV,
- uint32 tBits,
- const uint16 *table)
- {
-
- uint32 tShift = 32 - tBits;
- uint32 tRound = (1 << (tShift - 1));
- uint32 tLimit = 1 << tBits;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- int64 baseDelta = (offsetV + 32768) >> 16;
-
- baseDelta = baseDelta * baseDelta + tRound;
-
- int64 deltaH = offsetH + 32768;
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- int64 temp = deltaH >> 16;
-
- int64 delta = baseDelta + (temp * temp);
-
- uint32 index = Min_uint32 ((uint32) (delta >> tShift), tLimit);
-
- mPtr [col] = table [index];
-
- deltaH += stepH;
-
- }
-
- offsetV += stepV;
-
- mPtr += rowStep;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefVignette16 (int16 *sPtr,
- const uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sPlaneStep,
- int32 mRowStep,
- uint32 mBits)
- {
-
- const uint32 mRound = 1 << (mBits - 1);
-
- switch (planes)
- {
-
- case 1:
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- uint32 s = sPtr [col] + 32768;
-
- uint32 m = mPtr [col];
-
- s = (s * m + mRound) >> mBits;
-
- s = Min_uint32 (s, 65535);
-
- sPtr [col] = (int16) (s - 32768);
-
- }
-
- sPtr += sRowStep;
-
- mPtr += mRowStep;
-
- }
-
- break;
-
- }
-
- case 3:
- {
-
- int16 *rPtr = sPtr;
- int16 *gPtr = rPtr + sPlaneStep;
- int16 *bPtr = gPtr + sPlaneStep;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- uint32 r = rPtr [col] + 32768;
- uint32 g = gPtr [col] + 32768;
- uint32 b = bPtr [col] + 32768;
-
- uint32 m = mPtr [col];
-
- r = (r * m + mRound) >> mBits;
- g = (g * m + mRound) >> mBits;
- b = (b * m + mRound) >> mBits;
-
- r = Min_uint32 (r, 65535);
- g = Min_uint32 (g, 65535);
- b = Min_uint32 (b, 65535);
-
- rPtr [col] = (int16) (r - 32768);
- gPtr [col] = (int16) (g - 32768);
- bPtr [col] = (int16) (b - 32768);
-
- }
-
- rPtr += sRowStep;
- gPtr += sRowStep;
- bPtr += sRowStep;
-
- mPtr += mRowStep;
-
- }
-
- break;
-
- }
-
- case 4:
- {
-
- int16 *aPtr = sPtr;
- int16 *bPtr = aPtr + sPlaneStep;
- int16 *cPtr = bPtr + sPlaneStep;
- int16 *dPtr = cPtr + sPlaneStep;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- uint32 a = aPtr [col] + 32768;
- uint32 b = bPtr [col] + 32768;
- uint32 c = cPtr [col] + 32768;
- uint32 d = dPtr [col] + 32768;
-
- uint32 m = mPtr [col];
-
- a = (a * m + mRound) >> mBits;
- b = (b * m + mRound) >> mBits;
- c = (c * m + mRound) >> mBits;
- d = (d * m + mRound) >> mBits;
-
- a = Min_uint32 (a, 65535);
- b = Min_uint32 (b, 65535);
- c = Min_uint32 (c, 65535);
- d = Min_uint32 (d, 65535);
-
- aPtr [col] = (int16) (a - 32768);
- bPtr [col] = (int16) (b - 32768);
- cPtr [col] = (int16) (c - 32768);
- dPtr [col] = (int16) (d - 32768);
-
- }
-
- aPtr += sRowStep;
- bPtr += sRowStep;
- cPtr += sRowStep;
- dPtr += sRowStep;
-
- mPtr += mRowStep;
-
- }
-
- break;
-
- }
-
- default:
- {
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- int16 *planePtr = sPtr;
-
- const uint16 *maskPtr = mPtr;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- uint32 s = planePtr [col] + 32768;
-
- uint32 m = maskPtr [col];
-
- s = (s * m + mRound) >> mBits;
-
- s = Min_uint32 (s, 65535);
-
- planePtr [col] = (int16) (s - 32768);
-
- }
-
- planePtr += sRowStep;
-
- maskPtr += mRowStep;
-
- }
-
- sPtr += sPlaneStep;
-
- }
-
- break;
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void RefVignette32 (real32 *sPtr,
- const uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sPlaneStep,
- int32 mRowStep,
- uint32 mBits)
- {
-
- const real32 kNorm = 1.0f / (1 << mBits);
-
- switch (planes)
- {
-
- case 1:
- {
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- real32 s = sPtr [col];
-
- uint16 m = mPtr [col];
-
- real32 scale = m * kNorm;
-
- s = Min_real32 (s * scale, 1.0f);
-
- sPtr [col] = s;
-
- }
-
- sPtr += sRowStep;
-
- mPtr += mRowStep;
-
- }
-
- break;
-
- }
-
- case 3:
- {
-
- real32 *rPtr = sPtr;
- real32 *gPtr = rPtr + sPlaneStep;
- real32 *bPtr = gPtr + sPlaneStep;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- real32 r = rPtr [col];
- real32 g = gPtr [col];
- real32 b = bPtr [col];
-
- uint16 m = mPtr [col];
-
- real32 scale = m * kNorm;
-
- r = Min_real32 (r * scale, 1.0f);
- g = Min_real32 (g * scale, 1.0f);
- b = Min_real32 (b * scale, 1.0f);
-
- rPtr [col] = r;
- gPtr [col] = g;
- bPtr [col] = b;
-
- }
-
- rPtr += sRowStep;
- gPtr += sRowStep;
- bPtr += sRowStep;
-
- mPtr += mRowStep;
-
- }
-
- break;
-
- }
-
- case 4:
- {
-
- real32 *aPtr = sPtr;
- real32 *bPtr = aPtr + sPlaneStep;
- real32 *cPtr = bPtr + sPlaneStep;
- real32 *dPtr = cPtr + sPlaneStep;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- real32 a = aPtr [col];
- real32 b = bPtr [col];
- real32 c = cPtr [col];
- real32 d = dPtr [col];
-
- uint16 m = mPtr [col];
-
- real32 scale = m * kNorm;
-
- a = Min_real32 (a * scale, 1.0f);
- b = Min_real32 (b * scale, 1.0f);
- c = Min_real32 (c * scale, 1.0f);
- d = Min_real32 (d * scale, 1.0f);
-
- aPtr [col] = a;
- bPtr [col] = b;
- cPtr [col] = c;
- dPtr [col] = d;
-
- }
-
- aPtr += sRowStep;
- bPtr += sRowStep;
- cPtr += sRowStep;
- dPtr += sRowStep;
-
- mPtr += mRowStep;
-
- }
-
- break;
-
- }
-
- default:
- {
-
- for (uint32 plane = 0; plane < planes; plane++)
- {
-
- real32 *planePtr = sPtr;
-
- const uint16 *maskPtr = mPtr;
-
- for (uint32 row = 0; row < rows; row++)
- {
-
- for (uint32 col = 0; col < cols; col++)
- {
-
- real32 s = planePtr [col];
-
- uint16 m = maskPtr [col];
-
- real32 scale = m * kNorm;
-
- s = Min_real32 (s * scale, 1.0f);
-
- planePtr [col] = s;
-
- }
-
- planePtr += sRowStep;
-
- maskPtr += mRowStep;
-
- }
-
- sPtr += sPlaneStep;
-
- }
-
- break;
-
- }
-
- }
-
- }
-
-/******************************************************************************/
-
-void RefMapArea16 (uint16 *dPtr,
- uint32 count0,
- uint32 count1,
- uint32 count2,
- int32 step0,
- int32 step1,
- int32 step2,
- const uint16 *map)
- {
-
- if (step2 == 1 && count2 >= 32)
- {
-
- for (uint32 index0 = 0; index0 < count0; index0++)
- {
-
- uint16 *d1 = dPtr;
-
- for (uint32 index1 = 0; index1 < count1; index1++)
- {
-
- uint16 *d2 = d1;
-
- uint32 count = count2;
-
- // Get the data 32-bit aligned if it is not.
-
- if (!IsAligned32 (dPtr))
- {
-
- d2 [0] = map [d2 [0]];
-
- count--;
-
- d2++;
-
- }
-
- // Use 32-bit reads and writes for bulk processing.
-
- uint32 *dPtr32 = (uint32 *) d2;
-
- // Process in blocks of 16 pixels.
-
- uint32 blocks = count >> 4;
-
- count -= blocks << 4;
- d2 += blocks << 4;
-
- while (blocks--)
- {
-
- uint32 x0, x1, x2, x3, x4, x5, x6, x7;
- uint32 p0, p1, p2, p3, p4, p5, p6, p7;
-
- // Use 32 bit reads & writes, and pack and unpack the 16-bit values.
- // This results in slightly higher performance.
-
- // Note that this code runs on both little-endian and big-endian systems,
- // since the pixels are either never swapped or double swapped.
-
- x0 = dPtr32 [0];
- x1 = dPtr32 [1];
- x2 = dPtr32 [2];
- x3 = dPtr32 [3];
-
- p0 = map [x0 >> 16 ];
- p1 = map [x0 & 0x0FFFF];
- p2 = map [x1 >> 16 ];
- p3 = map [x1 & 0x0FFFF];
- p4 = map [x2 >> 16 ];
- p5 = map [x2 & 0x0FFFF];
- p6 = map [x3 >> 16 ];
- p7 = map [x3 & 0x0FFFF];
-
- x0 = (p0 << 16) | p1;
- x1 = (p2 << 16) | p3;
- x2 = (p4 << 16) | p5;
- x3 = (p6 << 16) | p7;
-
- x4 = dPtr32 [4];
- x5 = dPtr32 [5];
- x6 = dPtr32 [6];
- x7 = dPtr32 [7];
-
- dPtr32 [0] = x0;
- dPtr32 [1] = x1;
- dPtr32 [2] = x2;
- dPtr32 [3] = x3;
-
- p0 = map [x4 >> 16 ];
- p1 = map [x4 & 0x0FFFF];
- p2 = map [x5 >> 16 ];
- p3 = map [x5 & 0x0FFFF];
- p4 = map [x6 >> 16 ];
- p5 = map [x6 & 0x0FFFF];
- p6 = map [x7 >> 16 ];
- p7 = map [x7 & 0x0FFFF];
-
- x4 = (p0 << 16) | p1;
- x5 = (p2 << 16) | p3;
- x6 = (p4 << 16) | p5;
- x7 = (p6 << 16) | p7;
-
- dPtr32 [4] = x4;
- dPtr32 [5] = x5;
- dPtr32 [6] = x6;
- dPtr32 [7] = x7;
-
- dPtr32 += 8;
-
- }
-
- // Process remaining columns.
-
- for (uint32 j = 0; j < count; j++)
- {
-
- d2 [j] = map [d2 [j]];
-
- }
-
- d1 += step1;
-
- }
-
- dPtr += step0;
-
- }
-
- }
-
- else
- {
-
- for (uint32 index0 = 0; index0 < count0; index0++)
- {
-
- uint16 *d1 = dPtr;
-
- for (uint32 index1 = 0; index1 < count1; index1++)
- {
-
- uint16 *d2 = d1;
-
- for (uint32 index2 = 0; index2 < count2; index2++)
- {
-
- d2 [0] = map [d2 [0]];
-
- d2 += step2;
-
- }
-
- d1 += step1;
-
- }
-
- dPtr += step0;
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2009 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_reference.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_reference.h"
+
+#include "dng_1d_table.h"
+#include "dng_hue_sat_map.h"
+#include "dng_matrix.h"
+#include "dng_resample.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+// This module contains routines that should be as fast as possible, even
+// at the expense of slight code size increases.
+
+#include "dng_fast_module.h"
+
+/*****************************************************************************/
+
+void RefZeroBytes (void *dPtr,
+ uint32 count)
+ {
+
+ memset (dPtr, 0, count);
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyBytes (const void *sPtr,
+ void *dPtr,
+ uint32 count)
+ {
+
+ memcpy (dPtr, sPtr, count);
+
+ }
+
+/*****************************************************************************/
+
+void RefSwapBytes16 (uint16 *dPtr,
+ uint32 count)
+ {
+
+ for (uint32 j = 0; j < count; j++)
+ {
+
+ dPtr [j] = SwapBytes16 (dPtr [j]);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefSwapBytes32 (uint32 *dPtr,
+ uint32 count)
+ {
+
+ for (uint32 j = 0; j < count; j++)
+ {
+
+ dPtr [j] = SwapBytes32 (dPtr [j]);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefSetArea8 (uint8 *dPtr,
+ uint8 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ uint8 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ uint8 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = value;
+
+ dPtr2 += planeStep;
+
+ }
+
+ dPtr1 += colStep;
+
+ }
+
+ dPtr += rowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefSetArea16 (uint16 *dPtr,
+ uint16 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ uint16 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ uint16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = value;
+
+ dPtr2 += planeStep;
+
+ }
+
+ dPtr1 += colStep;
+
+ }
+
+ dPtr += rowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefSetArea32 (uint32 *dPtr,
+ uint32 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ uint32 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ uint32 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = value;
+
+ dPtr2 += planeStep;
+
+ }
+
+ dPtr1 += colStep;
+
+ }
+
+ dPtr += rowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea8 (const uint8 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint8 *sPtr1 = sPtr;
+ uint8 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint8 *sPtr2 = sPtr1;
+ uint8 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint16 *sPtr1 = sPtr;
+ uint16 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint16 *sPtr2 = sPtr1;
+ uint16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea32 (const uint32 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint32 *sPtr1 = sPtr;
+ uint32 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint32 *sPtr2 = sPtr1;
+ uint32 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea8_16 (const uint8 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint8 *sPtr1 = sPtr;
+ uint16 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint8 *sPtr2 = sPtr1;
+ uint16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea8_S16 (const uint8 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint8 *sPtr1 = sPtr;
+ int16 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint8 *sPtr2 = sPtr1;
+ int16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ int16 x = *sPtr;
+
+ *dPtr2 = x ^ 0x8000;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea8_32 (const uint8 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint8 *sPtr1 = sPtr;
+ uint32 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint8 *sPtr2 = sPtr1;
+ uint32 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea16_S16 (const uint16 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint16 *sPtr1 = sPtr;
+ int16 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint16 *sPtr2 = sPtr1;
+ int16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2 ^ 0x8000;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea16_32 (const uint16 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint16 *sPtr1 = sPtr;
+ uint32 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint16 *sPtr2 = sPtr1;
+ uint32 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea8_R32 (const uint8 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ real32 scale = 1.0f / (real32) pixelRange;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint8 *sPtr1 = sPtr;
+ real32 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint8 *sPtr2 = sPtr1;
+ real32 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = scale * (real32) *sPtr2;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyArea16_R32 (const uint16 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ real32 scale = 1.0f / (real32) pixelRange;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint16 *sPtr1 = sPtr;
+ real32 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint16 *sPtr2 = sPtr1;
+ real32 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = scale * (real32) *sPtr2;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyAreaS16_R32 (const int16 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ real32 scale = 1.0f / (real32) pixelRange;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const int16 *sPtr1 = sPtr;
+ real32 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const int16 *sPtr2 = sPtr1;
+ real32 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ int32 x = (*sPtr ^ 0x8000);
+
+ *dPtr2 = scale * (real32) x;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyAreaR32_8 (const real32 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ real32 scale = (real32) pixelRange;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const real32 *sPtr1 = sPtr;
+ uint8 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const real32 *sPtr2 = sPtr1;
+ uint8 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = (uint8) (Pin_Overrange (*sPtr2) * scale + 0.5f);
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyAreaR32_16 (const real32 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ real32 scale = (real32) pixelRange;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const real32 *sPtr1 = sPtr;
+ uint16 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const real32 *sPtr2 = sPtr1;
+ uint16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = (uint16) (Pin_Overrange (*sPtr2) * scale + 0.5f);
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefCopyAreaR32_S16 (const real32 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange)
+ {
+
+ real32 scale = (real32) pixelRange;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const real32 *sPtr1 = sPtr;
+ int16 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const real32 *sPtr2 = sPtr1;
+ int16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ int32 x = (int32) (Pin_Overrange (*sPtr2) * scale + 0.5f);
+
+ *dPtr2 = (int16) (x ^ 0x8000);
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefRepeatArea8 (const uint8 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH)
+ {
+
+ const uint8 *sPtr0 = sPtr + phaseV * rowStep +
+ phaseH * colStep;
+
+ int32 backStepV = (repeatV - 1) * rowStep;
+ int32 backStepH = (repeatH - 1) * colStep;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint8 *sPtr1 = sPtr0;
+ uint8 *dPtr1 = dPtr;
+
+ uint32 colPhase = phaseH;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint8 *sPtr2 = sPtr1;
+ uint8 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2;
+
+ sPtr2 += planeStep;
+ dPtr2 += planeStep;
+
+ }
+
+ if (++colPhase == repeatH)
+ {
+ colPhase = 0;
+ sPtr1 -= backStepH;
+ }
+ else
+ {
+ sPtr1 += colStep;
+ }
+
+ dPtr1 += colStep;
+
+ }
+
+ if (++phaseV == repeatV)
+ {
+ phaseV = 0;
+ sPtr0 -= backStepV;
+ }
+ else
+ {
+ sPtr0 += rowStep;
+ }
+
+ dPtr += rowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefRepeatArea16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH)
+ {
+
+ const uint16 *sPtr0 = sPtr + phaseV * rowStep +
+ phaseH * colStep;
+
+ int32 backStepV = (repeatV - 1) * rowStep;
+ int32 backStepH = (repeatH - 1) * colStep;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint16 *sPtr1 = sPtr0;
+ uint16 *dPtr1 = dPtr;
+
+ uint32 colPhase = phaseH;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint16 *sPtr2 = sPtr1;
+ uint16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2;
+
+ sPtr2 += planeStep;
+ dPtr2 += planeStep;
+
+ }
+
+ if (++colPhase == repeatH)
+ {
+ colPhase = 0;
+ sPtr1 -= backStepH;
+ }
+ else
+ {
+ sPtr1 += colStep;
+ }
+
+ dPtr1 += colStep;
+
+ }
+
+ if (++phaseV == repeatV)
+ {
+ phaseV = 0;
+ sPtr0 -= backStepV;
+ }
+ else
+ {
+ sPtr0 += rowStep;
+ }
+
+ dPtr += rowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefRepeatArea32 (const uint32 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH)
+ {
+
+ const uint32 *sPtr0 = sPtr + phaseV * rowStep +
+ phaseH * colStep;
+
+ int32 backStepV = (repeatV - 1) * rowStep;
+ int32 backStepH = (repeatH - 1) * colStep;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint32 *sPtr1 = sPtr0;
+ uint32 *dPtr1 = dPtr;
+
+ uint32 colPhase = phaseH;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint32 *sPtr2 = sPtr1;
+ uint32 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 = *sPtr2;
+
+ sPtr2 += planeStep;
+ dPtr2 += planeStep;
+
+ }
+
+ if (++colPhase == repeatH)
+ {
+ colPhase = 0;
+ sPtr1 -= backStepH;
+ }
+ else
+ {
+ sPtr1 += colStep;
+ }
+
+ dPtr1 += colStep;
+
+ }
+
+ if (++phaseV == repeatV)
+ {
+ phaseV = 0;
+ sPtr0 -= backStepV;
+ }
+ else
+ {
+ sPtr0 += rowStep;
+ }
+
+ dPtr += rowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefShiftRight16 (uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 shift)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ uint16 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ uint16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ *dPtr2 >>= shift;
+
+ dPtr2 += planeStep;
+
+ }
+
+ dPtr1 += colStep;
+
+ }
+
+ dPtr += rowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefBilinearRow16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 cols,
+ uint32 patPhase,
+ uint32 patCount,
+ const uint32 * kernCounts,
+ const int32 * const * kernOffsets,
+ const uint16 * const * kernWeights,
+ uint32 sShift)
+ {
+
+ for (uint32 j = 0; j < cols; j++)
+ {
+
+ const uint16 *p = sPtr + (j >> sShift);
+
+ uint32 count = kernCounts [patPhase];
+
+ const int32 *offsets = kernOffsets [patPhase];
+ const uint16 *weights = kernWeights [patPhase];
+
+ if (++patPhase == patCount)
+ {
+ patPhase = 0;
+ }
+
+ uint32 total = 128;
+
+ for (uint32 k = 0; k < count; k++)
+ {
+
+ int32 offset = offsets [k];
+ uint32 weight = weights [k];
+
+ uint32 pixel = p [offset];
+
+ total += pixel * weight;
+
+ }
+
+ dPtr [j] = (uint16) (total >> 8);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefBilinearRow32 (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 cols,
+ uint32 patPhase,
+ uint32 patCount,
+ const uint32 * kernCounts,
+ const int32 * const * kernOffsets,
+ const real32 * const * kernWeights,
+ uint32 sShift)
+ {
+
+ for (uint32 j = 0; j < cols; j++)
+ {
+
+ const real32 *p = sPtr + (j >> sShift);
+
+ uint32 count = kernCounts [patPhase];
+
+ const int32 *offsets = kernOffsets [patPhase];
+ const real32 *weights = kernWeights [patPhase];
+
+ if (++patPhase == patCount)
+ {
+ patPhase = 0;
+ }
+
+ real32 total = 0.0f;
+
+ for (uint32 k = 0; k < count; k++)
+ {
+
+ int32 offset = offsets [k];
+ real32 weight = weights [k];
+
+ real32 pixel = p [offset];
+
+ total += pixel * weight;
+
+ }
+
+ dPtr [j] = total;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefBaselineABCtoRGB (const real32 *sPtrA,
+ const real32 *sPtrB,
+ const real32 *sPtrC,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_vector &cameraWhite,
+ const dng_matrix &cameraToRGB)
+ {
+
+ real32 clipA = (real32) cameraWhite [0];
+ real32 clipB = (real32) cameraWhite [1];
+ real32 clipC = (real32) cameraWhite [2];
+
+ real32 m00 = (real32) cameraToRGB [0] [0];
+ real32 m01 = (real32) cameraToRGB [0] [1];
+ real32 m02 = (real32) cameraToRGB [0] [2];
+
+ real32 m10 = (real32) cameraToRGB [1] [0];
+ real32 m11 = (real32) cameraToRGB [1] [1];
+ real32 m12 = (real32) cameraToRGB [1] [2];
+
+ real32 m20 = (real32) cameraToRGB [2] [0];
+ real32 m21 = (real32) cameraToRGB [2] [1];
+ real32 m22 = (real32) cameraToRGB [2] [2];
+
+ for (uint32 col = 0; col < count; col++)
+ {
+
+ real32 A = sPtrA [col];
+ real32 B = sPtrB [col];
+ real32 C = sPtrC [col];
+
+ A = Min_real32 (A, clipA);
+ B = Min_real32 (B, clipB);
+ C = Min_real32 (C, clipC);
+
+ real32 r = m00 * A + m01 * B + m02 * C;
+ real32 g = m10 * A + m11 * B + m12 * C;
+ real32 b = m20 * A + m21 * B + m22 * C;
+
+ r = Pin_real32 (0.0f, r, 1.0f);
+ g = Pin_real32 (0.0f, g, 1.0f);
+ b = Pin_real32 (0.0f, b, 1.0f);
+
+ dPtrR [col] = r;
+ dPtrG [col] = g;
+ dPtrB [col] = b;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefBaselineABCDtoRGB (const real32 *sPtrA,
+ const real32 *sPtrB,
+ const real32 *sPtrC,
+ const real32 *sPtrD,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_vector &cameraWhite,
+ const dng_matrix &cameraToRGB)
+ {
+
+ real32 clipA = (real32) cameraWhite [0];
+ real32 clipB = (real32) cameraWhite [1];
+ real32 clipC = (real32) cameraWhite [2];
+ real32 clipD = (real32) cameraWhite [3];
+
+ real32 m00 = (real32) cameraToRGB [0] [0];
+ real32 m01 = (real32) cameraToRGB [0] [1];
+ real32 m02 = (real32) cameraToRGB [0] [2];
+ real32 m03 = (real32) cameraToRGB [0] [3];
+
+ real32 m10 = (real32) cameraToRGB [1] [0];
+ real32 m11 = (real32) cameraToRGB [1] [1];
+ real32 m12 = (real32) cameraToRGB [1] [2];
+ real32 m13 = (real32) cameraToRGB [1] [3];
+
+ real32 m20 = (real32) cameraToRGB [2] [0];
+ real32 m21 = (real32) cameraToRGB [2] [1];
+ real32 m22 = (real32) cameraToRGB [2] [2];
+ real32 m23 = (real32) cameraToRGB [2] [3];
+
+ for (uint32 col = 0; col < count; col++)
+ {
+
+ real32 A = sPtrA [col];
+ real32 B = sPtrB [col];
+ real32 C = sPtrC [col];
+ real32 D = sPtrD [col];
+
+ A = Min_real32 (A, clipA);
+ B = Min_real32 (B, clipB);
+ C = Min_real32 (C, clipC);
+ D = Min_real32 (D, clipD);
+
+ real32 r = m00 * A + m01 * B + m02 * C + m03 * D;
+ real32 g = m10 * A + m11 * B + m12 * C + m13 * D;
+ real32 b = m20 * A + m21 * B + m22 * C + m23 * D;
+
+ r = Pin_real32 (0.0f, r, 1.0f);
+ g = Pin_real32 (0.0f, g, 1.0f);
+ b = Pin_real32 (0.0f, b, 1.0f);
+
+ dPtrR [col] = r;
+ dPtrG [col] = g;
+ dPtrB [col] = b;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefBaselineHueSatMap (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_hue_sat_map &lut,
+ const dng_1d_table *encodeTable,
+ const dng_1d_table *decodeTable)
+ {
+
+ uint32 hueDivisions;
+ uint32 satDivisions;
+ uint32 valDivisions;
+
+ lut.GetDivisions (hueDivisions,
+ satDivisions,
+ valDivisions);
+
+ real32 hScale = (hueDivisions < 2) ? 0.0f : (hueDivisions * (1.0f / 6.0f));
+ real32 sScale = (real32) ((int32) satDivisions - 1);
+ real32 vScale = (real32) ((int32) valDivisions - 1);
+
+ int32 maxHueIndex0 = (int32) hueDivisions - 1;
+ int32 maxSatIndex0 = (int32) satDivisions - 2;
+ int32 maxValIndex0 = (int32) valDivisions - 2;
+
+ const bool hasEncodeTable = ((encodeTable != NULL) && (encodeTable->Table () != NULL));
+ const bool hasDecodeTable = ((decodeTable != NULL) && (decodeTable->Table () != NULL));
+
+ const bool hasTable = hasEncodeTable && hasDecodeTable;
+
+ const dng_hue_sat_map::HSBModify *tableBase = lut.GetConstDeltas ();
+
+ int32 hueStep = satDivisions;
+ int32 valStep = hueDivisions * hueStep;
+
+ #if 0 // Not required with "2.5D" table optimization.
+
+ if (valDivisions < 2)
+ {
+ valStep = 0;
+ maxValIndex0 = 0;
+ }
+
+ #endif
+
+ for (uint32 j = 0; j < count; j++)
+ {
+
+ real32 r = sPtrR [j];
+ real32 g = sPtrG [j];
+ real32 b = sPtrB [j];
+
+ real32 h, s, v;
+
+ DNG_RGBtoHSV (r, g, b, h, s, v);
+
+ real32 vEncoded = v;
+
+ real32 hueShift;
+ real32 satScale;
+ real32 valScale;
+
+ if (valDivisions < 2) // Optimize most common case of "2.5D" table.
+ {
+
+ real32 hScaled = h * hScale;
+ real32 sScaled = s * sScale;
+
+ int32 hIndex0 = (int32) hScaled;
+ int32 sIndex0 = (int32) sScaled;
+
+ sIndex0 = Min_int32 (sIndex0, maxSatIndex0);
+
+ int32 hIndex1 = hIndex0 + 1;
+
+ if (hIndex0 >= maxHueIndex0)
+ {
+ hIndex0 = maxHueIndex0;
+ hIndex1 = 0;
+ }
+
+ real32 hFract1 = hScaled - (real32) hIndex0;
+ real32 sFract1 = sScaled - (real32) sIndex0;
+
+ real32 hFract0 = 1.0f - hFract1;
+ real32 sFract0 = 1.0f - sFract1;
+
+ const dng_hue_sat_map::HSBModify *entry00 = tableBase + hIndex0 * hueStep +
+ sIndex0;
+
+ const dng_hue_sat_map::HSBModify *entry01 = entry00 + (hIndex1 - hIndex0) * hueStep;
+
+ real32 hueShift0 = hFract0 * entry00->fHueShift +
+ hFract1 * entry01->fHueShift;
+
+ real32 satScale0 = hFract0 * entry00->fSatScale +
+ hFract1 * entry01->fSatScale;
+
+ real32 valScale0 = hFract0 * entry00->fValScale +
+ hFract1 * entry01->fValScale;
+
+ entry00++;
+ entry01++;
+
+ real32 hueShift1 = hFract0 * entry00->fHueShift +
+ hFract1 * entry01->fHueShift;
+
+ real32 satScale1 = hFract0 * entry00->fSatScale +
+ hFract1 * entry01->fSatScale;
+
+ real32 valScale1 = hFract0 * entry00->fValScale +
+ hFract1 * entry01->fValScale;
+
+ hueShift = sFract0 * hueShift0 + sFract1 * hueShift1;
+ satScale = sFract0 * satScale0 + sFract1 * satScale1;
+ valScale = sFract0 * valScale0 + sFract1 * valScale1;
+
+ }
+
+ else
+ {
+
+ if (hasTable)
+ {
+ vEncoded = encodeTable->Interpolate (Pin_real32 (v));
+ }
+
+ real32 hScaled = h * hScale;
+ real32 sScaled = s * sScale;
+ real32 vScaled = vEncoded * vScale;
+
+ int32 hIndex0 = (int32) hScaled;
+ int32 sIndex0 = (int32) sScaled;
+ int32 vIndex0 = (int32) vScaled;
+
+ sIndex0 = Min_int32 (sIndex0, maxSatIndex0);
+ vIndex0 = Min_int32 (vIndex0, maxValIndex0);
+
+ int32 hIndex1 = hIndex0 + 1;
+
+ if (hIndex0 >= maxHueIndex0)
+ {
+ hIndex0 = maxHueIndex0;
+ hIndex1 = 0;
+ }
+
+ real32 hFract1 = hScaled - (real32) hIndex0;
+ real32 sFract1 = sScaled - (real32) sIndex0;
+ real32 vFract1 = vScaled - (real32) vIndex0;
+
+ real32 hFract0 = 1.0f - hFract1;
+ real32 sFract0 = 1.0f - sFract1;
+ real32 vFract0 = 1.0f - vFract1;
+
+ const dng_hue_sat_map::HSBModify *entry00 = tableBase + vIndex0 * valStep +
+ hIndex0 * hueStep +
+ sIndex0;
+
+ const dng_hue_sat_map::HSBModify *entry01 = entry00 + (hIndex1 - hIndex0) * hueStep;
+
+ const dng_hue_sat_map::HSBModify *entry10 = entry00 + valStep;
+ const dng_hue_sat_map::HSBModify *entry11 = entry01 + valStep;
+
+ real32 hueShift0 = vFract0 * (hFract0 * entry00->fHueShift +
+ hFract1 * entry01->fHueShift) +
+ vFract1 * (hFract0 * entry10->fHueShift +
+ hFract1 * entry11->fHueShift);
+
+ real32 satScale0 = vFract0 * (hFract0 * entry00->fSatScale +
+ hFract1 * entry01->fSatScale) +
+ vFract1 * (hFract0 * entry10->fSatScale +
+ hFract1 * entry11->fSatScale);
+
+ real32 valScale0 = vFract0 * (hFract0 * entry00->fValScale +
+ hFract1 * entry01->fValScale) +
+ vFract1 * (hFract0 * entry10->fValScale +
+ hFract1 * entry11->fValScale);
+
+ entry00++;
+ entry01++;
+ entry10++;
+ entry11++;
+
+ real32 hueShift1 = vFract0 * (hFract0 * entry00->fHueShift +
+ hFract1 * entry01->fHueShift) +
+ vFract1 * (hFract0 * entry10->fHueShift +
+ hFract1 * entry11->fHueShift);
+
+ real32 satScale1 = vFract0 * (hFract0 * entry00->fSatScale +
+ hFract1 * entry01->fSatScale) +
+ vFract1 * (hFract0 * entry10->fSatScale +
+ hFract1 * entry11->fSatScale);
+
+ real32 valScale1 = vFract0 * (hFract0 * entry00->fValScale +
+ hFract1 * entry01->fValScale) +
+ vFract1 * (hFract0 * entry10->fValScale +
+ hFract1 * entry11->fValScale);
+
+ hueShift = sFract0 * hueShift0 + sFract1 * hueShift1;
+ satScale = sFract0 * satScale0 + sFract1 * satScale1;
+ valScale = sFract0 * valScale0 + sFract1 * valScale1;
+
+ }
+
+ hueShift *= (6.0f / 360.0f); // Convert to internal hue range.
+
+ h += hueShift;
+
+ s = Min_real32 (s * satScale, 1.0f);
+
+ vEncoded = Pin_real32 (vEncoded * valScale);
+
+ v = hasTable ? decodeTable->Interpolate (vEncoded) : vEncoded;
+
+ DNG_HSVtoRGB (h, s, v, r, g, b);
+
+ dPtrR [j] = r;
+ dPtrG [j] = g;
+ dPtrB [j] = b;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefBaselineRGBtoGray (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrG,
+ uint32 count,
+ const dng_matrix &matrix)
+ {
+
+ real32 m00 = (real32) matrix [0] [0];
+ real32 m01 = (real32) matrix [0] [1];
+ real32 m02 = (real32) matrix [0] [2];
+
+ for (uint32 col = 0; col < count; col++)
+ {
+
+ real32 R = sPtrR [col];
+ real32 G = sPtrG [col];
+ real32 B = sPtrB [col];
+
+ real32 g = m00 * R + m01 * G + m02 * B;
+
+ g = Pin_real32 (0.0f, g, 1.0f);
+
+ dPtrG [col] = g;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefBaselineRGBtoRGB (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_matrix &matrix)
+ {
+
+ real32 m00 = (real32) matrix [0] [0];
+ real32 m01 = (real32) matrix [0] [1];
+ real32 m02 = (real32) matrix [0] [2];
+
+ real32 m10 = (real32) matrix [1] [0];
+ real32 m11 = (real32) matrix [1] [1];
+ real32 m12 = (real32) matrix [1] [2];
+
+ real32 m20 = (real32) matrix [2] [0];
+ real32 m21 = (real32) matrix [2] [1];
+ real32 m22 = (real32) matrix [2] [2];
+
+ for (uint32 col = 0; col < count; col++)
+ {
+
+ real32 R = sPtrR [col];
+ real32 G = sPtrG [col];
+ real32 B = sPtrB [col];
+
+ real32 r = m00 * R + m01 * G + m02 * B;
+ real32 g = m10 * R + m11 * G + m12 * B;
+ real32 b = m20 * R + m21 * G + m22 * B;
+
+ r = Pin_real32 (0.0f, r, 1.0f);
+ g = Pin_real32 (0.0f, g, 1.0f);
+ b = Pin_real32 (0.0f, b, 1.0f);
+
+ dPtrR [col] = r;
+ dPtrG [col] = g;
+ dPtrB [col] = b;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefBaseline1DTable (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 count,
+ const dng_1d_table &table)
+ {
+
+ for (uint32 col = 0; col < count; col++)
+ {
+
+ real32 x = sPtr [col];
+
+ real32 y = table.Interpolate (x);
+
+ dPtr [col] = y;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefBaselineRGBTone (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_1d_table &table)
+ {
+
+ for (uint32 col = 0; col < count; col++)
+ {
+
+ real32 r = sPtrR [col];
+ real32 g = sPtrG [col];
+ real32 b = sPtrB [col];
+
+ real32 rr;
+ real32 gg;
+ real32 bb;
+
+ #define RGBTone(r, g, b, rr, gg, bb)\
+ {\
+ \
+ DNG_ASSERT (r >= g && g >= b && r > b, "Logic Error RGBTone");\
+ \
+ rr = table.Interpolate (r);\
+ bb = table.Interpolate (b);\
+ \
+ gg = bb + ((rr - bb) * (g - b) / (r - b));\
+ \
+ }
+
+ if (r >= g)
+ {
+
+ if (g > b)
+ {
+
+ // Case 1: r >= g > b
+
+ RGBTone (r, g, b, rr, gg, bb);
+
+ }
+
+ else if (b > r)
+ {
+
+ // Case 2: b > r >= g
+
+ RGBTone (b, r, g, bb, rr, gg);
+
+ }
+
+ else if (b > g)
+ {
+
+ // Case 3: r >= b > g
+
+ RGBTone (r, b, g, rr, bb, gg);
+
+ }
+
+ else
+ {
+
+ // Case 4: r >= g == b
+
+ DNG_ASSERT (r >= g && g == b, "Logic Error 2");
+
+ rr = table.Interpolate (r);
+ gg = table.Interpolate (g);
+ bb = gg;
+
+ }
+
+ }
+
+ else
+ {
+
+ if (r >= b)
+ {
+
+ // Case 5: g > r >= b
+
+ RGBTone (g, r, b, gg, rr, bb);
+
+ }
+
+ else if (b > g)
+ {
+
+ // Case 6: b > g > r
+
+ RGBTone (b, g, r, bb, gg, rr);
+
+ }
+
+ else
+ {
+
+ // Case 7: g >= b > r
+
+ RGBTone (g, b, r, gg, bb, rr);
+
+ }
+
+ }
+
+ #undef RGBTone
+
+ dPtrR [col] = rr;
+ dPtrG [col] = gg;
+ dPtrB [col] = bb;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefResampleDown16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 sCount,
+ int32 sRowStep,
+ const int16 *wPtr,
+ uint32 wCount,
+ uint32 pixelRange)
+ {
+
+ for (uint32 j = 0; j < sCount; j++)
+ {
+
+ int32 total = 8192;
+
+ const uint16 *s = sPtr + j;
+
+ for (uint32 k = 0; k < wCount; k++)
+ {
+
+ total += wPtr [k] * (int32) s [0];
+
+ s += sRowStep;
+
+ }
+
+ dPtr [j] = (uint16) Pin_int32 (0,
+ total >> 14,
+ pixelRange);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefResampleDown32 (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 sCount,
+ int32 sRowStep,
+ const real32 *wPtr,
+ uint32 wCount)
+ {
+
+ uint32 col;
+
+ // Process first row.
+
+ real32 w = wPtr [0];
+
+ for (col = 0; col < sCount; col++)
+ {
+
+ dPtr [col] = w * sPtr [col];
+
+ }
+
+ sPtr += sRowStep;
+
+ // Process middle rows.
+
+ for (uint32 j = 1; j < wCount - 1; j++)
+ {
+
+ w = wPtr [j];
+
+ for (col = 0; col < sCount; col++)
+ {
+
+ dPtr [col] += w * sPtr [col];
+
+ }
+
+ sPtr += sRowStep;
+
+ }
+
+ // Process last row.
+
+ w = wPtr [wCount - 1];
+
+ for (col = 0; col < sCount; col++)
+ {
+
+ dPtr [col] = Pin_real32 (0.0f,
+ dPtr [col] + w * sPtr [col],
+ 1.0f);
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void RefResampleAcross16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 dCount,
+ const int32 *coord,
+ const int16 *wPtr,
+ uint32 wCount,
+ uint32 wStep,
+ uint32 pixelRange)
+ {
+
+ for (uint32 j = 0; j < dCount; j++)
+ {
+
+ int32 sCoord = coord [j];
+
+ int32 sFract = sCoord & kResampleSubsampleMask;
+ int32 sPixel = sCoord >> kResampleSubsampleBits;
+
+ const int16 *w = wPtr + sFract * wStep;
+ const uint16 *s = sPtr + sPixel;
+
+ int32 total = w [0] * (int32) s [0];
+
+ for (uint32 k = 1; k < wCount; k++)
+ {
+
+ total += w [k] * (int32) s [k];
+
+ }
+
+ dPtr [j] = (uint16) Pin_int32 (0,
+ (total + 8192) >> 14,
+ pixelRange);
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void RefResampleAcross32 (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 dCount,
+ const int32 *coord,
+ const real32 *wPtr,
+ uint32 wCount,
+ uint32 wStep)
+ {
+
+ for (uint32 j = 0; j < dCount; j++)
+ {
+
+ int32 sCoord = coord [j];
+
+ int32 sFract = sCoord & kResampleSubsampleMask;
+ int32 sPixel = sCoord >> kResampleSubsampleBits;
+
+ const real32 *w = wPtr + sFract * wStep;
+ const real32 *s = sPtr + sPixel;
+
+ real32 total = w [0] * s [0];
+
+ for (uint32 k = 1; k < wCount; k++)
+ {
+
+ total += w [k] * s [k];
+
+ }
+
+ dPtr [j] = Pin_real32 (0.0f, total, 1.0f);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool RefEqualBytes (const void *sPtr,
+ const void *dPtr,
+ uint32 count)
+ {
+
+ return memcmp (dPtr, sPtr, count) == 0;
+
+ }
+
+/*****************************************************************************/
+
+bool RefEqualArea8 (const uint8 *sPtr,
+ const uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint8 *sPtr1 = sPtr;
+ const uint8 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint8 *sPtr2 = sPtr1;
+ const uint8 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ if (*dPtr2 != *sPtr2)
+ return false;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool RefEqualArea16 (const uint16 *sPtr,
+ const uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint16 *sPtr1 = sPtr;
+ const uint16 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint16 *sPtr2 = sPtr1;
+ const uint16 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ if (*dPtr2 != *sPtr2)
+ return false;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool RefEqualArea32 (const uint32 *sPtr,
+ const uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep)
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ const uint32 *sPtr1 = sPtr;
+ const uint32 *dPtr1 = dPtr;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ const uint32 *sPtr2 = sPtr1;
+ const uint32 *dPtr2 = dPtr1;
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ if (*dPtr2 != *sPtr2)
+ return false;
+
+ sPtr2 += sPlaneStep;
+ dPtr2 += dPlaneStep;
+
+ }
+
+ sPtr1 += sColStep;
+ dPtr1 += dColStep;
+
+ }
+
+ sPtr += sRowStep;
+ dPtr += dRowStep;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+void RefVignetteMask16 (uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ int32 rowStep,
+ int64 offsetH,
+ int64 offsetV,
+ int64 stepH,
+ int64 stepV,
+ uint32 tBits,
+ const uint16 *table)
+ {
+
+ uint32 tShift = 32 - tBits;
+ uint32 tRound = (1 << (tShift - 1));
+ uint32 tLimit = 1 << tBits;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ int64 baseDelta = (offsetV + 32768) >> 16;
+
+ baseDelta = baseDelta * baseDelta + tRound;
+
+ int64 deltaH = offsetH + 32768;
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ int64 temp = deltaH >> 16;
+
+ int64 delta = baseDelta + (temp * temp);
+
+ uint32 index = Min_uint32 ((uint32) (delta >> tShift), tLimit);
+
+ mPtr [col] = table [index];
+
+ deltaH += stepH;
+
+ }
+
+ offsetV += stepV;
+
+ mPtr += rowStep;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefVignette16 (int16 *sPtr,
+ const uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sPlaneStep,
+ int32 mRowStep,
+ uint32 mBits)
+ {
+
+ const uint32 mRound = 1 << (mBits - 1);
+
+ switch (planes)
+ {
+
+ case 1:
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ uint32 s = sPtr [col] + 32768;
+
+ uint32 m = mPtr [col];
+
+ s = (s * m + mRound) >> mBits;
+
+ s = Min_uint32 (s, 65535);
+
+ sPtr [col] = (int16) (s - 32768);
+
+ }
+
+ sPtr += sRowStep;
+
+ mPtr += mRowStep;
+
+ }
+
+ break;
+
+ }
+
+ case 3:
+ {
+
+ int16 *rPtr = sPtr;
+ int16 *gPtr = rPtr + sPlaneStep;
+ int16 *bPtr = gPtr + sPlaneStep;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ uint32 r = rPtr [col] + 32768;
+ uint32 g = gPtr [col] + 32768;
+ uint32 b = bPtr [col] + 32768;
+
+ uint32 m = mPtr [col];
+
+ r = (r * m + mRound) >> mBits;
+ g = (g * m + mRound) >> mBits;
+ b = (b * m + mRound) >> mBits;
+
+ r = Min_uint32 (r, 65535);
+ g = Min_uint32 (g, 65535);
+ b = Min_uint32 (b, 65535);
+
+ rPtr [col] = (int16) (r - 32768);
+ gPtr [col] = (int16) (g - 32768);
+ bPtr [col] = (int16) (b - 32768);
+
+ }
+
+ rPtr += sRowStep;
+ gPtr += sRowStep;
+ bPtr += sRowStep;
+
+ mPtr += mRowStep;
+
+ }
+
+ break;
+
+ }
+
+ case 4:
+ {
+
+ int16 *aPtr = sPtr;
+ int16 *bPtr = aPtr + sPlaneStep;
+ int16 *cPtr = bPtr + sPlaneStep;
+ int16 *dPtr = cPtr + sPlaneStep;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ uint32 a = aPtr [col] + 32768;
+ uint32 b = bPtr [col] + 32768;
+ uint32 c = cPtr [col] + 32768;
+ uint32 d = dPtr [col] + 32768;
+
+ uint32 m = mPtr [col];
+
+ a = (a * m + mRound) >> mBits;
+ b = (b * m + mRound) >> mBits;
+ c = (c * m + mRound) >> mBits;
+ d = (d * m + mRound) >> mBits;
+
+ a = Min_uint32 (a, 65535);
+ b = Min_uint32 (b, 65535);
+ c = Min_uint32 (c, 65535);
+ d = Min_uint32 (d, 65535);
+
+ aPtr [col] = (int16) (a - 32768);
+ bPtr [col] = (int16) (b - 32768);
+ cPtr [col] = (int16) (c - 32768);
+ dPtr [col] = (int16) (d - 32768);
+
+ }
+
+ aPtr += sRowStep;
+ bPtr += sRowStep;
+ cPtr += sRowStep;
+ dPtr += sRowStep;
+
+ mPtr += mRowStep;
+
+ }
+
+ break;
+
+ }
+
+ default:
+ {
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ int16 *planePtr = sPtr;
+
+ const uint16 *maskPtr = mPtr;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ uint32 s = planePtr [col] + 32768;
+
+ uint32 m = maskPtr [col];
+
+ s = (s * m + mRound) >> mBits;
+
+ s = Min_uint32 (s, 65535);
+
+ planePtr [col] = (int16) (s - 32768);
+
+ }
+
+ planePtr += sRowStep;
+
+ maskPtr += mRowStep;
+
+ }
+
+ sPtr += sPlaneStep;
+
+ }
+
+ break;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void RefVignette32 (real32 *sPtr,
+ const uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sPlaneStep,
+ int32 mRowStep,
+ uint32 mBits)
+ {
+
+ const real32 kNorm = 1.0f / (1 << mBits);
+
+ switch (planes)
+ {
+
+ case 1:
+ {
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ real32 s = sPtr [col];
+
+ uint16 m = mPtr [col];
+
+ real32 scale = m * kNorm;
+
+ s = Min_real32 (s * scale, 1.0f);
+
+ sPtr [col] = s;
+
+ }
+
+ sPtr += sRowStep;
+
+ mPtr += mRowStep;
+
+ }
+
+ break;
+
+ }
+
+ case 3:
+ {
+
+ real32 *rPtr = sPtr;
+ real32 *gPtr = rPtr + sPlaneStep;
+ real32 *bPtr = gPtr + sPlaneStep;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ real32 r = rPtr [col];
+ real32 g = gPtr [col];
+ real32 b = bPtr [col];
+
+ uint16 m = mPtr [col];
+
+ real32 scale = m * kNorm;
+
+ r = Min_real32 (r * scale, 1.0f);
+ g = Min_real32 (g * scale, 1.0f);
+ b = Min_real32 (b * scale, 1.0f);
+
+ rPtr [col] = r;
+ gPtr [col] = g;
+ bPtr [col] = b;
+
+ }
+
+ rPtr += sRowStep;
+ gPtr += sRowStep;
+ bPtr += sRowStep;
+
+ mPtr += mRowStep;
+
+ }
+
+ break;
+
+ }
+
+ case 4:
+ {
+
+ real32 *aPtr = sPtr;
+ real32 *bPtr = aPtr + sPlaneStep;
+ real32 *cPtr = bPtr + sPlaneStep;
+ real32 *dPtr = cPtr + sPlaneStep;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ real32 a = aPtr [col];
+ real32 b = bPtr [col];
+ real32 c = cPtr [col];
+ real32 d = dPtr [col];
+
+ uint16 m = mPtr [col];
+
+ real32 scale = m * kNorm;
+
+ a = Min_real32 (a * scale, 1.0f);
+ b = Min_real32 (b * scale, 1.0f);
+ c = Min_real32 (c * scale, 1.0f);
+ d = Min_real32 (d * scale, 1.0f);
+
+ aPtr [col] = a;
+ bPtr [col] = b;
+ cPtr [col] = c;
+ dPtr [col] = d;
+
+ }
+
+ aPtr += sRowStep;
+ bPtr += sRowStep;
+ cPtr += sRowStep;
+ dPtr += sRowStep;
+
+ mPtr += mRowStep;
+
+ }
+
+ break;
+
+ }
+
+ default:
+ {
+
+ for (uint32 plane = 0; plane < planes; plane++)
+ {
+
+ real32 *planePtr = sPtr;
+
+ const uint16 *maskPtr = mPtr;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ real32 s = planePtr [col];
+
+ uint16 m = maskPtr [col];
+
+ real32 scale = m * kNorm;
+
+ s = Min_real32 (s * scale, 1.0f);
+
+ planePtr [col] = s;
+
+ }
+
+ planePtr += sRowStep;
+
+ maskPtr += mRowStep;
+
+ }
+
+ sPtr += sPlaneStep;
+
+ }
+
+ break;
+
+ }
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void RefMapArea16 (uint16 *dPtr,
+ uint32 count0,
+ uint32 count1,
+ uint32 count2,
+ int32 step0,
+ int32 step1,
+ int32 step2,
+ const uint16 *map)
+ {
+
+ if (step2 == 1 && count2 >= 32)
+ {
+
+ for (uint32 index0 = 0; index0 < count0; index0++)
+ {
+
+ uint16 *d1 = dPtr;
+
+ for (uint32 index1 = 0; index1 < count1; index1++)
+ {
+
+ uint16 *d2 = d1;
+
+ uint32 count = count2;
+
+ // Get the data 32-bit aligned if it is not.
+
+ if (!IsAligned32 (dPtr))
+ {
+
+ d2 [0] = map [d2 [0]];
+
+ count--;
+
+ d2++;
+
+ }
+
+ // Use 32-bit reads and writes for bulk processing.
+
+ uint32 *dPtr32 = (uint32 *) d2;
+
+ // Process in blocks of 16 pixels.
+
+ uint32 blocks = count >> 4;
+
+ count -= blocks << 4;
+ d2 += blocks << 4;
+
+ while (blocks--)
+ {
+
+ uint32 x0, x1, x2, x3, x4, x5, x6, x7;
+ uint32 p0, p1, p2, p3, p4, p5, p6, p7;
+
+ // Use 32 bit reads & writes, and pack and unpack the 16-bit values.
+ // This results in slightly higher performance.
+
+ // Note that this code runs on both little-endian and big-endian systems,
+ // since the pixels are either never swapped or double swapped.
+
+ x0 = dPtr32 [0];
+ x1 = dPtr32 [1];
+ x2 = dPtr32 [2];
+ x3 = dPtr32 [3];
+
+ p0 = map [x0 >> 16 ];
+ p1 = map [x0 & 0x0FFFF];
+ p2 = map [x1 >> 16 ];
+ p3 = map [x1 & 0x0FFFF];
+ p4 = map [x2 >> 16 ];
+ p5 = map [x2 & 0x0FFFF];
+ p6 = map [x3 >> 16 ];
+ p7 = map [x3 & 0x0FFFF];
+
+ x0 = (p0 << 16) | p1;
+ x1 = (p2 << 16) | p3;
+ x2 = (p4 << 16) | p5;
+ x3 = (p6 << 16) | p7;
+
+ x4 = dPtr32 [4];
+ x5 = dPtr32 [5];
+ x6 = dPtr32 [6];
+ x7 = dPtr32 [7];
+
+ dPtr32 [0] = x0;
+ dPtr32 [1] = x1;
+ dPtr32 [2] = x2;
+ dPtr32 [3] = x3;
+
+ p0 = map [x4 >> 16 ];
+ p1 = map [x4 & 0x0FFFF];
+ p2 = map [x5 >> 16 ];
+ p3 = map [x5 & 0x0FFFF];
+ p4 = map [x6 >> 16 ];
+ p5 = map [x6 & 0x0FFFF];
+ p6 = map [x7 >> 16 ];
+ p7 = map [x7 & 0x0FFFF];
+
+ x4 = (p0 << 16) | p1;
+ x5 = (p2 << 16) | p3;
+ x6 = (p4 << 16) | p5;
+ x7 = (p6 << 16) | p7;
+
+ dPtr32 [4] = x4;
+ dPtr32 [5] = x5;
+ dPtr32 [6] = x6;
+ dPtr32 [7] = x7;
+
+ dPtr32 += 8;
+
+ }
+
+ // Process remaining columns.
+
+ for (uint32 j = 0; j < count; j++)
+ {
+
+ d2 [j] = map [d2 [j]];
+
+ }
+
+ d1 += step1;
+
+ }
+
+ dPtr += step0;
+
+ }
+
+ }
+
+ else
+ {
+
+ for (uint32 index0 = 0; index0 < count0; index0++)
+ {
+
+ uint16 *d1 = dPtr;
+
+ for (uint32 index1 = 0; index1 < count1; index1++)
+ {
+
+ uint16 *d2 = d1;
+
+ for (uint32 index2 = 0; index2 < count2; index2++)
+ {
+
+ d2 [0] = map [d2 [0]];
+
+ d2 += step2;
+
+ }
+
+ d1 += step1;
+
+ }
+
+ dPtr += step0;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_reference.h b/source/dng_reference.h
index d75dcec..4a728f3 100644
--- a/source/dng_reference.h
+++ b/source/dng_reference.h
@@ -1,521 +1,521 @@
-/*****************************************************************************/
-// Copyright 2006-2009 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_reference.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_reference__
-#define __dng_reference__
-
-/*****************************************************************************/
-
-#include "dng_bottlenecks.h"
-
-/*****************************************************************************/
-
-void RefZeroBytes (void *dPtr,
- uint32 count);
-
-void RefCopyBytes (const void *sPtr,
- void *dPtr,
- uint32 count);
-
-/*****************************************************************************/
-
-void RefSwapBytes16 (uint16 *dPtr,
- uint32 count);
-
-void RefSwapBytes32 (uint32 *dPtr,
- uint32 count);
-
-/*****************************************************************************/
-
-void RefSetArea8 (uint8 *dPtr,
- uint8 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep);
-
-void RefSetArea16 (uint16 *dPtr,
- uint16 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep);
-
-void RefSetArea32 (uint32 *dPtr,
- uint32 value,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep);
-
-/*****************************************************************************/
-
-void RefCopyArea8 (const uint8 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-void RefCopyArea16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-void RefCopyArea32 (const uint32 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-void RefCopyArea8_16 (const uint8 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-void RefCopyArea8_S16 (const uint8 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-void RefCopyArea8_32 (const uint8 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-void RefCopyArea16_S16 (const uint16 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-void RefCopyArea16_32 (const uint16 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-void RefCopyArea8_R32 (const uint8 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-void RefCopyArea16_R32 (const uint16 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-void RefCopyAreaS16_R32 (const int16 *sPtr,
- real32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-void RefCopyAreaR32_8 (const real32 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-void RefCopyAreaR32_16 (const real32 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-void RefCopyAreaR32_S16 (const real32 *sPtr,
- int16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep,
- uint32 pixelRange);
-
-/*****************************************************************************/
-
-void RefRepeatArea8 (const uint8 *sPtr,
- uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH);
-
-void RefRepeatArea16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH);
-
-void RefRepeatArea32 (const uint32 *sPtr,
- uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 repeatV,
- uint32 repeatH,
- uint32 phaseV,
- uint32 phaseH);
-
-/*****************************************************************************/
-
-void RefShiftRight16 (uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 rowStep,
- int32 colStep,
- int32 planeStep,
- uint32 shift);
-
-/*****************************************************************************/
-
-void RefBilinearRow16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 cols,
- uint32 patPhase,
- uint32 patCount,
- const uint32 * kernCounts,
- const int32 * const * kernOffsets,
- const uint16 * const * kernWeights,
- uint32 sShift);
-
-void RefBilinearRow32 (const real32 *sPtr,
- real32 *dPtr,
- uint32 cols,
- uint32 patPhase,
- uint32 patCount,
- const uint32 * kernCounts,
- const int32 * const * kernOffsets,
- const real32 * const * kernWeights,
- uint32 sShift);
-
-/*****************************************************************************/
-
-void RefBaselineABCtoRGB (const real32 *sPtrA,
- const real32 *sPtrB,
- const real32 *sPtrC,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_vector &cameraWhite,
- const dng_matrix &cameraToRGB);
-
-void RefBaselineABCDtoRGB (const real32 *sPtrA,
- const real32 *sPtrB,
- const real32 *sPtrC,
- const real32 *sPtrD,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_vector &cameraWhite,
- const dng_matrix &cameraToRGB);
-
-/*****************************************************************************/
-
-void RefBaselineHueSatMap (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_hue_sat_map &lut,
- const dng_1d_table *encodeTable,
- const dng_1d_table *decodeTable);
-
-/*****************************************************************************/
-
-void RefBaselineRGBtoGray (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrG,
- uint32 count,
- const dng_matrix &matrix);
-
-void RefBaselineRGBtoRGB (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_matrix &matrix);
-
-/*****************************************************************************/
-
-void RefBaseline1DTable (const real32 *sPtr,
- real32 *dPtr,
- uint32 count,
- const dng_1d_table &table);
-
-/*****************************************************************************/
-
-void RefBaselineRGBTone (const real32 *sPtrR,
- const real32 *sPtrG,
- const real32 *sPtrB,
- real32 *dPtrR,
- real32 *dPtrG,
- real32 *dPtrB,
- uint32 count,
- const dng_1d_table &table);
-
-/*****************************************************************************/
-
-void RefResampleDown16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 sCount,
- int32 sRowStep,
- const int16 *wPtr,
- uint32 wCount,
- uint32 pixelRange);
-
-void RefResampleDown32 (const real32 *sPtr,
- real32 *dPtr,
- uint32 sCount,
- int32 sRowStep,
- const real32 *wPtr,
- uint32 wCount);
-
-/*****************************************************************************/
-
-void RefResampleAcross16 (const uint16 *sPtr,
- uint16 *dPtr,
- uint32 dCount,
- const int32 *coord,
- const int16 *wPtr,
- uint32 wCount,
- uint32 wStep,
- uint32 pixelRange);
-
-void RefResampleAcross32 (const real32 *sPtr,
- real32 *dPtr,
- uint32 dCount,
- const int32 *coord,
- const real32 *wPtr,
- uint32 wCount,
- uint32 wStep);
-
-/*****************************************************************************/
-
-bool RefEqualBytes (const void *sPtr,
- const void *dPtr,
- uint32 count);
-
-bool RefEqualArea8 (const uint8 *sPtr,
- const uint8 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-bool RefEqualArea16 (const uint16 *sPtr,
- const uint16 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-bool RefEqualArea32 (const uint32 *sPtr,
- const uint32 *dPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sColStep,
- int32 sPlaneStep,
- int32 dRowStep,
- int32 dColStep,
- int32 dPlaneStep);
-
-/*****************************************************************************/
-
-void RefVignetteMask16 (uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- int32 rowStep,
- int64 offsetH,
- int64 offsetV,
- int64 stepH,
- int64 stepV,
- uint32 tBits,
- const uint16 *table);
-
-/*****************************************************************************/
-
-void RefVignette16 (int16 *sPtr,
- const uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sPlaneStep,
- int32 mRowStep,
- uint32 mBits);
-
-/*****************************************************************************/
-
-void RefVignette32 (real32 *sPtr,
- const uint16 *mPtr,
- uint32 rows,
- uint32 cols,
- uint32 planes,
- int32 sRowStep,
- int32 sPlaneStep,
- int32 mRowStep,
- uint32 mBits);
-
-/*****************************************************************************/
-
-void RefMapArea16 (uint16 *dPtr,
- uint32 count0,
- uint32 count1,
- uint32 count2,
- int32 step0,
- int32 step1,
- int32 step2,
- const uint16 *map);
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2009 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_reference.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_reference__
+#define __dng_reference__
+
+/*****************************************************************************/
+
+#include "dng_bottlenecks.h"
+
+/*****************************************************************************/
+
+void RefZeroBytes (void *dPtr,
+ uint32 count);
+
+void RefCopyBytes (const void *sPtr,
+ void *dPtr,
+ uint32 count);
+
+/*****************************************************************************/
+
+void RefSwapBytes16 (uint16 *dPtr,
+ uint32 count);
+
+void RefSwapBytes32 (uint32 *dPtr,
+ uint32 count);
+
+/*****************************************************************************/
+
+void RefSetArea8 (uint8 *dPtr,
+ uint8 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep);
+
+void RefSetArea16 (uint16 *dPtr,
+ uint16 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep);
+
+void RefSetArea32 (uint32 *dPtr,
+ uint32 value,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep);
+
+/*****************************************************************************/
+
+void RefCopyArea8 (const uint8 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+void RefCopyArea16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+void RefCopyArea32 (const uint32 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+void RefCopyArea8_16 (const uint8 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+void RefCopyArea8_S16 (const uint8 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+void RefCopyArea8_32 (const uint8 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+void RefCopyArea16_S16 (const uint16 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+void RefCopyArea16_32 (const uint16 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+void RefCopyArea8_R32 (const uint8 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+void RefCopyArea16_R32 (const uint16 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+void RefCopyAreaS16_R32 (const int16 *sPtr,
+ real32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+void RefCopyAreaR32_8 (const real32 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+void RefCopyAreaR32_16 (const real32 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+void RefCopyAreaR32_S16 (const real32 *sPtr,
+ int16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep,
+ uint32 pixelRange);
+
+/*****************************************************************************/
+
+void RefRepeatArea8 (const uint8 *sPtr,
+ uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH);
+
+void RefRepeatArea16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH);
+
+void RefRepeatArea32 (const uint32 *sPtr,
+ uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 repeatV,
+ uint32 repeatH,
+ uint32 phaseV,
+ uint32 phaseH);
+
+/*****************************************************************************/
+
+void RefShiftRight16 (uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 rowStep,
+ int32 colStep,
+ int32 planeStep,
+ uint32 shift);
+
+/*****************************************************************************/
+
+void RefBilinearRow16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 cols,
+ uint32 patPhase,
+ uint32 patCount,
+ const uint32 * kernCounts,
+ const int32 * const * kernOffsets,
+ const uint16 * const * kernWeights,
+ uint32 sShift);
+
+void RefBilinearRow32 (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 cols,
+ uint32 patPhase,
+ uint32 patCount,
+ const uint32 * kernCounts,
+ const int32 * const * kernOffsets,
+ const real32 * const * kernWeights,
+ uint32 sShift);
+
+/*****************************************************************************/
+
+void RefBaselineABCtoRGB (const real32 *sPtrA,
+ const real32 *sPtrB,
+ const real32 *sPtrC,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_vector &cameraWhite,
+ const dng_matrix &cameraToRGB);
+
+void RefBaselineABCDtoRGB (const real32 *sPtrA,
+ const real32 *sPtrB,
+ const real32 *sPtrC,
+ const real32 *sPtrD,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_vector &cameraWhite,
+ const dng_matrix &cameraToRGB);
+
+/*****************************************************************************/
+
+void RefBaselineHueSatMap (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_hue_sat_map &lut,
+ const dng_1d_table *encodeTable,
+ const dng_1d_table *decodeTable);
+
+/*****************************************************************************/
+
+void RefBaselineRGBtoGray (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrG,
+ uint32 count,
+ const dng_matrix &matrix);
+
+void RefBaselineRGBtoRGB (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_matrix &matrix);
+
+/*****************************************************************************/
+
+void RefBaseline1DTable (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 count,
+ const dng_1d_table &table);
+
+/*****************************************************************************/
+
+void RefBaselineRGBTone (const real32 *sPtrR,
+ const real32 *sPtrG,
+ const real32 *sPtrB,
+ real32 *dPtrR,
+ real32 *dPtrG,
+ real32 *dPtrB,
+ uint32 count,
+ const dng_1d_table &table);
+
+/*****************************************************************************/
+
+void RefResampleDown16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 sCount,
+ int32 sRowStep,
+ const int16 *wPtr,
+ uint32 wCount,
+ uint32 pixelRange);
+
+void RefResampleDown32 (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 sCount,
+ int32 sRowStep,
+ const real32 *wPtr,
+ uint32 wCount);
+
+/*****************************************************************************/
+
+void RefResampleAcross16 (const uint16 *sPtr,
+ uint16 *dPtr,
+ uint32 dCount,
+ const int32 *coord,
+ const int16 *wPtr,
+ uint32 wCount,
+ uint32 wStep,
+ uint32 pixelRange);
+
+void RefResampleAcross32 (const real32 *sPtr,
+ real32 *dPtr,
+ uint32 dCount,
+ const int32 *coord,
+ const real32 *wPtr,
+ uint32 wCount,
+ uint32 wStep);
+
+/*****************************************************************************/
+
+bool RefEqualBytes (const void *sPtr,
+ const void *dPtr,
+ uint32 count);
+
+bool RefEqualArea8 (const uint8 *sPtr,
+ const uint8 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+bool RefEqualArea16 (const uint16 *sPtr,
+ const uint16 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+bool RefEqualArea32 (const uint32 *sPtr,
+ const uint32 *dPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sColStep,
+ int32 sPlaneStep,
+ int32 dRowStep,
+ int32 dColStep,
+ int32 dPlaneStep);
+
+/*****************************************************************************/
+
+void RefVignetteMask16 (uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ int32 rowStep,
+ int64 offsetH,
+ int64 offsetV,
+ int64 stepH,
+ int64 stepV,
+ uint32 tBits,
+ const uint16 *table);
+
+/*****************************************************************************/
+
+void RefVignette16 (int16 *sPtr,
+ const uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sPlaneStep,
+ int32 mRowStep,
+ uint32 mBits);
+
+/*****************************************************************************/
+
+void RefVignette32 (real32 *sPtr,
+ const uint16 *mPtr,
+ uint32 rows,
+ uint32 cols,
+ uint32 planes,
+ int32 sRowStep,
+ int32 sPlaneStep,
+ int32 mRowStep,
+ uint32 mBits);
+
+/*****************************************************************************/
+
+void RefMapArea16 (uint16 *dPtr,
+ uint32 count0,
+ uint32 count1,
+ uint32 count2,
+ int32 step0,
+ int32 step1,
+ int32 step2,
+ const uint16 *map);
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_render.h b/source/dng_render.h
index 4c9aec7..1a7ea02 100644
--- a/source/dng_render.h
+++ b/source/dng_render.h
@@ -1,312 +1,312 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_render.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Classes for conversion of RAW data to final image.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_render__
-#define __dng_render__
-
-/*****************************************************************************/
-
-#include "dng_1d_function.h"
-#include "dng_auto_ptr.h"
-#include "dng_classes.h"
-#include "dng_spline.h"
-#include "dng_xy_coord.h"
-
-/******************************************************************************/
-
-/// \brief Curve for pre-exposure-compensation adjustment based on noise floor,
-/// shadows, and highlight level.
-
-class dng_function_exposure_ramp: public dng_1d_function
- {
-
- public:
-
- real64 fSlope; // Slope of straight segment.
-
- real64 fBlack; // Intercept of straight segment.
-
- real64 fRadius; // Rounding radius.
-
- real64 fQScale; // Quadradic scale.
-
- public:
-
- dng_function_exposure_ramp (real64 white,
- real64 black,
- real64 minBlack);
-
- virtual real64 Evaluate (real64 x) const;
-
- };
-
-/******************************************************************************/
-
-/// \brief Exposure compensation curve for a given compensation amount in stops using
-/// quadric for roll-off.
-
-class dng_function_exposure_tone: public dng_1d_function
- {
-
- protected:
-
- bool fIsNOP; // Is this a NOP function?
-
- real64 fSlope; // Slope for lower part of curve.
-
- real64 a; // Quadradic parameters for upper two f-stops.
- real64 b;
- real64 c;
-
- public:
-
- dng_function_exposure_tone (real64 exposure);
-
- /// Returns output value for a given input tone.
-
- virtual real64 Evaluate (real64 x) const;
-
- };
-
-/*****************************************************************************/
-
-/// Default ACR3 tone curve.
-
-class dng_tone_curve_acr3_default: public dng_1d_function
- {
-
- public:
-
- /// Returns output value for a given input tone.
-
- virtual real64 Evaluate (real64 x) const;
-
- /// Returns nearest input value for a given output tone.
-
- virtual real64 EvaluateInverse (real64 x) const;
-
- static const dng_1d_function & Get ();
-
- };
-
-/*****************************************************************************/
-
-/// \brief Encoding gamma curve for a given color space.
-
-class dng_function_gamma_encode: public dng_1d_function
- {
-
- protected:
-
- const dng_color_space &fSpace;
-
- public:
-
- dng_function_gamma_encode (const dng_color_space &space);
-
- virtual real64 Evaluate (real64 x) const;
-
- };
-
-/*****************************************************************************/
-
-/// \brief Class used to render digital negative to displayable image.
-
-class dng_render
- {
-
- protected:
-
- dng_host &fHost;
-
- const dng_negative &fNegative;
-
- dng_xy_coord fWhiteXY;
-
- real64 fExposure;
-
- real64 fShadows;
-
- const dng_1d_function *fToneCurve;
-
- const dng_color_space *fFinalSpace;
-
- uint32 fFinalPixelType;
-
- uint32 fMaximumSize;
-
- private:
-
- AutoPtr<dng_spline_solver> fProfileToneCurve;
-
- public:
-
- /// Construct a rendering instance that will be used to convert a given digital negative.
- /// \param host The host to use for memory allocation, progress updates, and abort testing.
- /// \param negative The digital negative to convert to a displayable image.
-
- dng_render (dng_host &host,
- const dng_negative &negative);
-
- virtual ~dng_render ()
- {
- }
-
- /// Set the white point to be used for conversion.
- /// \param white White point to use.
-
- void SetWhiteXY (const dng_xy_coord &white)
- {
- fWhiteXY = white;
- }
-
- /// Get the white point to be used for conversion.
- /// \retval White point to use.
-
- const dng_xy_coord WhiteXY () const
- {
- return fWhiteXY;
- }
-
- /// Set exposure compensation.
- /// \param exposure Compensation value in stops, positive or negative.
-
- void SetExposure (real64 exposure)
- {
- fExposure = exposure;
- }
-
- /// Get exposure compensation.
- /// \retval Compensation value in stops, positive or negative.
-
- real64 Exposure () const
- {
- return fExposure;
- }
-
- /// Set shadow clip amount.
- /// \param shadows Shadow clip amount.
-
- void SetShadows (real64 shadows)
- {
- fShadows = shadows;
- }
-
- /// Get shadow clip amount.
- /// \retval Shadow clip amount.
-
- real64 Shadows () const
- {
- return fShadows;
- }
-
- /// Set custom tone curve for conversion.
- /// \param curve 1D function that defines tone mapping to use during conversion.
-
- void SetToneCurve (const dng_1d_function &curve)
- {
- fToneCurve = &curve;
- }
-
- /// Get custom tone curve for conversion.
- /// \retval 1D function that defines tone mapping to use during conversion.
-
- const dng_1d_function & ToneCurve () const
- {
- return *fToneCurve;
- }
-
- /// Set final color space in which resulting image data should be represented.
- /// (See dng_color_space.h for possible values.)
- /// \param space Color space to use.
-
- void SetFinalSpace (const dng_color_space &space)
- {
- fFinalSpace = &space;
- }
-
- /// Get final color space in which resulting image data should be represented.
- /// \retval Color space to use.
-
- const dng_color_space & FinalSpace () const
- {
- return *fFinalSpace;
- }
-
- /// Set pixel type of final image data.
- /// Can be ttByte (default), ttShort, or ttFloat.
- /// \param type Pixel type to use.
-
- void SetFinalPixelType (uint32 type)
- {
- fFinalPixelType = type;
- }
-
- /// Get pixel type of final image data.
- /// Can be ttByte (default), ttShort, or ttFloat.
- /// \retval Pixel type to use.
-
- uint32 FinalPixelType () const
- {
- return fFinalPixelType;
- }
-
- /// Set maximum dimension, in pixels, of resulting image.
- /// If final image would have either dimension larger than maximum, the larger
- /// of the two dimensions is set to this maximum size and the smaller dimension
- /// is adjusted to preserve aspect ratio.
- /// \param size Maximum size to allow.
-
- void SetMaximumSize (uint32 size)
- {
- fMaximumSize = size;
- }
-
- /// Get maximum dimension, in pixels, of resulting image.
- /// If the final image would have either dimension larger than this maximum, the larger
- /// of the two dimensions is set to this maximum size and the smaller dimension
- /// is adjusted to preserve the image's aspect ratio.
- /// \retval Maximum allowed size.
-
- uint32 MaximumSize () const
- {
- return fMaximumSize;
- }
-
- /// Actually render a digital negative to a displayable image.
- /// Input digital negative is passed to the constructor of this dng_render class.
- /// \retval The final resulting image.
-
- virtual dng_image * Render ();
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_render (const dng_render &render);
-
- dng_render & operator= (const dng_render &render);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_render.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Classes for conversion of RAW data to final image.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_render__
+#define __dng_render__
+
+/*****************************************************************************/
+
+#include "dng_1d_function.h"
+#include "dng_auto_ptr.h"
+#include "dng_classes.h"
+#include "dng_spline.h"
+#include "dng_xy_coord.h"
+
+/******************************************************************************/
+
+/// \brief Curve for pre-exposure-compensation adjustment based on noise floor,
+/// shadows, and highlight level.
+
+class dng_function_exposure_ramp: public dng_1d_function
+ {
+
+ public:
+
+ real64 fSlope; // Slope of straight segment.
+
+ real64 fBlack; // Intercept of straight segment.
+
+ real64 fRadius; // Rounding radius.
+
+ real64 fQScale; // Quadradic scale.
+
+ public:
+
+ dng_function_exposure_ramp (real64 white,
+ real64 black,
+ real64 minBlack);
+
+ virtual real64 Evaluate (real64 x) const;
+
+ };
+
+/******************************************************************************/
+
+/// \brief Exposure compensation curve for a given compensation amount in stops using
+/// quadric for roll-off.
+
+class dng_function_exposure_tone: public dng_1d_function
+ {
+
+ protected:
+
+ bool fIsNOP; // Is this a NOP function?
+
+ real64 fSlope; // Slope for lower part of curve.
+
+ real64 a; // Quadradic parameters for upper two f-stops.
+ real64 b;
+ real64 c;
+
+ public:
+
+ dng_function_exposure_tone (real64 exposure);
+
+ /// Returns output value for a given input tone.
+
+ virtual real64 Evaluate (real64 x) const;
+
+ };
+
+/*****************************************************************************/
+
+/// Default ACR3 tone curve.
+
+class dng_tone_curve_acr3_default: public dng_1d_function
+ {
+
+ public:
+
+ /// Returns output value for a given input tone.
+
+ virtual real64 Evaluate (real64 x) const;
+
+ /// Returns nearest input value for a given output tone.
+
+ virtual real64 EvaluateInverse (real64 x) const;
+
+ static const dng_1d_function & Get ();
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Encoding gamma curve for a given color space.
+
+class dng_function_gamma_encode: public dng_1d_function
+ {
+
+ protected:
+
+ const dng_color_space &fSpace;
+
+ public:
+
+ dng_function_gamma_encode (const dng_color_space &space);
+
+ virtual real64 Evaluate (real64 x) const;
+
+ };
+
+/*****************************************************************************/
+
+/// \brief Class used to render digital negative to displayable image.
+
+class dng_render
+ {
+
+ protected:
+
+ dng_host &fHost;
+
+ const dng_negative &fNegative;
+
+ dng_xy_coord fWhiteXY;
+
+ real64 fExposure;
+
+ real64 fShadows;
+
+ const dng_1d_function *fToneCurve;
+
+ const dng_color_space *fFinalSpace;
+
+ uint32 fFinalPixelType;
+
+ uint32 fMaximumSize;
+
+ private:
+
+ AutoPtr<dng_spline_solver> fProfileToneCurve;
+
+ public:
+
+ /// Construct a rendering instance that will be used to convert a given digital negative.
+ /// \param host The host to use for memory allocation, progress updates, and abort testing.
+ /// \param negative The digital negative to convert to a displayable image.
+
+ dng_render (dng_host &host,
+ const dng_negative &negative);
+
+ virtual ~dng_render ()
+ {
+ }
+
+ /// Set the white point to be used for conversion.
+ /// \param white White point to use.
+
+ void SetWhiteXY (const dng_xy_coord &white)
+ {
+ fWhiteXY = white;
+ }
+
+ /// Get the white point to be used for conversion.
+ /// \retval White point to use.
+
+ const dng_xy_coord WhiteXY () const
+ {
+ return fWhiteXY;
+ }
+
+ /// Set exposure compensation.
+ /// \param exposure Compensation value in stops, positive or negative.
+
+ void SetExposure (real64 exposure)
+ {
+ fExposure = exposure;
+ }
+
+ /// Get exposure compensation.
+ /// \retval Compensation value in stops, positive or negative.
+
+ real64 Exposure () const
+ {
+ return fExposure;
+ }
+
+ /// Set shadow clip amount.
+ /// \param shadows Shadow clip amount.
+
+ void SetShadows (real64 shadows)
+ {
+ fShadows = shadows;
+ }
+
+ /// Get shadow clip amount.
+ /// \retval Shadow clip amount.
+
+ real64 Shadows () const
+ {
+ return fShadows;
+ }
+
+ /// Set custom tone curve for conversion.
+ /// \param curve 1D function that defines tone mapping to use during conversion.
+
+ void SetToneCurve (const dng_1d_function &curve)
+ {
+ fToneCurve = &curve;
+ }
+
+ /// Get custom tone curve for conversion.
+ /// \retval 1D function that defines tone mapping to use during conversion.
+
+ const dng_1d_function & ToneCurve () const
+ {
+ return *fToneCurve;
+ }
+
+ /// Set final color space in which resulting image data should be represented.
+ /// (See dng_color_space.h for possible values.)
+ /// \param space Color space to use.
+
+ void SetFinalSpace (const dng_color_space &space)
+ {
+ fFinalSpace = &space;
+ }
+
+ /// Get final color space in which resulting image data should be represented.
+ /// \retval Color space to use.
+
+ const dng_color_space & FinalSpace () const
+ {
+ return *fFinalSpace;
+ }
+
+ /// Set pixel type of final image data.
+ /// Can be ttByte (default), ttShort, or ttFloat.
+ /// \param type Pixel type to use.
+
+ void SetFinalPixelType (uint32 type)
+ {
+ fFinalPixelType = type;
+ }
+
+ /// Get pixel type of final image data.
+ /// Can be ttByte (default), ttShort, or ttFloat.
+ /// \retval Pixel type to use.
+
+ uint32 FinalPixelType () const
+ {
+ return fFinalPixelType;
+ }
+
+ /// Set maximum dimension, in pixels, of resulting image.
+ /// If final image would have either dimension larger than maximum, the larger
+ /// of the two dimensions is set to this maximum size and the smaller dimension
+ /// is adjusted to preserve aspect ratio.
+ /// \param size Maximum size to allow.
+
+ void SetMaximumSize (uint32 size)
+ {
+ fMaximumSize = size;
+ }
+
+ /// Get maximum dimension, in pixels, of resulting image.
+ /// If the final image would have either dimension larger than this maximum, the larger
+ /// of the two dimensions is set to this maximum size and the smaller dimension
+ /// is adjusted to preserve the image's aspect ratio.
+ /// \retval Maximum allowed size.
+
+ uint32 MaximumSize () const
+ {
+ return fMaximumSize;
+ }
+
+ /// Actually render a digital negative to a displayable image.
+ /// Input digital negative is passed to the constructor of this dng_render class.
+ /// \retval The final resulting image.
+
+ virtual dng_image * Render ();
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_render (const dng_render &render);
+
+ dng_render & operator= (const dng_render &render);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_resample.h b/source/dng_resample.h
index 299302a..9116e6e 100644
--- a/source/dng_resample.h
+++ b/source/dng_resample.h
@@ -1,293 +1,293 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_resample.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_resample__
-#define __dng_resample__
-
-/*****************************************************************************/
-
-#include "dng_assertions.h"
-#include "dng_auto_ptr.h"
-#include "dng_classes.h"
-#include "dng_memory.h"
-#include "dng_point.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-class dng_resample_function
- {
-
- public:
-
- dng_resample_function ()
- {
- }
-
- virtual ~dng_resample_function ()
- {
- }
-
- virtual real64 Extent () const = 0;
-
- virtual real64 Evaluate (real64 x) const = 0;
-
- };
-
-/*****************************************************************************/
-
-class dng_resample_bicubic: public dng_resample_function
- {
-
- public:
-
- virtual real64 Extent () const;
-
- virtual real64 Evaluate (real64 x) const;
-
- static const dng_resample_function & Get ();
-
- };
-
-/******************************************************************************/
-
-const uint32 kResampleSubsampleBits = 7;
-const uint32 kResampleSubsampleCount = 1 << kResampleSubsampleBits;
-const uint32 kResampleSubsampleMask = kResampleSubsampleCount - 1;
-
-/*****************************************************************************/
-
-class dng_resample_coords
- {
-
- protected:
-
- int32 fOrigin;
-
- AutoPtr<dng_memory_block> fCoords;
-
- public:
-
- dng_resample_coords ();
-
- virtual ~dng_resample_coords ();
-
- void Initialize (int32 srcOrigin,
- int32 dstOrigin,
- uint32 srcCount,
- uint32 dstCount,
- dng_memory_allocator &allocator);
-
- const int32 * Coords (int32 index) const
- {
- return fCoords->Buffer_int32 () + (index - fOrigin);
- }
-
- const int32 Pixel (int32 index) const
- {
- return Coords (index) [0] >> kResampleSubsampleBits;
- }
-
- };
-
-/*****************************************************************************/
-
-class dng_resample_weights
- {
-
- protected:
-
- uint32 fRadius;
-
- uint32 fWeightStep;
-
- AutoPtr<dng_memory_block> fWeights32;
- AutoPtr<dng_memory_block> fWeights16;
-
- public:
-
- dng_resample_weights ();
-
- virtual ~dng_resample_weights ();
-
- void Initialize (real64 scale,
- const dng_resample_function &kernel,
- dng_memory_allocator &allocator);
-
- uint32 Radius () const
- {
- return fRadius;
- }
-
- uint32 Width () const
- {
- return fRadius * 2;
- }
-
- int32 Offset () const
- {
- return 1 - (int32) fRadius;
- }
-
- uint32 Step () const
- {
- return fWeightStep;
- }
-
- const real32 *Weights32 (uint32 fract) const
- {
-
- DNG_ASSERT (fWeights32->Buffer (), "Weights32 is NULL");
-
- if (fract >= kResampleSubsampleCount)
- {
-
- ThrowBadFormat ();
-
- }
-
- return fWeights32->Buffer_real32 () + fract * fWeightStep;
-
- }
-
- const int16 *Weights16 (uint32 fract) const
- {
-
- DNG_ASSERT (fWeights16->Buffer (), "Weights16 is NULL");
-
- if (fract >= kResampleSubsampleCount)
- {
-
- ThrowBadFormat ();
-
- }
-
- return fWeights16->Buffer_int16 () + fract * fWeightStep;
-
- }
-
- };
-
-/*****************************************************************************/
-
-const uint32 kResampleSubsampleBits2D = 5;
-const uint32 kResampleSubsampleCount2D = 1 << kResampleSubsampleBits2D;
-const uint32 kResampleSubsampleMask2D = kResampleSubsampleCount2D - 1;
-
-/*****************************************************************************/
-
-class dng_resample_weights_2d
- {
-
- protected:
-
- uint32 fRadius;
-
- uint32 fRowStep;
- uint32 fColStep;
-
- AutoPtr<dng_memory_block> fWeights32;
- AutoPtr<dng_memory_block> fWeights16;
-
- public:
-
- dng_resample_weights_2d ();
-
- virtual ~dng_resample_weights_2d ();
-
- void Initialize (const dng_resample_function &kernel,
- dng_memory_allocator &allocator);
-
- uint32 Radius () const
- {
- return fRadius;
- }
-
- uint32 Width () const
- {
- return fRadius * 2;
- }
-
- int32 Offset () const
- {
- return 1 - (int32) fRadius;
- }
-
- uint32 RowStep () const
- {
- return fRowStep;
- }
-
- uint32 ColStep () const
- {
- return fColStep;
- }
-
- const real32 *Weights32 (dng_point fract) const
- {
-
- DNG_ASSERT (fWeights32->Buffer (), "Weights32 is NULL");
-
- if (fract.v < 0 || fract.h < 0
- || fract.v >= static_cast<int32>(kResampleSubsampleCount2D)
- || fract.h >= static_cast<int32>(kResampleSubsampleCount2D))
- {
-
- ThrowBadFormat ();
-
- }
-
- const uint32 offset = fract.v * fRowStep + fract.h * fColStep;
-
- return fWeights32->Buffer_real32 () + offset;
-
- }
-
- const int16 *Weights16 (dng_point fract) const
- {
-
- DNG_ASSERT (fWeights16->Buffer (), "Weights16 is NULL");
-
- if (fract.v < 0 || fract.h < 0
- || fract.v >= static_cast<int32>(kResampleSubsampleCount2D)
- || fract.h >= static_cast<int32>(kResampleSubsampleCount2D))
- {
-
- ThrowBadFormat ();
-
- }
-
- const uint32 offset = fract.v * fRowStep + fract.h * fColStep;
-
- return fWeights16->Buffer_int16 () + offset;
-
- }
-
- };
-
-/*****************************************************************************/
-
-void ResampleImage (dng_host &host,
- const dng_image &srcImage,
- dng_image &dstImage,
- const dng_rect &srcBounds,
- const dng_rect &dstBounds,
- const dng_resample_function &kernel);
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_resample.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_resample__
+#define __dng_resample__
+
+/*****************************************************************************/
+
+#include "dng_assertions.h"
+#include "dng_auto_ptr.h"
+#include "dng_classes.h"
+#include "dng_memory.h"
+#include "dng_point.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+class dng_resample_function
+ {
+
+ public:
+
+ dng_resample_function ()
+ {
+ }
+
+ virtual ~dng_resample_function ()
+ {
+ }
+
+ virtual real64 Extent () const = 0;
+
+ virtual real64 Evaluate (real64 x) const = 0;
+
+ };
+
+/*****************************************************************************/
+
+class dng_resample_bicubic: public dng_resample_function
+ {
+
+ public:
+
+ virtual real64 Extent () const;
+
+ virtual real64 Evaluate (real64 x) const;
+
+ static const dng_resample_function & Get ();
+
+ };
+
+/******************************************************************************/
+
+const uint32 kResampleSubsampleBits = 7;
+const uint32 kResampleSubsampleCount = 1 << kResampleSubsampleBits;
+const uint32 kResampleSubsampleMask = kResampleSubsampleCount - 1;
+
+/*****************************************************************************/
+
+class dng_resample_coords
+ {
+
+ protected:
+
+ int32 fOrigin;
+
+ AutoPtr<dng_memory_block> fCoords;
+
+ public:
+
+ dng_resample_coords ();
+
+ virtual ~dng_resample_coords ();
+
+ void Initialize (int32 srcOrigin,
+ int32 dstOrigin,
+ uint32 srcCount,
+ uint32 dstCount,
+ dng_memory_allocator &allocator);
+
+ const int32 * Coords (int32 index) const
+ {
+ return fCoords->Buffer_int32 () + (index - fOrigin);
+ }
+
+ const int32 Pixel (int32 index) const
+ {
+ return Coords (index) [0] >> kResampleSubsampleBits;
+ }
+
+ };
+
+/*****************************************************************************/
+
+class dng_resample_weights
+ {
+
+ protected:
+
+ uint32 fRadius;
+
+ uint32 fWeightStep;
+
+ AutoPtr<dng_memory_block> fWeights32;
+ AutoPtr<dng_memory_block> fWeights16;
+
+ public:
+
+ dng_resample_weights ();
+
+ virtual ~dng_resample_weights ();
+
+ void Initialize (real64 scale,
+ const dng_resample_function &kernel,
+ dng_memory_allocator &allocator);
+
+ uint32 Radius () const
+ {
+ return fRadius;
+ }
+
+ uint32 Width () const
+ {
+ return fRadius * 2;
+ }
+
+ int32 Offset () const
+ {
+ return 1 - (int32) fRadius;
+ }
+
+ uint32 Step () const
+ {
+ return fWeightStep;
+ }
+
+ const real32 *Weights32 (uint32 fract) const
+ {
+
+ DNG_ASSERT (fWeights32->Buffer (), "Weights32 is NULL");
+
+ if (fract >= kResampleSubsampleCount)
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ return fWeights32->Buffer_real32 () + fract * fWeightStep;
+
+ }
+
+ const int16 *Weights16 (uint32 fract) const
+ {
+
+ DNG_ASSERT (fWeights16->Buffer (), "Weights16 is NULL");
+
+ if (fract >= kResampleSubsampleCount)
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ return fWeights16->Buffer_int16 () + fract * fWeightStep;
+
+ }
+
+ };
+
+/*****************************************************************************/
+
+const uint32 kResampleSubsampleBits2D = 5;
+const uint32 kResampleSubsampleCount2D = 1 << kResampleSubsampleBits2D;
+const uint32 kResampleSubsampleMask2D = kResampleSubsampleCount2D - 1;
+
+/*****************************************************************************/
+
+class dng_resample_weights_2d
+ {
+
+ protected:
+
+ uint32 fRadius;
+
+ uint32 fRowStep;
+ uint32 fColStep;
+
+ AutoPtr<dng_memory_block> fWeights32;
+ AutoPtr<dng_memory_block> fWeights16;
+
+ public:
+
+ dng_resample_weights_2d ();
+
+ virtual ~dng_resample_weights_2d ();
+
+ void Initialize (const dng_resample_function &kernel,
+ dng_memory_allocator &allocator);
+
+ uint32 Radius () const
+ {
+ return fRadius;
+ }
+
+ uint32 Width () const
+ {
+ return fRadius * 2;
+ }
+
+ int32 Offset () const
+ {
+ return 1 - (int32) fRadius;
+ }
+
+ uint32 RowStep () const
+ {
+ return fRowStep;
+ }
+
+ uint32 ColStep () const
+ {
+ return fColStep;
+ }
+
+ const real32 *Weights32 (dng_point fract) const
+ {
+
+ DNG_ASSERT (fWeights32->Buffer (), "Weights32 is NULL");
+
+ if (fract.v < 0 || fract.h < 0
+ || fract.v >= static_cast<int32>(kResampleSubsampleCount2D)
+ || fract.h >= static_cast<int32>(kResampleSubsampleCount2D))
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ const uint32 offset = fract.v * fRowStep + fract.h * fColStep;
+
+ return fWeights32->Buffer_real32 () + offset;
+
+ }
+
+ const int16 *Weights16 (dng_point fract) const
+ {
+
+ DNG_ASSERT (fWeights16->Buffer (), "Weights16 is NULL");
+
+ if (fract.v < 0 || fract.h < 0
+ || fract.v >= static_cast<int32>(kResampleSubsampleCount2D)
+ || fract.h >= static_cast<int32>(kResampleSubsampleCount2D))
+ {
+
+ ThrowBadFormat ();
+
+ }
+
+ const uint32 offset = fract.v * fRowStep + fract.h * fColStep;
+
+ return fWeights16->Buffer_int16 () + offset;
+
+ }
+
+ };
+
+/*****************************************************************************/
+
+void ResampleImage (dng_host &host,
+ const dng_image &srcImage,
+ dng_image &dstImage,
+ const dng_rect &srcBounds,
+ const dng_rect &dstBounds,
+ const dng_resample_function &kernel);
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_sdk_limits.h b/source/dng_sdk_limits.h
index e4feed7..4e393f5 100644
--- a/source/dng_sdk_limits.h
+++ b/source/dng_sdk_limits.h
@@ -1,78 +1,78 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_sdk_limits.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Collection of constants detailing maximum values used in processing in the DNG SDK.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_sdk_limits__
-#define __dng_sdk_limits__
-
-/*****************************************************************************/
-
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-/// The maximum number of previews (in addition to the main IFD's thumbnail)
-/// that we support embedded in a DNG.
-
-const uint32 kMaxDNGPreviews = 20;
-
-/// The maximum number of SubIFDs that will be parsed.
-
-const uint32 kMaxSubIFDs = kMaxDNGPreviews + 1;
-
-/// The maximum number of chained IFDs that will be parsed.
-
-const uint32 kMaxChainedIFDs = 10;
-
-/// The maximum number of samples per pixel.
-
-const uint32 kMaxSamplesPerPixel = 4;
-
-/// Maximum number of color planes.
-
-const uint32 kMaxColorPlanes = kMaxSamplesPerPixel;
-
-/// The maximum size of a CFA repeating pattern.
-
-const uint32 kMaxCFAPattern = 8;
-
-/// The maximum size of a black level repeating pattern.
-
-const uint32 kMaxBlackPattern = 8;
-
-/// The maximum number of masked area rectangles.
-
-const uint32 kMaxMaskedAreas = 4;
-
-/// The maximum image size supported (pixels per side).
-
-const uint32 kMaxImageSide = 65000;
-
-/// Maximum number of MP threads for dng_area_task operations.
-
-#if qDNG64Bit
-const uint32 kMaxMPThreads = 32;
-#else
-const uint32 kMaxMPThreads = 8;
-#endif
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_sdk_limits.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Collection of constants detailing maximum values used in processing in the DNG SDK.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_sdk_limits__
+#define __dng_sdk_limits__
+
+/*****************************************************************************/
+
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+/// The maximum number of previews (in addition to the main IFD's thumbnail)
+/// that we support embedded in a DNG.
+
+const uint32 kMaxDNGPreviews = 20;
+
+/// The maximum number of SubIFDs that will be parsed.
+
+const uint32 kMaxSubIFDs = kMaxDNGPreviews + 1;
+
+/// The maximum number of chained IFDs that will be parsed.
+
+const uint32 kMaxChainedIFDs = 10;
+
+/// The maximum number of samples per pixel.
+
+const uint32 kMaxSamplesPerPixel = 4;
+
+/// Maximum number of color planes.
+
+const uint32 kMaxColorPlanes = kMaxSamplesPerPixel;
+
+/// The maximum size of a CFA repeating pattern.
+
+const uint32 kMaxCFAPattern = 8;
+
+/// The maximum size of a black level repeating pattern.
+
+const uint32 kMaxBlackPattern = 8;
+
+/// The maximum number of masked area rectangles.
+
+const uint32 kMaxMaskedAreas = 4;
+
+/// The maximum image size supported (pixels per side).
+
+const uint32 kMaxImageSide = 65000;
+
+/// Maximum number of MP threads for dng_area_task operations.
+
+#if qDNG64Bit
+const uint32 kMaxMPThreads = 32;
+#else
+const uint32 kMaxMPThreads = 8;
+#endif
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_shared.h b/source/dng_shared.h
index 2ad586f..41a50e8 100644
--- a/source/dng_shared.h
+++ b/source/dng_shared.h
@@ -1,249 +1,249 @@
-/*****************************************************************************/
-// Copyright 2006-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_shared.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_shared__
-#define __dng_shared__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_fingerprint.h"
-#include "dng_matrix.h"
-#include "dng_memory.h"
-#include "dng_negative.h"
-#include "dng_rational.h"
-#include "dng_string.h"
-#include "dng_stream.h"
-#include "dng_sdk_limits.h"
-#include "dng_types.h"
-#include "dng_xy_coord.h"
-
-#include <vector>
-
-/*****************************************************************************/
-
-class dng_camera_profile_info
- {
-
- public:
-
- bool fBigEndian;
-
- uint32 fColorPlanes;
-
- uint32 fCalibrationIlluminant1;
- uint32 fCalibrationIlluminant2;
-
- dng_matrix fColorMatrix1;
- dng_matrix fColorMatrix2;
-
- dng_matrix fForwardMatrix1;
- dng_matrix fForwardMatrix2;
-
- dng_matrix fReductionMatrix1;
- dng_matrix fReductionMatrix2;
-
- dng_string fProfileCalibrationSignature;
-
- dng_string fProfileName;
-
- dng_string fProfileCopyright;
-
- uint32 fEmbedPolicy;
-
- uint32 fProfileHues;
- uint32 fProfileSats;
- uint32 fProfileVals;
-
- uint64 fHueSatDeltas1Offset;
- uint32 fHueSatDeltas1Count;
-
- uint64 fHueSatDeltas2Offset;
- uint32 fHueSatDeltas2Count;
-
- uint32 fHueSatMapEncoding;
-
- uint32 fLookTableHues;
- uint32 fLookTableSats;
- uint32 fLookTableVals;
-
- uint64 fLookTableOffset;
- uint32 fLookTableCount;
-
- uint32 fLookTableEncoding;
-
- dng_srational fBaselineExposureOffset;
-
- uint32 fDefaultBlackRender;
-
- uint64 fToneCurveOffset;
- uint32 fToneCurveCount;
-
- dng_string fUniqueCameraModel;
-
- public:
-
- dng_camera_profile_info ();
-
- ~dng_camera_profile_info ();
-
- bool ParseTag (dng_stream &stream,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- bool ParseExtended (dng_stream &stream);
-
- };
-
-/*****************************************************************************/
-
-class dng_shared
- {
-
- public:
-
- uint64 fExifIFD;
- uint64 fGPSInfo;
- uint64 fInteroperabilityIFD;
- uint64 fKodakDCRPrivateIFD;
- uint64 fKodakKDCPrivateIFD;
-
- uint32 fXMPCount;
- uint64 fXMPOffset;
-
- uint32 fIPTC_NAA_Count;
- uint64 fIPTC_NAA_Offset;
-
- uint32 fMakerNoteCount;
- uint64 fMakerNoteOffset;
- uint32 fMakerNoteSafety;
-
- uint32 fDNGVersion;
- uint32 fDNGBackwardVersion;
-
- dng_string fUniqueCameraModel;
- dng_string fLocalizedCameraModel;
-
- dng_camera_profile_info fCameraProfile;
-
- dng_std_vector<dng_camera_profile_info> fExtraCameraProfiles;
-
- dng_matrix fCameraCalibration1;
- dng_matrix fCameraCalibration2;
-
- dng_string fCameraCalibrationSignature;
-
- dng_vector fAnalogBalance;
-
- dng_vector fAsShotNeutral;
-
- dng_xy_coord fAsShotWhiteXY;
-
- dng_srational fBaselineExposure;
- dng_urational fBaselineNoise;
- dng_urational fNoiseReductionApplied;
- dng_urational fBaselineSharpness;
- dng_urational fLinearResponseLimit;
- dng_urational fShadowScale;
-
- bool fHasBaselineExposure;
- bool fHasShadowScale;
-
- uint32 fDNGPrivateDataCount;
- uint64 fDNGPrivateDataOffset;
-
- dng_fingerprint fRawImageDigest;
- dng_fingerprint fNewRawImageDigest;
-
- dng_fingerprint fRawDataUniqueID;
-
- dng_string fOriginalRawFileName;
-
- uint32 fOriginalRawFileDataCount;
- uint64 fOriginalRawFileDataOffset;
-
- dng_fingerprint fOriginalRawFileDigest;
-
- uint32 fAsShotICCProfileCount;
- uint64 fAsShotICCProfileOffset;
-
- dng_matrix fAsShotPreProfileMatrix;
-
- uint32 fCurrentICCProfileCount;
- uint64 fCurrentICCProfileOffset;
-
- dng_matrix fCurrentPreProfileMatrix;
-
- uint32 fColorimetricReference;
-
- dng_string fAsShotProfileName;
-
- dng_noise_profile fNoiseProfile;
-
- dng_point fOriginalDefaultFinalSize;
- dng_point fOriginalBestQualityFinalSize;
-
- dng_urational fOriginalDefaultCropSizeH;
- dng_urational fOriginalDefaultCropSizeV;
-
- public:
-
- dng_shared ();
-
- virtual ~dng_shared ();
-
- virtual bool ParseTag (dng_stream &stream,
- dng_exif &exif,
- uint32 parentCode,
- bool isMainIFD,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset,
- int64 offsetDelta);
-
- virtual void PostParse (dng_host &host,
- dng_exif &exif);
-
- virtual bool IsValidDNG ();
-
- protected:
-
- virtual bool Parse_ifd0 (dng_stream &stream,
- dng_exif &exif,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- virtual bool Parse_ifd0_exif (dng_stream &stream,
- dng_exif &exif,
- uint32 parentCode,
- uint32 tagCode,
- uint32 tagType,
- uint32 tagCount,
- uint64 tagOffset);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_shared.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_shared__
+#define __dng_shared__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_fingerprint.h"
+#include "dng_matrix.h"
+#include "dng_memory.h"
+#include "dng_negative.h"
+#include "dng_rational.h"
+#include "dng_string.h"
+#include "dng_stream.h"
+#include "dng_sdk_limits.h"
+#include "dng_types.h"
+#include "dng_xy_coord.h"
+
+#include <vector>
+
+/*****************************************************************************/
+
+class dng_camera_profile_info
+ {
+
+ public:
+
+ bool fBigEndian;
+
+ uint32 fColorPlanes;
+
+ uint32 fCalibrationIlluminant1;
+ uint32 fCalibrationIlluminant2;
+
+ dng_matrix fColorMatrix1;
+ dng_matrix fColorMatrix2;
+
+ dng_matrix fForwardMatrix1;
+ dng_matrix fForwardMatrix2;
+
+ dng_matrix fReductionMatrix1;
+ dng_matrix fReductionMatrix2;
+
+ dng_string fProfileCalibrationSignature;
+
+ dng_string fProfileName;
+
+ dng_string fProfileCopyright;
+
+ uint32 fEmbedPolicy;
+
+ uint32 fProfileHues;
+ uint32 fProfileSats;
+ uint32 fProfileVals;
+
+ uint64 fHueSatDeltas1Offset;
+ uint32 fHueSatDeltas1Count;
+
+ uint64 fHueSatDeltas2Offset;
+ uint32 fHueSatDeltas2Count;
+
+ uint32 fHueSatMapEncoding;
+
+ uint32 fLookTableHues;
+ uint32 fLookTableSats;
+ uint32 fLookTableVals;
+
+ uint64 fLookTableOffset;
+ uint32 fLookTableCount;
+
+ uint32 fLookTableEncoding;
+
+ dng_srational fBaselineExposureOffset;
+
+ uint32 fDefaultBlackRender;
+
+ uint64 fToneCurveOffset;
+ uint32 fToneCurveCount;
+
+ dng_string fUniqueCameraModel;
+
+ public:
+
+ dng_camera_profile_info ();
+
+ ~dng_camera_profile_info ();
+
+ bool ParseTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ bool ParseExtended (dng_stream &stream);
+
+ };
+
+/*****************************************************************************/
+
+class dng_shared
+ {
+
+ public:
+
+ uint64 fExifIFD;
+ uint64 fGPSInfo;
+ uint64 fInteroperabilityIFD;
+ uint64 fKodakDCRPrivateIFD;
+ uint64 fKodakKDCPrivateIFD;
+
+ uint32 fXMPCount;
+ uint64 fXMPOffset;
+
+ uint32 fIPTC_NAA_Count;
+ uint64 fIPTC_NAA_Offset;
+
+ uint32 fMakerNoteCount;
+ uint64 fMakerNoteOffset;
+ uint32 fMakerNoteSafety;
+
+ uint32 fDNGVersion;
+ uint32 fDNGBackwardVersion;
+
+ dng_string fUniqueCameraModel;
+ dng_string fLocalizedCameraModel;
+
+ dng_camera_profile_info fCameraProfile;
+
+ dng_std_vector<dng_camera_profile_info> fExtraCameraProfiles;
+
+ dng_matrix fCameraCalibration1;
+ dng_matrix fCameraCalibration2;
+
+ dng_string fCameraCalibrationSignature;
+
+ dng_vector fAnalogBalance;
+
+ dng_vector fAsShotNeutral;
+
+ dng_xy_coord fAsShotWhiteXY;
+
+ dng_srational fBaselineExposure;
+ dng_urational fBaselineNoise;
+ dng_urational fNoiseReductionApplied;
+ dng_urational fBaselineSharpness;
+ dng_urational fLinearResponseLimit;
+ dng_urational fShadowScale;
+
+ bool fHasBaselineExposure;
+ bool fHasShadowScale;
+
+ uint32 fDNGPrivateDataCount;
+ uint64 fDNGPrivateDataOffset;
+
+ dng_fingerprint fRawImageDigest;
+ dng_fingerprint fNewRawImageDigest;
+
+ dng_fingerprint fRawDataUniqueID;
+
+ dng_string fOriginalRawFileName;
+
+ uint32 fOriginalRawFileDataCount;
+ uint64 fOriginalRawFileDataOffset;
+
+ dng_fingerprint fOriginalRawFileDigest;
+
+ uint32 fAsShotICCProfileCount;
+ uint64 fAsShotICCProfileOffset;
+
+ dng_matrix fAsShotPreProfileMatrix;
+
+ uint32 fCurrentICCProfileCount;
+ uint64 fCurrentICCProfileOffset;
+
+ dng_matrix fCurrentPreProfileMatrix;
+
+ uint32 fColorimetricReference;
+
+ dng_string fAsShotProfileName;
+
+ dng_noise_profile fNoiseProfile;
+
+ dng_point fOriginalDefaultFinalSize;
+ dng_point fOriginalBestQualityFinalSize;
+
+ dng_urational fOriginalDefaultCropSizeH;
+ dng_urational fOriginalDefaultCropSizeV;
+
+ public:
+
+ dng_shared ();
+
+ virtual ~dng_shared ();
+
+ virtual bool ParseTag (dng_stream &stream,
+ dng_exif &exif,
+ uint32 parentCode,
+ bool isMainIFD,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset,
+ int64 offsetDelta);
+
+ virtual void PostParse (dng_host &host,
+ dng_exif &exif);
+
+ virtual bool IsValidDNG ();
+
+ protected:
+
+ virtual bool Parse_ifd0 (dng_stream &stream,
+ dng_exif &exif,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ virtual bool Parse_ifd0_exif (dng_stream &stream,
+ dng_exif &exif,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint64 tagOffset);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_simple_image.h b/source/dng_simple_image.h
index 006337d..e5afddf 100644
--- a/source/dng_simple_image.h
+++ b/source/dng_simple_image.h
@@ -1,82 +1,82 @@
-/*****************************************************************************/
-// Copyright 2006-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_simple_image.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_simple_image__
-#define __dng_simple_image__
-
-/*****************************************************************************/
-
-#include "dng_auto_ptr.h"
-#include "dng_image.h"
-#include "dng_pixel_buffer.h"
-
-/*****************************************************************************/
-
-/// dng_image derived class with simple Trim and Rotate functionality.
-
-class dng_simple_image : public dng_image
- {
-
- protected:
-
- dng_pixel_buffer fBuffer;
-
- AutoPtr<dng_memory_block> fMemory;
-
- dng_memory_allocator &fAllocator;
-
- public:
-
- dng_simple_image (const dng_rect &bounds,
- uint32 planes,
- uint32 pixelType,
- dng_memory_allocator &allocator);
-
- virtual ~dng_simple_image ();
-
- virtual dng_image * Clone () const;
-
- /// Setter for pixel type.
-
- virtual void SetPixelType (uint32 pixelType);
-
- /// Trim image data outside of given bounds. Memory is not reallocated or freed.
-
- virtual void Trim (const dng_rect &r);
-
- /// Rotate image according to orientation.
-
- virtual void Rotate (const dng_orientation &orientation);
-
- /// Get the buffer for direct processing. (Unique to dng_simple_image.)
-
- void GetPixelBuffer (dng_pixel_buffer &buffer)
- {
- buffer = fBuffer;
- }
-
- protected:
-
- virtual void AcquireTileBuffer (dng_tile_buffer &buffer,
- const dng_rect &area,
- bool dirty) const;
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_simple_image.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_simple_image__
+#define __dng_simple_image__
+
+/*****************************************************************************/
+
+#include "dng_auto_ptr.h"
+#include "dng_image.h"
+#include "dng_pixel_buffer.h"
+
+/*****************************************************************************/
+
+/// dng_image derived class with simple Trim and Rotate functionality.
+
+class dng_simple_image : public dng_image
+ {
+
+ protected:
+
+ dng_pixel_buffer fBuffer;
+
+ AutoPtr<dng_memory_block> fMemory;
+
+ dng_memory_allocator &fAllocator;
+
+ public:
+
+ dng_simple_image (const dng_rect &bounds,
+ uint32 planes,
+ uint32 pixelType,
+ dng_memory_allocator &allocator);
+
+ virtual ~dng_simple_image ();
+
+ virtual dng_image * Clone () const;
+
+ /// Setter for pixel type.
+
+ virtual void SetPixelType (uint32 pixelType);
+
+ /// Trim image data outside of given bounds. Memory is not reallocated or freed.
+
+ virtual void Trim (const dng_rect &r);
+
+ /// Rotate image according to orientation.
+
+ virtual void Rotate (const dng_orientation &orientation);
+
+ /// Get the buffer for direct processing. (Unique to dng_simple_image.)
+
+ void GetPixelBuffer (dng_pixel_buffer &buffer)
+ {
+ buffer = fBuffer;
+ }
+
+ protected:
+
+ virtual void AcquireTileBuffer (dng_tile_buffer &buffer,
+ const dng_rect &area,
+ bool dirty) const;
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_spline.cpp b/source/dng_spline.cpp
index 44a21a4..165b985 100644
--- a/source/dng_spline.cpp
+++ b/source/dng_spline.cpp
@@ -1,233 +1,233 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_spline.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_spline.h"
-
-#include "dng_assertions.h"
-#include "dng_exceptions.h"
-
-/******************************************************************************/
-
-dng_spline_solver::dng_spline_solver ()
-
- : X ()
- , Y ()
- , S ()
-
- {
-
- }
-
-/******************************************************************************/
-
-dng_spline_solver::~dng_spline_solver ()
- {
-
- }
-
-/******************************************************************************/
-
-void dng_spline_solver::Reset ()
- {
-
- X.clear ();
- Y.clear ();
-
- S.clear ();
-
- }
-
-/******************************************************************************/
-
-void dng_spline_solver::Add (real64 x, real64 y)
- {
-
- X.push_back (x);
- Y.push_back (y);
-
- }
-
-/******************************************************************************/
-
-void dng_spline_solver::Solve ()
- {
-
- // This code computes the unique curve such that:
- // It is C0, C1, and C2 continuous
- // The second derivative is zero at the end points
-
- int32 count = (int32) X.size ();
-
- DNG_ASSERT (count >= 2, "Too few points");
-
- int32 start = 0;
- int32 end = count;
-
- real64 A = X [start+1] - X [start];
- real64 B = (Y [start+1] - Y [start]) / A;
-
- S.resize (count);
-
- S [start] = B;
-
- int32 j;
-
- // Slopes here are a weighted average of the slopes
- // to each of the adjcent control points.
-
- for (j = start + 2; j < end; ++j)
- {
-
- real64 C = X [j] - X [j-1];
- real64 D = (Y [j] - Y [j-1]) / C;
-
- S [j-1] = (B * C + D * A) / (A + C);
-
- A = C;
- B = D;
-
- }
-
- S [end-1] = 2.0 * B - S [end-2];
- S [start] = 2.0 * S [start] - S [start+1];
-
- if ((end - start) > 2)
- {
-
- dng_std_vector<real64> E;
- dng_std_vector<real64> F;
- dng_std_vector<real64> G;
-
- E.resize (count);
- F.resize (count);
- G.resize (count);
-
- F [start] = 0.5;
- E [end-1] = 0.5;
- G [start] = 0.75 * (S [start] + S [start+1]);
- G [end-1] = 0.75 * (S [end-2] + S [end-1]);
-
- for (j = start+1; j < end - 1; ++j)
- {
-
- A = (X [j+1] - X [j-1]) * 2.0;
-
- E [j] = (X [j+1] - X [j]) / A;
- F [j] = (X [j] - X [j-1]) / A;
- G [j] = 1.5 * S [j];
-
- }
-
- for (j = start+1; j < end; ++j)
- {
-
- A = 1.0 - F [j-1] * E [j];
-
- if (j != end-1) F [j] /= A;
-
- G [j] = (G [j] - G [j-1] * E [j]) / A;
-
- }
-
- for (j = end - 2; j >= start; --j)
- G [j] = G [j] - F [j] * G [j+1];
-
- for (j = start; j < end; ++j)
- S [j] = G [j];
-
- }
-
- }
-
-/******************************************************************************/
-
-bool dng_spline_solver::IsIdentity () const
- {
-
- int32 count = (int32) X.size ();
-
- if (count != 2)
- return false;
-
- if (X [0] != 0.0 || X [1] != 1.0 ||
- Y [0] != 0.0 || Y [1] != 1.0)
- return false;
-
- return true;
-
- }
-
-/******************************************************************************/
-
-real64 dng_spline_solver::Evaluate (real64 x) const
- {
-
- int32 count = (int32) X.size ();
-
- // Check for off each end of point list.
-
- if (x <= X [0])
- return Y [0];
-
- if (x >= X [count-1])
- return Y [count-1];
-
- // Binary search for the index.
-
- int32 lower = 1;
- int32 upper = count - 1;
-
- while (upper > lower)
- {
-
- int32 mid = (lower + upper) >> 1;
-
- if (x == X [mid])
- {
- return Y [mid];
- }
-
- if (x > X [mid])
- lower = mid + 1;
- else
- upper = mid;
-
- }
-
- DNG_ASSERT (upper == lower, "Binary search error in point list");
-
- int32 j = lower;
-
- // X [j - 1] < x <= X [j]
- // A is the distance between the X [j] and X [j - 1]
- // B and C describe the fractional distance to either side. B + C = 1.
-
- // We compute a cubic spline between the two points with slopes
- // S[j-1] and S[j] at either end. Specifically, we compute the 1-D Bezier
- // with control values:
- //
- // Y[j-1], Y[j-1] + S[j-1]*A, Y[j]-S[j]*A, Y[j]
-
- return EvaluateSplineSegment (x,
- X [j - 1],
- Y [j - 1],
- S [j - 1],
- X [j ],
- Y [j ],
- S [j ]);
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_spline.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_spline.h"
+
+#include "dng_assertions.h"
+#include "dng_exceptions.h"
+
+/******************************************************************************/
+
+dng_spline_solver::dng_spline_solver ()
+
+ : X ()
+ , Y ()
+ , S ()
+
+ {
+
+ }
+
+/******************************************************************************/
+
+dng_spline_solver::~dng_spline_solver ()
+ {
+
+ }
+
+/******************************************************************************/
+
+void dng_spline_solver::Reset ()
+ {
+
+ X.clear ();
+ Y.clear ();
+
+ S.clear ();
+
+ }
+
+/******************************************************************************/
+
+void dng_spline_solver::Add (real64 x, real64 y)
+ {
+
+ X.push_back (x);
+ Y.push_back (y);
+
+ }
+
+/******************************************************************************/
+
+void dng_spline_solver::Solve ()
+ {
+
+ // This code computes the unique curve such that:
+ // It is C0, C1, and C2 continuous
+ // The second derivative is zero at the end points
+
+ int32 count = (int32) X.size ();
+
+ DNG_ASSERT (count >= 2, "Too few points");
+
+ int32 start = 0;
+ int32 end = count;
+
+ real64 A = X [start+1] - X [start];
+ real64 B = (Y [start+1] - Y [start]) / A;
+
+ S.resize (count);
+
+ S [start] = B;
+
+ int32 j;
+
+ // Slopes here are a weighted average of the slopes
+ // to each of the adjcent control points.
+
+ for (j = start + 2; j < end; ++j)
+ {
+
+ real64 C = X [j] - X [j-1];
+ real64 D = (Y [j] - Y [j-1]) / C;
+
+ S [j-1] = (B * C + D * A) / (A + C);
+
+ A = C;
+ B = D;
+
+ }
+
+ S [end-1] = 2.0 * B - S [end-2];
+ S [start] = 2.0 * S [start] - S [start+1];
+
+ if ((end - start) > 2)
+ {
+
+ dng_std_vector<real64> E;
+ dng_std_vector<real64> F;
+ dng_std_vector<real64> G;
+
+ E.resize (count);
+ F.resize (count);
+ G.resize (count);
+
+ F [start] = 0.5;
+ E [end-1] = 0.5;
+ G [start] = 0.75 * (S [start] + S [start+1]);
+ G [end-1] = 0.75 * (S [end-2] + S [end-1]);
+
+ for (j = start+1; j < end - 1; ++j)
+ {
+
+ A = (X [j+1] - X [j-1]) * 2.0;
+
+ E [j] = (X [j+1] - X [j]) / A;
+ F [j] = (X [j] - X [j-1]) / A;
+ G [j] = 1.5 * S [j];
+
+ }
+
+ for (j = start+1; j < end; ++j)
+ {
+
+ A = 1.0 - F [j-1] * E [j];
+
+ if (j != end-1) F [j] /= A;
+
+ G [j] = (G [j] - G [j-1] * E [j]) / A;
+
+ }
+
+ for (j = end - 2; j >= start; --j)
+ G [j] = G [j] - F [j] * G [j+1];
+
+ for (j = start; j < end; ++j)
+ S [j] = G [j];
+
+ }
+
+ }
+
+/******************************************************************************/
+
+bool dng_spline_solver::IsIdentity () const
+ {
+
+ int32 count = (int32) X.size ();
+
+ if (count != 2)
+ return false;
+
+ if (X [0] != 0.0 || X [1] != 1.0 ||
+ Y [0] != 0.0 || Y [1] != 1.0)
+ return false;
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+real64 dng_spline_solver::Evaluate (real64 x) const
+ {
+
+ int32 count = (int32) X.size ();
+
+ // Check for off each end of point list.
+
+ if (x <= X [0])
+ return Y [0];
+
+ if (x >= X [count-1])
+ return Y [count-1];
+
+ // Binary search for the index.
+
+ int32 lower = 1;
+ int32 upper = count - 1;
+
+ while (upper > lower)
+ {
+
+ int32 mid = (lower + upper) >> 1;
+
+ if (x == X [mid])
+ {
+ return Y [mid];
+ }
+
+ if (x > X [mid])
+ lower = mid + 1;
+ else
+ upper = mid;
+
+ }
+
+ DNG_ASSERT (upper == lower, "Binary search error in point list");
+
+ int32 j = lower;
+
+ // X [j - 1] < x <= X [j]
+ // A is the distance between the X [j] and X [j - 1]
+ // B and C describe the fractional distance to either side. B + C = 1.
+
+ // We compute a cubic spline between the two points with slopes
+ // S[j-1] and S[j] at either end. Specifically, we compute the 1-D Bezier
+ // with control values:
+ //
+ // Y[j-1], Y[j-1] + S[j-1]*A, Y[j]-S[j]*A, Y[j]
+
+ return EvaluateSplineSegment (x,
+ X [j - 1],
+ Y [j - 1],
+ S [j - 1],
+ X [j ],
+ Y [j ],
+ S [j ]);
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_spline.h b/source/dng_spline.h
index 6343d8b..cc79020 100644
--- a/source/dng_spline.h
+++ b/source/dng_spline.h
@@ -1,84 +1,84 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_spline.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_spline__
-#define __dng_spline__
-
-/*****************************************************************************/
-
-#include "dng_1d_function.h"
-#include "dng_memory.h"
-
-#include <vector>
-
-/*****************************************************************************/
-
-inline real64 EvaluateSplineSegment (real64 x,
- real64 x0,
- real64 y0,
- real64 s0,
- real64 x1,
- real64 y1,
- real64 s1)
- {
-
- real64 A = x1 - x0;
-
- real64 B = (x - x0) / A;
-
- real64 C = (x1 - x) / A;
-
- real64 D = ((y0 * (2.0 - C + B) + (s0 * A * B)) * (C * C)) +
- ((y1 * (2.0 - B + C) - (s1 * A * C)) * (B * B));
-
- return D;
-
- }
-
-/*****************************************************************************/
-
-class dng_spline_solver: public dng_1d_function
- {
-
- protected:
-
- dng_std_vector<real64> X;
- dng_std_vector<real64> Y;
-
- dng_std_vector<real64> S;
-
- public:
-
- dng_spline_solver ();
-
- virtual ~dng_spline_solver ();
-
- void Reset ();
-
- void Add (real64 x, real64 y);
-
- virtual void Solve ();
-
- virtual bool IsIdentity () const;
-
- virtual real64 Evaluate (real64 x) const;
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_spline.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_spline__
+#define __dng_spline__
+
+/*****************************************************************************/
+
+#include "dng_1d_function.h"
+#include "dng_memory.h"
+
+#include <vector>
+
+/*****************************************************************************/
+
+inline real64 EvaluateSplineSegment (real64 x,
+ real64 x0,
+ real64 y0,
+ real64 s0,
+ real64 x1,
+ real64 y1,
+ real64 s1)
+ {
+
+ real64 A = x1 - x0;
+
+ real64 B = (x - x0) / A;
+
+ real64 C = (x1 - x) / A;
+
+ real64 D = ((y0 * (2.0 - C + B) + (s0 * A * B)) * (C * C)) +
+ ((y1 * (2.0 - B + C) - (s1 * A * C)) * (B * B));
+
+ return D;
+
+ }
+
+/*****************************************************************************/
+
+class dng_spline_solver: public dng_1d_function
+ {
+
+ protected:
+
+ dng_std_vector<real64> X;
+ dng_std_vector<real64> Y;
+
+ dng_std_vector<real64> S;
+
+ public:
+
+ dng_spline_solver ();
+
+ virtual ~dng_spline_solver ();
+
+ void Reset ();
+
+ void Add (real64 x, real64 y);
+
+ virtual void Solve ();
+
+ virtual bool IsIdentity () const;
+
+ virtual real64 Evaluate (real64 x) const;
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_stream.cpp b/source/dng_stream.cpp
index f8548db..c1db250 100644
--- a/source/dng_stream.cpp
+++ b/source/dng_stream.cpp
@@ -1,1221 +1,1221 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_stream.cpp#2 $ */
-/* $DateTime: 2012/06/01 07:28:57 $ */
-/* $Change: 832715 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_stream.h"
-
-#include "dng_abort_sniffer.h"
-#include "dng_auto_ptr.h"
-#include "dng_bottlenecks.h"
-#include "dng_exceptions.h"
-#include "dng_flags.h"
-#include "dng_memory.h"
-#include "dng_tag_types.h"
-
-/*****************************************************************************/
-
-dng_stream::dng_stream (dng_abort_sniffer *sniffer,
- uint32 bufferSize,
- uint64 offsetInOriginalFile)
-
- : fSwapBytes (false)
- , fHaveLength (false)
- , fLength (0)
- , fOffsetInOriginalFile (offsetInOriginalFile)
- , fPosition (0)
- , fMemBlock (bufferSize)
- , fBuffer (fMemBlock.Buffer_uint8 ())
- , fBufferSize (bufferSize)
- , fBufferStart (0)
- , fBufferEnd (0)
- , fBufferLimit (bufferSize)
- , fBufferDirty (false)
- , fSniffer (sniffer)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_stream::dng_stream (const void *data,
- uint32 count,
- uint64 offsetInOriginalFile)
-
- : fSwapBytes (false)
- , fHaveLength (true)
- , fLength (count)
- , fOffsetInOriginalFile (offsetInOriginalFile)
- , fPosition (0)
- , fMemBlock ()
- , fBuffer ((uint8 *) data)
- , fBufferSize (count)
- , fBufferStart (0)
- , fBufferEnd (count)
- , fBufferLimit (count)
- , fBufferDirty (false)
- , fSniffer (NULL)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_stream::~dng_stream ()
- {
-
- }
-
-/*****************************************************************************/
-
-uint64 dng_stream::DoGetLength ()
- {
-
- ThrowProgramError ();
-
- return 0;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::DoRead (void * /* data */,
- uint32 /* count */,
- uint64 /* offset */)
- {
-
- ThrowProgramError ();
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::DoSetLength (uint64 /* length */)
- {
-
- ThrowProgramError ();
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::DoWrite (const void * /* data */,
- uint32 /* count */,
- uint64 /* offset */)
- {
-
- ThrowProgramError ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_stream::BigEndian () const
- {
-
- return fSwapBytes != (!!qDNGBigEndian);
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::SetBigEndian (bool bigEndian)
- {
-
- fSwapBytes = (bigEndian != (!!qDNGBigEndian));
-
- }
-
-/*****************************************************************************/
-
-const void * dng_stream::Data () const
- {
-
- if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength)
- {
-
- return fBuffer;
-
- }
-
- return NULL;
-
- }
-
-/*****************************************************************************/
-
-dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator)
- {
-
- Flush ();
-
- uint64 len64 = Length ();
-
- if (len64 > 0xFFFFFFFF)
- {
- ThrowProgramError ();
- }
-
- uint32 len = (uint32) len64;
-
- AutoPtr<dng_memory_block> block (allocator.Allocate (len));
-
- if (len)
- {
-
- SetReadPosition (0);
-
- Get (block->Buffer (), len);
-
- }
-
- return block.Release ();
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::SetReadPosition (uint64 offset)
- {
-
- fPosition = offset;
-
- if (fPosition > Length ())
- {
-
- ThrowEndOfFile ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-uint64 dng_stream::OffsetInOriginalFile () const
- {
-
- return fOffsetInOriginalFile;
-
- }
-
-/*****************************************************************************/
-
-uint64 dng_stream::PositionInOriginalFile () const
- {
-
- if (fOffsetInOriginalFile == kDNGStreamInvalidOffset)
- return kDNGStreamInvalidOffset;
-
- return fOffsetInOriginalFile + Position ();
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Get (void *data, uint32 count)
- {
-
- while (count)
- {
-
- // See if the request is totally inside buffer.
-
- if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd)
- {
-
- DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart),
- data,
- count);
-
- fPosition += count;
-
- return;
-
- }
-
- // See if first part of request is inside buffer.
-
- if (fPosition >= fBufferStart && fPosition < fBufferEnd)
- {
-
- uint32 block = (uint32) (fBufferEnd - fPosition);
-
- DoCopyBytes (fBuffer + (fPosition - fBufferStart),
- data,
- block);
-
- count -= block;
-
- data = (void *) (((char *) data) + block);
-
- fPosition += block;
-
- }
-
- // Flush buffer if dirty.
-
- Flush ();
-
- // Do large reads unbuffered.
-
- if (count > fBufferSize)
- {
-
- if (fPosition + count > Length ())
- {
-
- ThrowEndOfFile ();
-
- }
-
- DoRead (data,
- count,
- fPosition);
-
- fPosition += count;
-
- return;
-
- }
-
- // Figure out new buffer range.
-
- fBufferStart = fPosition;
-
- if (fBufferSize >= 4096)
- {
-
- // Align to a 4K file block.
-
- fBufferStart &= (uint64) ~((int64) 4095);
-
- }
-
- fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ());
-
- if (fBufferEnd <= fPosition)
- {
-
- ThrowEndOfFile ();
-
- }
-
- // Read data into buffer.
-
- dng_abort_sniffer::SniffForAbort (fSniffer);
-
- DoRead (fBuffer,
- (uint32) (fBufferEnd - fBufferStart),
- fBufferStart);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::SetWritePosition (uint64 offset)
- {
-
- fPosition = offset;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Flush ()
- {
-
- if (fBufferDirty)
- {
-
- dng_abort_sniffer::SniffForAbort (fSniffer);
-
- DoWrite (fBuffer,
- (uint32) (fBufferEnd - fBufferStart),
- fBufferStart);
-
- fBufferStart = 0;
- fBufferEnd = 0;
- fBufferLimit = fBufferSize;
-
- fBufferDirty = false;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::SetLength (uint64 length)
- {
-
- Flush ();
-
- if (Length () != length)
- {
-
- DoSetLength (length);
-
- fLength = length;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put (const void *data,
- uint32 count)
- {
-
- // See if we can replace or append to the existing buffer.
-
- uint64 endPosition = fPosition + count;
-
- if (fBufferDirty &&
- fPosition >= fBufferStart &&
- fPosition <= fBufferEnd &&
- endPosition <= fBufferLimit)
- {
-
- DoCopyBytes (data,
- fBuffer + (uint32) (fPosition - fBufferStart),
- count);
-
- if (fBufferEnd < endPosition)
- fBufferEnd = endPosition;
-
- }
-
- // Else we need to write to the file.
-
- else
- {
-
- // Write existing buffer.
-
- Flush ();
-
- // Write large blocks unbuffered.
-
- if (count >= fBufferSize)
- {
-
- dng_abort_sniffer::SniffForAbort (fSniffer);
-
- DoWrite (data, count, fPosition);
-
- }
-
- // Start a new buffer with small blocks.
-
- else
- {
-
- fBufferDirty = true;
-
- fBufferStart = fPosition;
- fBufferEnd = endPosition;
- fBufferLimit = fBufferStart + fBufferSize;
-
- DoCopyBytes (data,
- fBuffer,
- count);
-
- }
-
- }
-
- fPosition = endPosition;
-
- fLength = Max_uint64 (Length (), fPosition);
-
- }
-
-/*****************************************************************************/
-
-uint16 dng_stream::Get_uint16 ()
- {
-
- uint16 x;
-
- Get (&x, 2);
-
- if (fSwapBytes)
- {
-
- x = SwapBytes16 (x);
-
- }
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_uint16 (uint16 x)
- {
-
- if (fSwapBytes)
- {
-
- x = SwapBytes16 (x);
-
- }
-
- Put (&x, 2);
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_stream::Get_uint32 ()
- {
-
- uint32 x;
-
- Get (&x, 4);
-
- if (fSwapBytes)
- {
-
- x = SwapBytes32 (x);
-
- }
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_uint32 (uint32 x)
- {
-
- if (fSwapBytes)
- {
-
- x = SwapBytes32 (x);
-
- }
-
- Put (&x, 4);
-
- }
-
-/*****************************************************************************/
-
-uint64 dng_stream::Get_uint64 ()
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 u32 [2];
- uint64 u64;
- } u;
-
- u.u32 [1] = Get_uint32 ();
- u.u32 [0] = Get_uint32 ();
-
- return u.u64;
-
- }
-
- uint64 x;
-
- Get (&x, 8);
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_uint64 (uint64 x)
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 u32 [2];
- uint64 u64;
- } u;
-
- u.u64 = x;
-
- Put_uint32 (u.u32 [1]);
- Put_uint32 (u.u32 [0]);
-
- }
-
- else
- {
-
- Put (&x, 8);
-
- }
-
- }
-
-/*****************************************************************************/
-
-real32 dng_stream::Get_real32 ()
- {
-
- union
- {
- uint32 i;
- real32 r;
- } u;
-
- u.i = Get_uint32 ();
-
- return u.r;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_real32 (real32 x)
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 i;
- real32 r;
- } u;
-
- u.r = x;
-
- Put_uint32 (u.i);
-
- }
-
- else
- {
-
- Put (&x, 4);
-
- }
-
- }
-
-/*****************************************************************************/
-
-real64 dng_stream::Get_real64 ()
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 i [2];
- real64 r;
- } u;
-
- u.i [1] = Get_uint32 ();
- u.i [0] = Get_uint32 ();
-
- return u.r;
-
- }
-
- real64 x;
-
- Get (&x, 8);
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_real64 (real64 x)
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 i [2];
- real64 r;
- } u;
-
- u.r = x;
-
- Put_uint32 (u.i [1]);
- Put_uint32 (u.i [0]);
-
- }
-
- else
- {
-
- Put (&x, 8);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Get_CString (char *data, uint32 maxLength)
- {
-
- memset (data, 0, maxLength);
-
- uint32 index = 0;
-
- while (true)
- {
-
- char c = (char) Get_uint8 ();
-
- if (index + 1 < maxLength)
- data [index++] = c;
-
- if (c == 0)
- break;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Get_UString (char *data, uint32 maxLength)
- {
-
- memset (data, 0, maxLength);
-
- uint32 index = 0;
-
- while (true)
- {
-
- char c = (char) Get_uint16 ();
-
- if (index + 1 < maxLength)
- data [index++] = (char) c;
-
- if (c == 0)
- break;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::PutZeros (uint64 count)
- {
-
- const uint32 kZeroBufferSize = 4096;
-
- if (count >= kZeroBufferSize)
- {
-
- dng_memory_data zeroBuffer (kZeroBufferSize);
-
- DoZeroBytes (zeroBuffer.Buffer (),
- kZeroBufferSize);
-
- while (count)
- {
-
- uint64 blockSize = Min_uint64 (count, kZeroBufferSize);
-
- Put (zeroBuffer.Buffer (), (uint32) blockSize);
-
- count -= blockSize;
-
- }
-
- }
-
- else
- {
-
- uint32 count32 = (uint32) count;
-
- for (uint32 j = 0; j < count32; j++)
- {
-
- Put_uint8 (0);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::PadAlign2 ()
- {
-
- PutZeros (Position () & 1);
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::PadAlign4 ()
- {
-
- PutZeros ((4 - (Position () & 3)) & 3);
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_stream::TagValue_uint32 (uint32 tagType)
- {
-
- switch (tagType)
- {
-
- case ttByte:
- return (uint32) Get_uint8 ();
-
- case ttShort:
- return (uint32) Get_uint16 ();
-
- case ttLong:
- case ttIFD:
- return Get_uint32 ();
-
- }
-
- real64 x = TagValue_real64 (tagType);
-
- if (x < 0.0)
- x = 0.0;
-
- if (x > (real64) 0xFFFFFFFF)
- x = (real64) 0xFFFFFFFF;
-
- return (uint32) (x + 0.5);
-
- }
-
-/*****************************************************************************/
-
-int32 dng_stream::TagValue_int32 (uint32 tagType)
- {
-
- switch (tagType)
- {
-
- case ttSByte:
- return (int32) Get_int8 ();
-
- case ttSShort:
- return (int32) Get_int16 ();
-
- case ttSLong:
- return Get_int32 ();
-
- }
-
- real64 x = TagValue_real64 (tagType);
-
- if (x < 0.0)
- {
-
- if (x < -2147483648.0)
- x = -2147483648.0;
-
- return (int32) (x - 0.5);
-
- }
-
- else
- {
-
- if (x > 2147483647.0)
- x = 2147483647.0;
-
- return (int32) (x + 0.5);
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_urational dng_stream::TagValue_urational (uint32 tagType)
- {
-
- dng_urational result;
-
- result.n = 0;
- result.d = 1;
-
- switch (tagType)
- {
-
- case ttRational:
- {
-
- result.n = Get_uint32 ();
- result.d = Get_uint32 ();
-
- break;
-
- }
-
- case ttSRational:
- {
-
- int32 n = Get_int32 ();
- int32 d = Get_int32 ();
-
- if ((n < 0) == (d < 0))
- {
-
- if (d < 0)
- {
- result.n = (uint32) ((int64) n * -1);
- result.d = (uint32) ((int64) d * -1);
- }
- else
- {
- result.n = (uint32) n;
- result.d = (uint32) d;
- }
-
- }
-
- break;
-
- }
-
- case ttByte:
- case ttShort:
- case ttLong:
- case ttIFD:
- {
-
- result.n = TagValue_uint32 (tagType);
-
- break;
-
- }
-
- case ttSByte:
- case ttSShort:
- case ttSLong:
- {
-
- int32 n = TagValue_int32 (tagType);
-
- if (n > 0)
- {
- result.n = (uint32) n;
- }
-
- break;
-
- }
-
- default:
- {
-
- real64 x = TagValue_real64 (tagType);
-
- if (x > 0.0)
- {
-
- while (result.d < 10000 && x < 1000000)
- {
-
- result.d *= 10;
-
- x *= 10.0;
-
- }
-
- result.n = (uint32) (x + 0.5);
-
- }
-
- }
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-dng_srational dng_stream::TagValue_srational (uint32 tagType)
- {
-
- dng_srational result;
-
- result.n = 0;
- result.d = 1;
-
- switch (tagType)
- {
-
- case ttSRational:
- {
-
- result.n = Get_int32 ();
- result.d = Get_int32 ();
-
- break;
-
- }
-
- default:
- {
-
- real64 x = TagValue_real64 (tagType);
-
- if (x > 0.0)
- {
-
- while (result.d < 10000 && x < 1000000.0)
- {
-
- result.d *= 10;
-
- x *= 10.0;
-
- }
-
- result.n = (int32) (x + 0.5);
-
- }
-
- else
- {
-
- while (result.d < 10000 && x > -1000000.0)
- {
-
- result.d *= 10;
-
- x *= 10.0;
-
- }
-
- result.n = (int32) (x - 0.5);
-
- }
-
- }
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-real64 dng_stream::TagValue_real64 (uint32 tagType)
- {
-
- switch (tagType)
- {
-
- case ttByte:
- case ttShort:
- case ttLong:
- case ttIFD:
- return (real64) TagValue_uint32 (tagType);
-
- case ttSByte:
- case ttSShort:
- case ttSLong:
- return (real64) TagValue_int32 (tagType);
-
- case ttRational:
- {
-
- uint32 n = Get_uint32 ();
- uint32 d = Get_uint32 ();
-
- if (d == 0)
- return 0.0;
- else
- return (real64) n / (real64) d;
-
- }
-
- case ttSRational:
- {
-
- int32 n = Get_int32 ();
- int32 d = Get_int32 ();
-
- if (d == 0)
- return 0.0;
- else
- return (real64) n / (real64) d;
-
- }
-
- case ttFloat:
- return (real64) Get_real32 ();
-
- case ttDouble:
- return Get_real64 ();
-
- }
-
- return 0.0;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::CopyToStream (dng_stream &dstStream,
- uint64 count)
- {
-
- uint8 smallBuffer [1024];
-
- if (count <= sizeof (smallBuffer))
- {
-
- Get (smallBuffer, (uint32) count);
-
- dstStream.Put (smallBuffer, (uint32) count);
-
- }
-
- else
- {
-
- const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize,
- count);
-
- dng_memory_data bigBuffer (bigBufferSize);
-
- while (count)
- {
-
- uint32 blockCount = (uint32) Min_uint64 (bigBufferSize,
- count);
-
- Get (bigBuffer.Buffer (),
- blockCount);
-
- dstStream.Put (bigBuffer.Buffer (),
- blockCount);
-
- count -= blockCount;
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::DuplicateStream (dng_stream &dstStream)
- {
-
- // Turn off sniffers for this operation.
-
- TempStreamSniffer noSniffer1 (*this , NULL);
- TempStreamSniffer noSniffer2 (dstStream, NULL);
-
- // First grow the destination stream if required, in an attempt to
- // reserve any needed space before overwriting the existing data.
-
- if (dstStream.Length () < Length ())
- {
- dstStream.SetLength (Length ());
- }
-
- SetReadPosition (0);
-
- dstStream.SetWritePosition (0);
-
- CopyToStream (dstStream, Length ());
-
- dstStream.Flush ();
-
- dstStream.SetLength (Length ());
-
- }
-
-/*****************************************************************************/
-
-TempBigEndian::TempBigEndian (dng_stream &stream,
- bool bigEndian)
-
- : fStream (stream)
- , fOldSwap (stream.SwapBytes ())
-
- {
-
- fStream.SetBigEndian (bigEndian);
-
- }
-
-/*****************************************************************************/
-
-TempBigEndian::~TempBigEndian ()
- {
-
- fStream.SetSwapBytes (fOldSwap);
-
- }
-
-/*****************************************************************************/
-
-TempStreamSniffer::TempStreamSniffer (dng_stream &stream,
- dng_abort_sniffer *sniffer)
-
- : fStream (stream)
- , fOldSniffer (stream.Sniffer ())
-
- {
-
- fStream.SetSniffer (sniffer);
-
- }
-
-/*****************************************************************************/
-
-TempStreamSniffer::~TempStreamSniffer ()
- {
-
- fStream.SetSniffer (fOldSniffer);
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_stream.cpp#2 $ */
+/* $DateTime: 2012/06/01 07:28:57 $ */
+/* $Change: 832715 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_stream.h"
+
+#include "dng_abort_sniffer.h"
+#include "dng_auto_ptr.h"
+#include "dng_bottlenecks.h"
+#include "dng_exceptions.h"
+#include "dng_flags.h"
+#include "dng_memory.h"
+#include "dng_tag_types.h"
+
+/*****************************************************************************/
+
+dng_stream::dng_stream (dng_abort_sniffer *sniffer,
+ uint32 bufferSize,
+ uint64 offsetInOriginalFile)
+
+ : fSwapBytes (false)
+ , fHaveLength (false)
+ , fLength (0)
+ , fOffsetInOriginalFile (offsetInOriginalFile)
+ , fPosition (0)
+ , fMemBlock (bufferSize)
+ , fBuffer (fMemBlock.Buffer_uint8 ())
+ , fBufferSize (bufferSize)
+ , fBufferStart (0)
+ , fBufferEnd (0)
+ , fBufferLimit (bufferSize)
+ , fBufferDirty (false)
+ , fSniffer (sniffer)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_stream::dng_stream (const void *data,
+ uint32 count,
+ uint64 offsetInOriginalFile)
+
+ : fSwapBytes (false)
+ , fHaveLength (true)
+ , fLength (count)
+ , fOffsetInOriginalFile (offsetInOriginalFile)
+ , fPosition (0)
+ , fMemBlock ()
+ , fBuffer ((uint8 *) data)
+ , fBufferSize (count)
+ , fBufferStart (0)
+ , fBufferEnd (count)
+ , fBufferLimit (count)
+ , fBufferDirty (false)
+ , fSniffer (NULL)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_stream::~dng_stream ()
+ {
+
+ }
+
+/*****************************************************************************/
+
+uint64 dng_stream::DoGetLength ()
+ {
+
+ ThrowProgramError ();
+
+ return 0;
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::DoRead (void * /* data */,
+ uint32 /* count */,
+ uint64 /* offset */)
+ {
+
+ ThrowProgramError ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::DoSetLength (uint64 /* length */)
+ {
+
+ ThrowProgramError ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::DoWrite (const void * /* data */,
+ uint32 /* count */,
+ uint64 /* offset */)
+ {
+
+ ThrowProgramError ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_stream::BigEndian () const
+ {
+
+ return fSwapBytes != (!!qDNGBigEndian);
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::SetBigEndian (bool bigEndian)
+ {
+
+ fSwapBytes = (bigEndian != (!!qDNGBigEndian));
+
+ }
+
+/*****************************************************************************/
+
+const void * dng_stream::Data () const
+ {
+
+ if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength)
+ {
+
+ return fBuffer;
+
+ }
+
+ return NULL;
+
+ }
+
+/*****************************************************************************/
+
+dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator)
+ {
+
+ Flush ();
+
+ uint64 len64 = Length ();
+
+ if (len64 > 0xFFFFFFFF)
+ {
+ ThrowProgramError ();
+ }
+
+ uint32 len = (uint32) len64;
+
+ AutoPtr<dng_memory_block> block (allocator.Allocate (len));
+
+ if (len)
+ {
+
+ SetReadPosition (0);
+
+ Get (block->Buffer (), len);
+
+ }
+
+ return block.Release ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::SetReadPosition (uint64 offset)
+ {
+
+ fPosition = offset;
+
+ if (fPosition > Length ())
+ {
+
+ ThrowEndOfFile ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+uint64 dng_stream::OffsetInOriginalFile () const
+ {
+
+ return fOffsetInOriginalFile;
+
+ }
+
+/*****************************************************************************/
+
+uint64 dng_stream::PositionInOriginalFile () const
+ {
+
+ if (fOffsetInOriginalFile == kDNGStreamInvalidOffset)
+ return kDNGStreamInvalidOffset;
+
+ return fOffsetInOriginalFile + Position ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Get (void *data, uint32 count)
+ {
+
+ while (count)
+ {
+
+ // See if the request is totally inside buffer.
+
+ if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd)
+ {
+
+ DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart),
+ data,
+ count);
+
+ fPosition += count;
+
+ return;
+
+ }
+
+ // See if first part of request is inside buffer.
+
+ if (fPosition >= fBufferStart && fPosition < fBufferEnd)
+ {
+
+ uint32 block = (uint32) (fBufferEnd - fPosition);
+
+ DoCopyBytes (fBuffer + (fPosition - fBufferStart),
+ data,
+ block);
+
+ count -= block;
+
+ data = (void *) (((char *) data) + block);
+
+ fPosition += block;
+
+ }
+
+ // Flush buffer if dirty.
+
+ Flush ();
+
+ // Do large reads unbuffered.
+
+ if (count > fBufferSize)
+ {
+
+ if (fPosition + count > Length ())
+ {
+
+ ThrowEndOfFile ();
+
+ }
+
+ DoRead (data,
+ count,
+ fPosition);
+
+ fPosition += count;
+
+ return;
+
+ }
+
+ // Figure out new buffer range.
+
+ fBufferStart = fPosition;
+
+ if (fBufferSize >= 4096)
+ {
+
+ // Align to a 4K file block.
+
+ fBufferStart &= (uint64) ~((int64) 4095);
+
+ }
+
+ fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ());
+
+ if (fBufferEnd <= fPosition)
+ {
+
+ ThrowEndOfFile ();
+
+ }
+
+ // Read data into buffer.
+
+ dng_abort_sniffer::SniffForAbort (fSniffer);
+
+ DoRead (fBuffer,
+ (uint32) (fBufferEnd - fBufferStart),
+ fBufferStart);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::SetWritePosition (uint64 offset)
+ {
+
+ fPosition = offset;
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Flush ()
+ {
+
+ if (fBufferDirty)
+ {
+
+ dng_abort_sniffer::SniffForAbort (fSniffer);
+
+ DoWrite (fBuffer,
+ (uint32) (fBufferEnd - fBufferStart),
+ fBufferStart);
+
+ fBufferStart = 0;
+ fBufferEnd = 0;
+ fBufferLimit = fBufferSize;
+
+ fBufferDirty = false;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::SetLength (uint64 length)
+ {
+
+ Flush ();
+
+ if (Length () != length)
+ {
+
+ DoSetLength (length);
+
+ fLength = length;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Put (const void *data,
+ uint32 count)
+ {
+
+ // See if we can replace or append to the existing buffer.
+
+ uint64 endPosition = fPosition + count;
+
+ if (fBufferDirty &&
+ fPosition >= fBufferStart &&
+ fPosition <= fBufferEnd &&
+ endPosition <= fBufferLimit)
+ {
+
+ DoCopyBytes (data,
+ fBuffer + (uint32) (fPosition - fBufferStart),
+ count);
+
+ if (fBufferEnd < endPosition)
+ fBufferEnd = endPosition;
+
+ }
+
+ // Else we need to write to the file.
+
+ else
+ {
+
+ // Write existing buffer.
+
+ Flush ();
+
+ // Write large blocks unbuffered.
+
+ if (count >= fBufferSize)
+ {
+
+ dng_abort_sniffer::SniffForAbort (fSniffer);
+
+ DoWrite (data, count, fPosition);
+
+ }
+
+ // Start a new buffer with small blocks.
+
+ else
+ {
+
+ fBufferDirty = true;
+
+ fBufferStart = fPosition;
+ fBufferEnd = endPosition;
+ fBufferLimit = fBufferStart + fBufferSize;
+
+ DoCopyBytes (data,
+ fBuffer,
+ count);
+
+ }
+
+ }
+
+ fPosition = endPosition;
+
+ fLength = Max_uint64 (Length (), fPosition);
+
+ }
+
+/*****************************************************************************/
+
+uint16 dng_stream::Get_uint16 ()
+ {
+
+ uint16 x;
+
+ Get (&x, 2);
+
+ if (fSwapBytes)
+ {
+
+ x = SwapBytes16 (x);
+
+ }
+
+ return x;
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Put_uint16 (uint16 x)
+ {
+
+ if (fSwapBytes)
+ {
+
+ x = SwapBytes16 (x);
+
+ }
+
+ Put (&x, 2);
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_stream::Get_uint32 ()
+ {
+
+ uint32 x;
+
+ Get (&x, 4);
+
+ if (fSwapBytes)
+ {
+
+ x = SwapBytes32 (x);
+
+ }
+
+ return x;
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Put_uint32 (uint32 x)
+ {
+
+ if (fSwapBytes)
+ {
+
+ x = SwapBytes32 (x);
+
+ }
+
+ Put (&x, 4);
+
+ }
+
+/*****************************************************************************/
+
+uint64 dng_stream::Get_uint64 ()
+ {
+
+ if (fSwapBytes)
+ {
+
+ union
+ {
+ uint32 u32 [2];
+ uint64 u64;
+ } u;
+
+ u.u32 [1] = Get_uint32 ();
+ u.u32 [0] = Get_uint32 ();
+
+ return u.u64;
+
+ }
+
+ uint64 x;
+
+ Get (&x, 8);
+
+ return x;
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Put_uint64 (uint64 x)
+ {
+
+ if (fSwapBytes)
+ {
+
+ union
+ {
+ uint32 u32 [2];
+ uint64 u64;
+ } u;
+
+ u.u64 = x;
+
+ Put_uint32 (u.u32 [1]);
+ Put_uint32 (u.u32 [0]);
+
+ }
+
+ else
+ {
+
+ Put (&x, 8);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+real32 dng_stream::Get_real32 ()
+ {
+
+ union
+ {
+ uint32 i;
+ real32 r;
+ } u;
+
+ u.i = Get_uint32 ();
+
+ return u.r;
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Put_real32 (real32 x)
+ {
+
+ if (fSwapBytes)
+ {
+
+ union
+ {
+ uint32 i;
+ real32 r;
+ } u;
+
+ u.r = x;
+
+ Put_uint32 (u.i);
+
+ }
+
+ else
+ {
+
+ Put (&x, 4);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_stream::Get_real64 ()
+ {
+
+ if (fSwapBytes)
+ {
+
+ union
+ {
+ uint32 i [2];
+ real64 r;
+ } u;
+
+ u.i [1] = Get_uint32 ();
+ u.i [0] = Get_uint32 ();
+
+ return u.r;
+
+ }
+
+ real64 x;
+
+ Get (&x, 8);
+
+ return x;
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Put_real64 (real64 x)
+ {
+
+ if (fSwapBytes)
+ {
+
+ union
+ {
+ uint32 i [2];
+ real64 r;
+ } u;
+
+ u.r = x;
+
+ Put_uint32 (u.i [1]);
+ Put_uint32 (u.i [0]);
+
+ }
+
+ else
+ {
+
+ Put (&x, 8);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Get_CString (char *data, uint32 maxLength)
+ {
+
+ memset (data, 0, maxLength);
+
+ uint32 index = 0;
+
+ while (true)
+ {
+
+ char c = (char) Get_uint8 ();
+
+ if (index + 1 < maxLength)
+ data [index++] = c;
+
+ if (c == 0)
+ break;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::Get_UString (char *data, uint32 maxLength)
+ {
+
+ memset (data, 0, maxLength);
+
+ uint32 index = 0;
+
+ while (true)
+ {
+
+ char c = (char) Get_uint16 ();
+
+ if (index + 1 < maxLength)
+ data [index++] = (char) c;
+
+ if (c == 0)
+ break;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::PutZeros (uint64 count)
+ {
+
+ const uint32 kZeroBufferSize = 4096;
+
+ if (count >= kZeroBufferSize)
+ {
+
+ dng_memory_data zeroBuffer (kZeroBufferSize);
+
+ DoZeroBytes (zeroBuffer.Buffer (),
+ kZeroBufferSize);
+
+ while (count)
+ {
+
+ uint64 blockSize = Min_uint64 (count, kZeroBufferSize);
+
+ Put (zeroBuffer.Buffer (), (uint32) blockSize);
+
+ count -= blockSize;
+
+ }
+
+ }
+
+ else
+ {
+
+ uint32 count32 = (uint32) count;
+
+ for (uint32 j = 0; j < count32; j++)
+ {
+
+ Put_uint8 (0);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::PadAlign2 ()
+ {
+
+ PutZeros (Position () & 1);
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::PadAlign4 ()
+ {
+
+ PutZeros ((4 - (Position () & 3)) & 3);
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_stream::TagValue_uint32 (uint32 tagType)
+ {
+
+ switch (tagType)
+ {
+
+ case ttByte:
+ return (uint32) Get_uint8 ();
+
+ case ttShort:
+ return (uint32) Get_uint16 ();
+
+ case ttLong:
+ case ttIFD:
+ return Get_uint32 ();
+
+ }
+
+ real64 x = TagValue_real64 (tagType);
+
+ if (x < 0.0)
+ x = 0.0;
+
+ if (x > (real64) 0xFFFFFFFF)
+ x = (real64) 0xFFFFFFFF;
+
+ return (uint32) (x + 0.5);
+
+ }
+
+/*****************************************************************************/
+
+int32 dng_stream::TagValue_int32 (uint32 tagType)
+ {
+
+ switch (tagType)
+ {
+
+ case ttSByte:
+ return (int32) Get_int8 ();
+
+ case ttSShort:
+ return (int32) Get_int16 ();
+
+ case ttSLong:
+ return Get_int32 ();
+
+ }
+
+ real64 x = TagValue_real64 (tagType);
+
+ if (x < 0.0)
+ {
+
+ if (x < -2147483648.0)
+ x = -2147483648.0;
+
+ return (int32) (x - 0.5);
+
+ }
+
+ else
+ {
+
+ if (x > 2147483647.0)
+ x = 2147483647.0;
+
+ return (int32) (x + 0.5);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_urational dng_stream::TagValue_urational (uint32 tagType)
+ {
+
+ dng_urational result;
+
+ result.n = 0;
+ result.d = 1;
+
+ switch (tagType)
+ {
+
+ case ttRational:
+ {
+
+ result.n = Get_uint32 ();
+ result.d = Get_uint32 ();
+
+ break;
+
+ }
+
+ case ttSRational:
+ {
+
+ int32 n = Get_int32 ();
+ int32 d = Get_int32 ();
+
+ if ((n < 0) == (d < 0))
+ {
+
+ if (d < 0)
+ {
+ result.n = (uint32) ((int64) n * -1);
+ result.d = (uint32) ((int64) d * -1);
+ }
+ else
+ {
+ result.n = (uint32) n;
+ result.d = (uint32) d;
+ }
+
+ }
+
+ break;
+
+ }
+
+ case ttByte:
+ case ttShort:
+ case ttLong:
+ case ttIFD:
+ {
+
+ result.n = TagValue_uint32 (tagType);
+
+ break;
+
+ }
+
+ case ttSByte:
+ case ttSShort:
+ case ttSLong:
+ {
+
+ int32 n = TagValue_int32 (tagType);
+
+ if (n > 0)
+ {
+ result.n = (uint32) n;
+ }
+
+ break;
+
+ }
+
+ default:
+ {
+
+ real64 x = TagValue_real64 (tagType);
+
+ if (x > 0.0)
+ {
+
+ while (result.d < 10000 && x < 1000000)
+ {
+
+ result.d *= 10;
+
+ x *= 10.0;
+
+ }
+
+ result.n = (uint32) (x + 0.5);
+
+ }
+
+ }
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+dng_srational dng_stream::TagValue_srational (uint32 tagType)
+ {
+
+ dng_srational result;
+
+ result.n = 0;
+ result.d = 1;
+
+ switch (tagType)
+ {
+
+ case ttSRational:
+ {
+
+ result.n = Get_int32 ();
+ result.d = Get_int32 ();
+
+ break;
+
+ }
+
+ default:
+ {
+
+ real64 x = TagValue_real64 (tagType);
+
+ if (x > 0.0)
+ {
+
+ while (result.d < 10000 && x < 1000000.0)
+ {
+
+ result.d *= 10;
+
+ x *= 10.0;
+
+ }
+
+ result.n = (int32) (x + 0.5);
+
+ }
+
+ else
+ {
+
+ while (result.d < 10000 && x > -1000000.0)
+ {
+
+ result.d *= 10;
+
+ x *= 10.0;
+
+ }
+
+ result.n = (int32) (x - 0.5);
+
+ }
+
+ }
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+real64 dng_stream::TagValue_real64 (uint32 tagType)
+ {
+
+ switch (tagType)
+ {
+
+ case ttByte:
+ case ttShort:
+ case ttLong:
+ case ttIFD:
+ return (real64) TagValue_uint32 (tagType);
+
+ case ttSByte:
+ case ttSShort:
+ case ttSLong:
+ return (real64) TagValue_int32 (tagType);
+
+ case ttRational:
+ {
+
+ uint32 n = Get_uint32 ();
+ uint32 d = Get_uint32 ();
+
+ if (d == 0)
+ return 0.0;
+ else
+ return (real64) n / (real64) d;
+
+ }
+
+ case ttSRational:
+ {
+
+ int32 n = Get_int32 ();
+ int32 d = Get_int32 ();
+
+ if (d == 0)
+ return 0.0;
+ else
+ return (real64) n / (real64) d;
+
+ }
+
+ case ttFloat:
+ return (real64) Get_real32 ();
+
+ case ttDouble:
+ return Get_real64 ();
+
+ }
+
+ return 0.0;
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::CopyToStream (dng_stream &dstStream,
+ uint64 count)
+ {
+
+ uint8 smallBuffer [1024];
+
+ if (count <= sizeof (smallBuffer))
+ {
+
+ Get (smallBuffer, (uint32) count);
+
+ dstStream.Put (smallBuffer, (uint32) count);
+
+ }
+
+ else
+ {
+
+ const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize,
+ count);
+
+ dng_memory_data bigBuffer (bigBufferSize);
+
+ while (count)
+ {
+
+ uint32 blockCount = (uint32) Min_uint64 (bigBufferSize,
+ count);
+
+ Get (bigBuffer.Buffer (),
+ blockCount);
+
+ dstStream.Put (bigBuffer.Buffer (),
+ blockCount);
+
+ count -= blockCount;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_stream::DuplicateStream (dng_stream &dstStream)
+ {
+
+ // Turn off sniffers for this operation.
+
+ TempStreamSniffer noSniffer1 (*this , NULL);
+ TempStreamSniffer noSniffer2 (dstStream, NULL);
+
+ // First grow the destination stream if required, in an attempt to
+ // reserve any needed space before overwriting the existing data.
+
+ if (dstStream.Length () < Length ())
+ {
+ dstStream.SetLength (Length ());
+ }
+
+ SetReadPosition (0);
+
+ dstStream.SetWritePosition (0);
+
+ CopyToStream (dstStream, Length ());
+
+ dstStream.Flush ();
+
+ dstStream.SetLength (Length ());
+
+ }
+
+/*****************************************************************************/
+
+TempBigEndian::TempBigEndian (dng_stream &stream,
+ bool bigEndian)
+
+ : fStream (stream)
+ , fOldSwap (stream.SwapBytes ())
+
+ {
+
+ fStream.SetBigEndian (bigEndian);
+
+ }
+
+/*****************************************************************************/
+
+TempBigEndian::~TempBigEndian ()
+ {
+
+ fStream.SetSwapBytes (fOldSwap);
+
+ }
+
+/*****************************************************************************/
+
+TempStreamSniffer::TempStreamSniffer (dng_stream &stream,
+ dng_abort_sniffer *sniffer)
+
+ : fStream (stream)
+ , fOldSniffer (stream.Sniffer ())
+
+ {
+
+ fStream.SetSniffer (sniffer);
+
+ }
+
+/*****************************************************************************/
+
+TempStreamSniffer::~TempStreamSniffer ()
+ {
+
+ fStream.SetSniffer (fOldSniffer);
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_stream.h b/source/dng_stream.h
index df233ae..38ac49e 100644
--- a/source/dng_stream.h
+++ b/source/dng_stream.h
@@ -1,698 +1,698 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_stream.h#2 $ */
-/* $DateTime: 2012/06/01 07:28:57 $ */
-/* $Change: 832715 $ */
-/* $Author: tknoll $ */
-
-/** Data stream abstraction for serializing and deserializing sequences of
- * basic types and RAW image data.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_stream__
-#define __dng_stream__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_types.h"
-#include "dng_memory.h"
-#include "dng_rational.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-// Constants for invalid offset in streams.
-
-const uint64 kDNGStreamInvalidOffset = (uint64) (int64) -1;
-
-/*****************************************************************************/
-
-/// Base stream abstraction. Has support for going between stream and pointer
-/// abstraction.
-
-class dng_stream
- {
-
- public:
-
- enum
- {
-
- kSmallBufferSize = 4 * 1024,
- kBigBufferSize = 64 * 1024,
-
- kDefaultBufferSize = kSmallBufferSize
-
- };
-
- private:
-
- bool fSwapBytes;
-
- bool fHaveLength;
-
- uint64 fLength;
-
- const uint64 fOffsetInOriginalFile;
-
- uint64 fPosition;
-
- dng_memory_data fMemBlock;
-
- uint8 *fBuffer;
-
- uint32 fBufferSize;
-
- uint64 fBufferStart;
- uint64 fBufferEnd;
- uint64 fBufferLimit;
-
- bool fBufferDirty;
-
- dng_abort_sniffer *fSniffer;
-
- protected:
-
- dng_stream (dng_abort_sniffer *sniffer = NULL,
- uint32 bufferSize = kDefaultBufferSize,
- uint64 offsetInOriginalFile = kDNGStreamInvalidOffset);
-
- virtual uint64 DoGetLength ();
-
- virtual void DoRead (void *data,
- uint32 count,
- uint64 offset);
-
- virtual void DoSetLength (uint64 length);
-
- virtual void DoWrite (const void *data,
- uint32 count,
- uint64 offset);
-
- public:
-
- /// Construct a stream with initial data.
- /// \param data Pointer to initial contents of stream.
- /// \param count Number of bytes data is valid for.
- /// \param offsetInOriginalFile If data came from a file originally,
- /// offset can be saved here for later use.
-
- dng_stream (const void *data,
- uint32 count,
- uint64 offsetInOriginalFile = kDNGStreamInvalidOffset);
-
- virtual ~dng_stream ();
-
- /// Getter for whether stream is swapping byte order on input/output.
- /// \retval If true, data will be swapped on input/output.
-
- bool SwapBytes () const
- {
- return fSwapBytes;
- }
-
- /// Setter for whether stream is swapping byte order on input/output.
- /// \param swapBytes If true, stream will swap byte order on input or
- /// output for future reads/writes.
-
- void SetSwapBytes (bool swapBytes)
- {
- fSwapBytes = swapBytes;
- }
-
- /// Getter for whether data in stream is big endian.
- /// \retval If true, data in stream is big endian.
-
- bool BigEndian () const;
-
- /// Setter for whether data in stream is big endian.
- /// \param bigEndian If true, data in stream is big endian.
-
- void SetBigEndian (bool bigEndian = true);
-
- /// Getter for whether data in stream is big endian.
- /// \retval If true, data in stream is big endian.
-
- bool LittleEndian () const
- {
- return !BigEndian ();
- }
-
- /// Setter for whether data in stream is big endian.
- /// \param littleEndian If true, data in stream is big endian.
-
- void SetLittleEndian (bool littleEndian = true)
- {
- SetBigEndian (!littleEndian);
- }
-
- /// Returns the size of the buffer used by the stream.
-
- uint32 BufferSize () const
- {
- return fBufferSize;
- }
-
- /// Getter for length of data in stream.
- /// \retval Length of readable data in stream.
-
- uint64 Length ()
- {
-
- if (!fHaveLength)
- {
-
- fLength = DoGetLength ();
-
- fHaveLength = true;
-
- }
-
- return fLength;
-
- }
-
- /// Getter for current offset in stream.
- /// \retval current offset from start of stream.
-
- uint64 Position () const
- {
- return fPosition;
- }
-
- /// Getter for current position in original file, taking into account
- /// OffsetInOriginalFile stream data was taken from.
- /// \retval kInvalidOffset if no offset in original file is set, sum
- /// of offset in original file and current position otherwise.
-
- uint64 PositionInOriginalFile () const;
-
- /// Getter for offset in original file.
- /// \retval kInvalidOffset if no offset in original file is set,
- /// offset in original file otherwise.
-
- uint64 OffsetInOriginalFile () const;
-
- /// Return pointer to stream contents if the stream is entirely
- /// available as a single memory block, NULL otherwise.
-
- const void * Data () const;
-
- /// Return the entire stream as a single memory block.
- /// This works for all streams, but requires copying the data to a new buffer.
- /// \param allocator Allocator used to allocate memory.
-
- dng_memory_block * AsMemoryBlock (dng_memory_allocator &allocator);
-
- /// Seek to a new position in stream for reading.
-
- void SetReadPosition (uint64 offset);
-
- /// Skip forward in stream.
- /// \param delta Number of bytes to skip forward.
-
- void Skip (uint64 delta)
- {
- SetReadPosition (Position () + delta);
- }
-
- /// Get data from stream. Exception is thrown and no data is read if
- /// insufficient data available in stream.
- /// \param data Buffer to put data into. Must be valid for count bytes.
- /// \param count Bytes of data to read.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- void Get (void *data, uint32 count);
-
- /// Seek to a new position in stream for writing.
-
- void SetWritePosition (uint64 offset);
-
- /// Force any stored data in stream to be written to underlying storage.
-
- void Flush ();
-
- /// Set length of available data.
- /// \param length Number of bytes of avialble data in stream.
-
- void SetLength (uint64 length);
-
- /// Write data to stream.
- /// \param data Buffer of data to write to stream.
- /// \param count Bytes of in data.
-
- void Put (const void *data, uint32 count);
-
- /// Get an unsigned 8-bit integer from stream and advance read position.
- /// \retval One unsigned 8-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- uint8 Get_uint8 ()
- {
-
- // Fast check to see if in buffer
-
- if (fPosition >= fBufferStart && fPosition < fBufferEnd)
- {
-
- return fBuffer [fPosition++ - fBufferStart];
-
- }
-
- // Not in buffer, let main routine do the work.
-
- uint8 x;
-
- Get (&x, 1);
-
- return x;
-
- }
-
- /// Put an unsigned 8-bit integer to stream and advance write position.
- /// \param x One unsigned 8-bit integer.
-
- void Put_uint8 (uint8 x)
- {
-
- if (fBufferDirty &&
- fPosition >= fBufferStart &&
- fPosition <= fBufferEnd &&
- fPosition < fBufferLimit)
- {
-
- fBuffer [fPosition - fBufferStart] = x;
-
- fPosition++;
-
- if (fBufferEnd < fPosition)
- fBufferEnd = fPosition;
-
- fLength = Max_uint64 (Length (), fPosition);
-
- }
-
- else
- {
-
- Put (&x, 1);
-
- }
-
- }
-
- /// Get an unsigned 16-bit integer from stream and advance read position.
- /// Byte swap if byte swapping is turned on.
- /// \retval One unsigned 16-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- uint16 Get_uint16 ();
-
- /// Put an unsigned 16-bit integer to stream and advance write position.
- /// Byte swap if byte swapping is turned on.
- /// \param x One unsigned 16-bit integer.
-
- void Put_uint16 (uint16 x);
-
- /// Get an unsigned 32-bit integer from stream and advance read position.
- /// Byte swap if byte swapping is turned on.
- /// \retval One unsigned 32-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- uint32 Get_uint32 ();
-
- /// Put an unsigned 32-bit integer to stream and advance write position.
- /// Byte swap if byte swapping is turned on.
- /// \param x One unsigned 32-bit integer.
-
- void Put_uint32 (uint32 x);
-
- /// Get an unsigned 64-bit integer from stream and advance read position.
- /// Byte swap if byte swapping is turned on.
- /// \retval One unsigned 64-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- uint64 Get_uint64 ();
-
- /// Put an unsigned 64-bit integer to stream and advance write position.
- /// Byte swap if byte swapping is turned on.
- /// \param x One unsigned 64-bit integer.
-
- void Put_uint64 (uint64 x);
-
- /// Get one 8-bit integer from stream and advance read position.
- /// \retval One 8-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- int8 Get_int8 ()
- {
- return (int8) Get_uint8 ();
- }
-
- /// Put one 8-bit integer to stream and advance write position.
- /// \param x One 8-bit integer.
-
- void Put_int8 (int8 x)
- {
- Put_uint8 ((uint8) x);
- }
-
- /// Get one 16-bit integer from stream and advance read position.
- /// Byte swap if byte swapping is turned on.
- /// \retval One 16-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- int16 Get_int16 ()
- {
- return (int16) Get_uint16 ();
- }
-
- /// Put one 16-bit integer to stream and advance write position.
- /// Byte swap if byte swapping is turned on.
- /// \param x One 16-bit integer.
-
- void Put_int16 (int16 x)
- {
- Put_uint16 ((uint16) x);
- }
-
- /// Get one 32-bit integer from stream and advance read position.
- /// Byte swap if byte swapping is turned on.
- /// \retval One 32-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- int32 Get_int32 ()
- {
- return (int32) Get_uint32 ();
- }
-
- /// Put one 32-bit integer to stream and advance write position.
- /// Byte swap if byte swapping is turned on.
- /// \param x One 32-bit integer.
-
- void Put_int32 (int32 x)
- {
- Put_uint32 ((uint32) x);
- }
-
- /// Get one 64-bit integer from stream and advance read position.
- /// Byte swap if byte swapping is turned on.
- /// \retval One 64-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- int64 Get_int64 ()
- {
- return (int64) Get_uint64 ();
- }
-
- /// Put one 64-bit integer to stream and advance write position.
- /// Byte swap if byte swapping is turned on.
- /// \param x One 64-bit integer.
-
- void Put_int64 (int64 x)
- {
- Put_uint64 ((uint64) x);
- }
-
- /// Get one 32-bit IEEE floating-point number from stream and advance
- /// read position. Byte swap if byte swapping is turned on.
- /// \retval One 32-bit IEEE floating-point number.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- real32 Get_real32 ();
-
- /// Put one 32-bit IEEE floating-point number to stream and advance write
- /// position. Byte swap if byte swapping is turned on.
- /// \param x One 32-bit IEEE floating-point number.
-
- void Put_real32 (real32 x);
-
- /// Get one 64-bit IEEE floating-point number from stream and advance
- /// read position. Byte swap if byte swapping is turned on.
- /// \retval One 64-bit IEEE floating-point number .
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- real64 Get_real64 ();
-
- /// Put one 64-bit IEEE floating-point number to stream and advance write
- /// position. Byte swap if byte swapping is turned on.
- /// \param x One64-bit IEEE floating-point number.
-
- void Put_real64 (real64 x);
-
- /// Get an 8-bit character string from stream and advance read position.
- /// Routine always reads until a NUL character (8-bits of zero) is read.
- /// (That is, only maxLength bytes will be returned in buffer, but the
- /// stream is always advanced until a NUL is read or EOF is reached.)
- /// \param data Buffer in which string is returned.
- /// \param maxLength Maximum number of bytes to place in buffer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if stream runs out before NUL is seen.
-
- void Get_CString (char *data,
- uint32 maxLength);
-
- /// Get a 16-bit character string from stream and advance read position.
- /// 16-bit characters are truncated to 8-bits.
- /// Routine always reads until a NUL character (16-bits of zero) is read.
- /// (That is, only maxLength bytes will be returned in buffer, but the
- /// stream is always advanced until a NUL is read or EOF is reached.)
- /// \param data Buffer to place string in.
- /// \param maxLength Maximum number of bytes to place in buffer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if stream runs out before NUL is seen.
-
- void Get_UString (char *data,
- uint32 maxLength);
-
- /// Writes the specified number of zero bytes to stream.
- /// \param count Number of zero bytes to write.
-
- void PutZeros (uint64 count);
-
- /// Writes zeros to align the stream position to a multiple of 2.
-
- void PadAlign2 ();
-
- /// Writes zeros to align the stream position to a multiple of 4.
-
- void PadAlign4 ();
-
- /// Get a value of size indicated by tag type from stream and advance
- /// read position. Byte swap if byte swapping is turned on and tag type
- /// is larger than a byte. Value is returned as an unsigned 32-bit integer.
- /// \param tagType Tag type of data stored in stream.
- /// \retval One unsigned 32-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- uint32 TagValue_uint32 (uint32 tagType);
-
- /// Get a value of size indicated by tag type from stream and advance read
- /// position. Byte swap if byte swapping is turned on and tag type is larger
- /// than a byte. Value is returned as a 32-bit integer.
- /// \param tagType Tag type of data stored in stream.
- /// \retval One 32-bit integer.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- int32 TagValue_int32 (uint32 tagType);
-
- /// Get a value of size indicated by tag type from stream and advance read
- /// position. Byte swap if byte swapping is turned on and tag type is larger
- /// than a byte. Value is returned as a dng_urational.
- /// \param tagType Tag type of data stored in stream.
- /// \retval One dng_urational.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- dng_urational TagValue_urational (uint32 tagType);
-
- /// Get a value of size indicated by tag type from stream and advance read
- /// position. Byte swap if byte swapping is turned on and tag type is larger
- /// than a byte. Value is returned as a dng_srational.
- /// \param tagType Tag type of data stored in stream.
- /// \retval One dng_srational.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- dng_srational TagValue_srational (uint32 tagType);
-
- /// Get a value of size indicated by tag type from stream and advance read
- /// position. Byte swap if byte swapping is turned on and tag type is larger
- /// than a byte. Value is returned as a 64-bit IEEE floating-point number.
- /// \param tagType Tag type of data stored in stream.
- /// \retval One 64-bit IEEE floating-point number.
- /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
- /// if not enough data in stream.
-
- real64 TagValue_real64 (uint32 tagType);
-
- /// Getter for sniffer associated with stream.
- /// \retval The sniffer for this stream.
-
- dng_abort_sniffer * Sniffer () const
- {
- return fSniffer;
- }
-
- /// Putter for sniffer associated with stream.
- /// \param sniffer The new sniffer to use (or NULL for none).
-
- void SetSniffer (dng_abort_sniffer *sniffer)
- {
- fSniffer = sniffer;
- }
-
- /// Copy a specified number of bytes to a target stream.
- /// \param dstStream The target stream.
- /// \param count The number of bytes to copy.
-
- virtual void CopyToStream (dng_stream &dstStream,
- uint64 count);
-
- /// Makes the target stream a copy of this stream.
- /// \param dstStream The target stream.
-
- void DuplicateStream (dng_stream &dstStream);
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_stream (const dng_stream &stream);
-
- dng_stream & operator= (const dng_stream &stream);
-
- };
-
-/*****************************************************************************/
-
-class TempBigEndian
- {
-
- private:
-
- dng_stream & fStream;
-
- bool fOldSwap;
-
- public:
-
- TempBigEndian (dng_stream &stream,
- bool bigEndian = true);
-
- virtual ~TempBigEndian ();
-
- };
-
-/*****************************************************************************/
-
-class TempLittleEndian: public TempBigEndian
- {
-
- public:
-
- TempLittleEndian (dng_stream &stream,
- bool littleEndian = true)
-
- : TempBigEndian (stream, !littleEndian)
-
- {
- }
-
- virtual ~TempLittleEndian ()
- {
- }
-
- };
-
-/*****************************************************************************/
-
-class TempStreamSniffer
- {
-
- private:
-
- dng_stream & fStream;
-
- dng_abort_sniffer *fOldSniffer;
-
- public:
-
- TempStreamSniffer (dng_stream &stream,
- dng_abort_sniffer *sniffer);
-
- virtual ~TempStreamSniffer ();
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- TempStreamSniffer (const TempStreamSniffer &temp);
-
- TempStreamSniffer & operator= (const TempStreamSniffer &temp);
-
- };
-
-/*****************************************************************************/
-
-class PreserveStreamReadPosition
- {
-
- private:
-
- dng_stream & fStream;
-
- uint64 fPosition;
-
- public:
-
- PreserveStreamReadPosition (dng_stream &stream)
-
- : fStream (stream)
- , fPosition (stream.Position ())
-
- {
- }
-
- ~PreserveStreamReadPosition ()
- {
- fStream.SetReadPosition (fPosition);
- }
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- PreserveStreamReadPosition (const PreserveStreamReadPosition &rhs);
-
- PreserveStreamReadPosition & operator= (const PreserveStreamReadPosition &rhs);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_stream.h#2 $ */
+/* $DateTime: 2012/06/01 07:28:57 $ */
+/* $Change: 832715 $ */
+/* $Author: tknoll $ */
+
+/** Data stream abstraction for serializing and deserializing sequences of
+ * basic types and RAW image data.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_stream__
+#define __dng_stream__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_types.h"
+#include "dng_memory.h"
+#include "dng_rational.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+// Constants for invalid offset in streams.
+
+const uint64 kDNGStreamInvalidOffset = (uint64) (int64) -1;
+
+/*****************************************************************************/
+
+/// Base stream abstraction. Has support for going between stream and pointer
+/// abstraction.
+
+class dng_stream
+ {
+
+ public:
+
+ enum
+ {
+
+ kSmallBufferSize = 4 * 1024,
+ kBigBufferSize = 64 * 1024,
+
+ kDefaultBufferSize = kSmallBufferSize
+
+ };
+
+ private:
+
+ bool fSwapBytes;
+
+ bool fHaveLength;
+
+ uint64 fLength;
+
+ const uint64 fOffsetInOriginalFile;
+
+ uint64 fPosition;
+
+ dng_memory_data fMemBlock;
+
+ uint8 *fBuffer;
+
+ uint32 fBufferSize;
+
+ uint64 fBufferStart;
+ uint64 fBufferEnd;
+ uint64 fBufferLimit;
+
+ bool fBufferDirty;
+
+ dng_abort_sniffer *fSniffer;
+
+ protected:
+
+ dng_stream (dng_abort_sniffer *sniffer = NULL,
+ uint32 bufferSize = kDefaultBufferSize,
+ uint64 offsetInOriginalFile = kDNGStreamInvalidOffset);
+
+ virtual uint64 DoGetLength ();
+
+ virtual void DoRead (void *data,
+ uint32 count,
+ uint64 offset);
+
+ virtual void DoSetLength (uint64 length);
+
+ virtual void DoWrite (const void *data,
+ uint32 count,
+ uint64 offset);
+
+ public:
+
+ /// Construct a stream with initial data.
+ /// \param data Pointer to initial contents of stream.
+ /// \param count Number of bytes data is valid for.
+ /// \param offsetInOriginalFile If data came from a file originally,
+ /// offset can be saved here for later use.
+
+ dng_stream (const void *data,
+ uint32 count,
+ uint64 offsetInOriginalFile = kDNGStreamInvalidOffset);
+
+ virtual ~dng_stream ();
+
+ /// Getter for whether stream is swapping byte order on input/output.
+ /// \retval If true, data will be swapped on input/output.
+
+ bool SwapBytes () const
+ {
+ return fSwapBytes;
+ }
+
+ /// Setter for whether stream is swapping byte order on input/output.
+ /// \param swapBytes If true, stream will swap byte order on input or
+ /// output for future reads/writes.
+
+ void SetSwapBytes (bool swapBytes)
+ {
+ fSwapBytes = swapBytes;
+ }
+
+ /// Getter for whether data in stream is big endian.
+ /// \retval If true, data in stream is big endian.
+
+ bool BigEndian () const;
+
+ /// Setter for whether data in stream is big endian.
+ /// \param bigEndian If true, data in stream is big endian.
+
+ void SetBigEndian (bool bigEndian = true);
+
+ /// Getter for whether data in stream is big endian.
+ /// \retval If true, data in stream is big endian.
+
+ bool LittleEndian () const
+ {
+ return !BigEndian ();
+ }
+
+ /// Setter for whether data in stream is big endian.
+ /// \param littleEndian If true, data in stream is big endian.
+
+ void SetLittleEndian (bool littleEndian = true)
+ {
+ SetBigEndian (!littleEndian);
+ }
+
+ /// Returns the size of the buffer used by the stream.
+
+ uint32 BufferSize () const
+ {
+ return fBufferSize;
+ }
+
+ /// Getter for length of data in stream.
+ /// \retval Length of readable data in stream.
+
+ uint64 Length ()
+ {
+
+ if (!fHaveLength)
+ {
+
+ fLength = DoGetLength ();
+
+ fHaveLength = true;
+
+ }
+
+ return fLength;
+
+ }
+
+ /// Getter for current offset in stream.
+ /// \retval current offset from start of stream.
+
+ uint64 Position () const
+ {
+ return fPosition;
+ }
+
+ /// Getter for current position in original file, taking into account
+ /// OffsetInOriginalFile stream data was taken from.
+ /// \retval kInvalidOffset if no offset in original file is set, sum
+ /// of offset in original file and current position otherwise.
+
+ uint64 PositionInOriginalFile () const;
+
+ /// Getter for offset in original file.
+ /// \retval kInvalidOffset if no offset in original file is set,
+ /// offset in original file otherwise.
+
+ uint64 OffsetInOriginalFile () const;
+
+ /// Return pointer to stream contents if the stream is entirely
+ /// available as a single memory block, NULL otherwise.
+
+ const void * Data () const;
+
+ /// Return the entire stream as a single memory block.
+ /// This works for all streams, but requires copying the data to a new buffer.
+ /// \param allocator Allocator used to allocate memory.
+
+ dng_memory_block * AsMemoryBlock (dng_memory_allocator &allocator);
+
+ /// Seek to a new position in stream for reading.
+
+ void SetReadPosition (uint64 offset);
+
+ /// Skip forward in stream.
+ /// \param delta Number of bytes to skip forward.
+
+ void Skip (uint64 delta)
+ {
+ SetReadPosition (Position () + delta);
+ }
+
+ /// Get data from stream. Exception is thrown and no data is read if
+ /// insufficient data available in stream.
+ /// \param data Buffer to put data into. Must be valid for count bytes.
+ /// \param count Bytes of data to read.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ void Get (void *data, uint32 count);
+
+ /// Seek to a new position in stream for writing.
+
+ void SetWritePosition (uint64 offset);
+
+ /// Force any stored data in stream to be written to underlying storage.
+
+ void Flush ();
+
+ /// Set length of available data.
+ /// \param length Number of bytes of avialble data in stream.
+
+ void SetLength (uint64 length);
+
+ /// Write data to stream.
+ /// \param data Buffer of data to write to stream.
+ /// \param count Bytes of in data.
+
+ void Put (const void *data, uint32 count);
+
+ /// Get an unsigned 8-bit integer from stream and advance read position.
+ /// \retval One unsigned 8-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ uint8 Get_uint8 ()
+ {
+
+ // Fast check to see if in buffer
+
+ if (fPosition >= fBufferStart && fPosition < fBufferEnd)
+ {
+
+ return fBuffer [fPosition++ - fBufferStart];
+
+ }
+
+ // Not in buffer, let main routine do the work.
+
+ uint8 x;
+
+ Get (&x, 1);
+
+ return x;
+
+ }
+
+ /// Put an unsigned 8-bit integer to stream and advance write position.
+ /// \param x One unsigned 8-bit integer.
+
+ void Put_uint8 (uint8 x)
+ {
+
+ if (fBufferDirty &&
+ fPosition >= fBufferStart &&
+ fPosition <= fBufferEnd &&
+ fPosition < fBufferLimit)
+ {
+
+ fBuffer [fPosition - fBufferStart] = x;
+
+ fPosition++;
+
+ if (fBufferEnd < fPosition)
+ fBufferEnd = fPosition;
+
+ fLength = Max_uint64 (Length (), fPosition);
+
+ }
+
+ else
+ {
+
+ Put (&x, 1);
+
+ }
+
+ }
+
+ /// Get an unsigned 16-bit integer from stream and advance read position.
+ /// Byte swap if byte swapping is turned on.
+ /// \retval One unsigned 16-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ uint16 Get_uint16 ();
+
+ /// Put an unsigned 16-bit integer to stream and advance write position.
+ /// Byte swap if byte swapping is turned on.
+ /// \param x One unsigned 16-bit integer.
+
+ void Put_uint16 (uint16 x);
+
+ /// Get an unsigned 32-bit integer from stream and advance read position.
+ /// Byte swap if byte swapping is turned on.
+ /// \retval One unsigned 32-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ uint32 Get_uint32 ();
+
+ /// Put an unsigned 32-bit integer to stream and advance write position.
+ /// Byte swap if byte swapping is turned on.
+ /// \param x One unsigned 32-bit integer.
+
+ void Put_uint32 (uint32 x);
+
+ /// Get an unsigned 64-bit integer from stream and advance read position.
+ /// Byte swap if byte swapping is turned on.
+ /// \retval One unsigned 64-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ uint64 Get_uint64 ();
+
+ /// Put an unsigned 64-bit integer to stream and advance write position.
+ /// Byte swap if byte swapping is turned on.
+ /// \param x One unsigned 64-bit integer.
+
+ void Put_uint64 (uint64 x);
+
+ /// Get one 8-bit integer from stream and advance read position.
+ /// \retval One 8-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ int8 Get_int8 ()
+ {
+ return (int8) Get_uint8 ();
+ }
+
+ /// Put one 8-bit integer to stream and advance write position.
+ /// \param x One 8-bit integer.
+
+ void Put_int8 (int8 x)
+ {
+ Put_uint8 ((uint8) x);
+ }
+
+ /// Get one 16-bit integer from stream and advance read position.
+ /// Byte swap if byte swapping is turned on.
+ /// \retval One 16-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ int16 Get_int16 ()
+ {
+ return (int16) Get_uint16 ();
+ }
+
+ /// Put one 16-bit integer to stream and advance write position.
+ /// Byte swap if byte swapping is turned on.
+ /// \param x One 16-bit integer.
+
+ void Put_int16 (int16 x)
+ {
+ Put_uint16 ((uint16) x);
+ }
+
+ /// Get one 32-bit integer from stream and advance read position.
+ /// Byte swap if byte swapping is turned on.
+ /// \retval One 32-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ int32 Get_int32 ()
+ {
+ return (int32) Get_uint32 ();
+ }
+
+ /// Put one 32-bit integer to stream and advance write position.
+ /// Byte swap if byte swapping is turned on.
+ /// \param x One 32-bit integer.
+
+ void Put_int32 (int32 x)
+ {
+ Put_uint32 ((uint32) x);
+ }
+
+ /// Get one 64-bit integer from stream and advance read position.
+ /// Byte swap if byte swapping is turned on.
+ /// \retval One 64-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ int64 Get_int64 ()
+ {
+ return (int64) Get_uint64 ();
+ }
+
+ /// Put one 64-bit integer to stream and advance write position.
+ /// Byte swap if byte swapping is turned on.
+ /// \param x One 64-bit integer.
+
+ void Put_int64 (int64 x)
+ {
+ Put_uint64 ((uint64) x);
+ }
+
+ /// Get one 32-bit IEEE floating-point number from stream and advance
+ /// read position. Byte swap if byte swapping is turned on.
+ /// \retval One 32-bit IEEE floating-point number.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ real32 Get_real32 ();
+
+ /// Put one 32-bit IEEE floating-point number to stream and advance write
+ /// position. Byte swap if byte swapping is turned on.
+ /// \param x One 32-bit IEEE floating-point number.
+
+ void Put_real32 (real32 x);
+
+ /// Get one 64-bit IEEE floating-point number from stream and advance
+ /// read position. Byte swap if byte swapping is turned on.
+ /// \retval One 64-bit IEEE floating-point number .
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ real64 Get_real64 ();
+
+ /// Put one 64-bit IEEE floating-point number to stream and advance write
+ /// position. Byte swap if byte swapping is turned on.
+ /// \param x One64-bit IEEE floating-point number.
+
+ void Put_real64 (real64 x);
+
+ /// Get an 8-bit character string from stream and advance read position.
+ /// Routine always reads until a NUL character (8-bits of zero) is read.
+ /// (That is, only maxLength bytes will be returned in buffer, but the
+ /// stream is always advanced until a NUL is read or EOF is reached.)
+ /// \param data Buffer in which string is returned.
+ /// \param maxLength Maximum number of bytes to place in buffer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if stream runs out before NUL is seen.
+
+ void Get_CString (char *data,
+ uint32 maxLength);
+
+ /// Get a 16-bit character string from stream and advance read position.
+ /// 16-bit characters are truncated to 8-bits.
+ /// Routine always reads until a NUL character (16-bits of zero) is read.
+ /// (That is, only maxLength bytes will be returned in buffer, but the
+ /// stream is always advanced until a NUL is read or EOF is reached.)
+ /// \param data Buffer to place string in.
+ /// \param maxLength Maximum number of bytes to place in buffer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if stream runs out before NUL is seen.
+
+ void Get_UString (char *data,
+ uint32 maxLength);
+
+ /// Writes the specified number of zero bytes to stream.
+ /// \param count Number of zero bytes to write.
+
+ void PutZeros (uint64 count);
+
+ /// Writes zeros to align the stream position to a multiple of 2.
+
+ void PadAlign2 ();
+
+ /// Writes zeros to align the stream position to a multiple of 4.
+
+ void PadAlign4 ();
+
+ /// Get a value of size indicated by tag type from stream and advance
+ /// read position. Byte swap if byte swapping is turned on and tag type
+ /// is larger than a byte. Value is returned as an unsigned 32-bit integer.
+ /// \param tagType Tag type of data stored in stream.
+ /// \retval One unsigned 32-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ uint32 TagValue_uint32 (uint32 tagType);
+
+ /// Get a value of size indicated by tag type from stream and advance read
+ /// position. Byte swap if byte swapping is turned on and tag type is larger
+ /// than a byte. Value is returned as a 32-bit integer.
+ /// \param tagType Tag type of data stored in stream.
+ /// \retval One 32-bit integer.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ int32 TagValue_int32 (uint32 tagType);
+
+ /// Get a value of size indicated by tag type from stream and advance read
+ /// position. Byte swap if byte swapping is turned on and tag type is larger
+ /// than a byte. Value is returned as a dng_urational.
+ /// \param tagType Tag type of data stored in stream.
+ /// \retval One dng_urational.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ dng_urational TagValue_urational (uint32 tagType);
+
+ /// Get a value of size indicated by tag type from stream and advance read
+ /// position. Byte swap if byte swapping is turned on and tag type is larger
+ /// than a byte. Value is returned as a dng_srational.
+ /// \param tagType Tag type of data stored in stream.
+ /// \retval One dng_srational.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ dng_srational TagValue_srational (uint32 tagType);
+
+ /// Get a value of size indicated by tag type from stream and advance read
+ /// position. Byte swap if byte swapping is turned on and tag type is larger
+ /// than a byte. Value is returned as a 64-bit IEEE floating-point number.
+ /// \param tagType Tag type of data stored in stream.
+ /// \retval One 64-bit IEEE floating-point number.
+ /// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
+ /// if not enough data in stream.
+
+ real64 TagValue_real64 (uint32 tagType);
+
+ /// Getter for sniffer associated with stream.
+ /// \retval The sniffer for this stream.
+
+ dng_abort_sniffer * Sniffer () const
+ {
+ return fSniffer;
+ }
+
+ /// Putter for sniffer associated with stream.
+ /// \param sniffer The new sniffer to use (or NULL for none).
+
+ void SetSniffer (dng_abort_sniffer *sniffer)
+ {
+ fSniffer = sniffer;
+ }
+
+ /// Copy a specified number of bytes to a target stream.
+ /// \param dstStream The target stream.
+ /// \param count The number of bytes to copy.
+
+ virtual void CopyToStream (dng_stream &dstStream,
+ uint64 count);
+
+ /// Makes the target stream a copy of this stream.
+ /// \param dstStream The target stream.
+
+ void DuplicateStream (dng_stream &dstStream);
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_stream (const dng_stream &stream);
+
+ dng_stream & operator= (const dng_stream &stream);
+
+ };
+
+/*****************************************************************************/
+
+class TempBigEndian
+ {
+
+ private:
+
+ dng_stream & fStream;
+
+ bool fOldSwap;
+
+ public:
+
+ TempBigEndian (dng_stream &stream,
+ bool bigEndian = true);
+
+ virtual ~TempBigEndian ();
+
+ };
+
+/*****************************************************************************/
+
+class TempLittleEndian: public TempBigEndian
+ {
+
+ public:
+
+ TempLittleEndian (dng_stream &stream,
+ bool littleEndian = true)
+
+ : TempBigEndian (stream, !littleEndian)
+
+ {
+ }
+
+ virtual ~TempLittleEndian ()
+ {
+ }
+
+ };
+
+/*****************************************************************************/
+
+class TempStreamSniffer
+ {
+
+ private:
+
+ dng_stream & fStream;
+
+ dng_abort_sniffer *fOldSniffer;
+
+ public:
+
+ TempStreamSniffer (dng_stream &stream,
+ dng_abort_sniffer *sniffer);
+
+ virtual ~TempStreamSniffer ();
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ TempStreamSniffer (const TempStreamSniffer &temp);
+
+ TempStreamSniffer & operator= (const TempStreamSniffer &temp);
+
+ };
+
+/*****************************************************************************/
+
+class PreserveStreamReadPosition
+ {
+
+ private:
+
+ dng_stream & fStream;
+
+ uint64 fPosition;
+
+ public:
+
+ PreserveStreamReadPosition (dng_stream &stream)
+
+ : fStream (stream)
+ , fPosition (stream.Position ())
+
+ {
+ }
+
+ ~PreserveStreamReadPosition ()
+ {
+ fStream.SetReadPosition (fPosition);
+ }
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ PreserveStreamReadPosition (const PreserveStreamReadPosition &rhs);
+
+ PreserveStreamReadPosition & operator= (const PreserveStreamReadPosition &rhs);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_string.h b/source/dng_string.h
index 41608f1..94acb85 100644
--- a/source/dng_string.h
+++ b/source/dng_string.h
@@ -1,165 +1,165 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_string.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Text string representation.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_string__
-#define __dng_string__
-
-/*****************************************************************************/
-
-#include "dng_types.h"
-#include "dng_memory.h"
-
-/*****************************************************************************/
-
-class dng_string
- {
-
- private:
-
- // Always stored internally as a UTF-8 encoded string.
-
- dng_memory_data fData;
-
- public:
-
- dng_string ();
-
- dng_string (const dng_string &s);
-
- dng_string & operator= (const dng_string &s);
-
- ~dng_string ();
-
- const char * Get () const;
-
- bool IsASCII () const;
-
- void Set (const char *s);
-
- void Set_ASCII (const char *s);
-
- void Set_UTF8 (const char *s);
-
- uint32 Get_SystemEncoding (dng_memory_data &buffer) const;
-
- void Set_SystemEncoding (const char *s);
-
- bool ValidSystemEncoding () const;
-
- void Set_JIS_X208_1990 (const char *s);
-
- static uint32 DecodeUTF8 (const char *&s,
- uint32 maxBytes = 6,
- bool *isValid = NULL);
-
- static bool IsUTF8 (const char *s);
-
- void Set_UTF8_or_System (const char *s);
-
- uint32 Get_UTF16 (dng_memory_data &buffer) const;
-
- void Set_UTF16 (const uint16 *s);
-
- void Clear ();
-
- void Truncate (uint32 maxBytes);
-
- bool TrimTrailingBlanks ();
-
- bool TrimLeadingBlanks ();
-
- bool IsEmpty () const;
-
- bool NotEmpty () const
- {
- return !IsEmpty ();
- }
-
- uint32 Length () const;
-
- bool operator== (const dng_string &s) const;
-
- bool operator!= (const dng_string &s) const
- {
- return !(*this == s);
- }
-
- // A utility for doing case insensitive comparisons on strings...
-
- static bool Matches (const char *t,
- const char *s,
- bool case_sensitive = false);
-
- // ...wrapped up for use with dng_string.
-
- bool Matches (const char *s,
- bool case_sensitive = false) const;
-
- bool StartsWith (const char *s,
- bool case_sensitive = false) const;
-
- bool EndsWith (const char *s,
- bool case_sensitive = false) const;
-
- bool Contains (const char *s,
- bool case_sensitive = false,
- int32 *match_offset = NULL) const;
-
- bool Replace (const char *old_string,
- const char *new_string,
- bool case_sensitive = true);
-
- bool TrimLeading (const char *s,
- bool case_sensitive = false);
-
- void Append (const char *s);
-
- void SetUppercase ();
-
- void SetLowercase ();
-
- void SetLineEndings (char ending);
-
- void SetLineEndingsToNewLines ()
- {
- SetLineEndings ('\n');
- }
-
- void SetLineEndingsToReturns ()
- {
- SetLineEndings ('\r');
- }
-
- void StripLowASCII ();
-
- void ForceASCII ();
-
- int32 Compare (const dng_string &s) const;
-
- // A utility to convert fields of numbers into comma separated numbers.
-
- void NormalizeAsCommaSeparatedNumbers ();
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_string.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Text string representation.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_string__
+#define __dng_string__
+
+/*****************************************************************************/
+
+#include "dng_types.h"
+#include "dng_memory.h"
+
+/*****************************************************************************/
+
+class dng_string
+ {
+
+ private:
+
+ // Always stored internally as a UTF-8 encoded string.
+
+ dng_memory_data fData;
+
+ public:
+
+ dng_string ();
+
+ dng_string (const dng_string &s);
+
+ dng_string & operator= (const dng_string &s);
+
+ ~dng_string ();
+
+ const char * Get () const;
+
+ bool IsASCII () const;
+
+ void Set (const char *s);
+
+ void Set_ASCII (const char *s);
+
+ void Set_UTF8 (const char *s);
+
+ uint32 Get_SystemEncoding (dng_memory_data &buffer) const;
+
+ void Set_SystemEncoding (const char *s);
+
+ bool ValidSystemEncoding () const;
+
+ void Set_JIS_X208_1990 (const char *s);
+
+ static uint32 DecodeUTF8 (const char *&s,
+ uint32 maxBytes = 6,
+ bool *isValid = NULL);
+
+ static bool IsUTF8 (const char *s);
+
+ void Set_UTF8_or_System (const char *s);
+
+ uint32 Get_UTF16 (dng_memory_data &buffer) const;
+
+ void Set_UTF16 (const uint16 *s);
+
+ void Clear ();
+
+ void Truncate (uint32 maxBytes);
+
+ bool TrimTrailingBlanks ();
+
+ bool TrimLeadingBlanks ();
+
+ bool IsEmpty () const;
+
+ bool NotEmpty () const
+ {
+ return !IsEmpty ();
+ }
+
+ uint32 Length () const;
+
+ bool operator== (const dng_string &s) const;
+
+ bool operator!= (const dng_string &s) const
+ {
+ return !(*this == s);
+ }
+
+ // A utility for doing case insensitive comparisons on strings...
+
+ static bool Matches (const char *t,
+ const char *s,
+ bool case_sensitive = false);
+
+ // ...wrapped up for use with dng_string.
+
+ bool Matches (const char *s,
+ bool case_sensitive = false) const;
+
+ bool StartsWith (const char *s,
+ bool case_sensitive = false) const;
+
+ bool EndsWith (const char *s,
+ bool case_sensitive = false) const;
+
+ bool Contains (const char *s,
+ bool case_sensitive = false,
+ int32 *match_offset = NULL) const;
+
+ bool Replace (const char *old_string,
+ const char *new_string,
+ bool case_sensitive = true);
+
+ bool TrimLeading (const char *s,
+ bool case_sensitive = false);
+
+ void Append (const char *s);
+
+ void SetUppercase ();
+
+ void SetLowercase ();
+
+ void SetLineEndings (char ending);
+
+ void SetLineEndingsToNewLines ()
+ {
+ SetLineEndings ('\n');
+ }
+
+ void SetLineEndingsToReturns ()
+ {
+ SetLineEndings ('\r');
+ }
+
+ void StripLowASCII ();
+
+ void ForceASCII ();
+
+ int32 Compare (const dng_string &s) const;
+
+ // A utility to convert fields of numbers into comma separated numbers.
+
+ void NormalizeAsCommaSeparatedNumbers ();
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_string_list.cpp b/source/dng_string_list.cpp
index 2ae0334..59124e6 100644
--- a/source/dng_string_list.cpp
+++ b/source/dng_string_list.cpp
@@ -1,163 +1,163 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_string_list.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_string_list.h"
-
-#include "dng_bottlenecks.h"
-#include "dng_exceptions.h"
-#include "dng_string.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_string_list::dng_string_list ()
-
- : fCount (0)
- , fAllocated (0)
- , fList (NULL)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_string_list::~dng_string_list ()
- {
-
- Clear ();
-
- }
-
-/*****************************************************************************/
-
-void dng_string_list::Allocate (uint32 minSize)
- {
-
- if (fAllocated < minSize)
- {
-
- uint32 newSize = Max_uint32 (minSize, fAllocated * 2);
-
- dng_string **list = (dng_string **)
- malloc (newSize * sizeof (dng_string *));
-
- if (!list)
- {
-
- ThrowMemoryFull ();
-
- }
-
- if (fCount)
- {
-
- DoCopyBytes (fList, list, fCount * (uint32) sizeof (dng_string *));
-
- }
-
- if (fList)
- {
-
- free (fList);
-
- }
-
- fList = list;
-
- fAllocated = newSize;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_string_list::Insert (uint32 index,
- const dng_string &s)
- {
-
- Allocate (fCount + 1);
-
- dng_string *ss = new dng_string (s);
-
- if (!ss)
- {
-
- ThrowMemoryFull ();
-
- }
-
- fCount++;
-
- for (uint32 j = fCount - 1; j > index; j--)
- {
-
- fList [j] = fList [j - 1];
-
- }
-
- fList [index] = ss;
-
- }
-
-/*****************************************************************************/
-
-bool dng_string_list::Contains (const dng_string &s) const
- {
-
- for (uint32 j = 0; j < fCount; j++)
- {
-
- if ((*this) [j] == s)
- {
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-void dng_string_list::Clear ()
- {
-
- if (fList)
- {
-
- for (uint32 index = 0; index < fCount; index++)
- {
-
- delete fList [index];
-
- }
-
- free (fList);
-
- fList = NULL;
-
- }
-
- fCount = 0;
- fAllocated = 0;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_string_list.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_string_list.h"
+
+#include "dng_bottlenecks.h"
+#include "dng_exceptions.h"
+#include "dng_string.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_string_list::dng_string_list ()
+
+ : fCount (0)
+ , fAllocated (0)
+ , fList (NULL)
+
+ {
+
+ }
+
+/*****************************************************************************/
+
+dng_string_list::~dng_string_list ()
+ {
+
+ Clear ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_string_list::Allocate (uint32 minSize)
+ {
+
+ if (fAllocated < minSize)
+ {
+
+ uint32 newSize = Max_uint32 (minSize, fAllocated * 2);
+
+ dng_string **list = (dng_string **)
+ malloc (newSize * sizeof (dng_string *));
+
+ if (!list)
+ {
+
+ ThrowMemoryFull ();
+
+ }
+
+ if (fCount)
+ {
+
+ DoCopyBytes (fList, list, fCount * (uint32) sizeof (dng_string *));
+
+ }
+
+ if (fList)
+ {
+
+ free (fList);
+
+ }
+
+ fList = list;
+
+ fAllocated = newSize;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_string_list::Insert (uint32 index,
+ const dng_string &s)
+ {
+
+ Allocate (fCount + 1);
+
+ dng_string *ss = new dng_string (s);
+
+ if (!ss)
+ {
+
+ ThrowMemoryFull ();
+
+ }
+
+ fCount++;
+
+ for (uint32 j = fCount - 1; j > index; j--)
+ {
+
+ fList [j] = fList [j - 1];
+
+ }
+
+ fList [index] = ss;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_string_list::Contains (const dng_string &s) const
+ {
+
+ for (uint32 j = 0; j < fCount; j++)
+ {
+
+ if ((*this) [j] == s)
+ {
+
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_string_list::Clear ()
+ {
+
+ if (fList)
+ {
+
+ for (uint32 index = 0; index < fCount; index++)
+ {
+
+ delete fList [index];
+
+ }
+
+ free (fList);
+
+ fList = NULL;
+
+ }
+
+ fCount = 0;
+ fAllocated = 0;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_string_list.h b/source/dng_string_list.h
index c2e78d8..8cdb513 100644
--- a/source/dng_string_list.h
+++ b/source/dng_string_list.h
@@ -1,86 +1,86 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_string_list.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_string_list__
-#define __dng_string_list__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-class dng_string_list
- {
-
- private:
-
- uint32 fCount;
-
- uint32 fAllocated;
-
- dng_string **fList;
-
- public:
-
- dng_string_list ();
-
- ~dng_string_list ();
-
- uint32 Count () const
- {
- return fCount;
- }
-
- dng_string & operator[] (uint32 index)
- {
- return *(fList [index]);
- }
-
- const dng_string & operator[] (uint32 index) const
- {
- return *(fList [index]);
- }
-
- void Allocate (uint32 minSize);
-
- void Insert (uint32 index,
- const dng_string &s);
-
- void Append (const dng_string &s)
- {
- Insert (Count (), s);
- }
-
- bool Contains (const dng_string &s) const;
-
- void Clear ();
-
- private:
-
- // Hidden copy constructor and assignment operator.
-
- dng_string_list (const dng_string_list &list);
-
- dng_string_list & operator= (const dng_string_list &list);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_string_list.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_string_list__
+#define __dng_string_list__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+class dng_string_list
+ {
+
+ private:
+
+ uint32 fCount;
+
+ uint32 fAllocated;
+
+ dng_string **fList;
+
+ public:
+
+ dng_string_list ();
+
+ ~dng_string_list ();
+
+ uint32 Count () const
+ {
+ return fCount;
+ }
+
+ dng_string & operator[] (uint32 index)
+ {
+ return *(fList [index]);
+ }
+
+ const dng_string & operator[] (uint32 index) const
+ {
+ return *(fList [index]);
+ }
+
+ void Allocate (uint32 minSize);
+
+ void Insert (uint32 index,
+ const dng_string &s);
+
+ void Append (const dng_string &s)
+ {
+ Insert (Count (), s);
+ }
+
+ bool Contains (const dng_string &s) const;
+
+ void Clear ();
+
+ private:
+
+ // Hidden copy constructor and assignment operator.
+
+ dng_string_list (const dng_string_list &list);
+
+ dng_string_list & operator= (const dng_string_list &list);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_tag_codes.h b/source/dng_tag_codes.h
index f1332fc..65b23b6 100644
--- a/source/dng_tag_codes.h
+++ b/source/dng_tag_codes.h
@@ -1,543 +1,543 @@
-/*****************************************************************************/
-// Copyright 2006-2011 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_tag_codes.h#3 $ */
-/* $DateTime: 2012/05/31 13:27:06 $ */
-/* $Change: 832568 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_tag_codes__
-#define __dng_tag_codes__
-
-/*****************************************************************************/
-
-// TIFF tags 50706 through 50741 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2003-11-04 & 2003-12-02, purpose "Digital Negative".
-
-// TIFF tags 50778 through 50781 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2004-08-17, purpose "Digital Negative".
-
-// TIFF tags 50827 through 50834 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2004-12-06, purpose "Digital Negative".
-
-// TIFF tag number 50879 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2006-03-23, purpose "Digital Negative".
-
-// TIFF compression numbers 34892 through 34895 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2003-11-04, purpose "Digital Negative".
-
-// TIFF tags numbers 50931 through 50942 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2007-04-30, purpose "Digital Negative".
-
-// TIFF tags numbers 50964 through 50975 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2007-12-17, purpose "Digital Negative".
-
-// TIFF tags numbers 50981 through 50982 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2008-04-01, purpose "Digital Negative".
-
-// TIFF tags numbers 51008 through 51009 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2008-10-15, purpose "Digital Negative".
-
-// TIFF tag number 51022 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2008-12-15, purpose "Digital Negative".
-
-// TIFF tag number 51041 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2009-5-7, purpose "Digital Negative".
-
-// TIFF tags numbers 51089 through 51091 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2011-07-01, purpose "Digital Negative".
-
-// TIFF tags numbers 51107 through 51110 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2011-09-22, purpose "Digital Negative".
-
-// TIFF tag number 51111 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2011-10-07, purpose "Digital Negative".
-
-// TIFF tags numbers 51112 through 51114 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2011-10-25, purpose "Digital Negative".
-
-// TIFF tags number 51125 registered at:
-// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
-// on 2012-05-31, purpose "Digital Negative".
-
-/*****************************************************************************/
-
-// TIFF, DNG, TIFF/EP, and Exif tag codes all share the main TIFF tag code
-// number space. In cases where TIFF/EP and Exif have different values for
-// tags with the same name, "Exif" is appended to the name of the Exif version
-// of the tag.
-
-enum
- {
- tcNewSubFileType = 254,
- tcSubFileType = 255,
- tcImageWidth = 256,
- tcImageLength = 257,
- tcBitsPerSample = 258,
- tcCompression = 259,
- tcPhotometricInterpretation = 262,
- tcThresholding = 263,
- tcCellWidth = 264,
- tcCellLength = 265,
- tcFillOrder = 266,
- tcImageDescription = 270,
- tcMake = 271,
- tcModel = 272,
- tcStripOffsets = 273,
- tcOrientation = 274,
- tcSamplesPerPixel = 277,
- tcRowsPerStrip = 278,
- tcStripByteCounts = 279,
- tcMinSampleValue = 280,
- tcMaxSampleValue = 281,
- tcXResolution = 282,
- tcYResolution = 283,
- tcPlanarConfiguration = 284,
- tcFreeOffsets = 285,
- tcFreeByteCounts = 286,
- tcGrayResponseUnit = 290,
- tcGrayResponseCurve = 291,
- tcResolutionUnit = 296,
- tcTransferFunction = 301,
- tcSoftware = 305,
- tcDateTime = 306,
- tcArtist = 315,
- tcHostComputer = 316,
- tcPredictor = 317,
- tcWhitePoint = 318,
- tcPrimaryChromaticities = 319,
- tcColorMap = 320,
- tcTileWidth = 322,
- tcTileLength = 323,
- tcTileOffsets = 324,
- tcTileByteCounts = 325,
- tcSubIFDs = 330,
- tcExtraSamples = 338,
- tcSampleFormat = 339,
- tcJPEGTables = 347,
- tcJPEGProc = 512,
- tcJPEGInterchangeFormat = 513,
- tcJPEGInterchangeFormatLength = 514,
- tcYCbCrCoefficients = 529,
- tcYCbCrSubSampling = 530,
- tcYCbCrPositioning = 531,
- tcReferenceBlackWhite = 532,
- tcXMP = 700,
- tcKodakCameraSerialNumber = 33405,
- tcCFARepeatPatternDim = 33421,
- tcCFAPattern = 33422,
- tcBatteryLevel = 33423,
- tcKodakDCRPrivateIFD = 33424,
- tcCopyright = 33432,
- tcExposureTime = 33434,
- tcFNumber = 33437,
- tcIPTC_NAA = 33723,
- tcLeafPKTS = 34310,
- tcAdobeData = 34377,
- tcExifIFD = 34665,
- tcICCProfile = 34675,
- tcExposureProgram = 34850,
- tcSpectralSensitivity = 34852,
- tcGPSInfo = 34853,
- tcISOSpeedRatings = 34855, // EXIF 2.3: PhotographicSensitivity.
- tcOECF = 34856,
- tcInterlace = 34857,
- tcTimeZoneOffset = 34858,
- tcSelfTimerMode = 34859,
- tcSensitivityType = 34864,
- tcStandardOutputSensitivity = 34865,
- tcRecommendedExposureIndex = 34866,
- tcISOSpeed = 34867,
- tcISOSpeedLatitudeyyy = 34868,
- tcISOSpeedLatitudezzz = 34869,
- tcExifVersion = 36864,
- tcDateTimeOriginal = 36867,
- tcDateTimeDigitized = 36868,
- tcComponentsConfiguration = 37121,
- tcCompressedBitsPerPixel = 37122,
- tcShutterSpeedValue = 37377,
- tcApertureValue = 37378,
- tcBrightnessValue = 37379,
- tcExposureBiasValue = 37380,
- tcMaxApertureValue = 37381,
- tcSubjectDistance = 37382,
- tcMeteringMode = 37383,
- tcLightSource = 37384,
- tcFlash = 37385,
- tcFocalLength = 37386,
- tcFlashEnergy = 37387,
- tcSpatialFrequencyResponse = 37388,
- tcNoise = 37389,
- tcFocalPlaneXResolution = 37390,
- tcFocalPlaneYResolution = 37391,
- tcFocalPlaneResolutionUnit = 37392,
- tcImageNumber = 37393,
- tcSecurityClassification = 37394,
- tcImageHistory = 37395,
- tcSubjectArea = 37396,
- tcExposureIndex = 37397,
- tcTIFF_EP_StandardID = 37398,
- tcSensingMethod = 37399,
- tcMakerNote = 37500,
- tcUserComment = 37510,
- tcSubsecTime = 37520,
- tcSubsecTimeOriginal = 37521,
- tcSubsecTimeDigitized = 37522,
- tcAdobeLayerData = 37724,
- tcFlashPixVersion = 40960,
- tcColorSpace = 40961,
- tcPixelXDimension = 40962,
- tcPixelYDimension = 40963,
- tcRelatedSoundFile = 40964,
- tcInteroperabilityIFD = 40965,
- tcFlashEnergyExif = 41483,
- tcSpatialFrequencyResponseExif = 41484,
- tcFocalPlaneXResolutionExif = 41486,
- tcFocalPlaneYResolutionExif = 41487,
- tcFocalPlaneResolutionUnitExif = 41488,
- tcSubjectLocation = 41492,
- tcExposureIndexExif = 41493,
- tcSensingMethodExif = 41495,
- tcFileSource = 41728,
- tcSceneType = 41729,
- tcCFAPatternExif = 41730,
- tcCustomRendered = 41985,
- tcExposureMode = 41986,
- tcWhiteBalance = 41987,
- tcDigitalZoomRatio = 41988,
- tcFocalLengthIn35mmFilm = 41989,
- tcSceneCaptureType = 41990,
- tcGainControl = 41991,
- tcContrast = 41992,
- tcSaturation = 41993,
- tcSharpness = 41994,
- tcDeviceSettingDescription = 41995,
- tcSubjectDistanceRange = 41996,
- tcImageUniqueID = 42016,
- tcCameraOwnerNameExif = 42032,
- tcCameraSerialNumberExif = 42033,
- tcLensSpecificationExif = 42034,
- tcLensMakeExif = 42035,
- tcLensModelExif = 42036,
- tcLensSerialNumberExif = 42037,
- tcGamma = 42240,
- tcPrintImageMatchingInfo = 50341,
- tcDNGVersion = 50706,
- tcDNGBackwardVersion = 50707,
- tcUniqueCameraModel = 50708,
- tcLocalizedCameraModel = 50709,
- tcCFAPlaneColor = 50710,
- tcCFALayout = 50711,
- tcLinearizationTable = 50712,
- tcBlackLevelRepeatDim = 50713,
- tcBlackLevel = 50714,
- tcBlackLevelDeltaH = 50715,
- tcBlackLevelDeltaV = 50716,
- tcWhiteLevel = 50717,
- tcDefaultScale = 50718,
- tcDefaultCropOrigin = 50719,
- tcDefaultCropSize = 50720,
- tcColorMatrix1 = 50721,
- tcColorMatrix2 = 50722,
- tcCameraCalibration1 = 50723,
- tcCameraCalibration2 = 50724,
- tcReductionMatrix1 = 50725,
- tcReductionMatrix2 = 50726,
- tcAnalogBalance = 50727,
- tcAsShotNeutral = 50728,
- tcAsShotWhiteXY = 50729,
- tcBaselineExposure = 50730,
- tcBaselineNoise = 50731,
- tcBaselineSharpness = 50732,
- tcBayerGreenSplit = 50733,
- tcLinearResponseLimit = 50734,
- tcCameraSerialNumber = 50735,
- tcLensInfo = 50736,
- tcChromaBlurRadius = 50737,
- tcAntiAliasStrength = 50738,
- tcShadowScale = 50739,
- tcDNGPrivateData = 50740,
- tcMakerNoteSafety = 50741,
- tcCalibrationIlluminant1 = 50778,
- tcCalibrationIlluminant2 = 50779,
- tcBestQualityScale = 50780,
- tcRawDataUniqueID = 50781,
- tcOriginalRawFileName = 50827,
- tcOriginalRawFileData = 50828,
- tcActiveArea = 50829,
- tcMaskedAreas = 50830,
- tcAsShotICCProfile = 50831,
- tcAsShotPreProfileMatrix = 50832,
- tcCurrentICCProfile = 50833,
- tcCurrentPreProfileMatrix = 50834,
- tcColorimetricReference = 50879,
- tcCameraCalibrationSignature = 50931,
- tcProfileCalibrationSignature = 50932,
- tcExtraCameraProfiles = 50933,
- tcAsShotProfileName = 50934,
- tcNoiseReductionApplied = 50935,
- tcProfileName = 50936,
- tcProfileHueSatMapDims = 50937,
- tcProfileHueSatMapData1 = 50938,
- tcProfileHueSatMapData2 = 50939,
- tcProfileToneCurve = 50940,
- tcProfileEmbedPolicy = 50941,
- tcProfileCopyright = 50942,
- tcForwardMatrix1 = 50964,
- tcForwardMatrix2 = 50965,
- tcPreviewApplicationName = 50966,
- tcPreviewApplicationVersion = 50967,
- tcPreviewSettingsName = 50968,
- tcPreviewSettingsDigest = 50969,
- tcPreviewColorSpace = 50970,
- tcPreviewDateTime = 50971,
- tcRawImageDigest = 50972,
- tcOriginalRawFileDigest = 50973,
- tcSubTileBlockSize = 50974,
- tcRowInterleaveFactor = 50975,
- tcProfileLookTableDims = 50981,
- tcProfileLookTableData = 50982,
- tcOpcodeList1 = 51008,
- tcOpcodeList2 = 51009,
- tcOpcodeList3 = 51022,
- tcNoiseProfile = 51041,
- tcOriginalDefaultFinalSize = 51089,
- tcOriginalBestQualityFinalSize = 51090,
- tcOriginalDefaultCropSize = 51091,
- tcProfileHueSatMapEncoding = 51107,
- tcProfileLookTableEncoding = 51108,
- tcBaselineExposureOffset = 51109,
- tcDefaultBlackRender = 51110,
- tcNewRawImageDigest = 51111,
- tcRawToPreviewGain = 51112,
- tcCacheBlob = 51113,
- tcCacheVersion = 51114,
- tcDefaultUserCrop = 51125,
- tcKodakKDCPrivateIFD = 65024
- };
-
-/*****************************************************************************/
-
-// Additional values that can be passed as IFD parent codes.
-
-enum
- {
-
- tcFirstSubIFD = 0x10000,
- tcLastSubIFD = 0x1FFFF,
-
- tcFirstChainedIFD = 0x20000,
- tcLastChainedIFD = 0x2FFFF,
-
- tcFirstMakerNoteIFD = 0x30000,
- tcLastMakerNoteIFD = 0x3FFFF,
-
- tcCanonMakerNote = tcFirstMakerNoteIFD,
- tcCasioMakerNote,
- tcEpsonMakerNote,
- tcFujiMakerNote,
- tcHasselbladMakerNote,
- tcKodakMakerNote,
- tcKodakMakerNote65280,
- tcLeicaMakerNote,
- tcMamiyaMakerNote,
- tcMinoltaMakerNote,
- tcNikonMakerNote,
- tcOlympusMakerNote,
- tcOlympusMakerNote8208,
- tcOlympusMakerNote8224,
- tcOlympusMakerNote8240,
- tcOlympusMakerNote8256,
- tcOlympusMakerNote8272,
- tcOlympusMakerNote12288,
- tcPanasonicMakerNote,
- tcPentaxMakerNote,
- tcPhaseOneMakerNote,
- tcRicohMakerNote,
- tcRicohMakerNoteCameraInfo,
- tcSamsungMakerNote,
- tcSonyMakerNote,
- tcSonyMakerNoteSubInfo,
- tcSonyPrivateIFD1,
- tcSonyPrivateIFD2,
- tcSonyPrivateIFD3A,
- tcSonyPrivateIFD3B,
- tcSonyPrivateIFD3C,
-
- tcCanonCRW = 0x40000,
- tcContaxRAW,
- tcContaxHeader,
- tcFujiRAF,
- tcFujiHeader,
- tcFujiRawInfo1,
- tcFujiRawInfo2,
- tcLeafMOS,
- tcMinoltaMRW,
- tcPanasonicRAW,
- tcFoveonX3F,
- tcJPEG,
- tcAdobePSD
-
- };
-
-/*****************************************************************************/
-
-// GPS tag codes are only valid in the GPS IFD.
-
-enum
- {
- tcGPSVersionID = 0,
- tcGPSLatitudeRef = 1,
- tcGPSLatitude = 2,
- tcGPSLongitudeRef = 3,
- tcGPSLongitude = 4,
- tcGPSAltitudeRef = 5,
- tcGPSAltitude = 6,
- tcGPSTimeStamp = 7,
- tcGPSSatellites = 8,
- tcGPSStatus = 9,
- tcGPSMeasureMode = 10,
- tcGPSDOP = 11,
- tcGPSSpeedRef = 12,
- tcGPSSpeed = 13,
- tcGPSTrackRef = 14,
- tcGPSTrack = 15,
- tcGPSImgDirectionRef = 16,
- tcGPSImgDirection = 17,
- tcGPSMapDatum = 18,
- tcGPSDestLatitudeRef = 19,
- tcGPSDestLatitude = 20,
- tcGPSDestLongitudeRef = 21,
- tcGPSDestLongitude = 22,
- tcGPSDestBearingRef = 23,
- tcGPSDestBearing = 24,
- tcGPSDestDistanceRef = 25,
- tcGPSDestDistance = 26,
- tcGPSProcessingMethod = 27,
- tcGPSAreaInformation = 28,
- tcGPSDateStamp = 29,
- tcGPSDifferential = 30,
- tcGPSHPositioningError = 31
- };
-
-/*****************************************************************************/
-
-// Tag codes used in the Interoperability IFD.
-
-enum
- {
- tcInteroperabilityIndex = 0x0001,
- tcInteroperabilityVersion = 0x0002,
- tcRelatedImageFileFormat = 0x1000,
- tcRelatedImageWidth = 0x1001,
- tcRelatedImageLength = 0x1002
- };
-
-/*****************************************************************************/
-
-// JPEG marker codes.
-
-enum JpegMarker
- {
-
- M_TEM = 0x01,
-
- M_SOF0 = 0xc0,
- M_SOF1 = 0xc1,
- M_SOF2 = 0xc2,
- M_SOF3 = 0xc3,
- M_DHT = 0xc4,
- M_SOF5 = 0xc5,
- M_SOF6 = 0xc6,
- M_SOF7 = 0xc7,
- M_JPG = 0xc8,
- M_SOF9 = 0xc9,
- M_SOF10 = 0xca,
- M_SOF11 = 0xcb,
- M_DAC = 0xcc,
- M_SOF13 = 0xcd,
- M_SOF14 = 0xce,
- M_SOF15 = 0xcf,
-
- M_RST0 = 0xd0,
- M_RST1 = 0xd1,
- M_RST2 = 0xd2,
- M_RST3 = 0xd3,
- M_RST4 = 0xd4,
- M_RST5 = 0xd5,
- M_RST6 = 0xd6,
- M_RST7 = 0xd7,
-
- M_SOI = 0xd8,
- M_EOI = 0xd9,
- M_SOS = 0xda,
- M_DQT = 0xdb,
- M_DNL = 0xdc,
- M_DRI = 0xdd,
- M_DHP = 0xde,
- M_EXP = 0xdf,
-
- M_APP0 = 0xe0,
- M_APP1 = 0xe1,
- M_APP2 = 0xe2,
- M_APP3 = 0xe3,
- M_APP4 = 0xe4,
- M_APP5 = 0xe5,
- M_APP6 = 0xe6,
- M_APP7 = 0xe7,
- M_APP8 = 0xe8,
- M_APP9 = 0xe9,
- M_APP10 = 0xea,
- M_APP11 = 0xeb,
- M_APP12 = 0xec,
- M_APP13 = 0xed,
- M_APP14 = 0xee,
- M_APP15 = 0xef,
-
- M_JPG0 = 0xf0,
- M_JPG1 = 0xf1,
- M_JPG2 = 0xf2,
- M_JPG3 = 0xf3,
- M_JPG4 = 0xf4,
- M_JPG5 = 0xf5,
- M_JPG6 = 0xf6,
- M_JPG7 = 0xf7,
- M_JPG8 = 0xf8,
- M_JPG9 = 0xf9,
- M_JPG10 = 0xfa,
- M_JPG11 = 0xfb,
- M_JPG12 = 0xfc,
- M_JPG13 = 0xfd,
- M_COM = 0xfe,
-
- M_ERROR = 0x100
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2011 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_tag_codes.h#3 $ */
+/* $DateTime: 2012/05/31 13:27:06 $ */
+/* $Change: 832568 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_tag_codes__
+#define __dng_tag_codes__
+
+/*****************************************************************************/
+
+// TIFF tags 50706 through 50741 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2003-11-04 & 2003-12-02, purpose "Digital Negative".
+
+// TIFF tags 50778 through 50781 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2004-08-17, purpose "Digital Negative".
+
+// TIFF tags 50827 through 50834 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2004-12-06, purpose "Digital Negative".
+
+// TIFF tag number 50879 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2006-03-23, purpose "Digital Negative".
+
+// TIFF compression numbers 34892 through 34895 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2003-11-04, purpose "Digital Negative".
+
+// TIFF tags numbers 50931 through 50942 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2007-04-30, purpose "Digital Negative".
+
+// TIFF tags numbers 50964 through 50975 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2007-12-17, purpose "Digital Negative".
+
+// TIFF tags numbers 50981 through 50982 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2008-04-01, purpose "Digital Negative".
+
+// TIFF tags numbers 51008 through 51009 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2008-10-15, purpose "Digital Negative".
+
+// TIFF tag number 51022 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2008-12-15, purpose "Digital Negative".
+
+// TIFF tag number 51041 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2009-5-7, purpose "Digital Negative".
+
+// TIFF tags numbers 51089 through 51091 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2011-07-01, purpose "Digital Negative".
+
+// TIFF tags numbers 51107 through 51110 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2011-09-22, purpose "Digital Negative".
+
+// TIFF tag number 51111 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2011-10-07, purpose "Digital Negative".
+
+// TIFF tags numbers 51112 through 51114 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2011-10-25, purpose "Digital Negative".
+
+// TIFF tags number 51125 registered at:
+// http://partners.adobe.com/asn/tech/tiff/tiffregister.jsp
+// on 2012-05-31, purpose "Digital Negative".
+
+/*****************************************************************************/
+
+// TIFF, DNG, TIFF/EP, and Exif tag codes all share the main TIFF tag code
+// number space. In cases where TIFF/EP and Exif have different values for
+// tags with the same name, "Exif" is appended to the name of the Exif version
+// of the tag.
+
+enum
+ {
+ tcNewSubFileType = 254,
+ tcSubFileType = 255,
+ tcImageWidth = 256,
+ tcImageLength = 257,
+ tcBitsPerSample = 258,
+ tcCompression = 259,
+ tcPhotometricInterpretation = 262,
+ tcThresholding = 263,
+ tcCellWidth = 264,
+ tcCellLength = 265,
+ tcFillOrder = 266,
+ tcImageDescription = 270,
+ tcMake = 271,
+ tcModel = 272,
+ tcStripOffsets = 273,
+ tcOrientation = 274,
+ tcSamplesPerPixel = 277,
+ tcRowsPerStrip = 278,
+ tcStripByteCounts = 279,
+ tcMinSampleValue = 280,
+ tcMaxSampleValue = 281,
+ tcXResolution = 282,
+ tcYResolution = 283,
+ tcPlanarConfiguration = 284,
+ tcFreeOffsets = 285,
+ tcFreeByteCounts = 286,
+ tcGrayResponseUnit = 290,
+ tcGrayResponseCurve = 291,
+ tcResolutionUnit = 296,
+ tcTransferFunction = 301,
+ tcSoftware = 305,
+ tcDateTime = 306,
+ tcArtist = 315,
+ tcHostComputer = 316,
+ tcPredictor = 317,
+ tcWhitePoint = 318,
+ tcPrimaryChromaticities = 319,
+ tcColorMap = 320,
+ tcTileWidth = 322,
+ tcTileLength = 323,
+ tcTileOffsets = 324,
+ tcTileByteCounts = 325,
+ tcSubIFDs = 330,
+ tcExtraSamples = 338,
+ tcSampleFormat = 339,
+ tcJPEGTables = 347,
+ tcJPEGProc = 512,
+ tcJPEGInterchangeFormat = 513,
+ tcJPEGInterchangeFormatLength = 514,
+ tcYCbCrCoefficients = 529,
+ tcYCbCrSubSampling = 530,
+ tcYCbCrPositioning = 531,
+ tcReferenceBlackWhite = 532,
+ tcXMP = 700,
+ tcKodakCameraSerialNumber = 33405,
+ tcCFARepeatPatternDim = 33421,
+ tcCFAPattern = 33422,
+ tcBatteryLevel = 33423,
+ tcKodakDCRPrivateIFD = 33424,
+ tcCopyright = 33432,
+ tcExposureTime = 33434,
+ tcFNumber = 33437,
+ tcIPTC_NAA = 33723,
+ tcLeafPKTS = 34310,
+ tcAdobeData = 34377,
+ tcExifIFD = 34665,
+ tcICCProfile = 34675,
+ tcExposureProgram = 34850,
+ tcSpectralSensitivity = 34852,
+ tcGPSInfo = 34853,
+ tcISOSpeedRatings = 34855, // EXIF 2.3: PhotographicSensitivity.
+ tcOECF = 34856,
+ tcInterlace = 34857,
+ tcTimeZoneOffset = 34858,
+ tcSelfTimerMode = 34859,
+ tcSensitivityType = 34864,
+ tcStandardOutputSensitivity = 34865,
+ tcRecommendedExposureIndex = 34866,
+ tcISOSpeed = 34867,
+ tcISOSpeedLatitudeyyy = 34868,
+ tcISOSpeedLatitudezzz = 34869,
+ tcExifVersion = 36864,
+ tcDateTimeOriginal = 36867,
+ tcDateTimeDigitized = 36868,
+ tcComponentsConfiguration = 37121,
+ tcCompressedBitsPerPixel = 37122,
+ tcShutterSpeedValue = 37377,
+ tcApertureValue = 37378,
+ tcBrightnessValue = 37379,
+ tcExposureBiasValue = 37380,
+ tcMaxApertureValue = 37381,
+ tcSubjectDistance = 37382,
+ tcMeteringMode = 37383,
+ tcLightSource = 37384,
+ tcFlash = 37385,
+ tcFocalLength = 37386,
+ tcFlashEnergy = 37387,
+ tcSpatialFrequencyResponse = 37388,
+ tcNoise = 37389,
+ tcFocalPlaneXResolution = 37390,
+ tcFocalPlaneYResolution = 37391,
+ tcFocalPlaneResolutionUnit = 37392,
+ tcImageNumber = 37393,
+ tcSecurityClassification = 37394,
+ tcImageHistory = 37395,
+ tcSubjectArea = 37396,
+ tcExposureIndex = 37397,
+ tcTIFF_EP_StandardID = 37398,
+ tcSensingMethod = 37399,
+ tcMakerNote = 37500,
+ tcUserComment = 37510,
+ tcSubsecTime = 37520,
+ tcSubsecTimeOriginal = 37521,
+ tcSubsecTimeDigitized = 37522,
+ tcAdobeLayerData = 37724,
+ tcFlashPixVersion = 40960,
+ tcColorSpace = 40961,
+ tcPixelXDimension = 40962,
+ tcPixelYDimension = 40963,
+ tcRelatedSoundFile = 40964,
+ tcInteroperabilityIFD = 40965,
+ tcFlashEnergyExif = 41483,
+ tcSpatialFrequencyResponseExif = 41484,
+ tcFocalPlaneXResolutionExif = 41486,
+ tcFocalPlaneYResolutionExif = 41487,
+ tcFocalPlaneResolutionUnitExif = 41488,
+ tcSubjectLocation = 41492,
+ tcExposureIndexExif = 41493,
+ tcSensingMethodExif = 41495,
+ tcFileSource = 41728,
+ tcSceneType = 41729,
+ tcCFAPatternExif = 41730,
+ tcCustomRendered = 41985,
+ tcExposureMode = 41986,
+ tcWhiteBalance = 41987,
+ tcDigitalZoomRatio = 41988,
+ tcFocalLengthIn35mmFilm = 41989,
+ tcSceneCaptureType = 41990,
+ tcGainControl = 41991,
+ tcContrast = 41992,
+ tcSaturation = 41993,
+ tcSharpness = 41994,
+ tcDeviceSettingDescription = 41995,
+ tcSubjectDistanceRange = 41996,
+ tcImageUniqueID = 42016,
+ tcCameraOwnerNameExif = 42032,
+ tcCameraSerialNumberExif = 42033,
+ tcLensSpecificationExif = 42034,
+ tcLensMakeExif = 42035,
+ tcLensModelExif = 42036,
+ tcLensSerialNumberExif = 42037,
+ tcGamma = 42240,
+ tcPrintImageMatchingInfo = 50341,
+ tcDNGVersion = 50706,
+ tcDNGBackwardVersion = 50707,
+ tcUniqueCameraModel = 50708,
+ tcLocalizedCameraModel = 50709,
+ tcCFAPlaneColor = 50710,
+ tcCFALayout = 50711,
+ tcLinearizationTable = 50712,
+ tcBlackLevelRepeatDim = 50713,
+ tcBlackLevel = 50714,
+ tcBlackLevelDeltaH = 50715,
+ tcBlackLevelDeltaV = 50716,
+ tcWhiteLevel = 50717,
+ tcDefaultScale = 50718,
+ tcDefaultCropOrigin = 50719,
+ tcDefaultCropSize = 50720,
+ tcColorMatrix1 = 50721,
+ tcColorMatrix2 = 50722,
+ tcCameraCalibration1 = 50723,
+ tcCameraCalibration2 = 50724,
+ tcReductionMatrix1 = 50725,
+ tcReductionMatrix2 = 50726,
+ tcAnalogBalance = 50727,
+ tcAsShotNeutral = 50728,
+ tcAsShotWhiteXY = 50729,
+ tcBaselineExposure = 50730,
+ tcBaselineNoise = 50731,
+ tcBaselineSharpness = 50732,
+ tcBayerGreenSplit = 50733,
+ tcLinearResponseLimit = 50734,
+ tcCameraSerialNumber = 50735,
+ tcLensInfo = 50736,
+ tcChromaBlurRadius = 50737,
+ tcAntiAliasStrength = 50738,
+ tcShadowScale = 50739,
+ tcDNGPrivateData = 50740,
+ tcMakerNoteSafety = 50741,
+ tcCalibrationIlluminant1 = 50778,
+ tcCalibrationIlluminant2 = 50779,
+ tcBestQualityScale = 50780,
+ tcRawDataUniqueID = 50781,
+ tcOriginalRawFileName = 50827,
+ tcOriginalRawFileData = 50828,
+ tcActiveArea = 50829,
+ tcMaskedAreas = 50830,
+ tcAsShotICCProfile = 50831,
+ tcAsShotPreProfileMatrix = 50832,
+ tcCurrentICCProfile = 50833,
+ tcCurrentPreProfileMatrix = 50834,
+ tcColorimetricReference = 50879,
+ tcCameraCalibrationSignature = 50931,
+ tcProfileCalibrationSignature = 50932,
+ tcExtraCameraProfiles = 50933,
+ tcAsShotProfileName = 50934,
+ tcNoiseReductionApplied = 50935,
+ tcProfileName = 50936,
+ tcProfileHueSatMapDims = 50937,
+ tcProfileHueSatMapData1 = 50938,
+ tcProfileHueSatMapData2 = 50939,
+ tcProfileToneCurve = 50940,
+ tcProfileEmbedPolicy = 50941,
+ tcProfileCopyright = 50942,
+ tcForwardMatrix1 = 50964,
+ tcForwardMatrix2 = 50965,
+ tcPreviewApplicationName = 50966,
+ tcPreviewApplicationVersion = 50967,
+ tcPreviewSettingsName = 50968,
+ tcPreviewSettingsDigest = 50969,
+ tcPreviewColorSpace = 50970,
+ tcPreviewDateTime = 50971,
+ tcRawImageDigest = 50972,
+ tcOriginalRawFileDigest = 50973,
+ tcSubTileBlockSize = 50974,
+ tcRowInterleaveFactor = 50975,
+ tcProfileLookTableDims = 50981,
+ tcProfileLookTableData = 50982,
+ tcOpcodeList1 = 51008,
+ tcOpcodeList2 = 51009,
+ tcOpcodeList3 = 51022,
+ tcNoiseProfile = 51041,
+ tcOriginalDefaultFinalSize = 51089,
+ tcOriginalBestQualityFinalSize = 51090,
+ tcOriginalDefaultCropSize = 51091,
+ tcProfileHueSatMapEncoding = 51107,
+ tcProfileLookTableEncoding = 51108,
+ tcBaselineExposureOffset = 51109,
+ tcDefaultBlackRender = 51110,
+ tcNewRawImageDigest = 51111,
+ tcRawToPreviewGain = 51112,
+ tcCacheBlob = 51113,
+ tcCacheVersion = 51114,
+ tcDefaultUserCrop = 51125,
+ tcKodakKDCPrivateIFD = 65024
+ };
+
+/*****************************************************************************/
+
+// Additional values that can be passed as IFD parent codes.
+
+enum
+ {
+
+ tcFirstSubIFD = 0x10000,
+ tcLastSubIFD = 0x1FFFF,
+
+ tcFirstChainedIFD = 0x20000,
+ tcLastChainedIFD = 0x2FFFF,
+
+ tcFirstMakerNoteIFD = 0x30000,
+ tcLastMakerNoteIFD = 0x3FFFF,
+
+ tcCanonMakerNote = tcFirstMakerNoteIFD,
+ tcCasioMakerNote,
+ tcEpsonMakerNote,
+ tcFujiMakerNote,
+ tcHasselbladMakerNote,
+ tcKodakMakerNote,
+ tcKodakMakerNote65280,
+ tcLeicaMakerNote,
+ tcMamiyaMakerNote,
+ tcMinoltaMakerNote,
+ tcNikonMakerNote,
+ tcOlympusMakerNote,
+ tcOlympusMakerNote8208,
+ tcOlympusMakerNote8224,
+ tcOlympusMakerNote8240,
+ tcOlympusMakerNote8256,
+ tcOlympusMakerNote8272,
+ tcOlympusMakerNote12288,
+ tcPanasonicMakerNote,
+ tcPentaxMakerNote,
+ tcPhaseOneMakerNote,
+ tcRicohMakerNote,
+ tcRicohMakerNoteCameraInfo,
+ tcSamsungMakerNote,
+ tcSonyMakerNote,
+ tcSonyMakerNoteSubInfo,
+ tcSonyPrivateIFD1,
+ tcSonyPrivateIFD2,
+ tcSonyPrivateIFD3A,
+ tcSonyPrivateIFD3B,
+ tcSonyPrivateIFD3C,
+
+ tcCanonCRW = 0x40000,
+ tcContaxRAW,
+ tcContaxHeader,
+ tcFujiRAF,
+ tcFujiHeader,
+ tcFujiRawInfo1,
+ tcFujiRawInfo2,
+ tcLeafMOS,
+ tcMinoltaMRW,
+ tcPanasonicRAW,
+ tcFoveonX3F,
+ tcJPEG,
+ tcAdobePSD
+
+ };
+
+/*****************************************************************************/
+
+// GPS tag codes are only valid in the GPS IFD.
+
+enum
+ {
+ tcGPSVersionID = 0,
+ tcGPSLatitudeRef = 1,
+ tcGPSLatitude = 2,
+ tcGPSLongitudeRef = 3,
+ tcGPSLongitude = 4,
+ tcGPSAltitudeRef = 5,
+ tcGPSAltitude = 6,
+ tcGPSTimeStamp = 7,
+ tcGPSSatellites = 8,
+ tcGPSStatus = 9,
+ tcGPSMeasureMode = 10,
+ tcGPSDOP = 11,
+ tcGPSSpeedRef = 12,
+ tcGPSSpeed = 13,
+ tcGPSTrackRef = 14,
+ tcGPSTrack = 15,
+ tcGPSImgDirectionRef = 16,
+ tcGPSImgDirection = 17,
+ tcGPSMapDatum = 18,
+ tcGPSDestLatitudeRef = 19,
+ tcGPSDestLatitude = 20,
+ tcGPSDestLongitudeRef = 21,
+ tcGPSDestLongitude = 22,
+ tcGPSDestBearingRef = 23,
+ tcGPSDestBearing = 24,
+ tcGPSDestDistanceRef = 25,
+ tcGPSDestDistance = 26,
+ tcGPSProcessingMethod = 27,
+ tcGPSAreaInformation = 28,
+ tcGPSDateStamp = 29,
+ tcGPSDifferential = 30,
+ tcGPSHPositioningError = 31
+ };
+
+/*****************************************************************************/
+
+// Tag codes used in the Interoperability IFD.
+
+enum
+ {
+ tcInteroperabilityIndex = 0x0001,
+ tcInteroperabilityVersion = 0x0002,
+ tcRelatedImageFileFormat = 0x1000,
+ tcRelatedImageWidth = 0x1001,
+ tcRelatedImageLength = 0x1002
+ };
+
+/*****************************************************************************/
+
+// JPEG marker codes.
+
+enum JpegMarker
+ {
+
+ M_TEM = 0x01,
+
+ M_SOF0 = 0xc0,
+ M_SOF1 = 0xc1,
+ M_SOF2 = 0xc2,
+ M_SOF3 = 0xc3,
+ M_DHT = 0xc4,
+ M_SOF5 = 0xc5,
+ M_SOF6 = 0xc6,
+ M_SOF7 = 0xc7,
+ M_JPG = 0xc8,
+ M_SOF9 = 0xc9,
+ M_SOF10 = 0xca,
+ M_SOF11 = 0xcb,
+ M_DAC = 0xcc,
+ M_SOF13 = 0xcd,
+ M_SOF14 = 0xce,
+ M_SOF15 = 0xcf,
+
+ M_RST0 = 0xd0,
+ M_RST1 = 0xd1,
+ M_RST2 = 0xd2,
+ M_RST3 = 0xd3,
+ M_RST4 = 0xd4,
+ M_RST5 = 0xd5,
+ M_RST6 = 0xd6,
+ M_RST7 = 0xd7,
+
+ M_SOI = 0xd8,
+ M_EOI = 0xd9,
+ M_SOS = 0xda,
+ M_DQT = 0xdb,
+ M_DNL = 0xdc,
+ M_DRI = 0xdd,
+ M_DHP = 0xde,
+ M_EXP = 0xdf,
+
+ M_APP0 = 0xe0,
+ M_APP1 = 0xe1,
+ M_APP2 = 0xe2,
+ M_APP3 = 0xe3,
+ M_APP4 = 0xe4,
+ M_APP5 = 0xe5,
+ M_APP6 = 0xe6,
+ M_APP7 = 0xe7,
+ M_APP8 = 0xe8,
+ M_APP9 = 0xe9,
+ M_APP10 = 0xea,
+ M_APP11 = 0xeb,
+ M_APP12 = 0xec,
+ M_APP13 = 0xed,
+ M_APP14 = 0xee,
+ M_APP15 = 0xef,
+
+ M_JPG0 = 0xf0,
+ M_JPG1 = 0xf1,
+ M_JPG2 = 0xf2,
+ M_JPG3 = 0xf3,
+ M_JPG4 = 0xf4,
+ M_JPG5 = 0xf5,
+ M_JPG6 = 0xf6,
+ M_JPG7 = 0xf7,
+ M_JPG8 = 0xf8,
+ M_JPG9 = 0xf9,
+ M_JPG10 = 0xfa,
+ M_JPG11 = 0xfb,
+ M_JPG12 = 0xfc,
+ M_JPG13 = 0xfd,
+ M_COM = 0xfe,
+
+ M_ERROR = 0x100
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_tag_types.cpp b/source/dng_tag_types.cpp
index fcc34e0..59717e0 100644
--- a/source/dng_tag_types.cpp
+++ b/source/dng_tag_types.cpp
@@ -1,66 +1,66 @@
-/*****************************************************************************/
-// Copyright 2006 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_tag_types.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_tag_types.h"
-
-/*****************************************************************************/
-
-uint32 TagTypeSize (uint32 tagType)
- {
-
- switch (tagType)
- {
-
- case ttByte:
- case ttAscii:
- case ttSByte:
- case ttUndefined:
- {
- return 1;
- }
-
- case ttShort:
- case ttSShort:
- case ttUnicode:
- {
- return 2;
- }
-
- case ttLong:
- case ttSLong:
- case ttFloat:
- case ttIFD:
- {
- return 4;
- }
-
- case ttRational:
- case ttDouble:
- case ttSRational:
- case ttComplex:
- {
- return 8;
- }
-
- default:
- break;
-
- }
-
- return 0;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_tag_types.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_tag_types.h"
+
+/*****************************************************************************/
+
+uint32 TagTypeSize (uint32 tagType)
+ {
+
+ switch (tagType)
+ {
+
+ case ttByte:
+ case ttAscii:
+ case ttSByte:
+ case ttUndefined:
+ {
+ return 1;
+ }
+
+ case ttShort:
+ case ttSShort:
+ case ttUnicode:
+ {
+ return 2;
+ }
+
+ case ttLong:
+ case ttSLong:
+ case ttFloat:
+ case ttIFD:
+ {
+ return 4;
+ }
+
+ case ttRational:
+ case ttDouble:
+ case ttSRational:
+ case ttComplex:
+ {
+ return 8;
+ }
+
+ default:
+ break;
+
+ }
+
+ return 0;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_tag_types.h b/source/dng_tag_types.h
index 46fd6c5..aad0839 100644
--- a/source/dng_tag_types.h
+++ b/source/dng_tag_types.h
@@ -1,52 +1,52 @@
-/*****************************************************************************/
-// Copyright 2006 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_tag_types.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_tag_types__
-#define __dng_tag_types__
-
-/*****************************************************************************/
-
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-enum
- {
- ttByte = 1,
- ttAscii,
- ttShort,
- ttLong,
- ttRational,
- ttSByte,
- ttUndefined,
- ttSShort,
- ttSLong,
- ttSRational,
- ttFloat,
- ttDouble,
- ttIFD,
- ttUnicode,
- ttComplex
- };
-
-/*****************************************************************************/
-
-uint32 TagTypeSize (uint32 tagType);
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_tag_types.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_tag_types__
+#define __dng_tag_types__
+
+/*****************************************************************************/
+
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+enum
+ {
+ ttByte = 1,
+ ttAscii,
+ ttShort,
+ ttLong,
+ ttRational,
+ ttSByte,
+ ttUndefined,
+ ttSShort,
+ ttSLong,
+ ttSRational,
+ ttFloat,
+ ttDouble,
+ ttIFD,
+ ttUnicode,
+ ttComplex
+ };
+
+/*****************************************************************************/
+
+uint32 TagTypeSize (uint32 tagType);
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_tag_values.h b/source/dng_tag_values.h
index 3b295d8..a0c553c 100644
--- a/source/dng_tag_values.h
+++ b/source/dng_tag_values.h
@@ -1,493 +1,493 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_tag_values.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_tag_values__
-#define __dng_tag_values__
-
-/*****************************************************************************/
-
-#include "dng_flags.h"
-
-/*****************************************************************************/
-
-// Values for NewSubFileType tag.
-
-enum
- {
-
- // The main image data.
-
- sfMainImage = 0,
-
- // Preview image for the primary settings.
-
- sfPreviewImage = 1,
-
- // Transparency mask
-
- sfTransparencyMask = 4,
-
- // Preview Transparency mask
-
- sfPreviewMask = sfPreviewImage + sfTransparencyMask,
-
- // Preview image for non-primary settings.
-
- sfAltPreviewImage = 0x10001
-
- };
-
-/******************************************************************************/
-
-// Values for PhotometricInterpretation tag.
-
-enum
- {
-
- piWhiteIsZero = 0,
- piBlackIsZero = 1,
- piRGB = 2,
- piRGBPalette = 3,
- piTransparencyMask = 4,
- piCMYK = 5,
- piYCbCr = 6,
- piCIELab = 8,
- piICCLab = 9,
-
- piCFA = 32803, // TIFF-EP spec
-
- piLinearRaw = 34892
-
- };
-
-/******************************************************************************/
-
-// Values for PlanarConfiguration tag.
-
-enum
- {
-
- pcInterleaved = 1,
- pcPlanar = 2,
-
- // Ordering, using an RGB image as an example:
- //
- // RRRRRRRRRR
- // GGGGGGGGGG
- // BBBBBBBBBB
- // RRRRRRRRRR
- // GGGGGGGGGG
- // BBBBBBBBBB
- //
- // The "Align16" variant additionally ensures that the offset of each
- // plane's row is aligned to an integer multiple of 16 bytes from the
- // beginning of the buffer.
- pcRowInterleaved = 100000, // Internal use only
- pcRowInterleavedAlign16 = 100001 // Internal use only
-
- };
-
-/******************************************************************************/
-
-// Values for ExtraSamples tag.
-
-enum
- {
-
- esUnspecified = 0,
- esAssociatedAlpha = 1,
- esUnassociatedAlpha = 2
-
- };
-
-/******************************************************************************/
-
-// Values for SampleFormat tag.
-
-enum
- {
-
- sfUnsignedInteger = 1,
- sfSignedInteger = 2,
- sfFloatingPoint = 3,
- sfUndefined = 4
-
- };
-
-/******************************************************************************/
-
-// Values for Compression tag.
-
-enum
- {
-
- ccUncompressed = 1,
- ccLZW = 5,
- ccOldJPEG = 6,
- ccJPEG = 7,
- ccDeflate = 8,
- ccPackBits = 32773,
- ccOldDeflate = 32946,
-
- // Used in DNG files in places that allow lossless JPEG.
-
- ccLossyJPEG = 34892
-
- };
-
-/******************************************************************************/
-
-// Values for Predictor tag.
-
-enum
- {
-
- cpNullPredictor = 1,
- cpHorizontalDifference = 2,
- cpFloatingPoint = 3,
-
- cpHorizontalDifferenceX2 = 34892,
- cpHorizontalDifferenceX4 = 34893,
- cpFloatingPointX2 = 34894,
- cpFloatingPointX4 = 34895
-
- };
-
-/******************************************************************************/
-
-// Values for ResolutionUnit tag.
-
-enum
- {
-
- ruNone = 1,
- ruInch = 2,
- ruCM = 3,
- ruMM = 4,
- ruMicroM = 5
-
- };
-
-/******************************************************************************/
-
-// Values for LightSource tag.
-
-enum
- {
-
- lsUnknown = 0,
-
- lsDaylight = 1,
- lsFluorescent = 2,
- lsTungsten = 3,
- lsFlash = 4,
- lsFineWeather = 9,
- lsCloudyWeather = 10,
- lsShade = 11,
- lsDaylightFluorescent = 12, // D 5700 - 7100K
- lsDayWhiteFluorescent = 13, // N 4600 - 5500K
- lsCoolWhiteFluorescent = 14, // W 3800 - 4500K
- lsWhiteFluorescent = 15, // WW 3250 - 3800K
- lsWarmWhiteFluorescent = 16, // L 2600 - 3250K
- lsStandardLightA = 17,
- lsStandardLightB = 18,
- lsStandardLightC = 19,
- lsD55 = 20,
- lsD65 = 21,
- lsD75 = 22,
- lsD50 = 23,
- lsISOStudioTungsten = 24,
-
- lsOther = 255
-
- };
-
-/******************************************************************************/
-
-// Values for ExposureProgram tag.
-
-enum
- {
-
- epUnidentified = 0,
- epManual = 1,
- epProgramNormal = 2,
- epAperturePriority = 3,
- epShutterPriority = 4,
- epProgramCreative = 5,
- epProgramAction = 6,
- epPortraitMode = 7,
- epLandscapeMode = 8
-
- };
-
-/******************************************************************************/
-
-// Values for MeteringMode tag.
-
-enum
- {
-
- mmUnidentified = 0,
- mmAverage = 1,
- mmCenterWeightedAverage = 2,
- mmSpot = 3,
- mmMultiSpot = 4,
- mmPattern = 5,
- mmPartial = 6,
-
- mmOther = 255
-
- };
-
-/******************************************************************************/
-
-// CFA color codes from the TIFF/EP specification.
-
-enum ColorKeyCode
- {
-
- colorKeyRed = 0,
- colorKeyGreen = 1,
- colorKeyBlue = 2,
- colorKeyCyan = 3,
- colorKeyMagenta = 4,
- colorKeyYellow = 5,
- colorKeyWhite = 6,
-
- colorKeyMaxEnum = 0xFF
-
- };
-
-/*****************************************************************************/
-
-// Values for the SensitivityType tag.
-
-enum
- {
-
- stUnknown = 0,
-
- stStandardOutputSensitivity = 1,
- stRecommendedExposureIndex = 2,
- stISOSpeed = 3,
- stSOSandREI = 4,
- stSOSandISOSpeed = 5,
- stREIandISOSpeed = 6,
- stSOSandREIandISOSpeed = 7
-
- };
-
-/*****************************************************************************/
-
-// Values for the ColorimetricReference tag. It specifies the colorimetric
-// reference used for images with PhotometricInterpretation values of CFA
-// or LinearRaw.
-
-enum
- {
-
- // Scene referred (default):
-
- crSceneReferred = 0,
-
- // Output referred using the parameters of the ICC profile PCS.
-
- crICCProfilePCS = 1
-
- };
-
-/*****************************************************************************/
-
-// Values for the ProfileEmbedPolicy tag.
-
-enum
- {
-
- // Freely embedable and copyable into installations that encounter this
- // profile, so long as the profile is only used to process DNG files.
-
- pepAllowCopying = 0,
-
- // Can be embeded in a DNG for portable processing, but cannot be used
- // to process other files that the profile is not embedded in.
-
- pepEmbedIfUsed = 1,
-
- // Can only be used if installed on the machine processing the file.
- // Note that this only applies to stand-alone profiles. Profiles that
- // are already embedded inside a DNG file allowed to remain embedded
- // in that DNG, even if the DNG is resaved.
-
- pepEmbedNever = 2,
-
- // No restricts on profile use or embedding.
-
- pepNoRestrictions = 3
-
- };
-
-/*****************************************************************************/
-
-// Values for the ProfileHueSatMapEncoding and ProfileLookTableEncoding tags.
-
-enum
- {
-
- // 1. Convert linear ProPhoto RGB values to HSV.
- // 2. Use the HSV coordinates to index into the color table.
- // 3. Apply color table result to the original HSV values.
- // 4. Convert modified HSV values back to linear ProPhoto RGB.
-
- encoding_Linear = 0,
-
- // 1. Convert linear ProPhoto RGB values to HSV.
- // 2. Encode V coordinate using sRGB encoding curve.
- // 3. Use the encoded HSV coordinates to index into the color table.
- // 4. Apply color table result to the encoded values from step 2.
- // 5. Decode V coordinate using sRGB decoding curve (inverse of step 2).
- // 6. Convert HSV values back to linear ProPhoto RGB (inverse of step 1).
-
- encoding_sRGB = 1
-
- };
-
-/*****************************************************************************/
-
-// Values for the DefaultBlackRender tag.
-
-enum
- {
-
- // By default, the renderer applies (possibly auto-calculated) black subtraction
- // prior to the look table.
-
- defaultBlackRender_Auto = 0,
-
- // By default, the renderer does not apply any black subtraction prior to the
- // look table.
-
- defaultBlackRender_None = 1
-
- };
-
-/*****************************************************************************/
-
-// Values for the PreviewColorSpace tag.
-
-enum PreviewColorSpaceEnum
- {
-
- previewColorSpace_Unknown = 0,
- previewColorSpace_GrayGamma22 = 1,
- previewColorSpace_sRGB = 2,
- previewColorSpace_AdobeRGB = 3,
- previewColorSpace_ProPhotoRGB = 4,
-
- previewColorSpace_LastValid = previewColorSpace_ProPhotoRGB,
-
- previewColorSpace_MaxEnum = 0xFFFFFFFF
-
- };
-
-/*****************************************************************************/
-
-// Values for CacheVersion tag.
-
-enum
- {
-
- // The low-16 bits are a rendering version number.
-
- cacheVersionMask = 0x0FFFF,
-
- // Default cache version.
-
- cacheVersionDefault = 0x00100,
-
- // Is this an integer preview of a floating point image?
-
- cacheVersionDefloated = 0x10000,
-
- // Is this an flattening preview of an image with tranparency?
-
- cacheVersionFlattened = 0x20000,
-
- // Was this preview build using a the default baseline multi-channel
- // CFA merge (i.e. only using the first channel)?
-
- cacheVersionFakeMerge = 0x40000
-
- };
-
-/*****************************************************************************/
-
-// TIFF-style byte order markers.
-
-enum
- {
-
- byteOrderII = 0x4949, // 'II'
- byteOrderMM = 0x4D4D // 'MM'
-
- };
-
-/*****************************************************************************/
-
-// "Magic" numbers.
-
-enum
- {
-
- // DNG related.
-
- magicTIFF = 42, // TIFF (and DNG)
- magicExtendedProfile = 0x4352, // 'CR'
- magicRawCache = 1022, // Raw cache (fast load data)
-
- // Other raw formats - included here so the DNG SDK can parse them.
-
- magicPanasonic = 85,
- magicOlympusA = 0x4F52,
- magicOlympusB = 0x5352
-
- };
-
-/*****************************************************************************/
-
-// DNG Version numbers
-
-enum
- {
-
- dngVersion_None = 0,
-
- dngVersion_1_0_0_0 = 0x01000000,
- dngVersion_1_1_0_0 = 0x01010000,
- dngVersion_1_2_0_0 = 0x01020000,
- dngVersion_1_3_0_0 = 0x01030000,
- dngVersion_1_4_0_0 = 0x01040000,
-
- dngVersion_Current = dngVersion_1_4_0_0,
-
- dngVersion_SaveDefault = dngVersion_Current
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_tag_values.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_tag_values__
+#define __dng_tag_values__
+
+/*****************************************************************************/
+
+#include "dng_flags.h"
+
+/*****************************************************************************/
+
+// Values for NewSubFileType tag.
+
+enum
+ {
+
+ // The main image data.
+
+ sfMainImage = 0,
+
+ // Preview image for the primary settings.
+
+ sfPreviewImage = 1,
+
+ // Transparency mask
+
+ sfTransparencyMask = 4,
+
+ // Preview Transparency mask
+
+ sfPreviewMask = sfPreviewImage + sfTransparencyMask,
+
+ // Preview image for non-primary settings.
+
+ sfAltPreviewImage = 0x10001
+
+ };
+
+/******************************************************************************/
+
+// Values for PhotometricInterpretation tag.
+
+enum
+ {
+
+ piWhiteIsZero = 0,
+ piBlackIsZero = 1,
+ piRGB = 2,
+ piRGBPalette = 3,
+ piTransparencyMask = 4,
+ piCMYK = 5,
+ piYCbCr = 6,
+ piCIELab = 8,
+ piICCLab = 9,
+
+ piCFA = 32803, // TIFF-EP spec
+
+ piLinearRaw = 34892
+
+ };
+
+/******************************************************************************/
+
+// Values for PlanarConfiguration tag.
+
+enum
+ {
+
+ pcInterleaved = 1,
+ pcPlanar = 2,
+
+ // Ordering, using an RGB image as an example:
+ //
+ // RRRRRRRRRR
+ // GGGGGGGGGG
+ // BBBBBBBBBB
+ // RRRRRRRRRR
+ // GGGGGGGGGG
+ // BBBBBBBBBB
+ //
+ // The "Align16" variant additionally ensures that the offset of each
+ // plane's row is aligned to an integer multiple of 16 bytes from the
+ // beginning of the buffer.
+ pcRowInterleaved = 100000, // Internal use only
+ pcRowInterleavedAlign16 = 100001 // Internal use only
+
+ };
+
+/******************************************************************************/
+
+// Values for ExtraSamples tag.
+
+enum
+ {
+
+ esUnspecified = 0,
+ esAssociatedAlpha = 1,
+ esUnassociatedAlpha = 2
+
+ };
+
+/******************************************************************************/
+
+// Values for SampleFormat tag.
+
+enum
+ {
+
+ sfUnsignedInteger = 1,
+ sfSignedInteger = 2,
+ sfFloatingPoint = 3,
+ sfUndefined = 4
+
+ };
+
+/******************************************************************************/
+
+// Values for Compression tag.
+
+enum
+ {
+
+ ccUncompressed = 1,
+ ccLZW = 5,
+ ccOldJPEG = 6,
+ ccJPEG = 7,
+ ccDeflate = 8,
+ ccPackBits = 32773,
+ ccOldDeflate = 32946,
+
+ // Used in DNG files in places that allow lossless JPEG.
+
+ ccLossyJPEG = 34892
+
+ };
+
+/******************************************************************************/
+
+// Values for Predictor tag.
+
+enum
+ {
+
+ cpNullPredictor = 1,
+ cpHorizontalDifference = 2,
+ cpFloatingPoint = 3,
+
+ cpHorizontalDifferenceX2 = 34892,
+ cpHorizontalDifferenceX4 = 34893,
+ cpFloatingPointX2 = 34894,
+ cpFloatingPointX4 = 34895
+
+ };
+
+/******************************************************************************/
+
+// Values for ResolutionUnit tag.
+
+enum
+ {
+
+ ruNone = 1,
+ ruInch = 2,
+ ruCM = 3,
+ ruMM = 4,
+ ruMicroM = 5
+
+ };
+
+/******************************************************************************/
+
+// Values for LightSource tag.
+
+enum
+ {
+
+ lsUnknown = 0,
+
+ lsDaylight = 1,
+ lsFluorescent = 2,
+ lsTungsten = 3,
+ lsFlash = 4,
+ lsFineWeather = 9,
+ lsCloudyWeather = 10,
+ lsShade = 11,
+ lsDaylightFluorescent = 12, // D 5700 - 7100K
+ lsDayWhiteFluorescent = 13, // N 4600 - 5500K
+ lsCoolWhiteFluorescent = 14, // W 3800 - 4500K
+ lsWhiteFluorescent = 15, // WW 3250 - 3800K
+ lsWarmWhiteFluorescent = 16, // L 2600 - 3250K
+ lsStandardLightA = 17,
+ lsStandardLightB = 18,
+ lsStandardLightC = 19,
+ lsD55 = 20,
+ lsD65 = 21,
+ lsD75 = 22,
+ lsD50 = 23,
+ lsISOStudioTungsten = 24,
+
+ lsOther = 255
+
+ };
+
+/******************************************************************************/
+
+// Values for ExposureProgram tag.
+
+enum
+ {
+
+ epUnidentified = 0,
+ epManual = 1,
+ epProgramNormal = 2,
+ epAperturePriority = 3,
+ epShutterPriority = 4,
+ epProgramCreative = 5,
+ epProgramAction = 6,
+ epPortraitMode = 7,
+ epLandscapeMode = 8
+
+ };
+
+/******************************************************************************/
+
+// Values for MeteringMode tag.
+
+enum
+ {
+
+ mmUnidentified = 0,
+ mmAverage = 1,
+ mmCenterWeightedAverage = 2,
+ mmSpot = 3,
+ mmMultiSpot = 4,
+ mmPattern = 5,
+ mmPartial = 6,
+
+ mmOther = 255
+
+ };
+
+/******************************************************************************/
+
+// CFA color codes from the TIFF/EP specification.
+
+enum ColorKeyCode
+ {
+
+ colorKeyRed = 0,
+ colorKeyGreen = 1,
+ colorKeyBlue = 2,
+ colorKeyCyan = 3,
+ colorKeyMagenta = 4,
+ colorKeyYellow = 5,
+ colorKeyWhite = 6,
+
+ colorKeyMaxEnum = 0xFF
+
+ };
+
+/*****************************************************************************/
+
+// Values for the SensitivityType tag.
+
+enum
+ {
+
+ stUnknown = 0,
+
+ stStandardOutputSensitivity = 1,
+ stRecommendedExposureIndex = 2,
+ stISOSpeed = 3,
+ stSOSandREI = 4,
+ stSOSandISOSpeed = 5,
+ stREIandISOSpeed = 6,
+ stSOSandREIandISOSpeed = 7
+
+ };
+
+/*****************************************************************************/
+
+// Values for the ColorimetricReference tag. It specifies the colorimetric
+// reference used for images with PhotometricInterpretation values of CFA
+// or LinearRaw.
+
+enum
+ {
+
+ // Scene referred (default):
+
+ crSceneReferred = 0,
+
+ // Output referred using the parameters of the ICC profile PCS.
+
+ crICCProfilePCS = 1
+
+ };
+
+/*****************************************************************************/
+
+// Values for the ProfileEmbedPolicy tag.
+
+enum
+ {
+
+ // Freely embedable and copyable into installations that encounter this
+ // profile, so long as the profile is only used to process DNG files.
+
+ pepAllowCopying = 0,
+
+ // Can be embeded in a DNG for portable processing, but cannot be used
+ // to process other files that the profile is not embedded in.
+
+ pepEmbedIfUsed = 1,
+
+ // Can only be used if installed on the machine processing the file.
+ // Note that this only applies to stand-alone profiles. Profiles that
+ // are already embedded inside a DNG file allowed to remain embedded
+ // in that DNG, even if the DNG is resaved.
+
+ pepEmbedNever = 2,
+
+ // No restricts on profile use or embedding.
+
+ pepNoRestrictions = 3
+
+ };
+
+/*****************************************************************************/
+
+// Values for the ProfileHueSatMapEncoding and ProfileLookTableEncoding tags.
+
+enum
+ {
+
+ // 1. Convert linear ProPhoto RGB values to HSV.
+ // 2. Use the HSV coordinates to index into the color table.
+ // 3. Apply color table result to the original HSV values.
+ // 4. Convert modified HSV values back to linear ProPhoto RGB.
+
+ encoding_Linear = 0,
+
+ // 1. Convert linear ProPhoto RGB values to HSV.
+ // 2. Encode V coordinate using sRGB encoding curve.
+ // 3. Use the encoded HSV coordinates to index into the color table.
+ // 4. Apply color table result to the encoded values from step 2.
+ // 5. Decode V coordinate using sRGB decoding curve (inverse of step 2).
+ // 6. Convert HSV values back to linear ProPhoto RGB (inverse of step 1).
+
+ encoding_sRGB = 1
+
+ };
+
+/*****************************************************************************/
+
+// Values for the DefaultBlackRender tag.
+
+enum
+ {
+
+ // By default, the renderer applies (possibly auto-calculated) black subtraction
+ // prior to the look table.
+
+ defaultBlackRender_Auto = 0,
+
+ // By default, the renderer does not apply any black subtraction prior to the
+ // look table.
+
+ defaultBlackRender_None = 1
+
+ };
+
+/*****************************************************************************/
+
+// Values for the PreviewColorSpace tag.
+
+enum PreviewColorSpaceEnum
+ {
+
+ previewColorSpace_Unknown = 0,
+ previewColorSpace_GrayGamma22 = 1,
+ previewColorSpace_sRGB = 2,
+ previewColorSpace_AdobeRGB = 3,
+ previewColorSpace_ProPhotoRGB = 4,
+
+ previewColorSpace_LastValid = previewColorSpace_ProPhotoRGB,
+
+ previewColorSpace_MaxEnum = 0xFFFFFFFF
+
+ };
+
+/*****************************************************************************/
+
+// Values for CacheVersion tag.
+
+enum
+ {
+
+ // The low-16 bits are a rendering version number.
+
+ cacheVersionMask = 0x0FFFF,
+
+ // Default cache version.
+
+ cacheVersionDefault = 0x00100,
+
+ // Is this an integer preview of a floating point image?
+
+ cacheVersionDefloated = 0x10000,
+
+ // Is this an flattening preview of an image with tranparency?
+
+ cacheVersionFlattened = 0x20000,
+
+ // Was this preview build using a the default baseline multi-channel
+ // CFA merge (i.e. only using the first channel)?
+
+ cacheVersionFakeMerge = 0x40000
+
+ };
+
+/*****************************************************************************/
+
+// TIFF-style byte order markers.
+
+enum
+ {
+
+ byteOrderII = 0x4949, // 'II'
+ byteOrderMM = 0x4D4D // 'MM'
+
+ };
+
+/*****************************************************************************/
+
+// "Magic" numbers.
+
+enum
+ {
+
+ // DNG related.
+
+ magicTIFF = 42, // TIFF (and DNG)
+ magicExtendedProfile = 0x4352, // 'CR'
+ magicRawCache = 1022, // Raw cache (fast load data)
+
+ // Other raw formats - included here so the DNG SDK can parse them.
+
+ magicPanasonic = 85,
+ magicOlympusA = 0x4F52,
+ magicOlympusB = 0x5352
+
+ };
+
+/*****************************************************************************/
+
+// DNG Version numbers
+
+enum
+ {
+
+ dngVersion_None = 0,
+
+ dngVersion_1_0_0_0 = 0x01000000,
+ dngVersion_1_1_0_0 = 0x01010000,
+ dngVersion_1_2_0_0 = 0x01020000,
+ dngVersion_1_3_0_0 = 0x01030000,
+ dngVersion_1_4_0_0 = 0x01040000,
+
+ dngVersion_Current = dngVersion_1_4_0_0,
+
+ dngVersion_SaveDefault = dngVersion_Current
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_temperature.cpp b/source/dng_temperature.cpp
index 3635d91..47318ab 100644
--- a/source/dng_temperature.cpp
+++ b/source/dng_temperature.cpp
@@ -1,259 +1,259 @@
-/*****************************************************************************/
-// Copyright 2006 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_temperature.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-#include "dng_temperature.h"
-
-#include "dng_xy_coord.h"
-
-/*****************************************************************************/
-
-// Scale factor between distances in uv space to a more user friendly "tint"
-// parameter.
-
-static const real64 kTintScale = -3000.0;
-
-/*****************************************************************************/
-
-// Table from Wyszecki & Stiles, "Color Science", second edition, page 228.
-
-struct ruvt
- {
- real64 r;
- real64 u;
- real64 v;
- real64 t;
- };
-
-static const ruvt kTempTable [] =
- {
- { 0, 0.18006, 0.26352, -0.24341 },
- { 10, 0.18066, 0.26589, -0.25479 },
- { 20, 0.18133, 0.26846, -0.26876 },
- { 30, 0.18208, 0.27119, -0.28539 },
- { 40, 0.18293, 0.27407, -0.30470 },
- { 50, 0.18388, 0.27709, -0.32675 },
- { 60, 0.18494, 0.28021, -0.35156 },
- { 70, 0.18611, 0.28342, -0.37915 },
- { 80, 0.18740, 0.28668, -0.40955 },
- { 90, 0.18880, 0.28997, -0.44278 },
- { 100, 0.19032, 0.29326, -0.47888 },
- { 125, 0.19462, 0.30141, -0.58204 },
- { 150, 0.19962, 0.30921, -0.70471 },
- { 175, 0.20525, 0.31647, -0.84901 },
- { 200, 0.21142, 0.32312, -1.0182 },
- { 225, 0.21807, 0.32909, -1.2168 },
- { 250, 0.22511, 0.33439, -1.4512 },
- { 275, 0.23247, 0.33904, -1.7298 },
- { 300, 0.24010, 0.34308, -2.0637 },
- { 325, 0.24702, 0.34655, -2.4681 },
- { 350, 0.25591, 0.34951, -2.9641 },
- { 375, 0.26400, 0.35200, -3.5814 },
- { 400, 0.27218, 0.35407, -4.3633 },
- { 425, 0.28039, 0.35577, -5.3762 },
- { 450, 0.28863, 0.35714, -6.7262 },
- { 475, 0.29685, 0.35823, -8.5955 },
- { 500, 0.30505, 0.35907, -11.324 },
- { 525, 0.31320, 0.35968, -15.628 },
- { 550, 0.32129, 0.36011, -23.325 },
- { 575, 0.32931, 0.36038, -40.770 },
- { 600, 0.33724, 0.36051, -116.45 }
- };
-
-/*****************************************************************************/
-
-void dng_temperature::Set_xy_coord (const dng_xy_coord &xy)
- {
-
- // Convert to uv space.
-
- real64 u = 2.0 * xy.x / (1.5 - xy.x + 6.0 * xy.y);
- real64 v = 3.0 * xy.y / (1.5 - xy.x + 6.0 * xy.y);
-
- // Search for line pair coordinate is between.
-
- real64 last_dt = 0.0;
-
- real64 last_dv = 0.0;
- real64 last_du = 0.0;
-
- for (uint32 index = 1; index <= 30; index++)
- {
-
- // Convert slope to delta-u and delta-v, with length 1.
-
- real64 du = 1.0;
- real64 dv = kTempTable [index] . t;
-
- real64 len = sqrt (1.0 + dv * dv);
-
- du /= len;
- dv /= len;
-
- // Find delta from black body point to test coordinate.
-
- real64 uu = u - kTempTable [index] . u;
- real64 vv = v - kTempTable [index] . v;
-
- // Find distance above or below line.
-
- real64 dt = - uu * dv + vv * du;
-
- // If below line, we have found line pair.
-
- if (dt <= 0.0 || index == 30)
- {
-
- // Find fractional weight of two lines.
-
- if (dt > 0.0)
- dt = 0.0;
-
- dt = -dt;
-
- real64 f;
-
- if (index == 1)
- {
- f = 0.0;
- }
- else
- {
- f = dt / (last_dt + dt);
- }
-
- // Interpolate the temperature.
-
- fTemperature = 1.0E6 / (kTempTable [index - 1] . r * f +
- kTempTable [index ] . r * (1.0 - f));
-
- // Find delta from black body point to test coordinate.
-
- uu = u - (kTempTable [index - 1] . u * f +
- kTempTable [index ] . u * (1.0 - f));
-
- vv = v - (kTempTable [index - 1] . v * f +
- kTempTable [index ] . v * (1.0 - f));
-
- // Interpolate vectors along slope.
-
- du = du * (1.0 - f) + last_du * f;
- dv = dv * (1.0 - f) + last_dv * f;
-
- len = sqrt (du * du + dv * dv);
-
- du /= len;
- dv /= len;
-
- // Find distance along slope.
-
- fTint = (uu * du + vv * dv) * kTintScale;
-
- break;
-
- }
-
- // Try next line pair.
-
- last_dt = dt;
-
- last_du = du;
- last_dv = dv;
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_xy_coord dng_temperature::Get_xy_coord () const
- {
-
- dng_xy_coord result;
-
- // Find inverse temperature to use as index.
-
- real64 r = 1.0E6 / fTemperature;
-
- // Convert tint to offset is uv space.
-
- real64 offset = fTint * (1.0 / kTintScale);
-
- // Search for line pair containing coordinate.
-
- for (uint32 index = 0; index <= 29; index++)
- {
-
- if (r < kTempTable [index + 1] . r || index == 29)
- {
-
- // Find relative weight of first line.
-
- real64 f = (kTempTable [index + 1] . r - r) /
- (kTempTable [index + 1] . r - kTempTable [index] . r);
-
- // Interpolate the black body coordinates.
-
- real64 u = kTempTable [index ] . u * f +
- kTempTable [index + 1] . u * (1.0 - f);
-
- real64 v = kTempTable [index ] . v * f +
- kTempTable [index + 1] . v * (1.0 - f);
-
- // Find vectors along slope for each line.
-
- real64 uu1 = 1.0;
- real64 vv1 = kTempTable [index] . t;
-
- real64 uu2 = 1.0;
- real64 vv2 = kTempTable [index + 1] . t;
-
- real64 len1 = sqrt (1.0 + vv1 * vv1);
- real64 len2 = sqrt (1.0 + vv2 * vv2);
-
- uu1 /= len1;
- vv1 /= len1;
-
- uu2 /= len2;
- vv2 /= len2;
-
- // Find vector from black body point.
-
- real64 uu3 = uu1 * f + uu2 * (1.0 - f);
- real64 vv3 = vv1 * f + vv2 * (1.0 - f);
-
- real64 len3 = sqrt (uu3 * uu3 + vv3 * vv3);
-
- uu3 /= len3;
- vv3 /= len3;
-
- // Adjust coordinate along this vector.
-
- u += uu3 * offset;
- v += vv3 * offset;
-
- // Convert to xy coordinates.
-
- result.x = 1.5 * u / (u - 4.0 * v + 2.0);
- result.y = v / (u - 4.0 * v + 2.0);
-
- break;
-
- }
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_temperature.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+#include "dng_temperature.h"
+
+#include "dng_xy_coord.h"
+
+/*****************************************************************************/
+
+// Scale factor between distances in uv space to a more user friendly "tint"
+// parameter.
+
+static const real64 kTintScale = -3000.0;
+
+/*****************************************************************************/
+
+// Table from Wyszecki & Stiles, "Color Science", second edition, page 228.
+
+struct ruvt
+ {
+ real64 r;
+ real64 u;
+ real64 v;
+ real64 t;
+ };
+
+static const ruvt kTempTable [] =
+ {
+ { 0, 0.18006, 0.26352, -0.24341 },
+ { 10, 0.18066, 0.26589, -0.25479 },
+ { 20, 0.18133, 0.26846, -0.26876 },
+ { 30, 0.18208, 0.27119, -0.28539 },
+ { 40, 0.18293, 0.27407, -0.30470 },
+ { 50, 0.18388, 0.27709, -0.32675 },
+ { 60, 0.18494, 0.28021, -0.35156 },
+ { 70, 0.18611, 0.28342, -0.37915 },
+ { 80, 0.18740, 0.28668, -0.40955 },
+ { 90, 0.18880, 0.28997, -0.44278 },
+ { 100, 0.19032, 0.29326, -0.47888 },
+ { 125, 0.19462, 0.30141, -0.58204 },
+ { 150, 0.19962, 0.30921, -0.70471 },
+ { 175, 0.20525, 0.31647, -0.84901 },
+ { 200, 0.21142, 0.32312, -1.0182 },
+ { 225, 0.21807, 0.32909, -1.2168 },
+ { 250, 0.22511, 0.33439, -1.4512 },
+ { 275, 0.23247, 0.33904, -1.7298 },
+ { 300, 0.24010, 0.34308, -2.0637 },
+ { 325, 0.24702, 0.34655, -2.4681 },
+ { 350, 0.25591, 0.34951, -2.9641 },
+ { 375, 0.26400, 0.35200, -3.5814 },
+ { 400, 0.27218, 0.35407, -4.3633 },
+ { 425, 0.28039, 0.35577, -5.3762 },
+ { 450, 0.28863, 0.35714, -6.7262 },
+ { 475, 0.29685, 0.35823, -8.5955 },
+ { 500, 0.30505, 0.35907, -11.324 },
+ { 525, 0.31320, 0.35968, -15.628 },
+ { 550, 0.32129, 0.36011, -23.325 },
+ { 575, 0.32931, 0.36038, -40.770 },
+ { 600, 0.33724, 0.36051, -116.45 }
+ };
+
+/*****************************************************************************/
+
+void dng_temperature::Set_xy_coord (const dng_xy_coord &xy)
+ {
+
+ // Convert to uv space.
+
+ real64 u = 2.0 * xy.x / (1.5 - xy.x + 6.0 * xy.y);
+ real64 v = 3.0 * xy.y / (1.5 - xy.x + 6.0 * xy.y);
+
+ // Search for line pair coordinate is between.
+
+ real64 last_dt = 0.0;
+
+ real64 last_dv = 0.0;
+ real64 last_du = 0.0;
+
+ for (uint32 index = 1; index <= 30; index++)
+ {
+
+ // Convert slope to delta-u and delta-v, with length 1.
+
+ real64 du = 1.0;
+ real64 dv = kTempTable [index] . t;
+
+ real64 len = sqrt (1.0 + dv * dv);
+
+ du /= len;
+ dv /= len;
+
+ // Find delta from black body point to test coordinate.
+
+ real64 uu = u - kTempTable [index] . u;
+ real64 vv = v - kTempTable [index] . v;
+
+ // Find distance above or below line.
+
+ real64 dt = - uu * dv + vv * du;
+
+ // If below line, we have found line pair.
+
+ if (dt <= 0.0 || index == 30)
+ {
+
+ // Find fractional weight of two lines.
+
+ if (dt > 0.0)
+ dt = 0.0;
+
+ dt = -dt;
+
+ real64 f;
+
+ if (index == 1)
+ {
+ f = 0.0;
+ }
+ else
+ {
+ f = dt / (last_dt + dt);
+ }
+
+ // Interpolate the temperature.
+
+ fTemperature = 1.0E6 / (kTempTable [index - 1] . r * f +
+ kTempTable [index ] . r * (1.0 - f));
+
+ // Find delta from black body point to test coordinate.
+
+ uu = u - (kTempTable [index - 1] . u * f +
+ kTempTable [index ] . u * (1.0 - f));
+
+ vv = v - (kTempTable [index - 1] . v * f +
+ kTempTable [index ] . v * (1.0 - f));
+
+ // Interpolate vectors along slope.
+
+ du = du * (1.0 - f) + last_du * f;
+ dv = dv * (1.0 - f) + last_dv * f;
+
+ len = sqrt (du * du + dv * dv);
+
+ du /= len;
+ dv /= len;
+
+ // Find distance along slope.
+
+ fTint = (uu * du + vv * dv) * kTintScale;
+
+ break;
+
+ }
+
+ // Try next line pair.
+
+ last_dt = dt;
+
+ last_du = du;
+ last_dv = dv;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_xy_coord dng_temperature::Get_xy_coord () const
+ {
+
+ dng_xy_coord result;
+
+ // Find inverse temperature to use as index.
+
+ real64 r = 1.0E6 / fTemperature;
+
+ // Convert tint to offset is uv space.
+
+ real64 offset = fTint * (1.0 / kTintScale);
+
+ // Search for line pair containing coordinate.
+
+ for (uint32 index = 0; index <= 29; index++)
+ {
+
+ if (r < kTempTable [index + 1] . r || index == 29)
+ {
+
+ // Find relative weight of first line.
+
+ real64 f = (kTempTable [index + 1] . r - r) /
+ (kTempTable [index + 1] . r - kTempTable [index] . r);
+
+ // Interpolate the black body coordinates.
+
+ real64 u = kTempTable [index ] . u * f +
+ kTempTable [index + 1] . u * (1.0 - f);
+
+ real64 v = kTempTable [index ] . v * f +
+ kTempTable [index + 1] . v * (1.0 - f);
+
+ // Find vectors along slope for each line.
+
+ real64 uu1 = 1.0;
+ real64 vv1 = kTempTable [index] . t;
+
+ real64 uu2 = 1.0;
+ real64 vv2 = kTempTable [index + 1] . t;
+
+ real64 len1 = sqrt (1.0 + vv1 * vv1);
+ real64 len2 = sqrt (1.0 + vv2 * vv2);
+
+ uu1 /= len1;
+ vv1 /= len1;
+
+ uu2 /= len2;
+ vv2 /= len2;
+
+ // Find vector from black body point.
+
+ real64 uu3 = uu1 * f + uu2 * (1.0 - f);
+ real64 vv3 = vv1 * f + vv2 * (1.0 - f);
+
+ real64 len3 = sqrt (uu3 * uu3 + vv3 * vv3);
+
+ uu3 /= len3;
+ vv3 /= len3;
+
+ // Adjust coordinate along this vector.
+
+ u += uu3 * offset;
+ v += vv3 * offset;
+
+ // Convert to xy coordinates.
+
+ result.x = 1.5 * u / (u - 4.0 * v + 2.0);
+ result.y = v / (u - 4.0 * v + 2.0);
+
+ break;
+
+ }
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_temperature.h b/source/dng_temperature.h
index 7d662bd..6c94211 100644
--- a/source/dng_temperature.h
+++ b/source/dng_temperature.h
@@ -1,97 +1,97 @@
-/*****************************************************************************/
-// Copyright 2006 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_temperature.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Representation of color temperature and offset (tint) using black body
- * radiator definition.
- */
-
-#ifndef __dng_temperature__
-#define __dng_temperature__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-class dng_temperature
- {
-
- private:
-
- real64 fTemperature;
-
- real64 fTint;
-
- public:
-
- dng_temperature ()
-
- : fTemperature (0.0)
- , fTint (0.0)
-
- {
- }
-
- dng_temperature (real64 temperature,
- real64 tint)
-
- : fTemperature (temperature)
- , fTint (tint )
-
- {
-
- }
-
- dng_temperature (const dng_xy_coord &xy)
-
- : fTemperature (0.0)
- , fTint (0.0)
-
- {
- Set_xy_coord (xy);
- }
-
- void SetTemperature (real64 temperature)
- {
- fTemperature = temperature;
- }
-
- real64 Temperature () const
- {
- return fTemperature;
- }
-
- void SetTint (real64 tint)
- {
- fTint = tint;
- }
-
- real64 Tint () const
- {
- return fTint;
- }
-
- void Set_xy_coord (const dng_xy_coord &xy);
-
- dng_xy_coord Get_xy_coord () const;
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_temperature.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Representation of color temperature and offset (tint) using black body
+ * radiator definition.
+ */
+
+#ifndef __dng_temperature__
+#define __dng_temperature__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+class dng_temperature
+ {
+
+ private:
+
+ real64 fTemperature;
+
+ real64 fTint;
+
+ public:
+
+ dng_temperature ()
+
+ : fTemperature (0.0)
+ , fTint (0.0)
+
+ {
+ }
+
+ dng_temperature (real64 temperature,
+ real64 tint)
+
+ : fTemperature (temperature)
+ , fTint (tint )
+
+ {
+
+ }
+
+ dng_temperature (const dng_xy_coord &xy)
+
+ : fTemperature (0.0)
+ , fTint (0.0)
+
+ {
+ Set_xy_coord (xy);
+ }
+
+ void SetTemperature (real64 temperature)
+ {
+ fTemperature = temperature;
+ }
+
+ real64 Temperature () const
+ {
+ return fTemperature;
+ }
+
+ void SetTint (real64 tint)
+ {
+ fTint = tint;
+ }
+
+ real64 Tint () const
+ {
+ return fTint;
+ }
+
+ void Set_xy_coord (const dng_xy_coord &xy);
+
+ dng_xy_coord Get_xy_coord () const;
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_tile_iterator.cpp b/source/dng_tile_iterator.cpp
index b91a9dc..6015bc9 100644
--- a/source/dng_tile_iterator.cpp
+++ b/source/dng_tile_iterator.cpp
@@ -1,199 +1,199 @@
-/*****************************************************************************/
-// Copyright 2006 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_tile_iterator.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_tile_iterator.h"
-
-#include "dng_exceptions.h"
-#include "dng_image.h"
-#include "dng_pixel_buffer.h"
-#include "dng_tag_types.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-dng_tile_iterator::dng_tile_iterator (const dng_image &image,
- const dng_rect &area)
-
- : fArea ()
- , fTileWidth (0)
- , fTileHeight (0)
- , fTileTop (0)
- , fTileLeft (0)
- , fRowLeft (0)
- , fLeftPage (0)
- , fRightPage (0)
- , fTopPage (0)
- , fBottomPage (0)
- , fHorizontalPage (0)
- , fVerticalPage (0)
-
- {
-
- Initialize (image.RepeatingTile (),
- area & image.Bounds ());
-
- }
-
-/*****************************************************************************/
-
-dng_tile_iterator::dng_tile_iterator (const dng_point &tileSize,
- const dng_rect &area)
-
- : fArea ()
- , fTileWidth (0)
- , fTileHeight (0)
- , fTileTop (0)
- , fTileLeft (0)
- , fRowLeft (0)
- , fLeftPage (0)
- , fRightPage (0)
- , fTopPage (0)
- , fBottomPage (0)
- , fHorizontalPage (0)
- , fVerticalPage (0)
-
- {
-
- dng_rect tile (area);
-
- tile.b = Min_int32 (tile.b, tile.t + tileSize.v);
- tile.r = Min_int32 (tile.r, tile.l + tileSize.h);
-
- Initialize (tile,
- area);
-
- }
-
-/*****************************************************************************/
-
-dng_tile_iterator::dng_tile_iterator (const dng_rect &tile,
- const dng_rect &area)
-
- : fArea ()
- , fTileWidth (0)
- , fTileHeight (0)
- , fTileTop (0)
- , fTileLeft (0)
- , fRowLeft (0)
- , fLeftPage (0)
- , fRightPage (0)
- , fTopPage (0)
- , fBottomPage (0)
- , fHorizontalPage (0)
- , fVerticalPage (0)
-
- {
-
- Initialize (tile,
- area);
-
- }
-
-/*****************************************************************************/
-
-void dng_tile_iterator::Initialize (const dng_rect &tile,
- const dng_rect &area)
- {
-
- fArea = area;
-
- if (area.IsEmpty ())
- {
-
- fVerticalPage = 0;
- fBottomPage = -1;
-
- return;
-
- }
-
- int32 vOffset = tile.t;
- int32 hOffset = tile.l;
-
- int32 tileHeight = tile.b - vOffset;
- int32 tileWidth = tile.r - hOffset;
-
- fTileHeight = tileHeight;
- fTileWidth = tileWidth;
-
- fLeftPage = (fArea.l - hOffset ) / tileWidth;
- fRightPage = (fArea.r - hOffset - 1) / tileWidth;
-
- fHorizontalPage = fLeftPage;
-
- fTopPage = (fArea.t - vOffset ) / tileHeight;
- fBottomPage = (fArea.b - vOffset - 1) / tileHeight;
-
- fVerticalPage = fTopPage;
-
- fTileLeft = fHorizontalPage * tileWidth + hOffset;
- fTileTop = fVerticalPage * tileHeight + vOffset;
-
- fRowLeft = fTileLeft;
-
- }
-
-/*****************************************************************************/
-
-bool dng_tile_iterator::GetOneTile (dng_rect &tile)
- {
-
- if (fVerticalPage > fBottomPage)
- {
- return false;
- }
-
- if (fVerticalPage > fTopPage)
- tile.t = fTileTop;
- else
- tile.t = fArea.t;
-
- if (fVerticalPage < fBottomPage)
- tile.b = fTileTop + fTileHeight;
- else
- tile.b = fArea.b;
-
- if (fHorizontalPage > fLeftPage)
- tile.l = fTileLeft;
- else
- tile.l = fArea.l;
-
- if (fHorizontalPage < fRightPage)
- tile.r = fTileLeft + fTileWidth;
- else
- tile.r = fArea.r;
-
- if (fHorizontalPage < fRightPage)
- {
- fHorizontalPage++;
- fTileLeft += fTileWidth;
- }
-
- else
- {
-
- fVerticalPage++;
- fTileTop += fTileHeight;
-
- fHorizontalPage = fLeftPage;
- fTileLeft = fRowLeft;
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_tile_iterator.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_tile_iterator.h"
+
+#include "dng_exceptions.h"
+#include "dng_image.h"
+#include "dng_pixel_buffer.h"
+#include "dng_tag_types.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+dng_tile_iterator::dng_tile_iterator (const dng_image &image,
+ const dng_rect &area)
+
+ : fArea ()
+ , fTileWidth (0)
+ , fTileHeight (0)
+ , fTileTop (0)
+ , fTileLeft (0)
+ , fRowLeft (0)
+ , fLeftPage (0)
+ , fRightPage (0)
+ , fTopPage (0)
+ , fBottomPage (0)
+ , fHorizontalPage (0)
+ , fVerticalPage (0)
+
+ {
+
+ Initialize (image.RepeatingTile (),
+ area & image.Bounds ());
+
+ }
+
+/*****************************************************************************/
+
+dng_tile_iterator::dng_tile_iterator (const dng_point &tileSize,
+ const dng_rect &area)
+
+ : fArea ()
+ , fTileWidth (0)
+ , fTileHeight (0)
+ , fTileTop (0)
+ , fTileLeft (0)
+ , fRowLeft (0)
+ , fLeftPage (0)
+ , fRightPage (0)
+ , fTopPage (0)
+ , fBottomPage (0)
+ , fHorizontalPage (0)
+ , fVerticalPage (0)
+
+ {
+
+ dng_rect tile (area);
+
+ tile.b = Min_int32 (tile.b, tile.t + tileSize.v);
+ tile.r = Min_int32 (tile.r, tile.l + tileSize.h);
+
+ Initialize (tile,
+ area);
+
+ }
+
+/*****************************************************************************/
+
+dng_tile_iterator::dng_tile_iterator (const dng_rect &tile,
+ const dng_rect &area)
+
+ : fArea ()
+ , fTileWidth (0)
+ , fTileHeight (0)
+ , fTileTop (0)
+ , fTileLeft (0)
+ , fRowLeft (0)
+ , fLeftPage (0)
+ , fRightPage (0)
+ , fTopPage (0)
+ , fBottomPage (0)
+ , fHorizontalPage (0)
+ , fVerticalPage (0)
+
+ {
+
+ Initialize (tile,
+ area);
+
+ }
+
+/*****************************************************************************/
+
+void dng_tile_iterator::Initialize (const dng_rect &tile,
+ const dng_rect &area)
+ {
+
+ fArea = area;
+
+ if (area.IsEmpty ())
+ {
+
+ fVerticalPage = 0;
+ fBottomPage = -1;
+
+ return;
+
+ }
+
+ int32 vOffset = tile.t;
+ int32 hOffset = tile.l;
+
+ int32 tileHeight = tile.b - vOffset;
+ int32 tileWidth = tile.r - hOffset;
+
+ fTileHeight = tileHeight;
+ fTileWidth = tileWidth;
+
+ fLeftPage = (fArea.l - hOffset ) / tileWidth;
+ fRightPage = (fArea.r - hOffset - 1) / tileWidth;
+
+ fHorizontalPage = fLeftPage;
+
+ fTopPage = (fArea.t - vOffset ) / tileHeight;
+ fBottomPage = (fArea.b - vOffset - 1) / tileHeight;
+
+ fVerticalPage = fTopPage;
+
+ fTileLeft = fHorizontalPage * tileWidth + hOffset;
+ fTileTop = fVerticalPage * tileHeight + vOffset;
+
+ fRowLeft = fTileLeft;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_tile_iterator::GetOneTile (dng_rect &tile)
+ {
+
+ if (fVerticalPage > fBottomPage)
+ {
+ return false;
+ }
+
+ if (fVerticalPage > fTopPage)
+ tile.t = fTileTop;
+ else
+ tile.t = fArea.t;
+
+ if (fVerticalPage < fBottomPage)
+ tile.b = fTileTop + fTileHeight;
+ else
+ tile.b = fArea.b;
+
+ if (fHorizontalPage > fLeftPage)
+ tile.l = fTileLeft;
+ else
+ tile.l = fArea.l;
+
+ if (fHorizontalPage < fRightPage)
+ tile.r = fTileLeft + fTileWidth;
+ else
+ tile.r = fArea.r;
+
+ if (fHorizontalPage < fRightPage)
+ {
+ fHorizontalPage++;
+ fTileLeft += fTileWidth;
+ }
+
+ else
+ {
+
+ fVerticalPage++;
+ fTileTop += fTileHeight;
+
+ fHorizontalPage = fLeftPage;
+ fTileLeft = fRowLeft;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_tile_iterator.h b/source/dng_tile_iterator.h
index 98bdb1c..59a6173 100644
--- a/source/dng_tile_iterator.h
+++ b/source/dng_tile_iterator.h
@@ -1,76 +1,76 @@
-/*****************************************************************************/
-// Copyright 2006 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_tile_iterator.h#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_tile_iterator__
-#define __dng_tile_iterator__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_point.h"
-#include "dng_rect.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-class dng_tile_iterator
- {
-
- private:
-
- dng_rect fArea;
-
- int32 fTileWidth;
- int32 fTileHeight;
-
- int32 fTileTop;
- int32 fTileLeft;
-
- int32 fRowLeft;
-
- int32 fLeftPage;
- int32 fRightPage;
-
- int32 fTopPage;
- int32 fBottomPage;
-
- int32 fHorizontalPage;
- int32 fVerticalPage;
-
- public:
-
- dng_tile_iterator (const dng_image &image,
- const dng_rect &area);
-
- dng_tile_iterator (const dng_point &tileSize,
- const dng_rect &area);
-
- dng_tile_iterator (const dng_rect &tile,
- const dng_rect &area);
-
- bool GetOneTile (dng_rect &tile);
-
- private:
-
- void Initialize (const dng_rect &tile,
- const dng_rect &area);
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_tile_iterator.h#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_tile_iterator__
+#define __dng_tile_iterator__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_point.h"
+#include "dng_rect.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+class dng_tile_iterator
+ {
+
+ private:
+
+ dng_rect fArea;
+
+ int32 fTileWidth;
+ int32 fTileHeight;
+
+ int32 fTileTop;
+ int32 fTileLeft;
+
+ int32 fRowLeft;
+
+ int32 fLeftPage;
+ int32 fRightPage;
+
+ int32 fTopPage;
+ int32 fBottomPage;
+
+ int32 fHorizontalPage;
+ int32 fVerticalPage;
+
+ public:
+
+ dng_tile_iterator (const dng_image &image,
+ const dng_rect &area);
+
+ dng_tile_iterator (const dng_point &tileSize,
+ const dng_rect &area);
+
+ dng_tile_iterator (const dng_rect &tile,
+ const dng_rect &area);
+
+ bool GetOneTile (dng_rect &tile);
+
+ private:
+
+ void Initialize (const dng_rect &tile,
+ const dng_rect &area);
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_tone_curve.cpp b/source/dng_tone_curve.cpp
index 466ca95..458195d 100644
--- a/source/dng_tone_curve.cpp
+++ b/source/dng_tone_curve.cpp
@@ -1,138 +1,138 @@
-/*****************************************************************************/
-// Copyright 2007 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_tone_curve.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_tone_curve.h"
-
-#include "dng_assertions.h"
-#include "dng_spline.h"
-#include "dng_utils.h"
-
-/******************************************************************************/
-
-dng_tone_curve::dng_tone_curve ()
-
- : fCoord ()
-
- {
-
- SetNull ();
-
- }
-
-/******************************************************************************/
-
-bool dng_tone_curve::operator== (const dng_tone_curve &curve) const
- {
-
- return fCoord == curve.fCoord;
-
- }
-
-/******************************************************************************/
-
-void dng_tone_curve::SetNull ()
- {
-
- fCoord.resize (2);
-
- fCoord [0].h = 0.0;
- fCoord [0].v = 0.0;
-
- fCoord [1].h = 1.0;
- fCoord [1].v = 1.0;
-
- }
-
-/******************************************************************************/
-
-bool dng_tone_curve::IsNull () const
- {
-
- dng_tone_curve temp;
-
- return (*this == temp);
-
- }
-
-/******************************************************************************/
-
-void dng_tone_curve::SetInvalid ()
- {
-
- fCoord.clear ();
-
- }
-
-/******************************************************************************/
-
-bool dng_tone_curve::IsValid () const
- {
-
- if (fCoord.size () < 2)
- {
-
- return false;
-
- }
-
- for (uint32 j = 0; j < fCoord.size (); j++)
- {
-
- if (fCoord [j] . h < 0.0 || fCoord [j] . h > 1.0 ||
- fCoord [j] . v < 0.0 || fCoord [j] . v > 1.0)
- {
-
- return false;
-
- }
-
- if (j > 0)
- {
-
- if (fCoord [j] . h <= fCoord [j - 1] . h)
- {
-
- return false;
-
- }
-
- }
-
- }
-
- return true;
-
- }
-
-/******************************************************************************/
-
-void dng_tone_curve::Solve (dng_spline_solver &solver) const
- {
-
- solver.Reset ();
-
- for (uint32 index = 0; index < fCoord.size (); index++)
- {
-
- solver.Add (fCoord [index].h,
- fCoord [index].v);
-
- }
-
- solver.Solve ();
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2007 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_tone_curve.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_tone_curve.h"
+
+#include "dng_assertions.h"
+#include "dng_spline.h"
+#include "dng_utils.h"
+
+/******************************************************************************/
+
+dng_tone_curve::dng_tone_curve ()
+
+ : fCoord ()
+
+ {
+
+ SetNull ();
+
+ }
+
+/******************************************************************************/
+
+bool dng_tone_curve::operator== (const dng_tone_curve &curve) const
+ {
+
+ return fCoord == curve.fCoord;
+
+ }
+
+/******************************************************************************/
+
+void dng_tone_curve::SetNull ()
+ {
+
+ fCoord.resize (2);
+
+ fCoord [0].h = 0.0;
+ fCoord [0].v = 0.0;
+
+ fCoord [1].h = 1.0;
+ fCoord [1].v = 1.0;
+
+ }
+
+/******************************************************************************/
+
+bool dng_tone_curve::IsNull () const
+ {
+
+ dng_tone_curve temp;
+
+ return (*this == temp);
+
+ }
+
+/******************************************************************************/
+
+void dng_tone_curve::SetInvalid ()
+ {
+
+ fCoord.clear ();
+
+ }
+
+/******************************************************************************/
+
+bool dng_tone_curve::IsValid () const
+ {
+
+ if (fCoord.size () < 2)
+ {
+
+ return false;
+
+ }
+
+ for (uint32 j = 0; j < fCoord.size (); j++)
+ {
+
+ if (fCoord [j] . h < 0.0 || fCoord [j] . h > 1.0 ||
+ fCoord [j] . v < 0.0 || fCoord [j] . v > 1.0)
+ {
+
+ return false;
+
+ }
+
+ if (j > 0)
+ {
+
+ if (fCoord [j] . h <= fCoord [j - 1] . h)
+ {
+
+ return false;
+
+ }
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+/******************************************************************************/
+
+void dng_tone_curve::Solve (dng_spline_solver &solver) const
+ {
+
+ solver.Reset ();
+
+ for (uint32 index = 0; index < fCoord.size (); index++)
+ {
+
+ solver.Add (fCoord [index].h,
+ fCoord [index].v);
+
+ }
+
+ solver.Solve ();
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_tone_curve.h b/source/dng_tone_curve.h
index 97dec42..56a6bab 100644
--- a/source/dng_tone_curve.h
+++ b/source/dng_tone_curve.h
@@ -1,65 +1,65 @@
-/*****************************************************************************/
-// Copyright 2007 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_tone_curve.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Representation of 1-dimensional tone curve.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_tone_curve__
-#define __dng_tone_curve__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_memory.h"
-#include "dng_point.h"
-
-/*****************************************************************************/
-
-class dng_tone_curve
- {
-
- public:
-
- dng_std_vector<dng_point_real64> fCoord;
-
- public:
-
- dng_tone_curve ();
-
- bool operator== (const dng_tone_curve &curve) const;
-
- bool operator!= (const dng_tone_curve &curve) const
- {
- return !(*this == curve);
- }
-
- void SetNull ();
-
- bool IsNull () const;
-
- void SetInvalid ();
-
- bool IsValid () const;
-
- void Solve (dng_spline_solver &solver) const;
-
- };
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2007 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_tone_curve.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Representation of 1-dimensional tone curve.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_tone_curve__
+#define __dng_tone_curve__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_memory.h"
+#include "dng_point.h"
+
+/*****************************************************************************/
+
+class dng_tone_curve
+ {
+
+ public:
+
+ dng_std_vector<dng_point_real64> fCoord;
+
+ public:
+
+ dng_tone_curve ();
+
+ bool operator== (const dng_tone_curve &curve) const;
+
+ bool operator!= (const dng_tone_curve &curve) const
+ {
+ return !(*this == curve);
+ }
+
+ void SetNull ();
+
+ bool IsNull () const;
+
+ void SetInvalid ();
+
+ bool IsValid () const;
+
+ void Solve (dng_spline_solver &solver) const;
+
+ };
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_uncopyable.h b/source/dng_uncopyable.h
index f25745a..01f259c 100644
--- a/source/dng_uncopyable.h
+++ b/source/dng_uncopyable.h
@@ -1,48 +1,48 @@
-/*****************************************************************************/
-// Copyright 2012 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_uncopyable.h#1 $ */
-/* $DateTime: 2012/09/05 12:31:51 $ */
-/* $Change: 847652 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#ifndef __dng_uncopyable__
-#define __dng_uncopyable__
-
-/*****************************************************************************/
-
-// Virtual base class to prevent object copies.
-
-class dng_uncopyable
- {
-
- protected:
-
- dng_uncopyable ()
- {
- }
-
- ~dng_uncopyable ()
- {
- }
-
- private:
-
- dng_uncopyable (const dng_uncopyable &);
-
- dng_uncopyable & operator= (const dng_uncopyable &);
-
- };
-
-/*****************************************************************************/
-
-#endif // __dng_uncopyable__
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2012 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_uncopyable.h#1 $ */
+/* $DateTime: 2012/09/05 12:31:51 $ */
+/* $Change: 847652 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#ifndef __dng_uncopyable__
+#define __dng_uncopyable__
+
+/*****************************************************************************/
+
+// Virtual base class to prevent object copies.
+
+class dng_uncopyable
+ {
+
+ protected:
+
+ dng_uncopyable ()
+ {
+ }
+
+ ~dng_uncopyable ()
+ {
+ }
+
+ private:
+
+ dng_uncopyable (const dng_uncopyable &);
+
+ dng_uncopyable & operator= (const dng_uncopyable &);
+
+ };
+
+/*****************************************************************************/
+
+#endif // __dng_uncopyable__
+
+/*****************************************************************************/
diff --git a/source/dng_xmp.cpp b/source/dng_xmp.cpp
index aaed238..c7dc5c4 100644
--- a/source/dng_xmp.cpp
+++ b/source/dng_xmp.cpp
@@ -1,4417 +1,4417 @@
-/*****************************************************************************/
-// Copyright 2006-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_xmp.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-#if qDNGUseXMP
-
-#include "dng_xmp.h"
-
-#include "dng_assertions.h"
-#include "dng_date_time.h"
-#include "dng_exceptions.h"
-#include "dng_exif.h"
-#include "dng_image_writer.h"
-#include "dng_iptc.h"
-#include "dng_negative.h"
-#include "dng_string.h"
-#include "dng_string_list.h"
-#include "dng_utils.h"
-#include "dng_xmp_sdk.h"
-
-/*****************************************************************************/
-
-dng_xmp::dng_xmp (dng_memory_allocator &allocator)
-
- : fAllocator (allocator)
-
- , fSDK (NULL)
-
- {
-
- fSDK = new dng_xmp_sdk ();
-
- if (!fSDK)
- {
- ThrowMemoryFull ();
- }
-
- }
-
-/*****************************************************************************/
-
-dng_xmp::dng_xmp (const dng_xmp &xmp)
-
- : fAllocator (xmp.fAllocator)
-
- , fSDK (NULL)
-
- {
-
- fSDK = new dng_xmp_sdk (*xmp.fSDK);
-
- if (!fSDK)
- {
- ThrowMemoryFull ();
- }
-
- }
-
-/*****************************************************************************/
-
-dng_xmp::~dng_xmp ()
- {
-
- if (fSDK)
- {
-
- delete fSDK;
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_xmp * dng_xmp::Clone () const
- {
-
- dng_xmp *result = new dng_xmp (*this);
-
- if (!result)
- {
- ThrowMemoryFull ();
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::TrimDecimal (char *s)
- {
-
- uint32 len = (uint32) strlen (s);
-
- while (len > 0)
- {
-
- if (s [len - 1] == '0')
- s [--len] = 0;
-
- else
- break;
-
- }
-
- if (len > 0)
- {
-
- if (s [len - 1] == '.')
- s [--len] = 0;
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_string dng_xmp::EncodeFingerprint (const dng_fingerprint &f,
- bool allowInvalid)
- {
-
- dng_string result;
-
- if (f.IsValid () || allowInvalid)
- {
-
- char s [dng_fingerprint::kDNGFingerprintSize * 2 + 1];
-
- f.ToUtf8HexString (s);
-
- result.Set (s);
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-dng_fingerprint dng_xmp::DecodeFingerprint (const dng_string &s)
- {
-
- dng_fingerprint result;
-
- if (s.Length () == 32)
- result.FromUtf8HexString (s.Get ());
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-dng_string dng_xmp::EncodeGPSVersion (uint32 version)
- {
-
- dng_string result;
-
- if (version)
- {
-
- uint8 b0 = (uint8) (version >> 24);
- uint8 b1 = (uint8) (version >> 16);
- uint8 b2 = (uint8) (version >> 8);
- uint8 b3 = (uint8) (version );
-
- if (b0 <= 9 && b1 <= 9 && b2 <= 9 && b3 <= 9)
- {
-
- char s [32];
-
- sprintf (s,
- "%u.%u.%u.%u",
- (unsigned) b0,
- (unsigned) b1,
- (unsigned) b2,
- (unsigned) b3);
-
- result.Set (s);
-
- }
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_xmp::DecodeGPSVersion (const dng_string &s)
- {
-
- uint32 result = 0;
-
- if (s.Length () == 7)
- {
-
- unsigned b0 = 0;
- unsigned b1 = 0;
- unsigned b2 = 0;
- unsigned b3 = 0;
-
- if (sscanf (s.Get (),
- "%u.%u.%u.%u",
- &b0,
- &b1,
- &b2,
- &b3) == 4)
- {
-
- result = (b0 << 24) |
- (b1 << 16) |
- (b2 << 8) |
- (b3 );
-
- }
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-dng_string dng_xmp::EncodeGPSCoordinate (const dng_string &ref,
- const dng_urational *coord)
- {
-
- dng_string result;
-
- if (ref.Length () == 1 && coord [0].IsValid () &&
- coord [1].IsValid ())
- {
-
- char refChar = ForceUppercase (ref.Get () [0]);
-
- if (refChar == 'N' ||
- refChar == 'S' ||
- refChar == 'E' ||
- refChar == 'W')
- {
-
- char s [256];
-
- // Use the seconds case if all three values are
- // integers.
-
- if (coord [0].d == 1 &&
- coord [1].d == 1 &&
- coord [2].d == 1)
- {
-
- sprintf (s,
- "%u,%u,%u%c",
- (unsigned) coord [0].n,
- (unsigned) coord [1].n,
- (unsigned) coord [2].n,
- refChar);
-
- }
-
- // Else we need to use the fractional minutes case.
-
- else
- {
-
- // Find value minutes.
-
- real64 x = coord [0].As_real64 () * 60.0 +
- coord [1].As_real64 () +
- coord [2].As_real64 () * (1.0 / 60.0);
-
- // Round to fractional four decimal places.
-
- uint32 y = Round_uint32 (x * 10000.0);
-
- // Split into degrees and minutes.
-
- uint32 d = y / (60 * 10000);
- uint32 m = y % (60 * 10000);
-
- char min [32];
-
- sprintf (min, "%.4f", m * (1.0 / 10000.0));
-
- TrimDecimal (min);
-
- sprintf (s,
- "%u,%s%c",
- (unsigned) d,
- min,
- refChar);
-
- }
-
- result.Set (s);
-
- }
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::DecodeGPSCoordinate (const dng_string &s,
- dng_string &ref,
- dng_urational *coord)
- {
-
- ref.Clear ();
-
- coord [0].Clear ();
- coord [1].Clear ();
- coord [2].Clear ();
-
- if (s.Length () > 1)
- {
-
- char refChar = ForceUppercase (s.Get () [s.Length () - 1]);
-
- if (refChar == 'N' ||
- refChar == 'S' ||
- refChar == 'E' ||
- refChar == 'W')
- {
-
- dng_string ss (s);
-
- ss.Truncate (ss.Length () - 1);
-
- ss.NormalizeAsCommaSeparatedNumbers();
-
- int degrees = 0;
-
- real64 minutes = 0.0;
- real64 seconds = 0.0;
-
- int count = sscanf (ss.Get (),
- "%d,%lf,%lf",
- &degrees,
- &minutes,
- &seconds);
-
- if (count < 1)
- {
- return;
- }
-
- // The degree, minute, second values should always be positive.
-
- if (degrees < 0 || minutes < 0 || seconds < 0)
- {
- return;
- }
-
- coord [0] = dng_urational ((uint32) degrees, 1);
-
- if (count <= 2)
- {
- coord [1].Set_real64 (minutes, 10000);
- coord [2] = dng_urational (0, 1);
- }
- else
- {
- coord [1].Set_real64 (minutes, 1);
- coord [2].Set_real64 (seconds, 100);
- }
-
- char r [2];
-
- r [0] = refChar;
- r [1] = 0;
-
- ref.Set (r);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_string dng_xmp::EncodeGPSDateTime (const dng_string &dateStamp,
- const dng_urational *timeStamp)
- {
-
- dng_string result;
-
- if (timeStamp [0].IsValid () &&
- timeStamp [1].IsValid () &&
- timeStamp [2].IsValid ())
- {
-
- char s [256];
-
- char sec [32];
-
- sprintf (sec,
- "%09.6f",
- timeStamp [2].As_real64 ());
-
- TrimDecimal (sec);
-
- int year = 0;
- int month = 0;
- int day = 0;
-
- if (dateStamp.NotEmpty ())
- {
-
- sscanf (dateStamp.Get (),
- "%d:%d:%d",
- &year,
- &month,
- &day);
-
- }
-
- if (year >= 1 && year <= 9999 &&
- month >= 1 && month <= 12 &&
- day >= 1 && day <= 31)
- {
-
- sprintf (s,
- "%04d-%02d-%02dT%02u:%02u:%sZ",
- year,
- month,
- day,
- (unsigned) Round_uint32 (timeStamp [0].As_real64 ()),
- (unsigned) Round_uint32 (timeStamp [1].As_real64 ()),
- sec);
-
- }
-
- else
- {
-
- sprintf (s,
- "%02u:%02u:%sZ",
- (unsigned) Round_uint32 (timeStamp [0].As_real64 ()),
- (unsigned) Round_uint32 (timeStamp [1].As_real64 ()),
- sec);
-
- }
-
- result.Set (s);
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::DecodeGPSDateTime (const dng_string &s,
- dng_string &dateStamp,
- dng_urational *timeStamp)
- {
-
- dateStamp.Clear ();
-
- timeStamp [0].Clear ();
- timeStamp [1].Clear ();
- timeStamp [2].Clear ();
-
- if (s.NotEmpty ())
- {
-
- unsigned year = 0;
- unsigned month = 0;
- unsigned day = 0;
- unsigned hour = 0;
- unsigned minute = 0;
-
- double second = 0.0;
-
- if (sscanf (s.Get (),
- "%u-%u-%uT%u:%u:%lf",
- &year,
- &month,
- &day,
- &hour,
- &minute,
- &second) == 6)
- {
-
- if (year >= 1 && year <= 9999 &&
- month >= 1 && month <= 12 &&
- day >= 1 && day <= 31 )
- {
-
- char ss [64];
-
- sprintf (ss,
- "%04u:%02u:%02u",
- year,
- month,
- day);
-
- dateStamp.Set (ss);
-
- }
-
- }
-
- else if (sscanf (s.Get (),
- "%u:%u:%lf",
- &hour,
- &minute,
- &second) != 3)
- {
-
- return;
-
- }
-
- timeStamp [0] = dng_urational ((uint32) hour , 1);
- timeStamp [1] = dng_urational ((uint32) minute, 1);
-
- timeStamp [2].Set_real64 (second, 1000);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Parse (dng_host &host,
- const void *buffer,
- uint32 count)
- {
-
- fSDK->Parse (host,
- (const char *) buffer,
- count);
-
- }
-
-/*****************************************************************************/
-
-dng_memory_block * dng_xmp::Serialize (bool asPacket,
- uint32 targetBytes,
- uint32 padBytes,
- bool forJPEG,
- bool compact) const
- {
-
- return fSDK->Serialize (fAllocator,
- asPacket,
- targetBytes,
- padBytes,
- forJPEG,
- compact);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::PackageForJPEG (AutoPtr<dng_memory_block> &stdBlock,
- AutoPtr<dng_memory_block> &extBlock,
- dng_string &extDigest) const
- {
-
- fSDK->PackageForJPEG (fAllocator,
- stdBlock,
- extBlock,
- extDigest);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::MergeFromJPEG (const dng_xmp &xmp)
- {
-
- fSDK->MergeFromJPEG (xmp.fSDK);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::HasMeta () const
- {
-
- return fSDK->HasMeta ();
-
- }
-
-/*****************************************************************************/
-
-void * dng_xmp::GetPrivateMeta ()
- {
-
- return fSDK->GetPrivateMeta ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::Exists (const char *ns,
- const char *path) const
- {
-
- return fSDK->Exists (ns, path);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::HasNameSpace (const char *ns) const
- {
-
- return fSDK->HasNameSpace (ns);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::IteratePaths (IteratePathsCallback *callback,
- void *callbackData,
- const char *ns,
- const char *path)
- {
-
- return fSDK->IteratePaths (callback, callbackData, ns, path);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Remove (const char *ns,
- const char *path)
- {
-
- fSDK->Remove (ns, path);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::RemoveProperties (const char *ns)
- {
-
- fSDK->RemoveProperties (ns);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::RemoveEmptyStringOrArray (const char *ns,
- const char *path)
- {
-
- if (path == NULL || path [0] == 0)
- {
- return;
- }
-
- if (fSDK->IsEmptyString (ns, path) ||
- fSDK->IsEmptyArray (ns, path))
- {
-
- Remove (ns, path);
-
- }
-
- }
-
-/*****************************************************************************/
-
-static bool RemoveEmptyStringsAndArraysCallback (const char *ns,
- const char *path,
- void *callbackData)
- {
-
- dng_xmp *xmp = (dng_xmp *) callbackData;
-
- xmp->RemoveEmptyStringOrArray (ns, path);
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::RemoveEmptyStringsAndArrays (const char *ns)
- {
-
- IteratePaths (RemoveEmptyStringsAndArraysCallback,
- (void *) this,
- ns,
- NULL);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Set (const char *ns,
- const char *path,
- const char *text)
- {
-
- fSDK->Set (ns, path, text);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::GetString (const char *ns,
- const char *path,
- dng_string &s) const
- {
-
- return fSDK->GetString (ns, path, s);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SetString (const char *ns,
- const char *path,
- const dng_string &s)
- {
-
- fSDK->SetString (ns, path, s);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::SyncString (const char *ns,
- const char *path,
- dng_string &s,
- uint32 options)
- {
-
- bool isDefault = s.IsEmpty ();
-
- // Sync 1: Force XMP to match non-XMP.
-
- if (options & ignoreXMP)
- {
-
- if (isDefault || (options & removeXMP))
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- SetString (ns, path, s);
-
- }
-
- return false;
-
- }
-
- // Sync 2: From non-XMP to XMP if non-XMP is prefered.
-
- if ((options & preferNonXMP) && !isDefault)
- {
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- SetString (ns, path, s);
-
- }
-
- return false;
-
- }
-
- // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
-
- if ((options & preferXMP) || isDefault)
- {
-
- if (GetString (ns, path, s))
- {
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- return true;
-
- }
-
- }
-
- // Sync 4: From non-XMP to XMP.
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- else if (!isDefault)
- {
-
- SetString (ns, path, s);
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::GetStringList (const char *ns,
- const char *path,
- dng_string_list &list) const
- {
-
- return fSDK->GetStringList (ns, path, list);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SetStringList (const char *ns,
- const char *path,
- const dng_string_list &list,
- bool isBag)
- {
-
- fSDK->SetStringList (ns, path, list, isBag);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SyncStringList (const char *ns,
- const char *path,
- dng_string_list &list,
- bool isBag,
- uint32 options)
- {
-
- bool isDefault = (list.Count () == 0);
-
- // First make sure the XMP is not badly formatted, since
- // this breaks some Photoshop logic.
-
- ValidateStringList (ns, path);
-
- // Sync 1: Force XMP to match non-XMP.
-
- if (options & ignoreXMP)
- {
-
- if (isDefault)
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- SetStringList (ns, path, list, isBag);
-
- }
-
- return;
-
- }
-
- // Sync 2: From non-XMP to XMP if non-XMP is prefered.
-
- if ((options & preferNonXMP) && !isDefault)
- {
-
- SetStringList (ns, path, list, isBag);
-
- return;
-
- }
-
- // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
-
- if ((options & preferXMP) || isDefault)
- {
-
- if (GetStringList (ns, path, list))
- {
-
- return;
-
- }
-
- }
-
- // Sync 4: From non-XMP to XMP.
-
- if (!isDefault)
- {
-
- SetStringList (ns, path, list, isBag);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SetStructField (const char *ns,
- const char *path,
- const char *fieldNS,
- const char *fieldName,
- const dng_string &s)
- {
-
- dng_string ss (s);
-
- ss.SetLineEndings ('\n');
-
- ss.StripLowASCII ();
-
- fSDK->SetStructField (ns, path, fieldNS, fieldName, ss.Get ());
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SetStructField (const char *ns,
- const char *path,
- const char *fieldNS,
- const char *fieldName,
- const char *s)
- {
-
- fSDK->SetStructField (ns, path, fieldNS, fieldName, s);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::DeleteStructField (const char *ns,
- const char *path,
- const char *fieldNS,
- const char *fieldName)
- {
-
- fSDK->DeleteStructField (ns, path, fieldNS, fieldName);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::GetStructField (const char *ns,
- const char *path,
- const char *fieldNS,
- const char *fieldName,
- dng_string &s) const
- {
-
- return fSDK->GetStructField (ns, path, fieldNS, fieldName, s);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SetAltLangDefault (const char *ns,
- const char *path,
- const dng_string &s)
- {
-
- fSDK->SetAltLangDefault (ns, path, s);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::GetAltLangDefault (const char *ns,
- const char *path,
- dng_string &s) const
- {
-
- return fSDK->GetAltLangDefault (ns, path, s);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::SyncAltLangDefault (const char *ns,
- const char *path,
- dng_string &s,
- uint32 options)
- {
-
- bool isDefault = s.IsEmpty ();
-
- // Sync 1: Force XMP to match non-XMP.
-
- if (options & ignoreXMP)
- {
-
- if (isDefault)
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- SetAltLangDefault (ns, path, s);
-
- }
-
- return false;
-
- }
-
- // Sync 2: From non-XMP to XMP if non-XMP is prefered.
-
- if ((options & preferNonXMP) && !isDefault)
- {
-
- SetAltLangDefault (ns, path, s);
-
- return false;
-
- }
-
- // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
-
- if ((options & preferXMP) || isDefault)
- {
-
- if (GetAltLangDefault (ns, path, s))
- {
-
- return true;
-
- }
-
- }
-
- // Sync 4: From non-XMP to XMP.
-
- if (!isDefault)
- {
-
- SetAltLangDefault (ns, path, s);
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::GetBoolean (const char *ns,
- const char *path,
- bool &x) const
- {
-
- dng_string s;
-
- if (GetString (ns, path, s))
- {
-
- if (s.Matches ("True"))
- {
-
- x = true;
-
- return true;
-
- }
-
- if (s.Matches ("False"))
- {
-
- x = false;
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SetBoolean (const char *ns,
- const char *path,
- bool x)
- {
-
- Set (ns, path, x ? "True" : "False");
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::Get_int32 (const char *ns,
- const char *path,
- int32 &x) const
- {
-
- dng_string s;
-
- if (GetString (ns, path, s))
- {
-
- if (s.NotEmpty ())
- {
-
- int y = 0;
-
- if (sscanf (s.Get (), "%d", &y) == 1)
- {
-
- x = y;
-
- return true;
-
- }
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Set_int32 (const char *ns,
- const char *path,
- int32 x,
- bool usePlus)
- {
-
- char s [64];
-
- if (x > 0 && usePlus)
- {
- sprintf (s, "+%d", (int) x);
- }
- else
- {
- sprintf (s, "%d", (int) x);
- }
-
- Set (ns, path, s);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::Get_uint32 (const char *ns,
- const char *path,
- uint32 &x) const
- {
-
- dng_string s;
-
- if (GetString (ns, path, s))
- {
-
- if (s.NotEmpty ())
- {
-
- unsigned y = 0;
-
- if (sscanf (s.Get (), "%u", &y) == 1)
- {
-
- x = y;
-
- return true;
-
- }
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Set_uint32 (const char *ns,
- const char *path,
- uint32 x)
- {
-
- char s [64];
-
- sprintf (s,
- "%u",
- (unsigned) x);
-
- Set (ns, path, s);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Sync_uint32 (const char *ns,
- const char *path,
- uint32 &x,
- bool isDefault,
- uint32 options)
- {
-
- // Sync 1: Force XMP to match non-XMP.
-
- if (options & ignoreXMP)
- {
-
- if (isDefault || (options & removeXMP))
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- Set_uint32 (ns, path, x);
-
- }
-
- return;
-
- }
-
- // Sync 2: From non-XMP to XMP if non-XMP is prefered.
-
- if ((options & preferNonXMP) && !isDefault)
- {
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- Set_uint32 (ns, path, x);
-
- }
-
- return;
-
- }
-
- // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
-
- if ((options & preferXMP) || isDefault)
- {
-
- if (Get_uint32 (ns, path, x))
- {
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- return;
-
- }
-
- }
-
- // Sync 4: From non-XMP to XMP.
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- else if (!isDefault)
- {
-
- Set_uint32 (ns, path, x);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Sync_uint32_array (const char *ns,
- const char *path,
- uint32 *data,
- uint32 &count,
- uint32 maxCount,
- uint32 options)
- {
-
- dng_string_list list;
-
- for (uint32 j = 0; j < count; j++)
- {
-
- char s [32];
-
- sprintf (s, "%u", (unsigned) data [j]);
-
- dng_string ss;
-
- ss.Set (s);
-
- list.Append (ss);
-
- }
-
- SyncStringList (ns,
- path,
- list,
- false,
- options);
-
- count = 0;
-
- for (uint32 k = 0; k < maxCount; k++)
- {
-
- data [k] = 0;
-
- if (k < list.Count ())
- {
-
- unsigned x = 0;
-
- if (sscanf (list [k].Get (), "%u", &x) == 1)
- {
-
- data [count++] = x;
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::Get_real64 (const char *ns,
- const char *path,
- real64 &x) const
- {
-
- dng_string s;
-
- if (GetString (ns, path, s))
- {
-
- if (s.NotEmpty ())
- {
-
- double y = 0;
-
- if (sscanf (s.Get (), "%lf", &y) == 1)
- {
-
- x = y;
-
- return true;
-
- }
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Set_real64 (const char *ns,
- const char *path,
- real64 x,
- uint32 places,
- bool trim,
- bool usePlus)
- {
-
- char s [64];
-
- if (x > 0.0 && usePlus)
- {
- sprintf (s, "+%0.*f", (unsigned) places, (double) x);
- }
- else
- {
- sprintf (s, "%0.*f", (unsigned) places, (double) x);
- }
-
- if (trim)
- {
-
- while (s [strlen (s) - 1] == '0')
- {
- s [strlen (s) - 1] = 0;
- }
-
- if (s [strlen (s) - 1] == '.')
- {
- s [strlen (s) - 1] = 0;
- }
-
- }
-
- Set (ns, path, s);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::Get_urational (const char *ns,
- const char *path,
- dng_urational &r) const
- {
-
- dng_string s;
-
- if (GetString (ns, path, s))
- {
-
- if (s.NotEmpty ())
- {
-
- unsigned n = 0;
- unsigned d = 0;
-
- if (sscanf (s.Get (), "%u/%u", &n, &d) == 2)
- {
-
- if (d != 0)
- {
-
- r = dng_urational (n, d);
-
- return true;
-
- }
-
- }
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Set_urational (const char *ns,
- const char *path,
- const dng_urational &r)
- {
-
- char s [64];
-
- sprintf (s,
- "%u/%u",
- (unsigned) r.n,
- (unsigned) r.d);
-
- Set (ns, path, s);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Sync_urational (const char *ns,
- const char *path,
- dng_urational &r,
- uint32 options)
- {
-
- bool isDefault = r.NotValid ();
-
- // Sync 1: Force XMP to match non-XMP.
-
- if (options & ignoreXMP)
- {
-
- if (isDefault || (options & removeXMP))
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- Set_urational (ns, path, r);
-
- }
-
- return;
-
- }
-
- // Sync 2: From non-XMP to XMP if non-XMP is prefered.
-
- if ((options & preferNonXMP) && !isDefault)
- {
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- Set_urational (ns, path, r);
-
- }
-
- return;
-
- }
-
- // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
-
- if ((options & preferXMP) || isDefault)
- {
-
- if (Get_urational (ns, path, r))
- {
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- return;
-
- }
-
- }
-
- // Sync 4: From non-XMP to XMP.
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- else if (!isDefault)
- {
-
- Set_urational (ns, path, r);
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::Get_srational (const char *ns,
- const char *path,
- dng_srational &r) const
- {
-
- dng_string s;
-
- if (GetString (ns, path, s))
- {
-
- if (s.NotEmpty ())
- {
-
- int n = 0;
- int d = 0;
-
- if (sscanf (s.Get (), "%d/%d", &n, &d) == 2)
- {
-
- if (d != 0)
- {
-
- r = dng_srational (n, d);
-
- return true;
-
- }
-
- }
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Set_srational (const char *ns,
- const char *path,
- const dng_srational &r)
- {
-
- char s [64];
-
- sprintf (s,
- "%d/%d",
- (int) r.n,
- (int) r.d);
-
- Set (ns, path, s);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::Sync_srational (const char *ns,
- const char *path,
- dng_srational &r,
- uint32 options)
- {
-
- bool isDefault = r.NotValid ();
-
- // Sync 1: Force XMP to match non-XMP.
-
- if (options & ignoreXMP)
- {
-
- if (isDefault || (options & removeXMP))
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- Set_srational (ns, path, r);
-
- }
-
- return;
-
- }
-
- // Sync 2: From non-XMP to XMP if non-XMP is prefered.
-
- if ((options & preferNonXMP) && !isDefault)
- {
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- else
- {
-
- Set_srational (ns, path, r);
-
- }
-
- return;
-
- }
-
- // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
-
- if ((options & preferXMP) || isDefault)
- {
-
- if (Get_srational (ns, path, r))
- {
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- return;
-
- }
-
- }
-
- // Sync 4: From non-XMP to XMP.
-
- if (options & removeXMP)
- {
-
- Remove (ns, path);
-
- }
-
- else if (!isDefault)
- {
-
- Set_srational (ns, path, r);
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::GetFingerprint (const char *ns,
- const char *path,
- dng_fingerprint &print) const
- {
-
- dng_string s;
-
- if (GetString (ns, path, s))
- {
-
- dng_fingerprint temp = DecodeFingerprint (s);
-
- if (temp.IsValid ())
- {
-
- print = temp;
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::SetFingerprint (const char *ns,
- const char *tag,
- const dng_fingerprint &print,
- bool allowInvalid)
- {
-
- dng_string s = EncodeFingerprint (print, allowInvalid);
-
- if (s.IsEmpty ())
- {
-
- Remove (ns, tag);
-
- }
-
- else
- {
-
- SetString (ns, tag, s);
-
- }
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::SetVersion2to4 (const char *ns,
- const char *path,
- uint32 version)
- {
-
- char buf [32];
-
- if (version & 0x000000ff)
- {
-
- // x.x.x.x
-
- sprintf (buf,
- "%u.%u.%u.%u",
- (unsigned) ((version >> 24) & 0xff),
- (unsigned) ((version >> 16) & 0xff),
- (unsigned) ((version >> 8) & 0xff),
- (unsigned) ((version ) & 0xff));
-
- }
-
- else if (version & 0x0000ff00)
- {
-
- // x.x.x
-
- sprintf (buf,
- "%u.%u.%u",
- (unsigned) ((version >> 24) & 0xff),
- (unsigned) ((version >> 16) & 0xff),
- (unsigned) ((version >> 8) & 0xff));
-
- }
-
- else
- {
-
- // x.x
-
- sprintf (buf,
- "%u.%u",
- (unsigned) ((version >> 24) & 0xff),
- (unsigned) ((version >> 16) & 0xff));
-
- }
-
- Set (ns, path, buf);
-
- }
-
-/******************************************************************************/
-
-dng_fingerprint dng_xmp::GetIPTCDigest () const
- {
-
- dng_fingerprint digest;
-
- if (GetFingerprint (XMP_NS_PHOTOSHOP,
- "LegacyIPTCDigest",
- digest))
- {
-
- return digest;
-
- }
-
- return dng_fingerprint ();
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::SetIPTCDigest (dng_fingerprint &digest)
- {
-
- SetFingerprint (XMP_NS_PHOTOSHOP,
- "LegacyIPTCDigest",
- digest);
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::ClearIPTCDigest ()
- {
-
- Remove (XMP_NS_PHOTOSHOP, "LegacyIPTCDigest");
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SyncIPTC (dng_iptc &iptc,
- uint32 options)
- {
-
- SyncAltLangDefault (XMP_NS_DC,
- "title",
- iptc.fTitle,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "Category",
- iptc.fCategory,
- options);
-
- {
-
- uint32 x = 0xFFFFFFFF;
-
- if (iptc.fUrgency >= 0)
- {
-
- x = (uint32) iptc.fUrgency;
-
- }
-
- Sync_uint32 (XMP_NS_PHOTOSHOP,
- "Urgency",
- x,
- x == 0xFFFFFFFF,
- options);
-
- if (x <= 9)
- {
-
- iptc.fUrgency = (int32) x;
-
- }
-
- }
-
- SyncStringList (XMP_NS_PHOTOSHOP,
- "SupplementalCategories",
- iptc.fSupplementalCategories,
- true,
- options);
-
- SyncStringList (XMP_NS_PHOTOSHOP,
- "Keywords",
- iptc.fKeywords,
- true,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "Instructions",
- iptc.fInstructions,
- options);
-
- {
-
- dng_string s = iptc.fDateTimeCreated.Encode_ISO_8601 ();
-
- if (SyncString (XMP_NS_PHOTOSHOP,
- "DateCreated",
- s,
- options))
- {
-
- iptc.fDateTimeCreated.Decode_ISO_8601 (s.Get ());
-
- }
-
- }
-
- {
-
- dng_string s = iptc.fDigitalCreationDateTime.Encode_ISO_8601 ();
-
- if (SyncString (XMP_NS_EXIF,
- "DateTimeDigitized",
- s,
- options))
- {
-
- iptc.fDigitalCreationDateTime.Decode_ISO_8601 (s.Get ());
-
- }
-
- }
-
- SyncStringList (XMP_NS_DC,
- "creator",
- iptc.fAuthors,
- false,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "AuthorsPosition",
- iptc.fAuthorsPosition,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "City",
- iptc.fCity,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "State",
- iptc.fState,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "Country",
- iptc.fCountry,
- options);
-
- SyncString (XMP_NS_IPTC,
- "CountryCode",
- iptc.fCountryCode,
- options);
-
- SyncString (XMP_NS_IPTC,
- "Location",
- iptc.fLocation,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "TransmissionReference",
- iptc.fTransmissionReference,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "Headline",
- iptc.fHeadline,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "Credit",
- iptc.fCredit,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "Source",
- iptc.fSource,
- options);
-
- SyncAltLangDefault (XMP_NS_DC,
- "rights",
- iptc.fCopyrightNotice,
- options);
-
- SyncAltLangDefault (XMP_NS_DC,
- "description",
- iptc.fDescription,
- options);
-
- SyncString (XMP_NS_PHOTOSHOP,
- "CaptionWriter",
- iptc.fDescriptionWriter,
- options);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::IngestIPTC (dng_metadata &metadata,
- bool xmpIsNewer)
- {
-
- if (metadata.IPTCLength ())
- {
-
- // Parse the IPTC block.
-
- dng_iptc iptc;
-
- iptc.Parse (metadata.IPTCData (),
- metadata.IPTCLength (),
- metadata.IPTCOffset ());
-
- // Compute fingerprint of IPTC data both ways, including and
- // excluding the padding data.
-
- dng_fingerprint iptcDigest1 = metadata.IPTCDigest (true );
- dng_fingerprint iptcDigest2 = metadata.IPTCDigest (false);
-
- // See if there is an IPTC fingerprint stored in the XMP.
-
- dng_fingerprint xmpDigest = GetIPTCDigest ();
-
- if (xmpDigest.IsValid ())
- {
-
- // If they match, the XMP was already synced with this
- // IPTC block, and we should not resync since it might
- // overwrite changes in the XMP data.
-
- if (iptcDigest1 == xmpDigest)
- {
-
- return;
-
- }
-
- // If it matches the incorrectly computed digest, skip
- // the sync, but fix the digest in the XMP.
-
- if (iptcDigest2 == xmpDigest)
- {
-
- SetIPTCDigest (iptcDigest1);
-
- return;
-
- }
-
- // Else the IPTC has changed, so force an update.
-
- xmpIsNewer = false;
-
- }
-
- else
- {
-
- // There is no IPTC digest. Previously we would
- // prefer the IPTC in this case, but the MWG suggests
- // that we prefer the XMP in this case.
-
- xmpIsNewer = true;
-
- }
-
- // Remember the fingerprint of the IPTC we are syncing with.
-
- SetIPTCDigest (iptcDigest1);
-
- // Find the sync options.
-
- uint32 options = xmpIsNewer ? preferXMP
- : preferNonXMP;
-
- // Synchronize the fields.
-
- SyncIPTC (iptc, options);
-
- }
-
- // After the IPTC data is moved to XMP, we don't need it anymore.
-
- metadata.ClearIPTC ();
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::RebuildIPTC (dng_metadata &metadata,
- dng_memory_allocator &allocator,
- bool padForTIFF)
- {
-
- // If there is no XMP, then there is no IPTC.
-
- if (!fSDK->HasMeta ())
- {
- return;
- }
-
- // Extract the legacy IPTC fields from the XMP data.
-
- dng_iptc iptc;
-
- SyncIPTC (iptc, preferXMP);
-
- // Build legacy IPTC record
-
- if (iptc.NotEmpty ())
- {
-
- AutoPtr<dng_memory_block> block (iptc.Spool (allocator,
- padForTIFF));
-
- metadata.SetIPTC (block);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SyncFlash (uint32 &flashState,
- uint32 &flashMask,
- uint32 options)
- {
-
- bool isDefault = (flashState == 0xFFFFFFFF);
-
- if ((options & ignoreXMP) || !isDefault)
- {
-
- Remove (XMP_NS_EXIF, "Flash");
-
- }
-
- if (!isDefault)
- {
-
- fSDK->SetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "Fired",
- (flashState & 0x1) ? "True" : "False");
-
- if (((flashMask >> 1) & 3) == 3)
- {
-
- char s [8];
-
- sprintf (s, "%u", (unsigned) ((flashState >> 1) & 3));
-
- fSDK->SetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "Return",
- s);
-
- }
-
- if (((flashMask >> 3) & 3) == 3)
- {
-
- char s [8];
-
- sprintf (s, "%u", (unsigned) ((flashState >> 3) & 3));
-
- fSDK->SetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "Mode",
- s);
-
- }
-
- if ((flashMask & (1 << 5)) != 0)
- {
-
- fSDK->SetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "Function",
- (flashState & (1 << 5)) ? "True" : "False");
-
- }
-
- if ((flashMask & (1 << 6)) != 0)
- {
-
- fSDK->SetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "RedEyeMode",
- (flashState & (1 << 6)) ? "True" : "False");
-
- }
-
- }
-
- else if (fSDK->Exists (XMP_NS_EXIF, "Flash"))
- {
-
- dng_string s;
-
- if (fSDK->GetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "Fired",
- s))
- {
-
- flashState = 0;
- flashMask = 1;
-
- if (s.Matches ("True"))
- {
- flashState |= 1;
- }
-
- if (fSDK->GetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "Return",
- s))
- {
-
- unsigned x = 0;
-
- if (sscanf (s.Get (), "%u", &x) == 1 && x <= 3)
- {
-
- flashState |= x << 1;
- flashMask |= 3 << 1;
-
- }
-
- }
-
- if (fSDK->GetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "Mode",
- s))
- {
-
- unsigned x = 0;
-
- if (sscanf (s.Get (), "%u", &x) == 1 && x <= 3)
- {
-
- flashState |= x << 3;
- flashMask |= 3 << 3;
-
- }
-
- }
-
- if (fSDK->GetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "Function",
- s))
- {
-
- flashMask |= 1 << 5;
-
- if (s.Matches ("True"))
- {
- flashState |= 1 << 5;
- }
-
- }
-
- if (fSDK->GetStructField (XMP_NS_EXIF,
- "Flash",
- XMP_NS_EXIF,
- "RedEyeMode",
- s))
- {
-
- flashMask |= 1 << 6;
-
- if (s.Matches ("True"))
- {
- flashState |= 1 << 6;
- }
-
- }
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SyncExif (dng_exif &exif,
- const dng_exif *originalExif,
- bool doingUpdateFromXMP,
- bool removeFromXMP)
- {
-
- DNG_ASSERT (!doingUpdateFromXMP || originalExif,
- "Must have original EXIF if doingUpdateFromXMP");
-
- // Default synchronization options for the read-only fields.
-
- uint32 readOnly = doingUpdateFromXMP ? ignoreXMP
- : preferNonXMP;
-
- // Option for removable fields.
-
- uint32 removable = removeFromXMP ? removeXMP
- : 0;
-
- // Make:
-
- SyncString (XMP_NS_TIFF,
- "Make",
- exif.fMake,
- readOnly + removable);
-
- // Model:
-
- SyncString (XMP_NS_TIFF,
- "Model",
- exif.fModel,
- readOnly + removable);
-
- // Exif version number:
-
- {
-
- dng_string exifVersion;
-
- if (exif.fExifVersion)
- {
-
- unsigned b0 = ((exif.fExifVersion >> 24) & 0x0FF) - '0';
- unsigned b1 = ((exif.fExifVersion >> 16) & 0x0FF) - '0';
- unsigned b2 = ((exif.fExifVersion >> 8) & 0x0FF) - '0';
- unsigned b3 = ((exif.fExifVersion ) & 0x0FF) - '0';
-
- if (b0 <= 9 && b1 <= 9 && b2 <= 9 && b3 <= 9)
- {
-
- char s [5];
-
- sprintf (s,
- "%1u%1u%1u%1u",
- b0,
- b1,
- b2,
- b3);
-
- exifVersion.Set (s);
-
- }
-
- }
-
- SyncString (XMP_NS_EXIF,
- "ExifVersion",
- exifVersion,
- readOnly);
-
- if (exifVersion.NotEmpty ())
- {
-
- unsigned b0;
- unsigned b1;
- unsigned b2;
- unsigned b3;
-
- if (sscanf (exifVersion.Get (),
- "%1u%1u%1u%1u",
- &b0,
- &b1,
- &b2,
- &b3) == 4)
- {
-
- if (b0 <= 9 && b1 <= 9 && b2 <= 9 && b3 <= 9)
- {
-
- b0 += '0';
- b1 += '0';
- b2 += '0';
- b3 += '0';
-
- exif.fExifVersion = (b0 << 24) |
- (b1 << 16) |
- (b2 << 8) |
- (b3 );
-
- }
-
- }
-
- }
-
- // Provide default value for ExifVersion.
-
- if (!exif.fExifVersion)
- {
-
- exif.fExifVersion = DNG_CHAR4 ('0','2','2','1');
-
- Set (XMP_NS_EXIF,
- "ExifVersion",
- "0221");
-
- }
-
- if (removeFromXMP)
- {
-
- Remove (XMP_NS_EXIF, "ExifVersion");
-
- }
-
- }
-
- // ExposureTime / ShutterSpeedValue:
-
- {
-
- // Process twice in case XMP contains only one of the
- // two fields.
-
- for (uint32 pass = 0; pass < 2; pass++)
- {
-
- dng_urational et = exif.fExposureTime;
-
- Sync_urational (XMP_NS_EXIF,
- "ExposureTime",
- et,
- readOnly);
-
- if (et.IsValid ())
- {
-
- exif.SetExposureTime (et.As_real64 (), false);
-
- }
-
- dng_srational ss = exif.fShutterSpeedValue;
-
- Sync_srational (XMP_NS_EXIF,
- "ShutterSpeedValue",
- ss,
- readOnly);
-
- if (ss.IsValid ())
- {
-
- exif.SetShutterSpeedValue (ss.As_real64 ());
-
- }
-
- }
-
- if (removeFromXMP)
- {
-
- Remove (XMP_NS_EXIF, "ExposureTime");
-
- Remove (XMP_NS_EXIF, "ShutterSpeedValue");
-
- }
-
- }
-
- // FNumber / ApertureValue:
-
- {
-
- for (uint32 pass = 0; pass < 2; pass++)
- {
-
- dng_urational fs = exif.fFNumber;
-
- Sync_urational (XMP_NS_EXIF,
- "FNumber",
- fs,
- readOnly);
-
- if (fs.IsValid ())
- {
-
- exif.SetFNumber (fs.As_real64 ());
-
- }
-
- dng_urational av = exif.fApertureValue;
-
- Sync_urational (XMP_NS_EXIF,
- "ApertureValue",
- av,
- readOnly);
-
- if (av.IsValid ())
- {
-
- exif.SetApertureValue (av.As_real64 ());
-
- }
-
- }
-
- if (removeFromXMP)
- {
-
- Remove (XMP_NS_EXIF, "FNumber");
-
- Remove (XMP_NS_EXIF, "ApertureValue");
-
- }
-
- }
-
- // Exposure program:
-
- Sync_uint32 (XMP_NS_EXIF,
- "ExposureProgram",
- exif.fExposureProgram,
- exif.fExposureProgram == 0xFFFFFFFF,
- readOnly + removable);
-
- // ISO Speed Ratings:
-
- {
-
- uint32 isoSpeedRatingsCount = 0;
-
- uint32 isoSpeedRatingsOptions = readOnly;
-
- uint32 oldISOSpeedRatings [3];
-
- memcpy (oldISOSpeedRatings,
- exif.fISOSpeedRatings,
- sizeof (oldISOSpeedRatings));
-
- bool checkXMPForHigherISO = false;
-
- for (uint32 j = 0; j < 3; j++)
- {
-
- // Special case: the EXIF 2.2x standard represents ISO speed ratings with
- // 2 bytes, which cannot hold ISO speed ratings above 65535 (e.g.,
- // 102400). If the EXIF ISO speed rating value is 65535, prefer the XMP
- // ISOSpeedRatings tag value.
-
- if (exif.fISOSpeedRatings [j] == 65535)
- {
-
- isoSpeedRatingsOptions = preferXMP;
-
- checkXMPForHigherISO = true;
-
- isoSpeedRatingsCount = 0;
-
- break;
-
- }
-
- else if (exif.fISOSpeedRatings [j] == 0)
- {
- break;
- }
-
- isoSpeedRatingsCount++;
-
- }
-
- Sync_uint32_array (XMP_NS_EXIF,
- "ISOSpeedRatings",
- exif.fISOSpeedRatings,
- isoSpeedRatingsCount,
- 3,
- isoSpeedRatingsOptions);
-
- // If the EXIF ISO was 65535 and we failed to find anything meaningful in the
- // XMP, then we fall back to the EXIF ISO.
-
- if (checkXMPForHigherISO && (isoSpeedRatingsCount == 0))
- {
-
- memcpy (exif.fISOSpeedRatings,
- oldISOSpeedRatings,
- sizeof (oldISOSpeedRatings));
-
- }
-
- // Only remove the ISO tag if there are not ratings over 65535.
-
- if (removeFromXMP)
- {
-
- bool hasHighISO = false;
-
- for (uint32 j = 0; j < 3; j++)
- {
-
- if (exif.fISOSpeedRatings [j] == 0)
- {
- break;
- }
-
- hasHighISO = hasHighISO || (exif.fISOSpeedRatings [j] > 65535);
-
- }
-
- if (!hasHighISO)
- {
-
- Remove (XMP_NS_EXIF, "ISOSpeedRatings");
-
- }
-
- }
-
- }
-
- // SensitivityType:
-
- Sync_uint32 (XMP_NS_EXIF,
- "SensitivityType",
- exif.fSensitivityType,
- exif.fSensitivityType == stUnknown,
- readOnly + removable);
-
- // StandardOutputSensitivity:
-
- Sync_uint32 (XMP_NS_EXIF,
- "StandardOutputSensitivity",
- exif.fStandardOutputSensitivity,
- exif.fStandardOutputSensitivity == 0,
- readOnly + removable);
-
- // RecommendedExposureIndex:
-
- Sync_uint32 (XMP_NS_EXIF,
- "RecommendedExposureIndex",
- exif.fRecommendedExposureIndex,
- exif.fRecommendedExposureIndex == 0,
- readOnly + removable);
-
- // ISOSpeed:
-
- Sync_uint32 (XMP_NS_EXIF,
- "ISOSpeed",
- exif.fISOSpeed,
- exif.fISOSpeed == 0,
- readOnly + removable);
-
- // ISOSpeedLatitudeyyy:
-
- Sync_uint32 (XMP_NS_EXIF,
- "ISOSpeedLatitudeyyy",
- exif.fISOSpeedLatitudeyyy,
- exif.fISOSpeedLatitudeyyy == 0,
- readOnly + removable);
-
- // ISOSpeedLatitudezzz:
-
- Sync_uint32 (XMP_NS_EXIF,
- "ISOSpeedLatitudezzz",
- exif.fISOSpeedLatitudezzz,
- exif.fISOSpeedLatitudezzz == 0,
- readOnly + removable);
-
- // ExposureIndex:
-
- Sync_urational (XMP_NS_EXIF,
- "ExposureIndex",
- exif.fExposureIndex,
- readOnly + removable);
-
- // Brightness Value:
-
- Sync_srational (XMP_NS_EXIF,
- "BrightnessValue",
- exif.fBrightnessValue,
- readOnly + removable);
-
- // Exposure Bias:
-
- Sync_srational (XMP_NS_EXIF,
- "ExposureBiasValue",
- exif.fExposureBiasValue,
- readOnly + removable);
-
- // Max Aperture:
-
- Sync_urational (XMP_NS_EXIF,
- "MaxApertureValue",
- exif.fMaxApertureValue,
- readOnly + removable);
-
- // Subject Distance:
-
- Sync_urational (XMP_NS_EXIF,
- "SubjectDistance",
- exif.fSubjectDistance,
- readOnly + removable);
-
- // Metering Mode:
-
- Sync_uint32 (XMP_NS_EXIF,
- "MeteringMode",
- exif.fMeteringMode,
- exif.fMeteringMode == 0xFFFFFFFF,
- readOnly + removable);
-
- // Light Source:
-
- Sync_uint32 (XMP_NS_EXIF,
- "LightSource",
- exif.fLightSource,
- exif.fLightSource > 0x0FFFF,
- readOnly + removable);
-
- // Flash State:
-
- SyncFlash (exif.fFlash,
- exif.fFlashMask,
- readOnly);
-
- if (removeFromXMP)
- {
- Remove (XMP_NS_EXIF, "Flash");
- }
-
- // Focal Length:
-
- Sync_urational (XMP_NS_EXIF,
- "FocalLength",
- exif.fFocalLength,
- readOnly + removable);
-
- // Sensing Method.
-
- Sync_uint32 (XMP_NS_EXIF,
- "SensingMethod",
- exif.fSensingMethod,
- exif.fSensingMethod > 0x0FFFF,
- readOnly + removable);
-
- // File Source.
-
- Sync_uint32 (XMP_NS_EXIF,
- "FileSource",
- exif.fFileSource,
- exif.fFileSource > 0x0FF,
- readOnly + removable);
-
- // Scene Type.
-
- Sync_uint32 (XMP_NS_EXIF,
- "SceneType",
- exif.fSceneType,
- exif.fSceneType > 0x0FF,
- readOnly + removable);
-
- // Focal Length in 35mm Film:
-
- Sync_uint32 (XMP_NS_EXIF,
- "FocalLengthIn35mmFilm",
- exif.fFocalLengthIn35mmFilm,
- exif.fFocalLengthIn35mmFilm == 0,
- readOnly + removable);
-
- // Custom Rendered:
-
- Sync_uint32 (XMP_NS_EXIF,
- "CustomRendered",
- exif.fCustomRendered,
- exif.fCustomRendered > 0x0FFFF,
- readOnly + removable);
-
- // Exposure Mode:
-
- Sync_uint32 (XMP_NS_EXIF,
- "ExposureMode",
- exif.fExposureMode,
- exif.fExposureMode > 0x0FFFF,
- readOnly + removable);
-
- // White Balance:
-
- Sync_uint32 (XMP_NS_EXIF,
- "WhiteBalance",
- exif.fWhiteBalance,
- exif.fWhiteBalance > 0x0FFFF,
- readOnly + removable);
-
- // Scene Capture Type:
-
- Sync_uint32 (XMP_NS_EXIF,
- "SceneCaptureType",
- exif.fSceneCaptureType,
- exif.fSceneCaptureType > 0x0FFFF,
- readOnly + removable);
-
- // Gain Control:
-
- Sync_uint32 (XMP_NS_EXIF,
- "GainControl",
- exif.fGainControl,
- exif.fGainControl > 0x0FFFF,
- readOnly + removable);
-
- // Contrast:
-
- Sync_uint32 (XMP_NS_EXIF,
- "Contrast",
- exif.fContrast,
- exif.fContrast > 0x0FFFF,
- readOnly + removable);
-
- // Saturation:
-
- Sync_uint32 (XMP_NS_EXIF,
- "Saturation",
- exif.fSaturation,
- exif.fSaturation > 0x0FFFF,
- readOnly + removable);
-
- // Sharpness:
-
- Sync_uint32 (XMP_NS_EXIF,
- "Sharpness",
- exif.fSharpness,
- exif.fSharpness > 0x0FFFF,
- readOnly + removable);
-
- // Subject Distance Range:
-
- Sync_uint32 (XMP_NS_EXIF,
- "SubjectDistanceRange",
- exif.fSubjectDistanceRange,
- exif.fSubjectDistanceRange > 0x0FFFF,
- readOnly + removable);
-
- // Subject Area:
-
- Sync_uint32_array (XMP_NS_EXIF,
- "SubjectArea",
- exif.fSubjectArea,
- exif.fSubjectAreaCount,
- sizeof (exif.fSubjectArea ) /
- sizeof (exif.fSubjectArea [0]),
- readOnly);
-
- if (removeFromXMP)
- {
- Remove (XMP_NS_EXIF, "SubjectArea");
- }
-
- // Digital Zoom Ratio:
-
- Sync_urational (XMP_NS_EXIF,
- "DigitalZoomRatio",
- exif.fDigitalZoomRatio,
- readOnly + removable);
-
- // Focal Plane Resolution:
-
- Sync_urational (XMP_NS_EXIF,
- "FocalPlaneXResolution",
- exif.fFocalPlaneXResolution,
- readOnly + removable);
-
- Sync_urational (XMP_NS_EXIF,
- "FocalPlaneYResolution",
- exif.fFocalPlaneYResolution,
- readOnly + removable);
-
- Sync_uint32 (XMP_NS_EXIF,
- "FocalPlaneResolutionUnit",
- exif.fFocalPlaneResolutionUnit,
- exif.fFocalPlaneResolutionUnit > 0x0FFFF,
- readOnly + removable);
-
- // ImageDescription: (XMP is is always preferred)
-
- if (fSDK->GetAltLangDefault (XMP_NS_DC,
- "description",
- exif.fImageDescription))
-
- {
-
- }
-
- else if (doingUpdateFromXMP)
- {
-
- exif.fImageDescription.Clear ();
-
- if (originalExif->fImageDescription.NotEmpty ())
- {
-
- fSDK->SetAltLangDefault (XMP_NS_DC,
- "description",
- dng_string ());
-
- }
-
- }
-
- else if (exif.fImageDescription.NotEmpty ())
- {
-
- fSDK->SetAltLangDefault (XMP_NS_DC,
- "description",
- exif.fImageDescription);
-
- }
-
- // Artist: (XMP is is always preferred)
-
- {
-
- dng_string_list xmpList;
-
- if (fSDK->GetStringList (XMP_NS_DC,
- "creator",
- xmpList))
- {
-
- exif.fArtist.Clear ();
-
- if (xmpList.Count () > 0)
- {
-
- uint32 j;
-
- uint32 bufferSize = xmpList.Count () * 4 + 1;
-
- for (j = 0; j < xmpList.Count (); j++)
- {
-
- bufferSize += xmpList [j].Length () * 2;
-
- }
-
- dng_memory_data temp (bufferSize);
-
- char *t = temp.Buffer_char ();
-
- for (j = 0; j < xmpList.Count (); j++)
- {
-
- const char *s = xmpList [j].Get ();
-
- bool needQuotes = xmpList [j].Contains ("; ") ||
- s [0] == '\"';
-
- if (needQuotes)
- {
- *(t++) = '\"';
- }
-
- while (s [0] != 0)
- {
-
- if (s [0] == '\"' && needQuotes)
- {
- *(t++) = '\"';
- }
-
- *(t++) = *(s++);
-
- }
-
- if (needQuotes)
- {
- *(t++) = '\"';
- }
-
- if (j != xmpList.Count () - 1)
- {
- *(t++) = ';';
- *(t++) = ' ';
- }
- else
- {
- *t = 0;
- }
-
- }
-
- exif.fArtist.Set (temp.Buffer_char ());
-
- }
-
- }
-
- else if (doingUpdateFromXMP)
- {
-
- exif.fArtist.Clear ();
-
- if (originalExif->fArtist.NotEmpty ())
- {
-
- dng_string_list fakeList;
-
- fakeList.Append (dng_string ());
-
- SetStringList (XMP_NS_DC,
- "creator",
- fakeList,
- false);
-
- }
-
- }
-
- else if (exif.fArtist.NotEmpty ())
- {
-
- dng_string_list newList;
-
- dng_memory_data temp (exif.fArtist.Length () + 1);
-
- const char *s = exif.fArtist.Get ();
-
- char *t = temp.Buffer_char ();
-
- bool first = true;
-
- bool quoted = false;
-
- bool valid = true;
-
- while (s [0] != 0 && valid)
- {
-
- if (first)
- {
-
- if (s [0] == '\"')
- {
-
- quoted = true;
-
- s++;
-
- }
-
- }
-
- first = false;
-
- if (quoted)
- {
-
- if (s [0] == '\"' &&
- s [1] == '\"')
- {
-
- s+= 2;
-
- *(t++) = '\"';
-
- }
-
- else if (s [0] == '\"')
- {
-
- s++;
-
- quoted = false;
-
- valid = valid && ((s [0] == 0) || ((s [0] == ';' && s [1] == ' ')));
-
- }
-
- else
- {
-
- *(t++) = *(s++);
-
- }
-
- }
-
- else if (s [0] == ';' &&
- s [1] == ' ')
- {
-
- s += 2;
-
- t [0] = 0;
-
- dng_string ss;
-
- ss.Set (temp.Buffer_char ());
-
- newList.Append (ss);
-
- t = temp.Buffer_char ();
-
- first = true;
-
- }
-
- else
- {
-
- *(t++) = *(s++);
-
- }
-
- }
-
- if (quoted)
- {
-
- valid = false;
-
- }
-
- if (valid)
- {
-
- if (t != temp.Buffer_char ())
- {
-
- t [0] = 0;
-
- dng_string ss;
-
- ss.Set (temp.Buffer_char ());
-
- newList.Append (ss);
-
- }
-
- }
-
- else
- {
-
- newList.Clear ();
-
- newList.Append (exif.fArtist);
-
- }
-
- SetStringList (XMP_NS_DC,
- "creator",
- newList,
- false);
-
- }
-
- }
-
- // Software: (XMP is is always preferred)
-
- if (fSDK->GetString (XMP_NS_XAP,
- "CreatorTool",
- exif.fSoftware))
-
- {
-
- }
-
- else if (doingUpdateFromXMP)
- {
-
- exif.fSoftware.Clear ();
-
- if (originalExif->fSoftware.NotEmpty ())
- {
-
- fSDK->SetString (XMP_NS_XAP,
- "CreatorTool",
- dng_string ());
-
- }
-
- }
-
- else if (exif.fSoftware.NotEmpty ())
- {
-
- fSDK->SetString (XMP_NS_XAP,
- "CreatorTool",
- exif.fSoftware);
-
- }
-
- // Copyright: (XMP is is always preferred)
-
- if (fSDK->GetAltLangDefault (XMP_NS_DC,
- "rights",
- exif.fCopyright))
-
- {
-
- }
-
- else if (doingUpdateFromXMP)
- {
-
- exif.fCopyright.Clear ();
-
- if (originalExif->fCopyright.NotEmpty ())
- {
-
- fSDK->SetAltLangDefault (XMP_NS_DC,
- "rights",
- dng_string ());
-
- }
-
- }
-
- else if (exif.fCopyright.NotEmpty ())
- {
-
- fSDK->SetAltLangDefault (XMP_NS_DC,
- "rights",
- exif.fCopyright);
-
- }
-
- // Camera serial number private tag:
-
- SyncString (XMP_NS_AUX,
- "SerialNumber",
- exif.fCameraSerialNumber,
- readOnly);
-
- // Lens Info:
-
- {
-
- dng_string s;
-
- if (exif.fLensInfo [0].IsValid ())
- {
-
- char ss [256];
-
- sprintf (ss,
- "%u/%u %u/%u %u/%u %u/%u",
- (unsigned) exif.fLensInfo [0].n,
- (unsigned) exif.fLensInfo [0].d,
- (unsigned) exif.fLensInfo [1].n,
- (unsigned) exif.fLensInfo [1].d,
- (unsigned) exif.fLensInfo [2].n,
- (unsigned) exif.fLensInfo [2].d,
- (unsigned) exif.fLensInfo [3].n,
- (unsigned) exif.fLensInfo [3].d);
-
- s.Set (ss);
-
- }
-
- SyncString (XMP_NS_AUX,
- "LensInfo",
- s,
- readOnly);
-
- if (s.NotEmpty ())
- {
-
- unsigned n [4];
- unsigned d [4];
-
- if (sscanf (s.Get (),
- "%u/%u %u/%u %u/%u %u/%u",
- &n [0],
- &d [0],
- &n [1],
- &d [1],
- &n [2],
- &d [2],
- &n [3],
- &d [3]) == 8)
- {
-
- for (uint32 j = 0; j < 4; j++)
- {
-
- exif.fLensInfo [j] = dng_urational (n [j], d [j]);
-
- }
-
- }
-
-
- }
-
- }
-
- // Lens name:
-
- {
-
- // EXIF lens names are sometimes missing or wrong (esp. when non-OEM lenses
- // are used). So prefer the value from XMP.
-
- SyncString (XMP_NS_AUX,
- "Lens",
- exif.fLensName,
- preferXMP);
-
- // Generate default lens name from lens info if required.
- // Ignore names names that end in "f/0.0" due to third party bug.
-
- if ((exif.fLensName.IsEmpty () ||
- exif.fLensName.EndsWith ("f/0.0")) && exif.fLensInfo [0].IsValid ())
- {
-
- char s [256];
-
- real64 minFL = exif.fLensInfo [0].As_real64 ();
- real64 maxFL = exif.fLensInfo [1].As_real64 ();
-
- // The f-stop numbers are optional.
-
- if (exif.fLensInfo [2].IsValid ())
- {
-
- real64 minFS = exif.fLensInfo [2].As_real64 ();
- real64 maxFS = exif.fLensInfo [3].As_real64 ();
-
- if (minFL == maxFL)
- sprintf (s, "%.1f mm f/%.1f", minFL, minFS);
-
- else if (minFS == maxFS)
- sprintf (s, "%.1f-%.1f mm f/%.1f", minFL, maxFL, minFS);
-
- else
- sprintf (s, "%.1f-%.1f mm f/%.1f-%.1f", minFL, maxFL, minFS, maxFS);
-
- }
-
- else
- {
-
- if (minFL == maxFL)
- sprintf (s, "%.1f mm", minFL);
-
- else
- sprintf (s, "%.1f-%.1f mm", minFL, maxFL);
-
- }
-
- exif.fLensName.Set (s);
-
- SetString (XMP_NS_AUX,
- "Lens",
- exif.fLensName);
-
- }
-
- }
-
- // Lens ID:
-
- SyncString (XMP_NS_AUX,
- "LensID",
- exif.fLensID,
- readOnly);
-
- // Lens Make:
-
- SyncString (XMP_NS_EXIF,
- "LensMake",
- exif.fLensMake,
- readOnly + removable);
-
- // Lens Serial Number:
-
- SyncString (XMP_NS_AUX,
- "LensSerialNumber",
- exif.fLensSerialNumber,
- readOnly);
-
- // Image Number:
-
- Sync_uint32 (XMP_NS_AUX,
- "ImageNumber",
- exif.fImageNumber,
- exif.fImageNumber == 0xFFFFFFFF,
- readOnly);
-
- // User Comment:
-
- if (exif.fUserComment.NotEmpty ())
- {
-
- fSDK->SetAltLangDefault (XMP_NS_EXIF,
- "UserComment",
- exif.fUserComment);
-
- }
-
- else
- {
-
- (void) fSDK->GetAltLangDefault (XMP_NS_EXIF,
- "UserComment",
- exif.fUserComment);
-
- }
-
- if (removeFromXMP)
- {
- Remove (XMP_NS_EXIF, "UserComment");
- }
-
- // Approximate focus distance:
-
- SyncApproximateFocusDistance (exif,
- readOnly);
-
- // Flash Compensation:
-
- Sync_srational (XMP_NS_AUX,
- "FlashCompensation",
- exif.fFlashCompensation,
- readOnly);
-
- // Owner Name: (allow XMP updates)
-
- SyncString (XMP_NS_AUX,
- "OwnerName",
- exif.fOwnerName,
- preferXMP);
-
- // Firmware:
-
- SyncString (XMP_NS_AUX,
- "Firmware",
- exif.fFirmware,
- readOnly);
-
- // Image Unique ID:
-
- {
-
- dng_string s = EncodeFingerprint (exif.fImageUniqueID);
-
- SyncString (XMP_NS_EXIF,
- "ImageUniqueID",
- s,
- readOnly + removable);
-
- exif.fImageUniqueID = DecodeFingerprint (s);
-
- }
-
- // Allow EXIF GPS to be updated via updates from XMP.
-
- if (doingUpdateFromXMP)
- {
-
- // Require that at least one basic GPS field exist in the
- // XMP before overrriding the EXIF GPS fields.
-
- if (Exists (XMP_NS_EXIF, "GPSVersionID" ) ||
- Exists (XMP_NS_EXIF, "GPSLatitude" ) ||
- Exists (XMP_NS_EXIF, "GPSLongitude" ) ||
- Exists (XMP_NS_EXIF, "GPSAltitude" ) ||
- Exists (XMP_NS_EXIF, "GPSTimeStamp" ) ||
- Exists (XMP_NS_EXIF, "GPSProcessingMethod"))
- {
-
- // Clear out the GPS info from the EXIF so it will
- // replaced by the GPS info from the XMP.
-
- dng_exif blankExif;
-
- exif.CopyGPSFrom (blankExif);
-
- }
-
- }
-
- // GPS Version ID:
-
- {
-
- dng_string s = EncodeGPSVersion (exif.fGPSVersionID);
-
- if (SyncString (XMP_NS_EXIF,
- "GPSVersionID",
- s,
- preferNonXMP + removable))
- {
-
- exif.fGPSVersionID = DecodeGPSVersion (s);
-
- }
-
- }
-
- // GPS Latitude:
-
- {
-
- dng_string s = EncodeGPSCoordinate (exif.fGPSLatitudeRef,
- exif.fGPSLatitude);
-
- if (SyncString (XMP_NS_EXIF,
- "GPSLatitude",
- s,
- preferNonXMP + removable))
- {
-
- DecodeGPSCoordinate (s,
- exif.fGPSLatitudeRef,
- exif.fGPSLatitude);
-
- }
-
- }
-
- // GPS Longitude:
-
- {
-
- dng_string s = EncodeGPSCoordinate (exif.fGPSLongitudeRef,
- exif.fGPSLongitude);
-
- if (SyncString (XMP_NS_EXIF,
- "GPSLongitude",
- s,
- preferNonXMP + removable))
- {
-
- DecodeGPSCoordinate (s,
- exif.fGPSLongitudeRef,
- exif.fGPSLongitude);
-
- }
-
- }
-
- // Handle simple case of incorrectly written GPS altitude where someone didn't understand the GPSAltitudeRef and assumed the GPSAltitude RATIONAL is signed.
- // Only handle this case as we do not want to misinterpret e.g. a fixed point representation of very high GPS altitudes.
-
- uint32 &altitudeRef = exif.fGPSAltitudeRef;
- dng_urational &altitude = exif.fGPSAltitude;
-
- if (altitude.IsValid () &&
- (altitudeRef == 0 || altitudeRef == 0xFFFFFFFF)) // If the file contains a "below sea level" altitudeRef, assume the writing software is working according to the spec.
- {
-
- if ((altitude.n & (1U << 31)) &&
- altitude.d < 7) // As the denominator increases, large numerator values become possibly valid distances. Pick a limit on the conservative side (approx 33e6m) to prevent misinterpretation.
- // Noting that the normal case for this mistake has a denominator of 1
- {
-
- altitude.n = ~altitude.n + 1;
- altitudeRef = 1;
-
- }
-
- }
-
- // GPS Altitude Reference:
-
- Sync_uint32 (XMP_NS_EXIF,
- "GPSAltitudeRef",
- altitudeRef,
- altitudeRef == 0xFFFFFFFF,
- preferNonXMP + removable);
-
- // GPS Altitude:
-
- Sync_urational (XMP_NS_EXIF,
- "GPSAltitude",
- altitude,
- preferNonXMP + removable);
-
- // GPS Date/Time:
-
- {
-
- dng_string s = EncodeGPSDateTime (exif.fGPSDateStamp,
- exif.fGPSTimeStamp);
-
- if (SyncString (XMP_NS_EXIF,
- "GPSTimeStamp",
- s,
- preferNonXMP + removable))
- {
-
- DecodeGPSDateTime (s,
- exif.fGPSDateStamp,
- exif.fGPSTimeStamp);
-
- }
-
- }
-
- // GPS Satellites:
-
- SyncString (XMP_NS_EXIF,
- "GPSSatellites",
- exif.fGPSSatellites,
- preferNonXMP + removable);
-
- // GPS Status:
-
- SyncString (XMP_NS_EXIF,
- "GPSStatus",
- exif.fGPSStatus,
- preferNonXMP + removable);
-
- // GPS Measure Mode:
-
- SyncString (XMP_NS_EXIF,
- "GPSMeasureMode",
- exif.fGPSMeasureMode,
- preferNonXMP + removable);
-
- // GPS DOP:
-
- Sync_urational (XMP_NS_EXIF,
- "GPSDOP",
- exif.fGPSDOP,
- preferNonXMP + removable);
-
- // GPS Speed Reference:
-
- SyncString (XMP_NS_EXIF,
- "GPSSpeedRef",
- exif.fGPSSpeedRef,
- preferNonXMP + removable);
-
- // GPS Speed:
-
- Sync_urational (XMP_NS_EXIF,
- "GPSSpeed",
- exif.fGPSSpeed,
- preferNonXMP + removable);
-
- // GPS Track Reference:
-
- SyncString (XMP_NS_EXIF,
- "GPSTrackRef",
- exif.fGPSTrackRef,
- preferNonXMP + removable);
-
- // GPS Track:
-
- Sync_urational (XMP_NS_EXIF,
- "GPSTrack",
- exif.fGPSTrack,
- preferNonXMP + removable);
-
- // GPS Image Direction Reference:
-
- SyncString (XMP_NS_EXIF,
- "GPSImgDirectionRef",
- exif.fGPSImgDirectionRef,
- preferNonXMP + removable);
-
- // GPS Image Direction:
-
- Sync_urational (XMP_NS_EXIF,
- "GPSImgDirection",
- exif.fGPSImgDirection,
- preferNonXMP + removable);
-
- // GPS Map Datum:
-
- SyncString (XMP_NS_EXIF,
- "GPSMapDatum",
- exif.fGPSMapDatum,
- preferNonXMP + removable);
-
- // GPS Destination Latitude:
-
- {
-
- dng_string s = EncodeGPSCoordinate (exif.fGPSDestLatitudeRef,
- exif.fGPSDestLatitude);
-
- if (SyncString (XMP_NS_EXIF,
- "GPSDestLatitude",
- s,
- preferNonXMP + removable))
- {
-
- DecodeGPSCoordinate (s,
- exif.fGPSDestLatitudeRef,
- exif.fGPSDestLatitude);
-
- }
-
- }
-
- // GPS Destination Longitude:
-
- {
-
- dng_string s = EncodeGPSCoordinate (exif.fGPSDestLongitudeRef,
- exif.fGPSDestLongitude);
-
- if (SyncString (XMP_NS_EXIF,
- "GPSDestLongitude",
- s,
- preferNonXMP + removable))
- {
-
- DecodeGPSCoordinate (s,
- exif.fGPSDestLongitudeRef,
- exif.fGPSDestLongitude);
-
- }
-
- }
-
- // GPS Destination Bearing Reference:
-
- SyncString (XMP_NS_EXIF,
- "GPSDestBearingRef",
- exif.fGPSDestBearingRef,
- preferNonXMP + removable);
-
- // GPS Destination Bearing:
-
- Sync_urational (XMP_NS_EXIF,
- "GPSDestBearing",
- exif.fGPSDestBearing,
- preferNonXMP + removable);
-
- // GPS Destination Distance Reference:
-
- SyncString (XMP_NS_EXIF,
- "GPSDestDistanceRef",
- exif.fGPSDestDistanceRef,
- preferNonXMP + removable);
-
- // GPS Destination Distance:
-
- Sync_urational (XMP_NS_EXIF,
- "GPSDestDistance",
- exif.fGPSDestDistance,
- preferNonXMP + removable);
-
- // GPS Processing Method:
-
- SyncString (XMP_NS_EXIF,
- "GPSProcessingMethod",
- exif.fGPSProcessingMethod,
- preferNonXMP + removable);
-
- // GPS Area Information:
-
- SyncString (XMP_NS_EXIF,
- "GPSAreaInformation",
- exif.fGPSAreaInformation,
- preferNonXMP + removable);
-
- // GPS Differential:
-
- Sync_uint32 (XMP_NS_EXIF,
- "GPSDifferential",
- exif.fGPSDifferential,
- exif.fGPSDifferential == 0xFFFFFFFF,
- preferNonXMP + removable);
-
- // GPS Horizontal Positioning Error:
-
- Sync_urational (XMP_NS_EXIF,
- "GPSHPositioningError",
- exif.fGPSHPositioningError,
- preferNonXMP + removable);
-
- // Sync date/times.
-
- UpdateExifDates (exif, removeFromXMP);
-
- // We are syncing EXIF and XMP, but we are not updating the
- // NativeDigest tags. It is better to just delete them than leave
- // the stale values around.
-
- Remove (XMP_NS_EXIF, "NativeDigest");
- Remove (XMP_NS_TIFF, "NativeDigest");
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SyncApproximateFocusDistance (dng_exif &exif,
- const uint32 readOnly)
- {
-
- Sync_urational (XMP_NS_AUX,
- "ApproximateFocusDistance",
- exif.fApproxFocusDistance,
- readOnly);
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::ValidateStringList (const char *ns,
- const char *path)
- {
-
- fSDK->ValidateStringList (ns, path);
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::ValidateMetadata ()
- {
-
- // The following values should be arrays, but are not always. So
- // fix them up because Photoshop sometimes has problems parsing invalid
- // tags.
-
- ValidateStringList (XMP_NS_DC, "creator");
-
- ValidateStringList (XMP_NS_PHOTOSHOP, "Keywords");
- ValidateStringList (XMP_NS_PHOTOSHOP, "SupplementalCategories");
-
- }
-
-/******************************************************************************/
-
-bool dng_xmp::DateTimeIsDateOnly (const char *ns,
- const char *path)
- {
-
- dng_string s;
-
- if (GetString (ns, path, s))
- {
-
- uint32 len = s.Length ();
-
- if (len)
- {
-
- for (uint32 j = 0; j < len; j++)
- {
-
- if (s.Get () [j] == 'T')
- {
-
- return false;
-
- }
-
- }
-
- return true;
-
- }
-
- }
-
- return false;
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::UpdateExifDates (dng_exif &exif,
- bool removeFromXMP)
- {
-
- // For the following three date/time fields, we always prefer XMP to
- // the EXIF values. This is to allow the user to correct the date/times
- // via changes in a sidecar XMP file, without modifying the original
- // raw file.
-
- // Kludge: The Nikon D4 is writing date only date/times into XMP, so
- // prefer the EXIF values if the XMP only contains a date.
-
- // Modification Date/Time:
- // exif.fDateTime
- // kXMP_NS_XMP:"ModifyDate" & kXMP_NS_TIFF:"DateTime" are aliased
-
- {
-
- dng_string s = exif.fDateTime.Encode_ISO_8601 ();
-
- bool dateOnly = DateTimeIsDateOnly (XMP_NS_TIFF, "DateTime");
-
- SyncString (XMP_NS_TIFF,
- "DateTime",
- s,
- dateOnly ? preferNonXMP : preferXMP);
-
- if (s.NotEmpty ())
- {
-
- exif.fDateTime.Decode_ISO_8601 (s.Get ());
-
- // Round trip again in case we need to add a fake time zone.
-
- s = exif.fDateTime.Encode_ISO_8601 ();
-
- SetString (XMP_NS_TIFF,
- "DateTime",
- s);
-
- }
-
- }
-
- // Original Date/Time:
- // exif.fDateTimeOriginal
- // IPTC: DateCreated
- // XMP_NS_EXIF:"DateTimeOriginal" & XMP_NS_PHOTOSHOP:"DateCreated"
- // Adobe has decided to keep the two XMP fields separate.
-
- {
-
- dng_string s = exif.fDateTimeOriginal.Encode_ISO_8601 ();
-
- bool dateOnly = DateTimeIsDateOnly (XMP_NS_EXIF, "DateTimeOriginal");
-
- SyncString (XMP_NS_EXIF,
- "DateTimeOriginal",
- s,
- dateOnly ? preferNonXMP : preferXMP);
-
- if (s.NotEmpty ())
- {
-
- exif.fDateTimeOriginal.Decode_ISO_8601 (s.Get ());
-
- // Round trip again in case we need to add a fake time zone.
-
- s = exif.fDateTimeOriginal.Encode_ISO_8601 ();
-
- SetString (XMP_NS_EXIF,
- "DateTimeOriginal",
- s);
-
- }
-
- // Sync the IPTC value to the EXIF value if only the EXIF
- // value exists.
-
- if (s.NotEmpty () && !Exists (XMP_NS_PHOTOSHOP, "DateCreated"))
- {
-
- SetString (XMP_NS_PHOTOSHOP, "DateCreated", s);
-
- }
-
- if (removeFromXMP)
- {
-
- Remove (XMP_NS_EXIF, "DateTimeOriginal");
-
- }
-
- }
-
- // Date Time Digitized:
- // XMP_NS_EXIF:"DateTimeDigitized" & kXMP_NS_XMP:"CreateDate" are aliased
-
- {
-
- dng_string s = exif.fDateTimeDigitized.Encode_ISO_8601 ();
-
- bool dateOnly = DateTimeIsDateOnly (XMP_NS_EXIF, "DateTimeDigitized");
-
- SyncString (XMP_NS_EXIF,
- "DateTimeDigitized",
- s,
- dateOnly ? preferNonXMP : preferXMP);
-
- if (s.NotEmpty ())
- {
-
- exif.fDateTimeDigitized.Decode_ISO_8601 (s.Get ());
-
- // Round trip again in case we need to add a fake time zone.
-
- s = exif.fDateTimeDigitized.Encode_ISO_8601 ();
-
- SetString (XMP_NS_EXIF,
- "DateTimeDigitized",
- s);
-
- }
-
- }
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::UpdateDateTime (const dng_date_time_info &dt)
- {
-
- dng_string s = dt.Encode_ISO_8601 ();
-
- SetString (XMP_NS_TIFF,
- "DateTime",
- s);
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::UpdateMetadataDate (const dng_date_time_info &dt)
- {
-
- dng_string s = dt.Encode_ISO_8601 ();
-
- SetString (XMP_NS_XAP,
- "MetadataDate",
- s);
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp::HasOrientation () const
- {
-
- uint32 x = 0;
-
- if (Get_uint32 (XMP_NS_TIFF,
- "Orientation",
- x))
- {
-
- return (x >= 1) && (x <= 8);
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-dng_orientation dng_xmp::GetOrientation () const
- {
-
- dng_orientation result;
-
- uint32 x = 0;
-
- if (Get_uint32 (XMP_NS_TIFF,
- "Orientation",
- x))
- {
-
- if ((x >= 1) && (x <= 8))
- {
-
- result.SetTIFF (x);
-
- }
-
- }
-
- return result;
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::ClearOrientation ()
- {
-
- fSDK->Remove (XMP_NS_TIFF, "Orientation");
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::SetOrientation (const dng_orientation &orientation)
- {
-
- Set_uint32 (XMP_NS_TIFF,
- "Orientation",
- orientation.GetTIFF ());
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SyncOrientation (dng_negative &negative,
- bool xmpIsMaster)
- {
-
- SyncOrientation (negative.Metadata (), xmpIsMaster);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::SyncOrientation (dng_metadata &metadata,
- bool xmpIsMaster)
- {
-
- // See if XMP contains the orientation.
-
- bool xmpHasOrientation = HasOrientation ();
-
- // See if XMP is the master value.
-
- if (xmpHasOrientation && (xmpIsMaster || !metadata.HasBaseOrientation ()))
- {
-
- metadata.SetBaseOrientation (GetOrientation ());
-
- }
-
- else
- {
-
- SetOrientation (metadata.BaseOrientation ());
-
- }
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::ClearImageInfo ()
- {
-
- Remove (XMP_NS_TIFF, "ImageWidth" );
- Remove (XMP_NS_TIFF, "ImageLength");
-
- Remove (XMP_NS_EXIF, "PixelXDimension");
- Remove (XMP_NS_EXIF, "PixelYDimension");
-
- Remove (XMP_NS_TIFF, "BitsPerSample");
-
- Remove (XMP_NS_TIFF, "Compression");
-
- Remove (XMP_NS_TIFF, "PhotometricInterpretation");
-
- // "Orientation" is handled separately.
-
- Remove (XMP_NS_TIFF, "SamplesPerPixel");
-
- Remove (XMP_NS_TIFF, "PlanarConfiguration");
-
- Remove (XMP_NS_TIFF, "XResolution");
- Remove (XMP_NS_TIFF, "YResolution");
-
- Remove (XMP_NS_TIFF, "ResolutionUnit");
-
- Remove (XMP_NS_PHOTOSHOP, "ColorMode" );
- Remove (XMP_NS_PHOTOSHOP, "ICCProfile");
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::SetImageSize (const dng_point &size)
- {
-
- Set_uint32 (XMP_NS_TIFF, "ImageWidth" , size.h);
- Set_uint32 (XMP_NS_TIFF, "ImageLength", size.v);
-
- // Mirror these values to the EXIF tags.
-
- Set_uint32 (XMP_NS_EXIF, "PixelXDimension" , size.h);
- Set_uint32 (XMP_NS_EXIF, "PixelYDimension" , size.v);
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::SetSampleInfo (uint32 samplesPerPixel,
- uint32 bitsPerSample)
- {
-
- Set_uint32 (XMP_NS_TIFF, "SamplesPerPixel", samplesPerPixel);
-
- char s [32];
-
- sprintf (s, "%u", (unsigned) bitsPerSample);
-
- dng_string ss;
-
- ss.Set (s);
-
- dng_string_list list;
-
- for (uint32 j = 0; j < samplesPerPixel; j++)
- {
- list.Append (ss);
- }
-
- SetStringList (XMP_NS_TIFF, "BitsPerSample", list, false);
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::SetPhotometricInterpretation (uint32 pi)
- {
-
- Set_uint32 (XMP_NS_TIFF, "PhotometricInterpretation", pi);
-
- }
-
-/******************************************************************************/
-
-void dng_xmp::SetResolution (const dng_resolution &res)
- {
-
- Set_urational (XMP_NS_TIFF, "XResolution", res.fXResolution);
- Set_urational (XMP_NS_TIFF, "YResolution", res.fYResolution);
-
- Set_uint32 (XMP_NS_TIFF, "ResolutionUnit", res.fResolutionUnit);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::ComposeArrayItemPath (const char *ns,
- const char *arrayName,
- int32 itemNumber,
- dng_string &s) const
- {
-
- fSDK->ComposeArrayItemPath (ns, arrayName, itemNumber, s);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::ComposeStructFieldPath (const char *ns,
- const char *structName,
- const char *fieldNS,
- const char *fieldName,
- dng_string &s) const
- {
-
- fSDK->ComposeStructFieldPath (ns, structName, fieldNS, fieldName, s);
-
- }
-
-/*****************************************************************************/
-
-int32 dng_xmp::CountArrayItems (const char *ns,
- const char *path) const
- {
-
- return fSDK->CountArrayItems (ns, path);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::AppendArrayItem (const char *ns,
- const char *arrayName,
- const char *itemValue,
- bool isBag,
- bool propIsStruct)
- {
-
- fSDK->AppendArrayItem (ns,
- arrayName,
- itemValue,
- isBag,
- propIsStruct);
- }
-
-/*****************************************************************************/
-
-#if qDNGXMPDocOps
-
-/*****************************************************************************/
-
-void dng_xmp::DocOpsOpenXMP (const char *srcMIMI)
- {
-
- fSDK->DocOpsOpenXMP (srcMIMI);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::DocOpsPrepareForSave (const char *srcMIMI,
- const char *dstMIMI,
- bool newPath)
- {
-
- fSDK->DocOpsPrepareForSave (srcMIMI,
- dstMIMI,
- newPath);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp::DocOpsUpdateMetadata (const char *srcMIMI)
- {
-
- fSDK->DocOpsUpdateMetadata (srcMIMI);
-
- }
-
-/*****************************************************************************/
-
-#endif
-
-#endif
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-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_xmp.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+#if qDNGUseXMP
+
+#include "dng_xmp.h"
+
+#include "dng_assertions.h"
+#include "dng_date_time.h"
+#include "dng_exceptions.h"
+#include "dng_exif.h"
+#include "dng_image_writer.h"
+#include "dng_iptc.h"
+#include "dng_negative.h"
+#include "dng_string.h"
+#include "dng_string_list.h"
+#include "dng_utils.h"
+#include "dng_xmp_sdk.h"
+
+/*****************************************************************************/
+
+dng_xmp::dng_xmp (dng_memory_allocator &allocator)
+
+ : fAllocator (allocator)
+
+ , fSDK (NULL)
+
+ {
+
+ fSDK = new dng_xmp_sdk ();
+
+ if (!fSDK)
+ {
+ ThrowMemoryFull ();
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_xmp::dng_xmp (const dng_xmp &xmp)
+
+ : fAllocator (xmp.fAllocator)
+
+ , fSDK (NULL)
+
+ {
+
+ fSDK = new dng_xmp_sdk (*xmp.fSDK);
+
+ if (!fSDK)
+ {
+ ThrowMemoryFull ();
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_xmp::~dng_xmp ()
+ {
+
+ if (fSDK)
+ {
+
+ delete fSDK;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_xmp * dng_xmp::Clone () const
+ {
+
+ dng_xmp *result = new dng_xmp (*this);
+
+ if (!result)
+ {
+ ThrowMemoryFull ();
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::TrimDecimal (char *s)
+ {
+
+ uint32 len = (uint32) strlen (s);
+
+ while (len > 0)
+ {
+
+ if (s [len - 1] == '0')
+ s [--len] = 0;
+
+ else
+ break;
+
+ }
+
+ if (len > 0)
+ {
+
+ if (s [len - 1] == '.')
+ s [--len] = 0;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_string dng_xmp::EncodeFingerprint (const dng_fingerprint &f,
+ bool allowInvalid)
+ {
+
+ dng_string result;
+
+ if (f.IsValid () || allowInvalid)
+ {
+
+ char s [dng_fingerprint::kDNGFingerprintSize * 2 + 1];
+
+ f.ToUtf8HexString (s);
+
+ result.Set (s);
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+dng_fingerprint dng_xmp::DecodeFingerprint (const dng_string &s)
+ {
+
+ dng_fingerprint result;
+
+ if (s.Length () == 32)
+ result.FromUtf8HexString (s.Get ());
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+dng_string dng_xmp::EncodeGPSVersion (uint32 version)
+ {
+
+ dng_string result;
+
+ if (version)
+ {
+
+ uint8 b0 = (uint8) (version >> 24);
+ uint8 b1 = (uint8) (version >> 16);
+ uint8 b2 = (uint8) (version >> 8);
+ uint8 b3 = (uint8) (version );
+
+ if (b0 <= 9 && b1 <= 9 && b2 <= 9 && b3 <= 9)
+ {
+
+ char s [32];
+
+ sprintf (s,
+ "%u.%u.%u.%u",
+ (unsigned) b0,
+ (unsigned) b1,
+ (unsigned) b2,
+ (unsigned) b3);
+
+ result.Set (s);
+
+ }
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+uint32 dng_xmp::DecodeGPSVersion (const dng_string &s)
+ {
+
+ uint32 result = 0;
+
+ if (s.Length () == 7)
+ {
+
+ unsigned b0 = 0;
+ unsigned b1 = 0;
+ unsigned b2 = 0;
+ unsigned b3 = 0;
+
+ if (sscanf (s.Get (),
+ "%u.%u.%u.%u",
+ &b0,
+ &b1,
+ &b2,
+ &b3) == 4)
+ {
+
+ result = (b0 << 24) |
+ (b1 << 16) |
+ (b2 << 8) |
+ (b3 );
+
+ }
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+dng_string dng_xmp::EncodeGPSCoordinate (const dng_string &ref,
+ const dng_urational *coord)
+ {
+
+ dng_string result;
+
+ if (ref.Length () == 1 && coord [0].IsValid () &&
+ coord [1].IsValid ())
+ {
+
+ char refChar = ForceUppercase (ref.Get () [0]);
+
+ if (refChar == 'N' ||
+ refChar == 'S' ||
+ refChar == 'E' ||
+ refChar == 'W')
+ {
+
+ char s [256];
+
+ // Use the seconds case if all three values are
+ // integers.
+
+ if (coord [0].d == 1 &&
+ coord [1].d == 1 &&
+ coord [2].d == 1)
+ {
+
+ sprintf (s,
+ "%u,%u,%u%c",
+ (unsigned) coord [0].n,
+ (unsigned) coord [1].n,
+ (unsigned) coord [2].n,
+ refChar);
+
+ }
+
+ // Else we need to use the fractional minutes case.
+
+ else
+ {
+
+ // Find value minutes.
+
+ real64 x = coord [0].As_real64 () * 60.0 +
+ coord [1].As_real64 () +
+ coord [2].As_real64 () * (1.0 / 60.0);
+
+ // Round to fractional four decimal places.
+
+ uint32 y = Round_uint32 (x * 10000.0);
+
+ // Split into degrees and minutes.
+
+ uint32 d = y / (60 * 10000);
+ uint32 m = y % (60 * 10000);
+
+ char min [32];
+
+ sprintf (min, "%.4f", m * (1.0 / 10000.0));
+
+ TrimDecimal (min);
+
+ sprintf (s,
+ "%u,%s%c",
+ (unsigned) d,
+ min,
+ refChar);
+
+ }
+
+ result.Set (s);
+
+ }
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::DecodeGPSCoordinate (const dng_string &s,
+ dng_string &ref,
+ dng_urational *coord)
+ {
+
+ ref.Clear ();
+
+ coord [0].Clear ();
+ coord [1].Clear ();
+ coord [2].Clear ();
+
+ if (s.Length () > 1)
+ {
+
+ char refChar = ForceUppercase (s.Get () [s.Length () - 1]);
+
+ if (refChar == 'N' ||
+ refChar == 'S' ||
+ refChar == 'E' ||
+ refChar == 'W')
+ {
+
+ dng_string ss (s);
+
+ ss.Truncate (ss.Length () - 1);
+
+ ss.NormalizeAsCommaSeparatedNumbers();
+
+ int degrees = 0;
+
+ real64 minutes = 0.0;
+ real64 seconds = 0.0;
+
+ int count = sscanf (ss.Get (),
+ "%d,%lf,%lf",
+ &degrees,
+ &minutes,
+ &seconds);
+
+ if (count < 1)
+ {
+ return;
+ }
+
+ // The degree, minute, second values should always be positive.
+
+ if (degrees < 0 || minutes < 0 || seconds < 0)
+ {
+ return;
+ }
+
+ coord [0] = dng_urational ((uint32) degrees, 1);
+
+ if (count <= 2)
+ {
+ coord [1].Set_real64 (minutes, 10000);
+ coord [2] = dng_urational (0, 1);
+ }
+ else
+ {
+ coord [1].Set_real64 (minutes, 1);
+ coord [2].Set_real64 (seconds, 100);
+ }
+
+ char r [2];
+
+ r [0] = refChar;
+ r [1] = 0;
+
+ ref.Set (r);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_string dng_xmp::EncodeGPSDateTime (const dng_string &dateStamp,
+ const dng_urational *timeStamp)
+ {
+
+ dng_string result;
+
+ if (timeStamp [0].IsValid () &&
+ timeStamp [1].IsValid () &&
+ timeStamp [2].IsValid ())
+ {
+
+ char s [256];
+
+ char sec [32];
+
+ sprintf (sec,
+ "%09.6f",
+ timeStamp [2].As_real64 ());
+
+ TrimDecimal (sec);
+
+ int year = 0;
+ int month = 0;
+ int day = 0;
+
+ if (dateStamp.NotEmpty ())
+ {
+
+ sscanf (dateStamp.Get (),
+ "%d:%d:%d",
+ &year,
+ &month,
+ &day);
+
+ }
+
+ if (year >= 1 && year <= 9999 &&
+ month >= 1 && month <= 12 &&
+ day >= 1 && day <= 31)
+ {
+
+ sprintf (s,
+ "%04d-%02d-%02dT%02u:%02u:%sZ",
+ year,
+ month,
+ day,
+ (unsigned) Round_uint32 (timeStamp [0].As_real64 ()),
+ (unsigned) Round_uint32 (timeStamp [1].As_real64 ()),
+ sec);
+
+ }
+
+ else
+ {
+
+ sprintf (s,
+ "%02u:%02u:%sZ",
+ (unsigned) Round_uint32 (timeStamp [0].As_real64 ()),
+ (unsigned) Round_uint32 (timeStamp [1].As_real64 ()),
+ sec);
+
+ }
+
+ result.Set (s);
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::DecodeGPSDateTime (const dng_string &s,
+ dng_string &dateStamp,
+ dng_urational *timeStamp)
+ {
+
+ dateStamp.Clear ();
+
+ timeStamp [0].Clear ();
+ timeStamp [1].Clear ();
+ timeStamp [2].Clear ();
+
+ if (s.NotEmpty ())
+ {
+
+ unsigned year = 0;
+ unsigned month = 0;
+ unsigned day = 0;
+ unsigned hour = 0;
+ unsigned minute = 0;
+
+ double second = 0.0;
+
+ if (sscanf (s.Get (),
+ "%u-%u-%uT%u:%u:%lf",
+ &year,
+ &month,
+ &day,
+ &hour,
+ &minute,
+ &second) == 6)
+ {
+
+ if (year >= 1 && year <= 9999 &&
+ month >= 1 && month <= 12 &&
+ day >= 1 && day <= 31 )
+ {
+
+ char ss [64];
+
+ sprintf (ss,
+ "%04u:%02u:%02u",
+ year,
+ month,
+ day);
+
+ dateStamp.Set (ss);
+
+ }
+
+ }
+
+ else if (sscanf (s.Get (),
+ "%u:%u:%lf",
+ &hour,
+ &minute,
+ &second) != 3)
+ {
+
+ return;
+
+ }
+
+ timeStamp [0] = dng_urational ((uint32) hour , 1);
+ timeStamp [1] = dng_urational ((uint32) minute, 1);
+
+ timeStamp [2].Set_real64 (second, 1000);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Parse (dng_host &host,
+ const void *buffer,
+ uint32 count)
+ {
+
+ fSDK->Parse (host,
+ (const char *) buffer,
+ count);
+
+ }
+
+/*****************************************************************************/
+
+dng_memory_block * dng_xmp::Serialize (bool asPacket,
+ uint32 targetBytes,
+ uint32 padBytes,
+ bool forJPEG,
+ bool compact) const
+ {
+
+ return fSDK->Serialize (fAllocator,
+ asPacket,
+ targetBytes,
+ padBytes,
+ forJPEG,
+ compact);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::PackageForJPEG (AutoPtr<dng_memory_block> &stdBlock,
+ AutoPtr<dng_memory_block> &extBlock,
+ dng_string &extDigest) const
+ {
+
+ fSDK->PackageForJPEG (fAllocator,
+ stdBlock,
+ extBlock,
+ extDigest);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::MergeFromJPEG (const dng_xmp &xmp)
+ {
+
+ fSDK->MergeFromJPEG (xmp.fSDK);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::HasMeta () const
+ {
+
+ return fSDK->HasMeta ();
+
+ }
+
+/*****************************************************************************/
+
+void * dng_xmp::GetPrivateMeta ()
+ {
+
+ return fSDK->GetPrivateMeta ();
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::Exists (const char *ns,
+ const char *path) const
+ {
+
+ return fSDK->Exists (ns, path);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::HasNameSpace (const char *ns) const
+ {
+
+ return fSDK->HasNameSpace (ns);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::IteratePaths (IteratePathsCallback *callback,
+ void *callbackData,
+ const char *ns,
+ const char *path)
+ {
+
+ return fSDK->IteratePaths (callback, callbackData, ns, path);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Remove (const char *ns,
+ const char *path)
+ {
+
+ fSDK->Remove (ns, path);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::RemoveProperties (const char *ns)
+ {
+
+ fSDK->RemoveProperties (ns);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::RemoveEmptyStringOrArray (const char *ns,
+ const char *path)
+ {
+
+ if (path == NULL || path [0] == 0)
+ {
+ return;
+ }
+
+ if (fSDK->IsEmptyString (ns, path) ||
+ fSDK->IsEmptyArray (ns, path))
+ {
+
+ Remove (ns, path);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+static bool RemoveEmptyStringsAndArraysCallback (const char *ns,
+ const char *path,
+ void *callbackData)
+ {
+
+ dng_xmp *xmp = (dng_xmp *) callbackData;
+
+ xmp->RemoveEmptyStringOrArray (ns, path);
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::RemoveEmptyStringsAndArrays (const char *ns)
+ {
+
+ IteratePaths (RemoveEmptyStringsAndArraysCallback,
+ (void *) this,
+ ns,
+ NULL);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Set (const char *ns,
+ const char *path,
+ const char *text)
+ {
+
+ fSDK->Set (ns, path, text);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::GetString (const char *ns,
+ const char *path,
+ dng_string &s) const
+ {
+
+ return fSDK->GetString (ns, path, s);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SetString (const char *ns,
+ const char *path,
+ const dng_string &s)
+ {
+
+ fSDK->SetString (ns, path, s);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::SyncString (const char *ns,
+ const char *path,
+ dng_string &s,
+ uint32 options)
+ {
+
+ bool isDefault = s.IsEmpty ();
+
+ // Sync 1: Force XMP to match non-XMP.
+
+ if (options & ignoreXMP)
+ {
+
+ if (isDefault || (options & removeXMP))
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ SetString (ns, path, s);
+
+ }
+
+ return false;
+
+ }
+
+ // Sync 2: From non-XMP to XMP if non-XMP is prefered.
+
+ if ((options & preferNonXMP) && !isDefault)
+ {
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ SetString (ns, path, s);
+
+ }
+
+ return false;
+
+ }
+
+ // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
+
+ if ((options & preferXMP) || isDefault)
+ {
+
+ if (GetString (ns, path, s))
+ {
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ return true;
+
+ }
+
+ }
+
+ // Sync 4: From non-XMP to XMP.
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else if (!isDefault)
+ {
+
+ SetString (ns, path, s);
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::GetStringList (const char *ns,
+ const char *path,
+ dng_string_list &list) const
+ {
+
+ return fSDK->GetStringList (ns, path, list);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SetStringList (const char *ns,
+ const char *path,
+ const dng_string_list &list,
+ bool isBag)
+ {
+
+ fSDK->SetStringList (ns, path, list, isBag);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SyncStringList (const char *ns,
+ const char *path,
+ dng_string_list &list,
+ bool isBag,
+ uint32 options)
+ {
+
+ bool isDefault = (list.Count () == 0);
+
+ // First make sure the XMP is not badly formatted, since
+ // this breaks some Photoshop logic.
+
+ ValidateStringList (ns, path);
+
+ // Sync 1: Force XMP to match non-XMP.
+
+ if (options & ignoreXMP)
+ {
+
+ if (isDefault)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ SetStringList (ns, path, list, isBag);
+
+ }
+
+ return;
+
+ }
+
+ // Sync 2: From non-XMP to XMP if non-XMP is prefered.
+
+ if ((options & preferNonXMP) && !isDefault)
+ {
+
+ SetStringList (ns, path, list, isBag);
+
+ return;
+
+ }
+
+ // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
+
+ if ((options & preferXMP) || isDefault)
+ {
+
+ if (GetStringList (ns, path, list))
+ {
+
+ return;
+
+ }
+
+ }
+
+ // Sync 4: From non-XMP to XMP.
+
+ if (!isDefault)
+ {
+
+ SetStringList (ns, path, list, isBag);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SetStructField (const char *ns,
+ const char *path,
+ const char *fieldNS,
+ const char *fieldName,
+ const dng_string &s)
+ {
+
+ dng_string ss (s);
+
+ ss.SetLineEndings ('\n');
+
+ ss.StripLowASCII ();
+
+ fSDK->SetStructField (ns, path, fieldNS, fieldName, ss.Get ());
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SetStructField (const char *ns,
+ const char *path,
+ const char *fieldNS,
+ const char *fieldName,
+ const char *s)
+ {
+
+ fSDK->SetStructField (ns, path, fieldNS, fieldName, s);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::DeleteStructField (const char *ns,
+ const char *path,
+ const char *fieldNS,
+ const char *fieldName)
+ {
+
+ fSDK->DeleteStructField (ns, path, fieldNS, fieldName);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::GetStructField (const char *ns,
+ const char *path,
+ const char *fieldNS,
+ const char *fieldName,
+ dng_string &s) const
+ {
+
+ return fSDK->GetStructField (ns, path, fieldNS, fieldName, s);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SetAltLangDefault (const char *ns,
+ const char *path,
+ const dng_string &s)
+ {
+
+ fSDK->SetAltLangDefault (ns, path, s);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::GetAltLangDefault (const char *ns,
+ const char *path,
+ dng_string &s) const
+ {
+
+ return fSDK->GetAltLangDefault (ns, path, s);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::SyncAltLangDefault (const char *ns,
+ const char *path,
+ dng_string &s,
+ uint32 options)
+ {
+
+ bool isDefault = s.IsEmpty ();
+
+ // Sync 1: Force XMP to match non-XMP.
+
+ if (options & ignoreXMP)
+ {
+
+ if (isDefault)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ SetAltLangDefault (ns, path, s);
+
+ }
+
+ return false;
+
+ }
+
+ // Sync 2: From non-XMP to XMP if non-XMP is prefered.
+
+ if ((options & preferNonXMP) && !isDefault)
+ {
+
+ SetAltLangDefault (ns, path, s);
+
+ return false;
+
+ }
+
+ // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
+
+ if ((options & preferXMP) || isDefault)
+ {
+
+ if (GetAltLangDefault (ns, path, s))
+ {
+
+ return true;
+
+ }
+
+ }
+
+ // Sync 4: From non-XMP to XMP.
+
+ if (!isDefault)
+ {
+
+ SetAltLangDefault (ns, path, s);
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::GetBoolean (const char *ns,
+ const char *path,
+ bool &x) const
+ {
+
+ dng_string s;
+
+ if (GetString (ns, path, s))
+ {
+
+ if (s.Matches ("True"))
+ {
+
+ x = true;
+
+ return true;
+
+ }
+
+ if (s.Matches ("False"))
+ {
+
+ x = false;
+
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SetBoolean (const char *ns,
+ const char *path,
+ bool x)
+ {
+
+ Set (ns, path, x ? "True" : "False");
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::Get_int32 (const char *ns,
+ const char *path,
+ int32 &x) const
+ {
+
+ dng_string s;
+
+ if (GetString (ns, path, s))
+ {
+
+ if (s.NotEmpty ())
+ {
+
+ int y = 0;
+
+ if (sscanf (s.Get (), "%d", &y) == 1)
+ {
+
+ x = y;
+
+ return true;
+
+ }
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Set_int32 (const char *ns,
+ const char *path,
+ int32 x,
+ bool usePlus)
+ {
+
+ char s [64];
+
+ if (x > 0 && usePlus)
+ {
+ sprintf (s, "+%d", (int) x);
+ }
+ else
+ {
+ sprintf (s, "%d", (int) x);
+ }
+
+ Set (ns, path, s);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::Get_uint32 (const char *ns,
+ const char *path,
+ uint32 &x) const
+ {
+
+ dng_string s;
+
+ if (GetString (ns, path, s))
+ {
+
+ if (s.NotEmpty ())
+ {
+
+ unsigned y = 0;
+
+ if (sscanf (s.Get (), "%u", &y) == 1)
+ {
+
+ x = y;
+
+ return true;
+
+ }
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Set_uint32 (const char *ns,
+ const char *path,
+ uint32 x)
+ {
+
+ char s [64];
+
+ sprintf (s,
+ "%u",
+ (unsigned) x);
+
+ Set (ns, path, s);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Sync_uint32 (const char *ns,
+ const char *path,
+ uint32 &x,
+ bool isDefault,
+ uint32 options)
+ {
+
+ // Sync 1: Force XMP to match non-XMP.
+
+ if (options & ignoreXMP)
+ {
+
+ if (isDefault || (options & removeXMP))
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ Set_uint32 (ns, path, x);
+
+ }
+
+ return;
+
+ }
+
+ // Sync 2: From non-XMP to XMP if non-XMP is prefered.
+
+ if ((options & preferNonXMP) && !isDefault)
+ {
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ Set_uint32 (ns, path, x);
+
+ }
+
+ return;
+
+ }
+
+ // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
+
+ if ((options & preferXMP) || isDefault)
+ {
+
+ if (Get_uint32 (ns, path, x))
+ {
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ return;
+
+ }
+
+ }
+
+ // Sync 4: From non-XMP to XMP.
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else if (!isDefault)
+ {
+
+ Set_uint32 (ns, path, x);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Sync_uint32_array (const char *ns,
+ const char *path,
+ uint32 *data,
+ uint32 &count,
+ uint32 maxCount,
+ uint32 options)
+ {
+
+ dng_string_list list;
+
+ for (uint32 j = 0; j < count; j++)
+ {
+
+ char s [32];
+
+ sprintf (s, "%u", (unsigned) data [j]);
+
+ dng_string ss;
+
+ ss.Set (s);
+
+ list.Append (ss);
+
+ }
+
+ SyncStringList (ns,
+ path,
+ list,
+ false,
+ options);
+
+ count = 0;
+
+ for (uint32 k = 0; k < maxCount; k++)
+ {
+
+ data [k] = 0;
+
+ if (k < list.Count ())
+ {
+
+ unsigned x = 0;
+
+ if (sscanf (list [k].Get (), "%u", &x) == 1)
+ {
+
+ data [count++] = x;
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::Get_real64 (const char *ns,
+ const char *path,
+ real64 &x) const
+ {
+
+ dng_string s;
+
+ if (GetString (ns, path, s))
+ {
+
+ if (s.NotEmpty ())
+ {
+
+ double y = 0;
+
+ if (sscanf (s.Get (), "%lf", &y) == 1)
+ {
+
+ x = y;
+
+ return true;
+
+ }
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Set_real64 (const char *ns,
+ const char *path,
+ real64 x,
+ uint32 places,
+ bool trim,
+ bool usePlus)
+ {
+
+ char s [64];
+
+ if (x > 0.0 && usePlus)
+ {
+ sprintf (s, "+%0.*f", (unsigned) places, (double) x);
+ }
+ else
+ {
+ sprintf (s, "%0.*f", (unsigned) places, (double) x);
+ }
+
+ if (trim)
+ {
+
+ while (s [strlen (s) - 1] == '0')
+ {
+ s [strlen (s) - 1] = 0;
+ }
+
+ if (s [strlen (s) - 1] == '.')
+ {
+ s [strlen (s) - 1] = 0;
+ }
+
+ }
+
+ Set (ns, path, s);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::Get_urational (const char *ns,
+ const char *path,
+ dng_urational &r) const
+ {
+
+ dng_string s;
+
+ if (GetString (ns, path, s))
+ {
+
+ if (s.NotEmpty ())
+ {
+
+ unsigned n = 0;
+ unsigned d = 0;
+
+ if (sscanf (s.Get (), "%u/%u", &n, &d) == 2)
+ {
+
+ if (d != 0)
+ {
+
+ r = dng_urational (n, d);
+
+ return true;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Set_urational (const char *ns,
+ const char *path,
+ const dng_urational &r)
+ {
+
+ char s [64];
+
+ sprintf (s,
+ "%u/%u",
+ (unsigned) r.n,
+ (unsigned) r.d);
+
+ Set (ns, path, s);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Sync_urational (const char *ns,
+ const char *path,
+ dng_urational &r,
+ uint32 options)
+ {
+
+ bool isDefault = r.NotValid ();
+
+ // Sync 1: Force XMP to match non-XMP.
+
+ if (options & ignoreXMP)
+ {
+
+ if (isDefault || (options & removeXMP))
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ Set_urational (ns, path, r);
+
+ }
+
+ return;
+
+ }
+
+ // Sync 2: From non-XMP to XMP if non-XMP is prefered.
+
+ if ((options & preferNonXMP) && !isDefault)
+ {
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ Set_urational (ns, path, r);
+
+ }
+
+ return;
+
+ }
+
+ // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
+
+ if ((options & preferXMP) || isDefault)
+ {
+
+ if (Get_urational (ns, path, r))
+ {
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ return;
+
+ }
+
+ }
+
+ // Sync 4: From non-XMP to XMP.
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else if (!isDefault)
+ {
+
+ Set_urational (ns, path, r);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::Get_srational (const char *ns,
+ const char *path,
+ dng_srational &r) const
+ {
+
+ dng_string s;
+
+ if (GetString (ns, path, s))
+ {
+
+ if (s.NotEmpty ())
+ {
+
+ int n = 0;
+ int d = 0;
+
+ if (sscanf (s.Get (), "%d/%d", &n, &d) == 2)
+ {
+
+ if (d != 0)
+ {
+
+ r = dng_srational (n, d);
+
+ return true;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Set_srational (const char *ns,
+ const char *path,
+ const dng_srational &r)
+ {
+
+ char s [64];
+
+ sprintf (s,
+ "%d/%d",
+ (int) r.n,
+ (int) r.d);
+
+ Set (ns, path, s);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::Sync_srational (const char *ns,
+ const char *path,
+ dng_srational &r,
+ uint32 options)
+ {
+
+ bool isDefault = r.NotValid ();
+
+ // Sync 1: Force XMP to match non-XMP.
+
+ if (options & ignoreXMP)
+ {
+
+ if (isDefault || (options & removeXMP))
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ Set_srational (ns, path, r);
+
+ }
+
+ return;
+
+ }
+
+ // Sync 2: From non-XMP to XMP if non-XMP is prefered.
+
+ if ((options & preferNonXMP) && !isDefault)
+ {
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else
+ {
+
+ Set_srational (ns, path, r);
+
+ }
+
+ return;
+
+ }
+
+ // Sync 3: From XMP to non-XMP if XMP is prefered or default non-XMP.
+
+ if ((options & preferXMP) || isDefault)
+ {
+
+ if (Get_srational (ns, path, r))
+ {
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ return;
+
+ }
+
+ }
+
+ // Sync 4: From non-XMP to XMP.
+
+ if (options & removeXMP)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ else if (!isDefault)
+ {
+
+ Set_srational (ns, path, r);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::GetFingerprint (const char *ns,
+ const char *path,
+ dng_fingerprint &print) const
+ {
+
+ dng_string s;
+
+ if (GetString (ns, path, s))
+ {
+
+ dng_fingerprint temp = DecodeFingerprint (s);
+
+ if (temp.IsValid ())
+ {
+
+ print = temp;
+
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::SetFingerprint (const char *ns,
+ const char *tag,
+ const dng_fingerprint &print,
+ bool allowInvalid)
+ {
+
+ dng_string s = EncodeFingerprint (print, allowInvalid);
+
+ if (s.IsEmpty ())
+ {
+
+ Remove (ns, tag);
+
+ }
+
+ else
+ {
+
+ SetString (ns, tag, s);
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::SetVersion2to4 (const char *ns,
+ const char *path,
+ uint32 version)
+ {
+
+ char buf [32];
+
+ if (version & 0x000000ff)
+ {
+
+ // x.x.x.x
+
+ sprintf (buf,
+ "%u.%u.%u.%u",
+ (unsigned) ((version >> 24) & 0xff),
+ (unsigned) ((version >> 16) & 0xff),
+ (unsigned) ((version >> 8) & 0xff),
+ (unsigned) ((version ) & 0xff));
+
+ }
+
+ else if (version & 0x0000ff00)
+ {
+
+ // x.x.x
+
+ sprintf (buf,
+ "%u.%u.%u",
+ (unsigned) ((version >> 24) & 0xff),
+ (unsigned) ((version >> 16) & 0xff),
+ (unsigned) ((version >> 8) & 0xff));
+
+ }
+
+ else
+ {
+
+ // x.x
+
+ sprintf (buf,
+ "%u.%u",
+ (unsigned) ((version >> 24) & 0xff),
+ (unsigned) ((version >> 16) & 0xff));
+
+ }
+
+ Set (ns, path, buf);
+
+ }
+
+/******************************************************************************/
+
+dng_fingerprint dng_xmp::GetIPTCDigest () const
+ {
+
+ dng_fingerprint digest;
+
+ if (GetFingerprint (XMP_NS_PHOTOSHOP,
+ "LegacyIPTCDigest",
+ digest))
+ {
+
+ return digest;
+
+ }
+
+ return dng_fingerprint ();
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::SetIPTCDigest (dng_fingerprint &digest)
+ {
+
+ SetFingerprint (XMP_NS_PHOTOSHOP,
+ "LegacyIPTCDigest",
+ digest);
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::ClearIPTCDigest ()
+ {
+
+ Remove (XMP_NS_PHOTOSHOP, "LegacyIPTCDigest");
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SyncIPTC (dng_iptc &iptc,
+ uint32 options)
+ {
+
+ SyncAltLangDefault (XMP_NS_DC,
+ "title",
+ iptc.fTitle,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "Category",
+ iptc.fCategory,
+ options);
+
+ {
+
+ uint32 x = 0xFFFFFFFF;
+
+ if (iptc.fUrgency >= 0)
+ {
+
+ x = (uint32) iptc.fUrgency;
+
+ }
+
+ Sync_uint32 (XMP_NS_PHOTOSHOP,
+ "Urgency",
+ x,
+ x == 0xFFFFFFFF,
+ options);
+
+ if (x <= 9)
+ {
+
+ iptc.fUrgency = (int32) x;
+
+ }
+
+ }
+
+ SyncStringList (XMP_NS_PHOTOSHOP,
+ "SupplementalCategories",
+ iptc.fSupplementalCategories,
+ true,
+ options);
+
+ SyncStringList (XMP_NS_PHOTOSHOP,
+ "Keywords",
+ iptc.fKeywords,
+ true,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "Instructions",
+ iptc.fInstructions,
+ options);
+
+ {
+
+ dng_string s = iptc.fDateTimeCreated.Encode_ISO_8601 ();
+
+ if (SyncString (XMP_NS_PHOTOSHOP,
+ "DateCreated",
+ s,
+ options))
+ {
+
+ iptc.fDateTimeCreated.Decode_ISO_8601 (s.Get ());
+
+ }
+
+ }
+
+ {
+
+ dng_string s = iptc.fDigitalCreationDateTime.Encode_ISO_8601 ();
+
+ if (SyncString (XMP_NS_EXIF,
+ "DateTimeDigitized",
+ s,
+ options))
+ {
+
+ iptc.fDigitalCreationDateTime.Decode_ISO_8601 (s.Get ());
+
+ }
+
+ }
+
+ SyncStringList (XMP_NS_DC,
+ "creator",
+ iptc.fAuthors,
+ false,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "AuthorsPosition",
+ iptc.fAuthorsPosition,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "City",
+ iptc.fCity,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "State",
+ iptc.fState,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "Country",
+ iptc.fCountry,
+ options);
+
+ SyncString (XMP_NS_IPTC,
+ "CountryCode",
+ iptc.fCountryCode,
+ options);
+
+ SyncString (XMP_NS_IPTC,
+ "Location",
+ iptc.fLocation,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "TransmissionReference",
+ iptc.fTransmissionReference,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "Headline",
+ iptc.fHeadline,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "Credit",
+ iptc.fCredit,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "Source",
+ iptc.fSource,
+ options);
+
+ SyncAltLangDefault (XMP_NS_DC,
+ "rights",
+ iptc.fCopyrightNotice,
+ options);
+
+ SyncAltLangDefault (XMP_NS_DC,
+ "description",
+ iptc.fDescription,
+ options);
+
+ SyncString (XMP_NS_PHOTOSHOP,
+ "CaptionWriter",
+ iptc.fDescriptionWriter,
+ options);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::IngestIPTC (dng_metadata &metadata,
+ bool xmpIsNewer)
+ {
+
+ if (metadata.IPTCLength ())
+ {
+
+ // Parse the IPTC block.
+
+ dng_iptc iptc;
+
+ iptc.Parse (metadata.IPTCData (),
+ metadata.IPTCLength (),
+ metadata.IPTCOffset ());
+
+ // Compute fingerprint of IPTC data both ways, including and
+ // excluding the padding data.
+
+ dng_fingerprint iptcDigest1 = metadata.IPTCDigest (true );
+ dng_fingerprint iptcDigest2 = metadata.IPTCDigest (false);
+
+ // See if there is an IPTC fingerprint stored in the XMP.
+
+ dng_fingerprint xmpDigest = GetIPTCDigest ();
+
+ if (xmpDigest.IsValid ())
+ {
+
+ // If they match, the XMP was already synced with this
+ // IPTC block, and we should not resync since it might
+ // overwrite changes in the XMP data.
+
+ if (iptcDigest1 == xmpDigest)
+ {
+
+ return;
+
+ }
+
+ // If it matches the incorrectly computed digest, skip
+ // the sync, but fix the digest in the XMP.
+
+ if (iptcDigest2 == xmpDigest)
+ {
+
+ SetIPTCDigest (iptcDigest1);
+
+ return;
+
+ }
+
+ // Else the IPTC has changed, so force an update.
+
+ xmpIsNewer = false;
+
+ }
+
+ else
+ {
+
+ // There is no IPTC digest. Previously we would
+ // prefer the IPTC in this case, but the MWG suggests
+ // that we prefer the XMP in this case.
+
+ xmpIsNewer = true;
+
+ }
+
+ // Remember the fingerprint of the IPTC we are syncing with.
+
+ SetIPTCDigest (iptcDigest1);
+
+ // Find the sync options.
+
+ uint32 options = xmpIsNewer ? preferXMP
+ : preferNonXMP;
+
+ // Synchronize the fields.
+
+ SyncIPTC (iptc, options);
+
+ }
+
+ // After the IPTC data is moved to XMP, we don't need it anymore.
+
+ metadata.ClearIPTC ();
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::RebuildIPTC (dng_metadata &metadata,
+ dng_memory_allocator &allocator,
+ bool padForTIFF)
+ {
+
+ // If there is no XMP, then there is no IPTC.
+
+ if (!fSDK->HasMeta ())
+ {
+ return;
+ }
+
+ // Extract the legacy IPTC fields from the XMP data.
+
+ dng_iptc iptc;
+
+ SyncIPTC (iptc, preferXMP);
+
+ // Build legacy IPTC record
+
+ if (iptc.NotEmpty ())
+ {
+
+ AutoPtr<dng_memory_block> block (iptc.Spool (allocator,
+ padForTIFF));
+
+ metadata.SetIPTC (block);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SyncFlash (uint32 &flashState,
+ uint32 &flashMask,
+ uint32 options)
+ {
+
+ bool isDefault = (flashState == 0xFFFFFFFF);
+
+ if ((options & ignoreXMP) || !isDefault)
+ {
+
+ Remove (XMP_NS_EXIF, "Flash");
+
+ }
+
+ if (!isDefault)
+ {
+
+ fSDK->SetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "Fired",
+ (flashState & 0x1) ? "True" : "False");
+
+ if (((flashMask >> 1) & 3) == 3)
+ {
+
+ char s [8];
+
+ sprintf (s, "%u", (unsigned) ((flashState >> 1) & 3));
+
+ fSDK->SetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "Return",
+ s);
+
+ }
+
+ if (((flashMask >> 3) & 3) == 3)
+ {
+
+ char s [8];
+
+ sprintf (s, "%u", (unsigned) ((flashState >> 3) & 3));
+
+ fSDK->SetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "Mode",
+ s);
+
+ }
+
+ if ((flashMask & (1 << 5)) != 0)
+ {
+
+ fSDK->SetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "Function",
+ (flashState & (1 << 5)) ? "True" : "False");
+
+ }
+
+ if ((flashMask & (1 << 6)) != 0)
+ {
+
+ fSDK->SetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "RedEyeMode",
+ (flashState & (1 << 6)) ? "True" : "False");
+
+ }
+
+ }
+
+ else if (fSDK->Exists (XMP_NS_EXIF, "Flash"))
+ {
+
+ dng_string s;
+
+ if (fSDK->GetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "Fired",
+ s))
+ {
+
+ flashState = 0;
+ flashMask = 1;
+
+ if (s.Matches ("True"))
+ {
+ flashState |= 1;
+ }
+
+ if (fSDK->GetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "Return",
+ s))
+ {
+
+ unsigned x = 0;
+
+ if (sscanf (s.Get (), "%u", &x) == 1 && x <= 3)
+ {
+
+ flashState |= x << 1;
+ flashMask |= 3 << 1;
+
+ }
+
+ }
+
+ if (fSDK->GetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "Mode",
+ s))
+ {
+
+ unsigned x = 0;
+
+ if (sscanf (s.Get (), "%u", &x) == 1 && x <= 3)
+ {
+
+ flashState |= x << 3;
+ flashMask |= 3 << 3;
+
+ }
+
+ }
+
+ if (fSDK->GetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "Function",
+ s))
+ {
+
+ flashMask |= 1 << 5;
+
+ if (s.Matches ("True"))
+ {
+ flashState |= 1 << 5;
+ }
+
+ }
+
+ if (fSDK->GetStructField (XMP_NS_EXIF,
+ "Flash",
+ XMP_NS_EXIF,
+ "RedEyeMode",
+ s))
+ {
+
+ flashMask |= 1 << 6;
+
+ if (s.Matches ("True"))
+ {
+ flashState |= 1 << 6;
+ }
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SyncExif (dng_exif &exif,
+ const dng_exif *originalExif,
+ bool doingUpdateFromXMP,
+ bool removeFromXMP)
+ {
+
+ DNG_ASSERT (!doingUpdateFromXMP || originalExif,
+ "Must have original EXIF if doingUpdateFromXMP");
+
+ // Default synchronization options for the read-only fields.
+
+ uint32 readOnly = doingUpdateFromXMP ? ignoreXMP
+ : preferNonXMP;
+
+ // Option for removable fields.
+
+ uint32 removable = removeFromXMP ? removeXMP
+ : 0;
+
+ // Make:
+
+ SyncString (XMP_NS_TIFF,
+ "Make",
+ exif.fMake,
+ readOnly + removable);
+
+ // Model:
+
+ SyncString (XMP_NS_TIFF,
+ "Model",
+ exif.fModel,
+ readOnly + removable);
+
+ // Exif version number:
+
+ {
+
+ dng_string exifVersion;
+
+ if (exif.fExifVersion)
+ {
+
+ unsigned b0 = ((exif.fExifVersion >> 24) & 0x0FF) - '0';
+ unsigned b1 = ((exif.fExifVersion >> 16) & 0x0FF) - '0';
+ unsigned b2 = ((exif.fExifVersion >> 8) & 0x0FF) - '0';
+ unsigned b3 = ((exif.fExifVersion ) & 0x0FF) - '0';
+
+ if (b0 <= 9 && b1 <= 9 && b2 <= 9 && b3 <= 9)
+ {
+
+ char s [5];
+
+ sprintf (s,
+ "%1u%1u%1u%1u",
+ b0,
+ b1,
+ b2,
+ b3);
+
+ exifVersion.Set (s);
+
+ }
+
+ }
+
+ SyncString (XMP_NS_EXIF,
+ "ExifVersion",
+ exifVersion,
+ readOnly);
+
+ if (exifVersion.NotEmpty ())
+ {
+
+ unsigned b0;
+ unsigned b1;
+ unsigned b2;
+ unsigned b3;
+
+ if (sscanf (exifVersion.Get (),
+ "%1u%1u%1u%1u",
+ &b0,
+ &b1,
+ &b2,
+ &b3) == 4)
+ {
+
+ if (b0 <= 9 && b1 <= 9 && b2 <= 9 && b3 <= 9)
+ {
+
+ b0 += '0';
+ b1 += '0';
+ b2 += '0';
+ b3 += '0';
+
+ exif.fExifVersion = (b0 << 24) |
+ (b1 << 16) |
+ (b2 << 8) |
+ (b3 );
+
+ }
+
+ }
+
+ }
+
+ // Provide default value for ExifVersion.
+
+ if (!exif.fExifVersion)
+ {
+
+ exif.fExifVersion = DNG_CHAR4 ('0','2','2','1');
+
+ Set (XMP_NS_EXIF,
+ "ExifVersion",
+ "0221");
+
+ }
+
+ if (removeFromXMP)
+ {
+
+ Remove (XMP_NS_EXIF, "ExifVersion");
+
+ }
+
+ }
+
+ // ExposureTime / ShutterSpeedValue:
+
+ {
+
+ // Process twice in case XMP contains only one of the
+ // two fields.
+
+ for (uint32 pass = 0; pass < 2; pass++)
+ {
+
+ dng_urational et = exif.fExposureTime;
+
+ Sync_urational (XMP_NS_EXIF,
+ "ExposureTime",
+ et,
+ readOnly);
+
+ if (et.IsValid ())
+ {
+
+ exif.SetExposureTime (et.As_real64 (), false);
+
+ }
+
+ dng_srational ss = exif.fShutterSpeedValue;
+
+ Sync_srational (XMP_NS_EXIF,
+ "ShutterSpeedValue",
+ ss,
+ readOnly);
+
+ if (ss.IsValid ())
+ {
+
+ exif.SetShutterSpeedValue (ss.As_real64 ());
+
+ }
+
+ }
+
+ if (removeFromXMP)
+ {
+
+ Remove (XMP_NS_EXIF, "ExposureTime");
+
+ Remove (XMP_NS_EXIF, "ShutterSpeedValue");
+
+ }
+
+ }
+
+ // FNumber / ApertureValue:
+
+ {
+
+ for (uint32 pass = 0; pass < 2; pass++)
+ {
+
+ dng_urational fs = exif.fFNumber;
+
+ Sync_urational (XMP_NS_EXIF,
+ "FNumber",
+ fs,
+ readOnly);
+
+ if (fs.IsValid ())
+ {
+
+ exif.SetFNumber (fs.As_real64 ());
+
+ }
+
+ dng_urational av = exif.fApertureValue;
+
+ Sync_urational (XMP_NS_EXIF,
+ "ApertureValue",
+ av,
+ readOnly);
+
+ if (av.IsValid ())
+ {
+
+ exif.SetApertureValue (av.As_real64 ());
+
+ }
+
+ }
+
+ if (removeFromXMP)
+ {
+
+ Remove (XMP_NS_EXIF, "FNumber");
+
+ Remove (XMP_NS_EXIF, "ApertureValue");
+
+ }
+
+ }
+
+ // Exposure program:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "ExposureProgram",
+ exif.fExposureProgram,
+ exif.fExposureProgram == 0xFFFFFFFF,
+ readOnly + removable);
+
+ // ISO Speed Ratings:
+
+ {
+
+ uint32 isoSpeedRatingsCount = 0;
+
+ uint32 isoSpeedRatingsOptions = readOnly;
+
+ uint32 oldISOSpeedRatings [3];
+
+ memcpy (oldISOSpeedRatings,
+ exif.fISOSpeedRatings,
+ sizeof (oldISOSpeedRatings));
+
+ bool checkXMPForHigherISO = false;
+
+ for (uint32 j = 0; j < 3; j++)
+ {
+
+ // Special case: the EXIF 2.2x standard represents ISO speed ratings with
+ // 2 bytes, which cannot hold ISO speed ratings above 65535 (e.g.,
+ // 102400). If the EXIF ISO speed rating value is 65535, prefer the XMP
+ // ISOSpeedRatings tag value.
+
+ if (exif.fISOSpeedRatings [j] == 65535)
+ {
+
+ isoSpeedRatingsOptions = preferXMP;
+
+ checkXMPForHigherISO = true;
+
+ isoSpeedRatingsCount = 0;
+
+ break;
+
+ }
+
+ else if (exif.fISOSpeedRatings [j] == 0)
+ {
+ break;
+ }
+
+ isoSpeedRatingsCount++;
+
+ }
+
+ Sync_uint32_array (XMP_NS_EXIF,
+ "ISOSpeedRatings",
+ exif.fISOSpeedRatings,
+ isoSpeedRatingsCount,
+ 3,
+ isoSpeedRatingsOptions);
+
+ // If the EXIF ISO was 65535 and we failed to find anything meaningful in the
+ // XMP, then we fall back to the EXIF ISO.
+
+ if (checkXMPForHigherISO && (isoSpeedRatingsCount == 0))
+ {
+
+ memcpy (exif.fISOSpeedRatings,
+ oldISOSpeedRatings,
+ sizeof (oldISOSpeedRatings));
+
+ }
+
+ // Only remove the ISO tag if there are not ratings over 65535.
+
+ if (removeFromXMP)
+ {
+
+ bool hasHighISO = false;
+
+ for (uint32 j = 0; j < 3; j++)
+ {
+
+ if (exif.fISOSpeedRatings [j] == 0)
+ {
+ break;
+ }
+
+ hasHighISO = hasHighISO || (exif.fISOSpeedRatings [j] > 65535);
+
+ }
+
+ if (!hasHighISO)
+ {
+
+ Remove (XMP_NS_EXIF, "ISOSpeedRatings");
+
+ }
+
+ }
+
+ }
+
+ // SensitivityType:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "SensitivityType",
+ exif.fSensitivityType,
+ exif.fSensitivityType == stUnknown,
+ readOnly + removable);
+
+ // StandardOutputSensitivity:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "StandardOutputSensitivity",
+ exif.fStandardOutputSensitivity,
+ exif.fStandardOutputSensitivity == 0,
+ readOnly + removable);
+
+ // RecommendedExposureIndex:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "RecommendedExposureIndex",
+ exif.fRecommendedExposureIndex,
+ exif.fRecommendedExposureIndex == 0,
+ readOnly + removable);
+
+ // ISOSpeed:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "ISOSpeed",
+ exif.fISOSpeed,
+ exif.fISOSpeed == 0,
+ readOnly + removable);
+
+ // ISOSpeedLatitudeyyy:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "ISOSpeedLatitudeyyy",
+ exif.fISOSpeedLatitudeyyy,
+ exif.fISOSpeedLatitudeyyy == 0,
+ readOnly + removable);
+
+ // ISOSpeedLatitudezzz:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "ISOSpeedLatitudezzz",
+ exif.fISOSpeedLatitudezzz,
+ exif.fISOSpeedLatitudezzz == 0,
+ readOnly + removable);
+
+ // ExposureIndex:
+
+ Sync_urational (XMP_NS_EXIF,
+ "ExposureIndex",
+ exif.fExposureIndex,
+ readOnly + removable);
+
+ // Brightness Value:
+
+ Sync_srational (XMP_NS_EXIF,
+ "BrightnessValue",
+ exif.fBrightnessValue,
+ readOnly + removable);
+
+ // Exposure Bias:
+
+ Sync_srational (XMP_NS_EXIF,
+ "ExposureBiasValue",
+ exif.fExposureBiasValue,
+ readOnly + removable);
+
+ // Max Aperture:
+
+ Sync_urational (XMP_NS_EXIF,
+ "MaxApertureValue",
+ exif.fMaxApertureValue,
+ readOnly + removable);
+
+ // Subject Distance:
+
+ Sync_urational (XMP_NS_EXIF,
+ "SubjectDistance",
+ exif.fSubjectDistance,
+ readOnly + removable);
+
+ // Metering Mode:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "MeteringMode",
+ exif.fMeteringMode,
+ exif.fMeteringMode == 0xFFFFFFFF,
+ readOnly + removable);
+
+ // Light Source:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "LightSource",
+ exif.fLightSource,
+ exif.fLightSource > 0x0FFFF,
+ readOnly + removable);
+
+ // Flash State:
+
+ SyncFlash (exif.fFlash,
+ exif.fFlashMask,
+ readOnly);
+
+ if (removeFromXMP)
+ {
+ Remove (XMP_NS_EXIF, "Flash");
+ }
+
+ // Focal Length:
+
+ Sync_urational (XMP_NS_EXIF,
+ "FocalLength",
+ exif.fFocalLength,
+ readOnly + removable);
+
+ // Sensing Method.
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "SensingMethod",
+ exif.fSensingMethod,
+ exif.fSensingMethod > 0x0FFFF,
+ readOnly + removable);
+
+ // File Source.
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "FileSource",
+ exif.fFileSource,
+ exif.fFileSource > 0x0FF,
+ readOnly + removable);
+
+ // Scene Type.
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "SceneType",
+ exif.fSceneType,
+ exif.fSceneType > 0x0FF,
+ readOnly + removable);
+
+ // Focal Length in 35mm Film:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "FocalLengthIn35mmFilm",
+ exif.fFocalLengthIn35mmFilm,
+ exif.fFocalLengthIn35mmFilm == 0,
+ readOnly + removable);
+
+ // Custom Rendered:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "CustomRendered",
+ exif.fCustomRendered,
+ exif.fCustomRendered > 0x0FFFF,
+ readOnly + removable);
+
+ // Exposure Mode:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "ExposureMode",
+ exif.fExposureMode,
+ exif.fExposureMode > 0x0FFFF,
+ readOnly + removable);
+
+ // White Balance:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "WhiteBalance",
+ exif.fWhiteBalance,
+ exif.fWhiteBalance > 0x0FFFF,
+ readOnly + removable);
+
+ // Scene Capture Type:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "SceneCaptureType",
+ exif.fSceneCaptureType,
+ exif.fSceneCaptureType > 0x0FFFF,
+ readOnly + removable);
+
+ // Gain Control:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "GainControl",
+ exif.fGainControl,
+ exif.fGainControl > 0x0FFFF,
+ readOnly + removable);
+
+ // Contrast:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "Contrast",
+ exif.fContrast,
+ exif.fContrast > 0x0FFFF,
+ readOnly + removable);
+
+ // Saturation:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "Saturation",
+ exif.fSaturation,
+ exif.fSaturation > 0x0FFFF,
+ readOnly + removable);
+
+ // Sharpness:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "Sharpness",
+ exif.fSharpness,
+ exif.fSharpness > 0x0FFFF,
+ readOnly + removable);
+
+ // Subject Distance Range:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "SubjectDistanceRange",
+ exif.fSubjectDistanceRange,
+ exif.fSubjectDistanceRange > 0x0FFFF,
+ readOnly + removable);
+
+ // Subject Area:
+
+ Sync_uint32_array (XMP_NS_EXIF,
+ "SubjectArea",
+ exif.fSubjectArea,
+ exif.fSubjectAreaCount,
+ sizeof (exif.fSubjectArea ) /
+ sizeof (exif.fSubjectArea [0]),
+ readOnly);
+
+ if (removeFromXMP)
+ {
+ Remove (XMP_NS_EXIF, "SubjectArea");
+ }
+
+ // Digital Zoom Ratio:
+
+ Sync_urational (XMP_NS_EXIF,
+ "DigitalZoomRatio",
+ exif.fDigitalZoomRatio,
+ readOnly + removable);
+
+ // Focal Plane Resolution:
+
+ Sync_urational (XMP_NS_EXIF,
+ "FocalPlaneXResolution",
+ exif.fFocalPlaneXResolution,
+ readOnly + removable);
+
+ Sync_urational (XMP_NS_EXIF,
+ "FocalPlaneYResolution",
+ exif.fFocalPlaneYResolution,
+ readOnly + removable);
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "FocalPlaneResolutionUnit",
+ exif.fFocalPlaneResolutionUnit,
+ exif.fFocalPlaneResolutionUnit > 0x0FFFF,
+ readOnly + removable);
+
+ // ImageDescription: (XMP is is always preferred)
+
+ if (fSDK->GetAltLangDefault (XMP_NS_DC,
+ "description",
+ exif.fImageDescription))
+
+ {
+
+ }
+
+ else if (doingUpdateFromXMP)
+ {
+
+ exif.fImageDescription.Clear ();
+
+ if (originalExif->fImageDescription.NotEmpty ())
+ {
+
+ fSDK->SetAltLangDefault (XMP_NS_DC,
+ "description",
+ dng_string ());
+
+ }
+
+ }
+
+ else if (exif.fImageDescription.NotEmpty ())
+ {
+
+ fSDK->SetAltLangDefault (XMP_NS_DC,
+ "description",
+ exif.fImageDescription);
+
+ }
+
+ // Artist: (XMP is is always preferred)
+
+ {
+
+ dng_string_list xmpList;
+
+ if (fSDK->GetStringList (XMP_NS_DC,
+ "creator",
+ xmpList))
+ {
+
+ exif.fArtist.Clear ();
+
+ if (xmpList.Count () > 0)
+ {
+
+ uint32 j;
+
+ uint32 bufferSize = xmpList.Count () * 4 + 1;
+
+ for (j = 0; j < xmpList.Count (); j++)
+ {
+
+ bufferSize += xmpList [j].Length () * 2;
+
+ }
+
+ dng_memory_data temp (bufferSize);
+
+ char *t = temp.Buffer_char ();
+
+ for (j = 0; j < xmpList.Count (); j++)
+ {
+
+ const char *s = xmpList [j].Get ();
+
+ bool needQuotes = xmpList [j].Contains ("; ") ||
+ s [0] == '\"';
+
+ if (needQuotes)
+ {
+ *(t++) = '\"';
+ }
+
+ while (s [0] != 0)
+ {
+
+ if (s [0] == '\"' && needQuotes)
+ {
+ *(t++) = '\"';
+ }
+
+ *(t++) = *(s++);
+
+ }
+
+ if (needQuotes)
+ {
+ *(t++) = '\"';
+ }
+
+ if (j != xmpList.Count () - 1)
+ {
+ *(t++) = ';';
+ *(t++) = ' ';
+ }
+ else
+ {
+ *t = 0;
+ }
+
+ }
+
+ exif.fArtist.Set (temp.Buffer_char ());
+
+ }
+
+ }
+
+ else if (doingUpdateFromXMP)
+ {
+
+ exif.fArtist.Clear ();
+
+ if (originalExif->fArtist.NotEmpty ())
+ {
+
+ dng_string_list fakeList;
+
+ fakeList.Append (dng_string ());
+
+ SetStringList (XMP_NS_DC,
+ "creator",
+ fakeList,
+ false);
+
+ }
+
+ }
+
+ else if (exif.fArtist.NotEmpty ())
+ {
+
+ dng_string_list newList;
+
+ dng_memory_data temp (exif.fArtist.Length () + 1);
+
+ const char *s = exif.fArtist.Get ();
+
+ char *t = temp.Buffer_char ();
+
+ bool first = true;
+
+ bool quoted = false;
+
+ bool valid = true;
+
+ while (s [0] != 0 && valid)
+ {
+
+ if (first)
+ {
+
+ if (s [0] == '\"')
+ {
+
+ quoted = true;
+
+ s++;
+
+ }
+
+ }
+
+ first = false;
+
+ if (quoted)
+ {
+
+ if (s [0] == '\"' &&
+ s [1] == '\"')
+ {
+
+ s+= 2;
+
+ *(t++) = '\"';
+
+ }
+
+ else if (s [0] == '\"')
+ {
+
+ s++;
+
+ quoted = false;
+
+ valid = valid && ((s [0] == 0) || ((s [0] == ';' && s [1] == ' ')));
+
+ }
+
+ else
+ {
+
+ *(t++) = *(s++);
+
+ }
+
+ }
+
+ else if (s [0] == ';' &&
+ s [1] == ' ')
+ {
+
+ s += 2;
+
+ t [0] = 0;
+
+ dng_string ss;
+
+ ss.Set (temp.Buffer_char ());
+
+ newList.Append (ss);
+
+ t = temp.Buffer_char ();
+
+ first = true;
+
+ }
+
+ else
+ {
+
+ *(t++) = *(s++);
+
+ }
+
+ }
+
+ if (quoted)
+ {
+
+ valid = false;
+
+ }
+
+ if (valid)
+ {
+
+ if (t != temp.Buffer_char ())
+ {
+
+ t [0] = 0;
+
+ dng_string ss;
+
+ ss.Set (temp.Buffer_char ());
+
+ newList.Append (ss);
+
+ }
+
+ }
+
+ else
+ {
+
+ newList.Clear ();
+
+ newList.Append (exif.fArtist);
+
+ }
+
+ SetStringList (XMP_NS_DC,
+ "creator",
+ newList,
+ false);
+
+ }
+
+ }
+
+ // Software: (XMP is is always preferred)
+
+ if (fSDK->GetString (XMP_NS_XAP,
+ "CreatorTool",
+ exif.fSoftware))
+
+ {
+
+ }
+
+ else if (doingUpdateFromXMP)
+ {
+
+ exif.fSoftware.Clear ();
+
+ if (originalExif->fSoftware.NotEmpty ())
+ {
+
+ fSDK->SetString (XMP_NS_XAP,
+ "CreatorTool",
+ dng_string ());
+
+ }
+
+ }
+
+ else if (exif.fSoftware.NotEmpty ())
+ {
+
+ fSDK->SetString (XMP_NS_XAP,
+ "CreatorTool",
+ exif.fSoftware);
+
+ }
+
+ // Copyright: (XMP is is always preferred)
+
+ if (fSDK->GetAltLangDefault (XMP_NS_DC,
+ "rights",
+ exif.fCopyright))
+
+ {
+
+ }
+
+ else if (doingUpdateFromXMP)
+ {
+
+ exif.fCopyright.Clear ();
+
+ if (originalExif->fCopyright.NotEmpty ())
+ {
+
+ fSDK->SetAltLangDefault (XMP_NS_DC,
+ "rights",
+ dng_string ());
+
+ }
+
+ }
+
+ else if (exif.fCopyright.NotEmpty ())
+ {
+
+ fSDK->SetAltLangDefault (XMP_NS_DC,
+ "rights",
+ exif.fCopyright);
+
+ }
+
+ // Camera serial number private tag:
+
+ SyncString (XMP_NS_AUX,
+ "SerialNumber",
+ exif.fCameraSerialNumber,
+ readOnly);
+
+ // Lens Info:
+
+ {
+
+ dng_string s;
+
+ if (exif.fLensInfo [0].IsValid ())
+ {
+
+ char ss [256];
+
+ sprintf (ss,
+ "%u/%u %u/%u %u/%u %u/%u",
+ (unsigned) exif.fLensInfo [0].n,
+ (unsigned) exif.fLensInfo [0].d,
+ (unsigned) exif.fLensInfo [1].n,
+ (unsigned) exif.fLensInfo [1].d,
+ (unsigned) exif.fLensInfo [2].n,
+ (unsigned) exif.fLensInfo [2].d,
+ (unsigned) exif.fLensInfo [3].n,
+ (unsigned) exif.fLensInfo [3].d);
+
+ s.Set (ss);
+
+ }
+
+ SyncString (XMP_NS_AUX,
+ "LensInfo",
+ s,
+ readOnly);
+
+ if (s.NotEmpty ())
+ {
+
+ unsigned n [4];
+ unsigned d [4];
+
+ if (sscanf (s.Get (),
+ "%u/%u %u/%u %u/%u %u/%u",
+ &n [0],
+ &d [0],
+ &n [1],
+ &d [1],
+ &n [2],
+ &d [2],
+ &n [3],
+ &d [3]) == 8)
+ {
+
+ for (uint32 j = 0; j < 4; j++)
+ {
+
+ exif.fLensInfo [j] = dng_urational (n [j], d [j]);
+
+ }
+
+ }
+
+
+ }
+
+ }
+
+ // Lens name:
+
+ {
+
+ // EXIF lens names are sometimes missing or wrong (esp. when non-OEM lenses
+ // are used). So prefer the value from XMP.
+
+ SyncString (XMP_NS_AUX,
+ "Lens",
+ exif.fLensName,
+ preferXMP);
+
+ // Generate default lens name from lens info if required.
+ // Ignore names names that end in "f/0.0" due to third party bug.
+
+ if ((exif.fLensName.IsEmpty () ||
+ exif.fLensName.EndsWith ("f/0.0")) && exif.fLensInfo [0].IsValid ())
+ {
+
+ char s [256];
+
+ real64 minFL = exif.fLensInfo [0].As_real64 ();
+ real64 maxFL = exif.fLensInfo [1].As_real64 ();
+
+ // The f-stop numbers are optional.
+
+ if (exif.fLensInfo [2].IsValid ())
+ {
+
+ real64 minFS = exif.fLensInfo [2].As_real64 ();
+ real64 maxFS = exif.fLensInfo [3].As_real64 ();
+
+ if (minFL == maxFL)
+ sprintf (s, "%.1f mm f/%.1f", minFL, minFS);
+
+ else if (minFS == maxFS)
+ sprintf (s, "%.1f-%.1f mm f/%.1f", minFL, maxFL, minFS);
+
+ else
+ sprintf (s, "%.1f-%.1f mm f/%.1f-%.1f", minFL, maxFL, minFS, maxFS);
+
+ }
+
+ else
+ {
+
+ if (minFL == maxFL)
+ sprintf (s, "%.1f mm", minFL);
+
+ else
+ sprintf (s, "%.1f-%.1f mm", minFL, maxFL);
+
+ }
+
+ exif.fLensName.Set (s);
+
+ SetString (XMP_NS_AUX,
+ "Lens",
+ exif.fLensName);
+
+ }
+
+ }
+
+ // Lens ID:
+
+ SyncString (XMP_NS_AUX,
+ "LensID",
+ exif.fLensID,
+ readOnly);
+
+ // Lens Make:
+
+ SyncString (XMP_NS_EXIF,
+ "LensMake",
+ exif.fLensMake,
+ readOnly + removable);
+
+ // Lens Serial Number:
+
+ SyncString (XMP_NS_AUX,
+ "LensSerialNumber",
+ exif.fLensSerialNumber,
+ readOnly);
+
+ // Image Number:
+
+ Sync_uint32 (XMP_NS_AUX,
+ "ImageNumber",
+ exif.fImageNumber,
+ exif.fImageNumber == 0xFFFFFFFF,
+ readOnly);
+
+ // User Comment:
+
+ if (exif.fUserComment.NotEmpty ())
+ {
+
+ fSDK->SetAltLangDefault (XMP_NS_EXIF,
+ "UserComment",
+ exif.fUserComment);
+
+ }
+
+ else
+ {
+
+ (void) fSDK->GetAltLangDefault (XMP_NS_EXIF,
+ "UserComment",
+ exif.fUserComment);
+
+ }
+
+ if (removeFromXMP)
+ {
+ Remove (XMP_NS_EXIF, "UserComment");
+ }
+
+ // Approximate focus distance:
+
+ SyncApproximateFocusDistance (exif,
+ readOnly);
+
+ // Flash Compensation:
+
+ Sync_srational (XMP_NS_AUX,
+ "FlashCompensation",
+ exif.fFlashCompensation,
+ readOnly);
+
+ // Owner Name: (allow XMP updates)
+
+ SyncString (XMP_NS_AUX,
+ "OwnerName",
+ exif.fOwnerName,
+ preferXMP);
+
+ // Firmware:
+
+ SyncString (XMP_NS_AUX,
+ "Firmware",
+ exif.fFirmware,
+ readOnly);
+
+ // Image Unique ID:
+
+ {
+
+ dng_string s = EncodeFingerprint (exif.fImageUniqueID);
+
+ SyncString (XMP_NS_EXIF,
+ "ImageUniqueID",
+ s,
+ readOnly + removable);
+
+ exif.fImageUniqueID = DecodeFingerprint (s);
+
+ }
+
+ // Allow EXIF GPS to be updated via updates from XMP.
+
+ if (doingUpdateFromXMP)
+ {
+
+ // Require that at least one basic GPS field exist in the
+ // XMP before overrriding the EXIF GPS fields.
+
+ if (Exists (XMP_NS_EXIF, "GPSVersionID" ) ||
+ Exists (XMP_NS_EXIF, "GPSLatitude" ) ||
+ Exists (XMP_NS_EXIF, "GPSLongitude" ) ||
+ Exists (XMP_NS_EXIF, "GPSAltitude" ) ||
+ Exists (XMP_NS_EXIF, "GPSTimeStamp" ) ||
+ Exists (XMP_NS_EXIF, "GPSProcessingMethod"))
+ {
+
+ // Clear out the GPS info from the EXIF so it will
+ // replaced by the GPS info from the XMP.
+
+ dng_exif blankExif;
+
+ exif.CopyGPSFrom (blankExif);
+
+ }
+
+ }
+
+ // GPS Version ID:
+
+ {
+
+ dng_string s = EncodeGPSVersion (exif.fGPSVersionID);
+
+ if (SyncString (XMP_NS_EXIF,
+ "GPSVersionID",
+ s,
+ preferNonXMP + removable))
+ {
+
+ exif.fGPSVersionID = DecodeGPSVersion (s);
+
+ }
+
+ }
+
+ // GPS Latitude:
+
+ {
+
+ dng_string s = EncodeGPSCoordinate (exif.fGPSLatitudeRef,
+ exif.fGPSLatitude);
+
+ if (SyncString (XMP_NS_EXIF,
+ "GPSLatitude",
+ s,
+ preferNonXMP + removable))
+ {
+
+ DecodeGPSCoordinate (s,
+ exif.fGPSLatitudeRef,
+ exif.fGPSLatitude);
+
+ }
+
+ }
+
+ // GPS Longitude:
+
+ {
+
+ dng_string s = EncodeGPSCoordinate (exif.fGPSLongitudeRef,
+ exif.fGPSLongitude);
+
+ if (SyncString (XMP_NS_EXIF,
+ "GPSLongitude",
+ s,
+ preferNonXMP + removable))
+ {
+
+ DecodeGPSCoordinate (s,
+ exif.fGPSLongitudeRef,
+ exif.fGPSLongitude);
+
+ }
+
+ }
+
+ // Handle simple case of incorrectly written GPS altitude where someone didn't understand the GPSAltitudeRef and assumed the GPSAltitude RATIONAL is signed.
+ // Only handle this case as we do not want to misinterpret e.g. a fixed point representation of very high GPS altitudes.
+
+ uint32 &altitudeRef = exif.fGPSAltitudeRef;
+ dng_urational &altitude = exif.fGPSAltitude;
+
+ if (altitude.IsValid () &&
+ (altitudeRef == 0 || altitudeRef == 0xFFFFFFFF)) // If the file contains a "below sea level" altitudeRef, assume the writing software is working according to the spec.
+ {
+
+ if ((altitude.n & (1U << 31)) &&
+ altitude.d < 7) // As the denominator increases, large numerator values become possibly valid distances. Pick a limit on the conservative side (approx 33e6m) to prevent misinterpretation.
+ // Noting that the normal case for this mistake has a denominator of 1
+ {
+
+ altitude.n = ~altitude.n + 1;
+ altitudeRef = 1;
+
+ }
+
+ }
+
+ // GPS Altitude Reference:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "GPSAltitudeRef",
+ altitudeRef,
+ altitudeRef == 0xFFFFFFFF,
+ preferNonXMP + removable);
+
+ // GPS Altitude:
+
+ Sync_urational (XMP_NS_EXIF,
+ "GPSAltitude",
+ altitude,
+ preferNonXMP + removable);
+
+ // GPS Date/Time:
+
+ {
+
+ dng_string s = EncodeGPSDateTime (exif.fGPSDateStamp,
+ exif.fGPSTimeStamp);
+
+ if (SyncString (XMP_NS_EXIF,
+ "GPSTimeStamp",
+ s,
+ preferNonXMP + removable))
+ {
+
+ DecodeGPSDateTime (s,
+ exif.fGPSDateStamp,
+ exif.fGPSTimeStamp);
+
+ }
+
+ }
+
+ // GPS Satellites:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSSatellites",
+ exif.fGPSSatellites,
+ preferNonXMP + removable);
+
+ // GPS Status:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSStatus",
+ exif.fGPSStatus,
+ preferNonXMP + removable);
+
+ // GPS Measure Mode:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSMeasureMode",
+ exif.fGPSMeasureMode,
+ preferNonXMP + removable);
+
+ // GPS DOP:
+
+ Sync_urational (XMP_NS_EXIF,
+ "GPSDOP",
+ exif.fGPSDOP,
+ preferNonXMP + removable);
+
+ // GPS Speed Reference:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSSpeedRef",
+ exif.fGPSSpeedRef,
+ preferNonXMP + removable);
+
+ // GPS Speed:
+
+ Sync_urational (XMP_NS_EXIF,
+ "GPSSpeed",
+ exif.fGPSSpeed,
+ preferNonXMP + removable);
+
+ // GPS Track Reference:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSTrackRef",
+ exif.fGPSTrackRef,
+ preferNonXMP + removable);
+
+ // GPS Track:
+
+ Sync_urational (XMP_NS_EXIF,
+ "GPSTrack",
+ exif.fGPSTrack,
+ preferNonXMP + removable);
+
+ // GPS Image Direction Reference:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSImgDirectionRef",
+ exif.fGPSImgDirectionRef,
+ preferNonXMP + removable);
+
+ // GPS Image Direction:
+
+ Sync_urational (XMP_NS_EXIF,
+ "GPSImgDirection",
+ exif.fGPSImgDirection,
+ preferNonXMP + removable);
+
+ // GPS Map Datum:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSMapDatum",
+ exif.fGPSMapDatum,
+ preferNonXMP + removable);
+
+ // GPS Destination Latitude:
+
+ {
+
+ dng_string s = EncodeGPSCoordinate (exif.fGPSDestLatitudeRef,
+ exif.fGPSDestLatitude);
+
+ if (SyncString (XMP_NS_EXIF,
+ "GPSDestLatitude",
+ s,
+ preferNonXMP + removable))
+ {
+
+ DecodeGPSCoordinate (s,
+ exif.fGPSDestLatitudeRef,
+ exif.fGPSDestLatitude);
+
+ }
+
+ }
+
+ // GPS Destination Longitude:
+
+ {
+
+ dng_string s = EncodeGPSCoordinate (exif.fGPSDestLongitudeRef,
+ exif.fGPSDestLongitude);
+
+ if (SyncString (XMP_NS_EXIF,
+ "GPSDestLongitude",
+ s,
+ preferNonXMP + removable))
+ {
+
+ DecodeGPSCoordinate (s,
+ exif.fGPSDestLongitudeRef,
+ exif.fGPSDestLongitude);
+
+ }
+
+ }
+
+ // GPS Destination Bearing Reference:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSDestBearingRef",
+ exif.fGPSDestBearingRef,
+ preferNonXMP + removable);
+
+ // GPS Destination Bearing:
+
+ Sync_urational (XMP_NS_EXIF,
+ "GPSDestBearing",
+ exif.fGPSDestBearing,
+ preferNonXMP + removable);
+
+ // GPS Destination Distance Reference:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSDestDistanceRef",
+ exif.fGPSDestDistanceRef,
+ preferNonXMP + removable);
+
+ // GPS Destination Distance:
+
+ Sync_urational (XMP_NS_EXIF,
+ "GPSDestDistance",
+ exif.fGPSDestDistance,
+ preferNonXMP + removable);
+
+ // GPS Processing Method:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSProcessingMethod",
+ exif.fGPSProcessingMethod,
+ preferNonXMP + removable);
+
+ // GPS Area Information:
+
+ SyncString (XMP_NS_EXIF,
+ "GPSAreaInformation",
+ exif.fGPSAreaInformation,
+ preferNonXMP + removable);
+
+ // GPS Differential:
+
+ Sync_uint32 (XMP_NS_EXIF,
+ "GPSDifferential",
+ exif.fGPSDifferential,
+ exif.fGPSDifferential == 0xFFFFFFFF,
+ preferNonXMP + removable);
+
+ // GPS Horizontal Positioning Error:
+
+ Sync_urational (XMP_NS_EXIF,
+ "GPSHPositioningError",
+ exif.fGPSHPositioningError,
+ preferNonXMP + removable);
+
+ // Sync date/times.
+
+ UpdateExifDates (exif, removeFromXMP);
+
+ // We are syncing EXIF and XMP, but we are not updating the
+ // NativeDigest tags. It is better to just delete them than leave
+ // the stale values around.
+
+ Remove (XMP_NS_EXIF, "NativeDigest");
+ Remove (XMP_NS_TIFF, "NativeDigest");
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SyncApproximateFocusDistance (dng_exif &exif,
+ const uint32 readOnly)
+ {
+
+ Sync_urational (XMP_NS_AUX,
+ "ApproximateFocusDistance",
+ exif.fApproxFocusDistance,
+ readOnly);
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::ValidateStringList (const char *ns,
+ const char *path)
+ {
+
+ fSDK->ValidateStringList (ns, path);
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::ValidateMetadata ()
+ {
+
+ // The following values should be arrays, but are not always. So
+ // fix them up because Photoshop sometimes has problems parsing invalid
+ // tags.
+
+ ValidateStringList (XMP_NS_DC, "creator");
+
+ ValidateStringList (XMP_NS_PHOTOSHOP, "Keywords");
+ ValidateStringList (XMP_NS_PHOTOSHOP, "SupplementalCategories");
+
+ }
+
+/******************************************************************************/
+
+bool dng_xmp::DateTimeIsDateOnly (const char *ns,
+ const char *path)
+ {
+
+ dng_string s;
+
+ if (GetString (ns, path, s))
+ {
+
+ uint32 len = s.Length ();
+
+ if (len)
+ {
+
+ for (uint32 j = 0; j < len; j++)
+ {
+
+ if (s.Get () [j] == 'T')
+ {
+
+ return false;
+
+ }
+
+ }
+
+ return true;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::UpdateExifDates (dng_exif &exif,
+ bool removeFromXMP)
+ {
+
+ // For the following three date/time fields, we always prefer XMP to
+ // the EXIF values. This is to allow the user to correct the date/times
+ // via changes in a sidecar XMP file, without modifying the original
+ // raw file.
+
+ // Kludge: The Nikon D4 is writing date only date/times into XMP, so
+ // prefer the EXIF values if the XMP only contains a date.
+
+ // Modification Date/Time:
+ // exif.fDateTime
+ // kXMP_NS_XMP:"ModifyDate" & kXMP_NS_TIFF:"DateTime" are aliased
+
+ {
+
+ dng_string s = exif.fDateTime.Encode_ISO_8601 ();
+
+ bool dateOnly = DateTimeIsDateOnly (XMP_NS_TIFF, "DateTime");
+
+ SyncString (XMP_NS_TIFF,
+ "DateTime",
+ s,
+ dateOnly ? preferNonXMP : preferXMP);
+
+ if (s.NotEmpty ())
+ {
+
+ exif.fDateTime.Decode_ISO_8601 (s.Get ());
+
+ // Round trip again in case we need to add a fake time zone.
+
+ s = exif.fDateTime.Encode_ISO_8601 ();
+
+ SetString (XMP_NS_TIFF,
+ "DateTime",
+ s);
+
+ }
+
+ }
+
+ // Original Date/Time:
+ // exif.fDateTimeOriginal
+ // IPTC: DateCreated
+ // XMP_NS_EXIF:"DateTimeOriginal" & XMP_NS_PHOTOSHOP:"DateCreated"
+ // Adobe has decided to keep the two XMP fields separate.
+
+ {
+
+ dng_string s = exif.fDateTimeOriginal.Encode_ISO_8601 ();
+
+ bool dateOnly = DateTimeIsDateOnly (XMP_NS_EXIF, "DateTimeOriginal");
+
+ SyncString (XMP_NS_EXIF,
+ "DateTimeOriginal",
+ s,
+ dateOnly ? preferNonXMP : preferXMP);
+
+ if (s.NotEmpty ())
+ {
+
+ exif.fDateTimeOriginal.Decode_ISO_8601 (s.Get ());
+
+ // Round trip again in case we need to add a fake time zone.
+
+ s = exif.fDateTimeOriginal.Encode_ISO_8601 ();
+
+ SetString (XMP_NS_EXIF,
+ "DateTimeOriginal",
+ s);
+
+ }
+
+ // Sync the IPTC value to the EXIF value if only the EXIF
+ // value exists.
+
+ if (s.NotEmpty () && !Exists (XMP_NS_PHOTOSHOP, "DateCreated"))
+ {
+
+ SetString (XMP_NS_PHOTOSHOP, "DateCreated", s);
+
+ }
+
+ if (removeFromXMP)
+ {
+
+ Remove (XMP_NS_EXIF, "DateTimeOriginal");
+
+ }
+
+ }
+
+ // Date Time Digitized:
+ // XMP_NS_EXIF:"DateTimeDigitized" & kXMP_NS_XMP:"CreateDate" are aliased
+
+ {
+
+ dng_string s = exif.fDateTimeDigitized.Encode_ISO_8601 ();
+
+ bool dateOnly = DateTimeIsDateOnly (XMP_NS_EXIF, "DateTimeDigitized");
+
+ SyncString (XMP_NS_EXIF,
+ "DateTimeDigitized",
+ s,
+ dateOnly ? preferNonXMP : preferXMP);
+
+ if (s.NotEmpty ())
+ {
+
+ exif.fDateTimeDigitized.Decode_ISO_8601 (s.Get ());
+
+ // Round trip again in case we need to add a fake time zone.
+
+ s = exif.fDateTimeDigitized.Encode_ISO_8601 ();
+
+ SetString (XMP_NS_EXIF,
+ "DateTimeDigitized",
+ s);
+
+ }
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::UpdateDateTime (const dng_date_time_info &dt)
+ {
+
+ dng_string s = dt.Encode_ISO_8601 ();
+
+ SetString (XMP_NS_TIFF,
+ "DateTime",
+ s);
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::UpdateMetadataDate (const dng_date_time_info &dt)
+ {
+
+ dng_string s = dt.Encode_ISO_8601 ();
+
+ SetString (XMP_NS_XAP,
+ "MetadataDate",
+ s);
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp::HasOrientation () const
+ {
+
+ uint32 x = 0;
+
+ if (Get_uint32 (XMP_NS_TIFF,
+ "Orientation",
+ x))
+ {
+
+ return (x >= 1) && (x <= 8);
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+dng_orientation dng_xmp::GetOrientation () const
+ {
+
+ dng_orientation result;
+
+ uint32 x = 0;
+
+ if (Get_uint32 (XMP_NS_TIFF,
+ "Orientation",
+ x))
+ {
+
+ if ((x >= 1) && (x <= 8))
+ {
+
+ result.SetTIFF (x);
+
+ }
+
+ }
+
+ return result;
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::ClearOrientation ()
+ {
+
+ fSDK->Remove (XMP_NS_TIFF, "Orientation");
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::SetOrientation (const dng_orientation &orientation)
+ {
+
+ Set_uint32 (XMP_NS_TIFF,
+ "Orientation",
+ orientation.GetTIFF ());
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SyncOrientation (dng_negative &negative,
+ bool xmpIsMaster)
+ {
+
+ SyncOrientation (negative.Metadata (), xmpIsMaster);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::SyncOrientation (dng_metadata &metadata,
+ bool xmpIsMaster)
+ {
+
+ // See if XMP contains the orientation.
+
+ bool xmpHasOrientation = HasOrientation ();
+
+ // See if XMP is the master value.
+
+ if (xmpHasOrientation && (xmpIsMaster || !metadata.HasBaseOrientation ()))
+ {
+
+ metadata.SetBaseOrientation (GetOrientation ());
+
+ }
+
+ else
+ {
+
+ SetOrientation (metadata.BaseOrientation ());
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::ClearImageInfo ()
+ {
+
+ Remove (XMP_NS_TIFF, "ImageWidth" );
+ Remove (XMP_NS_TIFF, "ImageLength");
+
+ Remove (XMP_NS_EXIF, "PixelXDimension");
+ Remove (XMP_NS_EXIF, "PixelYDimension");
+
+ Remove (XMP_NS_TIFF, "BitsPerSample");
+
+ Remove (XMP_NS_TIFF, "Compression");
+
+ Remove (XMP_NS_TIFF, "PhotometricInterpretation");
+
+ // "Orientation" is handled separately.
+
+ Remove (XMP_NS_TIFF, "SamplesPerPixel");
+
+ Remove (XMP_NS_TIFF, "PlanarConfiguration");
+
+ Remove (XMP_NS_TIFF, "XResolution");
+ Remove (XMP_NS_TIFF, "YResolution");
+
+ Remove (XMP_NS_TIFF, "ResolutionUnit");
+
+ Remove (XMP_NS_PHOTOSHOP, "ColorMode" );
+ Remove (XMP_NS_PHOTOSHOP, "ICCProfile");
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::SetImageSize (const dng_point &size)
+ {
+
+ Set_uint32 (XMP_NS_TIFF, "ImageWidth" , size.h);
+ Set_uint32 (XMP_NS_TIFF, "ImageLength", size.v);
+
+ // Mirror these values to the EXIF tags.
+
+ Set_uint32 (XMP_NS_EXIF, "PixelXDimension" , size.h);
+ Set_uint32 (XMP_NS_EXIF, "PixelYDimension" , size.v);
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::SetSampleInfo (uint32 samplesPerPixel,
+ uint32 bitsPerSample)
+ {
+
+ Set_uint32 (XMP_NS_TIFF, "SamplesPerPixel", samplesPerPixel);
+
+ char s [32];
+
+ sprintf (s, "%u", (unsigned) bitsPerSample);
+
+ dng_string ss;
+
+ ss.Set (s);
+
+ dng_string_list list;
+
+ for (uint32 j = 0; j < samplesPerPixel; j++)
+ {
+ list.Append (ss);
+ }
+
+ SetStringList (XMP_NS_TIFF, "BitsPerSample", list, false);
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::SetPhotometricInterpretation (uint32 pi)
+ {
+
+ Set_uint32 (XMP_NS_TIFF, "PhotometricInterpretation", pi);
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp::SetResolution (const dng_resolution &res)
+ {
+
+ Set_urational (XMP_NS_TIFF, "XResolution", res.fXResolution);
+ Set_urational (XMP_NS_TIFF, "YResolution", res.fYResolution);
+
+ Set_uint32 (XMP_NS_TIFF, "ResolutionUnit", res.fResolutionUnit);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::ComposeArrayItemPath (const char *ns,
+ const char *arrayName,
+ int32 itemNumber,
+ dng_string &s) const
+ {
+
+ fSDK->ComposeArrayItemPath (ns, arrayName, itemNumber, s);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::ComposeStructFieldPath (const char *ns,
+ const char *structName,
+ const char *fieldNS,
+ const char *fieldName,
+ dng_string &s) const
+ {
+
+ fSDK->ComposeStructFieldPath (ns, structName, fieldNS, fieldName, s);
+
+ }
+
+/*****************************************************************************/
+
+int32 dng_xmp::CountArrayItems (const char *ns,
+ const char *path) const
+ {
+
+ return fSDK->CountArrayItems (ns, path);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::AppendArrayItem (const char *ns,
+ const char *arrayName,
+ const char *itemValue,
+ bool isBag,
+ bool propIsStruct)
+ {
+
+ fSDK->AppendArrayItem (ns,
+ arrayName,
+ itemValue,
+ isBag,
+ propIsStruct);
+ }
+
+/*****************************************************************************/
+
+#if qDNGXMPDocOps
+
+/*****************************************************************************/
+
+void dng_xmp::DocOpsOpenXMP (const char *srcMIMI)
+ {
+
+ fSDK->DocOpsOpenXMP (srcMIMI);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::DocOpsPrepareForSave (const char *srcMIMI,
+ const char *dstMIMI,
+ bool newPath)
+ {
+
+ fSDK->DocOpsPrepareForSave (srcMIMI,
+ dstMIMI,
+ newPath);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp::DocOpsUpdateMetadata (const char *srcMIMI)
+ {
+
+ fSDK->DocOpsUpdateMetadata (srcMIMI);
+
+ }
+
+/*****************************************************************************/
+
+#endif
+
+#endif
+/*****************************************************************************/
diff --git a/source/dng_xmp_sdk.cpp b/source/dng_xmp_sdk.cpp
index d7ef225..b218870 100644
--- a/source/dng_xmp_sdk.cpp
+++ b/source/dng_xmp_sdk.cpp
@@ -1,1679 +1,1679 @@
-/*****************************************************************************/
-// Copyright 2006-2012 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_xmp_sdk.cpp#4 $ */
-/* $DateTime: 2012/09/05 12:31:51 $ */
-/* $Change: 847652 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_xmp_sdk.h"
-
-#include "dng_auto_ptr.h"
-#include "dng_assertions.h"
-#include "dng_exceptions.h"
-#include "dng_flags.h"
-#include "dng_host.h"
-#include "dng_memory.h"
-#include "dng_string.h"
-#include "dng_string_list.h"
-#include "dng_utils.h"
-
-/*****************************************************************************/
-
-#if qMacOS
-#ifndef MAC_ENV
-#define MAC_ENV 1
-#endif
-#endif
-
-#if qWinOS
-#ifndef WIN_ENV
-#define WIN_ENV 1
-#endif
-#endif
-
-#include <new>
-#include <string>
-
-#define TXMP_STRING_TYPE std::string
-
-#define XMP_INCLUDE_XMPFILES qDNGXMPFiles
-
-#define XMP_StaticBuild 1
-
-#include "XMP.incl_cpp"
-
-/*****************************************************************************/
-
-const char *XMP_NS_TIFF = "http://ns.adobe.com/tiff/1.0/";
-const char *XMP_NS_EXIF = "http://ns.adobe.com/exif/1.0/";
-const char *XMP_NS_PHOTOSHOP = "http://ns.adobe.com/photoshop/1.0/";
-const char *XMP_NS_XAP = "http://ns.adobe.com/xap/1.0/";
-const char *XMP_NS_XAP_RIGHTS = "http://ns.adobe.com/xap/1.0/rights/";
-const char *XMP_NS_DC = "http://purl.org/dc/elements/1.1/";
-const char *XMP_NS_XMP_NOTE = "http://ns.adobe.com/xmp/note/";
-const char *XMP_NS_MM = "http://ns.adobe.com/xap/1.0/mm/";
-
-const char *XMP_NS_CRS = "http://ns.adobe.com/camera-raw-settings/1.0/";
-const char *XMP_NS_CRSS = "http://ns.adobe.com/camera-raw-saved-settings/1.0/";
-const char *XMP_NS_AUX = "http://ns.adobe.com/exif/1.0/aux/";
-
-const char *XMP_NS_LCP = "http://ns.adobe.com/photoshop/1.0/camera-profile";
-
-const char *XMP_NS_IPTC = "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/";
-const char *XMP_NS_IPTC_EXT = "http://iptc.org/std/Iptc4xmpExt/2008-02-29/";
-
-const char *XMP_NS_CRX = "http://ns.adobe.com/lightroom-settings-experimental/1.0/";
-
-const char *XMP_NS_DNG = "http://ns.adobe.com/dng/1.0/";
-
-/******************************************************************************/
-
-#define CATCH_XMP(routine, fatal)\
- \
- catch (std::bad_alloc &)\
- {\
- DNG_REPORT ("Info: XMP " routine " threw memory exception");\
- ThrowMemoryFull ();\
- }\
- \
- catch (XMP_Error &error)\
- {\
- const char *errMessage = error.GetErrMsg ();\
- if (errMessage && strlen (errMessage) <= 128)\
- {\
- char errBuffer [256];\
- sprintf (errBuffer, "Info: XMP " routine " threw '%s' exception", errMessage);\
- DNG_REPORT ( errBuffer);\
- }\
- else\
- {\
- DNG_REPORT ("Info: XMP " routine " threw unnamed exception");\
- }\
- if (fatal) ThrowProgramError ();\
- }\
- \
- catch (...)\
- {\
- DNG_REPORT ("Info: XMP " routine " threw unknown exception");\
- if (fatal) ThrowProgramError ();\
- }
-
-/*****************************************************************************/
-
-class dng_xmp_private
- {
-
- public:
-
- SXMPMeta *fMeta;
-
- dng_xmp_private ()
- : fMeta (NULL)
- {
- }
-
- dng_xmp_private (const dng_xmp_private &xmp);
-
- ~dng_xmp_private ()
- {
- if (fMeta)
- {
- delete fMeta;
- }
- }
-
- private:
-
- // Hidden assignment operator.
-
- dng_xmp_private & operator= (const dng_xmp_private &xmp);
-
- };
-
-/*****************************************************************************/
-
-dng_xmp_private::dng_xmp_private (const dng_xmp_private &xmp)
-
- : fMeta (NULL)
-
- {
-
- if (xmp.fMeta)
- {
-
- fMeta = new SXMPMeta (xmp.fMeta->Clone (0));
-
- if (!fMeta)
- {
- ThrowMemoryFull ();
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_xmp_sdk::dng_xmp_sdk ()
-
- : fPrivate (NULL)
-
- {
-
- fPrivate = new dng_xmp_private;
-
- if (!fPrivate)
- {
- ThrowMemoryFull ();
- }
-
- }
-
-/*****************************************************************************/
-
-dng_xmp_sdk::dng_xmp_sdk (const dng_xmp_sdk &sdk)
-
- : fPrivate (NULL)
-
- {
-
- fPrivate = new dng_xmp_private (*sdk.fPrivate);
-
- if (!fPrivate)
- {
- ThrowMemoryFull ();
- }
-
- }
-
-/*****************************************************************************/
-
-dng_xmp_sdk::~dng_xmp_sdk ()
- {
-
- if (fPrivate)
- {
- delete fPrivate;
- }
-
- }
-
-/*****************************************************************************/
-
-static bool gInitializedXMP = false;
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::InitializeSDK (dng_xmp_namespace * extraNamespaces,
- const char *software)
- {
-
- if (!gInitializedXMP)
- {
-
- try
- {
-
- if (!SXMPMeta::Initialize ())
- {
- ThrowProgramError ();
- }
-
- // Register Lightroom beta settings namespace.
- // We no longer read this but I don't want to cut it out this close
- // to a release. [bruzenak]
-
- {
-
- TXMP_STRING_TYPE ss;
-
- SXMPMeta::RegisterNamespace (XMP_NS_CRX,
- "crx",
- &ss);
-
- }
-
- // Register CRSS snapshots namespace
-
- {
-
- TXMP_STRING_TYPE ss;
-
- SXMPMeta::RegisterNamespace (XMP_NS_CRSS,
- "crss",
- &ss);
-
- }
-
- // Register LCP (lens correction profiles) namespace
-
- {
-
- TXMP_STRING_TYPE ss;
-
- SXMPMeta::RegisterNamespace (XMP_NS_LCP,
- "stCamera",
- &ss);
-
- }
-
- // Register DNG format metadata namespace
-
- {
-
- TXMP_STRING_TYPE ss;
-
- SXMPMeta::RegisterNamespace (XMP_NS_DNG,
- "dng",
- &ss);
-
- }
-
- // Register extra namespaces.
-
- if (extraNamespaces != NULL)
- {
-
- for (; extraNamespaces->fullName != NULL; ++extraNamespaces)
- {
-
- TXMP_STRING_TYPE ss;
-
- SXMPMeta::RegisterNamespace (extraNamespaces->fullName,
- extraNamespaces->shortName,
- &ss);
-
- }
-
- }
-
- #if qDNGXMPFiles
-
- #if qLinux
- if (!SXMPFiles::Initialize (kXMPFiles_IgnoreLocalText))
- #else
- if (!SXMPFiles::Initialize ())
- #endif
- {
- ThrowProgramError ();
- }
-
- #endif
-
- #if qDNGXMPDocOps
-
- if (software)
- {
-
- SXMPDocOps::SetAppName (software);
-
- }
-
- #else
-
- (void) software;
-
- #endif
-
- }
-
- CATCH_XMP ("Initialization", true)
-
- gInitializedXMP = true;
-
- }
-
- }
-
-/******************************************************************************/
-
-void dng_xmp_sdk::TerminateSDK ()
- {
-
- if (gInitializedXMP)
- {
-
- try
- {
-
- #if qDNGXMPFiles
-
- SXMPFiles::Terminate ();
-
- #endif
-
- SXMPMeta::Terminate ();
-
- }
-
- catch (...)
- {
-
- }
-
- gInitializedXMP = false;
-
- }
-
- }
-
-/******************************************************************************/
-
-bool dng_xmp_sdk::HasMeta () const
- {
-
- if (fPrivate->fMeta)
- {
-
- return true;
-
- }
-
- return false;
-
- }
-
-/******************************************************************************/
-
-void dng_xmp_sdk::ClearMeta ()
- {
-
- if (HasMeta ())
- {
-
- delete fPrivate->fMeta;
-
- fPrivate->fMeta = NULL;
-
- }
-
- }
-
-/******************************************************************************/
-
-void dng_xmp_sdk::MakeMeta ()
- {
-
- ClearMeta ();
-
- InitializeSDK ();
-
- try
- {
-
- fPrivate->fMeta = new SXMPMeta;
-
- if (!fPrivate->fMeta)
- {
-
- ThrowMemoryFull ();
-
- }
-
- }
-
- CATCH_XMP ("MakeMeta", true)
-
- }
-
-/******************************************************************************/
-
-void dng_xmp_sdk::NeedMeta ()
- {
-
- if (!HasMeta ())
- {
-
- MakeMeta ();
-
- }
-
- }
-
-/******************************************************************************/
-
-void * dng_xmp_sdk::GetPrivateMeta ()
- {
-
- NeedMeta ();
-
- return (void *) fPrivate->fMeta;
-
- }
-
-/******************************************************************************/
-
-void dng_xmp_sdk::Parse (dng_host &host,
- const char *buffer,
- uint32 count)
- {
-
- MakeMeta ();
-
- try
- {
-
- try
- {
-
- fPrivate->fMeta->ParseFromBuffer (buffer, count);
-
- }
-
- CATCH_XMP ("ParseFromBuffer", true)
-
- }
-
- catch (dng_exception &except)
- {
-
- ClearMeta ();
-
- if (host.IsTransientError (except.ErrorCode ()))
- {
-
- throw;
-
- }
-
- ThrowBadFormat ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::AppendArrayItem (const char *ns,
- const char *arrayName,
- const char *itemValue,
- bool isBag,
- bool propIsStruct)
- {
-
- NeedMeta();
-
- try
- {
-
- fPrivate->fMeta->AppendArrayItem (ns,
- arrayName,
- isBag ? kXMP_PropValueIsArray
- : kXMP_PropArrayIsOrdered,
- itemValue,
- propIsStruct ? kXMP_PropValueIsStruct
- : 0);
-
- }
- CATCH_XMP ("AppendArrayItem", true )
-
- }
-
-/*****************************************************************************/
-
-int32 dng_xmp_sdk::CountArrayItems (const char *ns,
- const char *path) const
- {
-
- if (HasMeta ())
- {
-
- try
- {
-
- return fPrivate->fMeta->CountArrayItems (ns, path);
-
- }
-
- CATCH_XMP ("CountArrayItems", false)
-
- }
-
- return 0;
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::Exists (const char *ns,
- const char *path) const
- {
-
- if (HasMeta ())
- {
-
- try
- {
-
- return fPrivate->fMeta->DoesPropertyExist (ns, path);
-
- }
-
- catch (...)
- {
-
- // Does not exist...
-
- }
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::HasNameSpace (const char *ns) const
- {
-
- bool result = false;
-
- if (HasMeta ())
- {
-
- try
- {
-
- SXMPIterator iter (*fPrivate->fMeta, ns);
-
- TXMP_STRING_TYPE nsTemp;
- TXMP_STRING_TYPE prop;
-
- if (iter.Next (&nsTemp,
- &prop,
- NULL,
- NULL))
- {
-
- result = true;
-
- }
-
- }
-
- CATCH_XMP ("HasNameSpace", true)
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::Remove (const char *ns,
- const char *path)
- {
-
- if (HasMeta ())
- {
-
- try
- {
-
- fPrivate->fMeta->DeleteProperty (ns, path);
-
- }
-
- CATCH_XMP ("DeleteProperty", false)
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::RemoveProperties (const char *ns)
- {
-
- if (HasMeta ())
- {
-
- try
- {
-
- SXMPUtils::RemoveProperties (fPrivate->fMeta,
- ns,
- NULL,
- kXMPUtil_DoAllProperties);
-
- }
-
- catch (...)
- {
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::IsEmptyString (const char *ns,
- const char *path)
- {
-
- if (HasMeta ())
- {
-
- try
- {
-
- TXMP_STRING_TYPE ss;
-
- XMP_OptionBits options = 0;
-
- if (fPrivate->fMeta->GetProperty (ns,
- path,
- &ss,
- &options))
- {
-
- // Item must be simple.
-
- if (XMP_PropIsSimple (options))
- {
-
- // Check for null strings.
-
- return (ss.c_str () == 0 ||
- ss.c_str () [0] == 0);
-
- }
-
- }
-
- }
-
- CATCH_XMP ("IsEmptyString", false)
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::IsEmptyArray (const char *ns,
- const char *path)
- {
-
- if (HasMeta ())
- {
-
- try
- {
-
- TXMP_STRING_TYPE ss;
-
- XMP_OptionBits options = 0;
-
- if (fPrivate->fMeta->GetProperty (ns,
- path,
- &ss,
- &options))
- {
-
- if (XMP_PropIsArray (options))
- {
-
- if (fPrivate->fMeta->GetArrayItem (ns,
- path,
- 1,
- &ss,
- &options))
- {
-
- // If the first item is a null string...
-
- if (XMP_PropIsSimple (options))
- {
-
- if ((ss.c_str () == 0 ||
- ss.c_str () [0] == 0))
- {
-
- // And there is no second item.
-
- if (!fPrivate->fMeta->GetArrayItem (ns,
- path,
- 2,
- &ss,
- &options))
- {
-
- // Then we have an empty array.
-
- return true;
-
- }
-
- }
-
- }
-
- }
-
- else
- {
-
- // Unable to get first item, so array is empty.
-
- return true;
-
- }
-
- }
-
- }
-
- }
-
- CATCH_XMP ("IsEmptyArray", false)
-
- }
-
- return false;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::ComposeArrayItemPath (const char *ns,
- const char *arrayName,
- int32 index,
- dng_string &s) const
- {
-
- try
- {
-
- std::string ss;
-
- SXMPUtils::ComposeArrayItemPath (ns, arrayName, index, &ss);
-
- s.Set (ss.c_str ());
-
- return;
-
- }
-
- CATCH_XMP ("ComposeArrayItemPath", true)
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::ComposeStructFieldPath (const char *ns,
- const char *structName,
- const char *fieldNS,
- const char *fieldName,
- dng_string &s) const
- {
-
- try
- {
-
- std::string ss;
-
- SXMPUtils::ComposeStructFieldPath (ns,
- structName,
- fieldNS,
- fieldName,
- &ss);
-
- s.Set (ss.c_str ());
-
- return;
-
- }
-
- CATCH_XMP ("ComposeStructFieldPath", true)
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::GetNamespacePrefix (const char *uri,
- dng_string &s) const
- {
-
- bool result = false;
-
- if (HasMeta ())
- {
-
- try
- {
-
- std::string ss;
-
- fPrivate->fMeta->GetNamespacePrefix (uri, &ss);
-
- s.Set (ss.c_str ());
-
- result = true;
-
- }
-
- CATCH_XMP ("GetNamespacePrefix", false)
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::GetString (const char *ns,
- const char *path,
- dng_string &s) const
- {
-
- bool result = false;
-
- if (HasMeta ())
- {
-
- try
- {
-
- TXMP_STRING_TYPE ss;
-
- if (fPrivate->fMeta->GetProperty (ns, path, &ss, NULL))
- {
-
- s.Set (ss.c_str ());
-
- result = true;
-
- }
-
- }
-
- CATCH_XMP ("GetProperty", false)
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::ValidateStringList (const char *ns,
- const char *path)
- {
-
- if (Exists (ns, path))
- {
-
- bool bogus = true;
-
- try
- {
-
- XMP_Index index = 1;
-
- TXMP_STRING_TYPE ss;
-
- while (fPrivate->fMeta->GetArrayItem (ns,
- path,
- index++,
- &ss,
- NULL))
- {
-
- }
-
- bogus = false;
-
- }
-
- CATCH_XMP ("GetArrayItem", false)
-
- if (bogus)
- {
-
- Remove (ns, path);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::GetStringList (const char *ns,
- const char *path,
- dng_string_list &list) const
- {
-
- bool result = false;
-
- if (HasMeta ())
- {
-
- try
- {
-
- XMP_Index index = 1;
-
- TXMP_STRING_TYPE ss;
-
- while (fPrivate->fMeta->GetArrayItem (ns,
- path,
- index++,
- &ss,
- NULL))
- {
-
- dng_string s;
-
- s.Set (ss.c_str ());
-
- list.Append (s);
-
- result = true;
-
- }
-
- }
-
- CATCH_XMP ("GetArrayItem", false)
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::GetAltLangDefault (const char *ns,
- const char *path,
- dng_string &s) const
- {
-
- bool result = false;
-
- if (HasMeta ())
- {
-
- try
- {
-
- TXMP_STRING_TYPE ss;
-
- if (fPrivate->fMeta->GetLocalizedText (ns,
- path,
- "x-default",
- "x-default",
- NULL,
- &ss,
- NULL))
- {
-
- s.Set (ss.c_str ());
-
- result = true;
-
- }
- //
- // Special Case: treat the following two representation equivalently.
- // The first is an empty alt lang array; the second is an array with
- // an empty item. It seems that xmp lib could be generating both under
- // some circumstances!
- //
- // <dc:description>
- // <rdf:Alt/>
- // </dc:description>
- //
- // and
- //
- // <dc:description>
- // <rdf:Alt>
- // <rdf:li xml:lang="x-default"/>
- // </rdf:Alt>
- // </dc:description>
- //
- else if (fPrivate->fMeta->GetProperty (ns,
- path,
- &ss,
- NULL))
- {
-
- if (ss.empty ())
- {
-
- s.Clear ();
-
- result = true;
-
- }
-
- }
-
- }
-
- CATCH_XMP ("GetLocalizedText", false)
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::GetStructField (const char *ns,
- const char *path,
- const char *fieldNS,
- const char *fieldName,
- dng_string &s) const
- {
-
- bool result = false;
-
- if (HasMeta ())
- {
-
- try
- {
-
- TXMP_STRING_TYPE ss;
-
- if (fPrivate->fMeta->GetStructField (ns,
- path,
- fieldNS,
- fieldName,
- &ss,
- NULL))
- {
-
- s.Set (ss.c_str ());
-
- result = true;
-
- }
-
- }
-
- CATCH_XMP ("GetStructField", false)
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::Set (const char *ns,
- const char *path,
- const char *text)
- {
-
- NeedMeta ();
-
- try
- {
-
- fPrivate->fMeta->SetProperty (ns, path, text);
-
- return;
-
- }
-
- catch (...)
- {
-
- // Failed for some reason.
-
- }
-
- // Remove existing value and try again.
-
- Remove (ns, path);
-
- try
- {
-
- fPrivate->fMeta->SetProperty (ns, path, text);
-
- }
-
- CATCH_XMP ("SetProperty", true)
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::SetString (const char *ns,
- const char *path,
- const dng_string &s)
- {
-
- dng_string ss (s);
-
- ss.SetLineEndings ('\n');
-
- ss.StripLowASCII ();
-
- Set (ns, path, ss.Get ());
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::SetStringList (const char *ns,
- const char *path,
- const dng_string_list &list,
- bool isBag)
- {
-
- // Remove any existing structure.
-
- Remove (ns, path);
-
- // If list is not empty, add the items.
-
- if (list.Count ())
- {
-
- NeedMeta ();
-
- for (uint32 index = 0; index < list.Count (); index++)
- {
-
- dng_string s (list [index]);
-
- s.SetLineEndings ('\n');
-
- s.StripLowASCII ();
-
- try
- {
-
- fPrivate->fMeta->AppendArrayItem (ns,
- path,
- isBag ? kXMP_PropValueIsArray
- : kXMP_PropArrayIsOrdered,
- s.Get ());
-
- }
-
- CATCH_XMP ("AppendArrayItem", true)
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::SetAltLangDefault (const char *ns,
- const char *path,
- const dng_string &s)
- {
-
- NeedMeta ();
-
- Remove (ns, path);
-
- dng_string ss (s);
-
- ss.SetLineEndings ('\n');
-
- ss.StripLowASCII ();
-
- try
- {
-
- fPrivate->fMeta->SetLocalizedText (ns,
- path,
- "x-default",
- "x-default",
- ss.Get ());
-
- }
-
- CATCH_XMP ("SetLocalizedText", true)
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::SetStructField (const char *ns,
- const char *path,
- const char *fieldNS,
- const char *fieldName,
- const char *text)
- {
-
- NeedMeta ();
-
- try
- {
-
- fPrivate->fMeta->SetStructField (ns,
- path,
- fieldNS,
- fieldName,
- text);
-
- }
-
- CATCH_XMP ("SetStructField", true)
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::DeleteStructField (const char *ns,
- const char *structName,
- const char *fieldNS,
- const char *fieldName)
- {
-
- if (HasMeta ())
- {
-
- try
- {
-
- fPrivate->fMeta->DeleteStructField (ns, structName, fieldNS, fieldName);
-
- }
-
- catch (...)
- {
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_memory_block * dng_xmp_sdk::Serialize (dng_memory_allocator &allocator,
- bool asPacket,
- uint32 targetBytes,
- uint32 padBytes,
- bool forJPEG,
- bool compact) const
- {
-
- // The largest XMP packet you can embed in JPEG using normal methods:
-
- const uint32 kJPEG_XMP_Limit = 65504;
-
- if (HasMeta ())
- {
-
- TXMP_STRING_TYPE s;
-
- bool havePacket = false;
-
- // Note that the XMP lib is changing its default to compact format
- // in the future, so the following line will need to change.
-
- uint32 formatOption = compact ? kXMP_UseCompactFormat : 0;
-
- if (asPacket && targetBytes)
- {
-
- try
- {
-
- fPrivate->fMeta->SerializeToBuffer (&s,
- formatOption | kXMP_ExactPacketLength,
- targetBytes,
- "",
- " ");
-
- havePacket = true;
-
- }
-
- catch (...)
- {
-
- // Most likely the packet cannot fit in the target
- // byte count. So try again without the limit.
-
- }
-
- }
-
- if (!havePacket)
- {
-
- try
- {
-
- fPrivate->fMeta->SerializeToBuffer (&s,
- formatOption |
- (asPacket ? 0
- : kXMP_OmitPacketWrapper),
- (asPacket ? padBytes
- : 0),
- "",
- " ");
-
- }
-
- CATCH_XMP ("SerializeToBuffer", true)
-
- }
-
- uint32 packetLen = (uint32) s.size ();
-
- if (forJPEG && asPacket && padBytes > 0 && targetBytes <= kJPEG_XMP_Limit &&
- packetLen > kJPEG_XMP_Limit)
- {
-
- uint32 overLimitCount = packetLen - kJPEG_XMP_Limit;
-
- if (overLimitCount > padBytes)
- {
- padBytes = 0;
- }
- else
- {
- padBytes -= overLimitCount;
- }
-
- try
- {
-
- fPrivate->fMeta->SerializeToBuffer (&s,
- formatOption,
- padBytes,
- "",
- " ");
-
- }
-
- CATCH_XMP ("SerializeToBuffer", true)
-
- packetLen = (uint32) s.size ();
-
- }
-
- if (packetLen)
- {
-
- AutoPtr<dng_memory_block> buffer (allocator.Allocate (packetLen));
-
- memcpy (buffer->Buffer (), s.c_str (), packetLen);
-
- return buffer.Release ();
-
- }
-
- }
-
- return NULL;
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::PackageForJPEG (dng_memory_allocator &allocator,
- AutoPtr<dng_memory_block> &stdBlock,
- AutoPtr<dng_memory_block> &extBlock,
- dng_string &extDigest) const
- {
-
- if (HasMeta ())
- {
-
- TXMP_STRING_TYPE stdStr;
- TXMP_STRING_TYPE extStr;
- TXMP_STRING_TYPE digestStr;
-
- try
- {
-
- SXMPUtils::PackageForJPEG (*fPrivate->fMeta,
- &stdStr,
- &extStr,
- &digestStr);
-
- }
-
- CATCH_XMP ("PackageForJPEG", true)
-
- uint32 stdLen = (uint32) stdStr.size ();
- uint32 extLen = (uint32) extStr.size ();
-
- if (stdLen)
- {
-
- stdBlock.Reset (allocator.Allocate (stdLen));
-
- memcpy (stdBlock->Buffer (), stdStr.c_str (), stdLen);
-
- }
-
- if (extLen)
- {
-
- extBlock.Reset (allocator.Allocate (extLen));
-
- memcpy (extBlock->Buffer (), extStr.c_str (), extLen);
-
- if (digestStr.size () != 32)
- {
- ThrowProgramError ();
- }
-
- extDigest.Set (digestStr.c_str ());
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::MergeFromJPEG (const dng_xmp_sdk *xmp)
- {
-
- if (xmp && xmp->HasMeta ())
- {
-
- NeedMeta ();
-
- try
- {
-
- SXMPUtils::MergeFromJPEG (fPrivate->fMeta,
- *xmp->fPrivate->fMeta);
-
- }
-
- CATCH_XMP ("MergeFromJPEG", true)
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::ReplaceXMP (dng_xmp_sdk *xmp)
- {
-
- ClearMeta ();
-
- if (xmp && xmp->HasMeta ())
- {
-
- fPrivate->fMeta = xmp->fPrivate->fMeta;
-
- xmp->fPrivate->fMeta = NULL;
-
- }
-
- }
-
-/*****************************************************************************/
-
-bool dng_xmp_sdk::IteratePaths (IteratePathsCallback *callback,
- void *callbackData,
- const char* startingNS,
- const char* startingPath)
- {
-
- if (HasMeta ())
- {
-
- try
- {
-
- SXMPIterator iter (*fPrivate->fMeta, startingNS, startingPath);
-
- TXMP_STRING_TYPE ns;
- TXMP_STRING_TYPE prop;
-
- while (iter.Next (&ns,
- &prop,
- NULL,
- NULL))
- {
-
- if (!callback (ns .c_str (),
- prop.c_str (),
- callbackData))
- {
-
- return false;
-
- }
-
- }
-
- }
-
- CATCH_XMP ("IteratePaths", true)
-
- }
-
- return true;
-
- }
-
-/*****************************************************************************/
-
-#if qDNGXMPDocOps
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::DocOpsOpenXMP (const char *srcMIMI)
- {
-
- if (srcMIMI [0])
- {
-
- NeedMeta ();
-
- try
- {
-
- SXMPDocOps docOps;
-
- docOps.OpenXMP (fPrivate->fMeta,
- srcMIMI);
-
- }
-
- CATCH_XMP ("DocOpsOpenXMP", false)
-
- Set (XMP_NS_DC,
- "format",
- srcMIMI);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::DocOpsPrepareForSave (const char *srcMIMI,
- const char *dstMIMI,
- bool newPath)
- {
-
- NeedMeta ();
-
- try
- {
-
- SXMPDocOps docOps;
-
- docOps.OpenXMP (fPrivate->fMeta,
- srcMIMI,
- "old path");
-
- docOps.NoteChange (kXMP_Part_All);
-
- docOps.PrepareForSave (dstMIMI,
- newPath ? "new path" : "old path");
-
- }
-
- CATCH_XMP ("DocOpsPrepareForSave", false)
-
- Set (XMP_NS_DC,
- "format",
- dstMIMI);
-
- }
-
-/*****************************************************************************/
-
-void dng_xmp_sdk::DocOpsUpdateMetadata (const char *srcMIMI)
- {
-
- NeedMeta ();
-
- try
- {
-
- SXMPDocOps docOps;
-
- docOps.OpenXMP (fPrivate->fMeta,
- srcMIMI);
-
- docOps.NoteChange (kXMP_Part_Metadata);
-
- docOps.PrepareForSave (srcMIMI);
-
- }
-
- CATCH_XMP ("DocOpsUpdateMetadata", false)
-
- }
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2012 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_xmp_sdk.cpp#4 $ */
+/* $DateTime: 2012/09/05 12:31:51 $ */
+/* $Change: 847652 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_xmp_sdk.h"
+
+#include "dng_auto_ptr.h"
+#include "dng_assertions.h"
+#include "dng_exceptions.h"
+#include "dng_flags.h"
+#include "dng_host.h"
+#include "dng_memory.h"
+#include "dng_string.h"
+#include "dng_string_list.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+#if qMacOS
+#ifndef MAC_ENV
+#define MAC_ENV 1
+#endif
+#endif
+
+#if qWinOS
+#ifndef WIN_ENV
+#define WIN_ENV 1
+#endif
+#endif
+
+#include <new>
+#include <string>
+
+#define TXMP_STRING_TYPE std::string
+
+#define XMP_INCLUDE_XMPFILES qDNGXMPFiles
+
+#define XMP_StaticBuild 1
+
+#include "XMP.incl_cpp"
+
+/*****************************************************************************/
+
+const char *XMP_NS_TIFF = "http://ns.adobe.com/tiff/1.0/";
+const char *XMP_NS_EXIF = "http://ns.adobe.com/exif/1.0/";
+const char *XMP_NS_PHOTOSHOP = "http://ns.adobe.com/photoshop/1.0/";
+const char *XMP_NS_XAP = "http://ns.adobe.com/xap/1.0/";
+const char *XMP_NS_XAP_RIGHTS = "http://ns.adobe.com/xap/1.0/rights/";
+const char *XMP_NS_DC = "http://purl.org/dc/elements/1.1/";
+const char *XMP_NS_XMP_NOTE = "http://ns.adobe.com/xmp/note/";
+const char *XMP_NS_MM = "http://ns.adobe.com/xap/1.0/mm/";
+
+const char *XMP_NS_CRS = "http://ns.adobe.com/camera-raw-settings/1.0/";
+const char *XMP_NS_CRSS = "http://ns.adobe.com/camera-raw-saved-settings/1.0/";
+const char *XMP_NS_AUX = "http://ns.adobe.com/exif/1.0/aux/";
+
+const char *XMP_NS_LCP = "http://ns.adobe.com/photoshop/1.0/camera-profile";
+
+const char *XMP_NS_IPTC = "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/";
+const char *XMP_NS_IPTC_EXT = "http://iptc.org/std/Iptc4xmpExt/2008-02-29/";
+
+const char *XMP_NS_CRX = "http://ns.adobe.com/lightroom-settings-experimental/1.0/";
+
+const char *XMP_NS_DNG = "http://ns.adobe.com/dng/1.0/";
+
+/******************************************************************************/
+
+#define CATCH_XMP(routine, fatal)\
+ \
+ catch (std::bad_alloc &)\
+ {\
+ DNG_REPORT ("Info: XMP " routine " threw memory exception");\
+ ThrowMemoryFull ();\
+ }\
+ \
+ catch (XMP_Error &error)\
+ {\
+ const char *errMessage = error.GetErrMsg ();\
+ if (errMessage && strlen (errMessage) <= 128)\
+ {\
+ char errBuffer [256];\
+ sprintf (errBuffer, "Info: XMP " routine " threw '%s' exception", errMessage);\
+ DNG_REPORT ( errBuffer);\
+ }\
+ else\
+ {\
+ DNG_REPORT ("Info: XMP " routine " threw unnamed exception");\
+ }\
+ if (fatal) ThrowProgramError ();\
+ }\
+ \
+ catch (...)\
+ {\
+ DNG_REPORT ("Info: XMP " routine " threw unknown exception");\
+ if (fatal) ThrowProgramError ();\
+ }
+
+/*****************************************************************************/
+
+class dng_xmp_private
+ {
+
+ public:
+
+ SXMPMeta *fMeta;
+
+ dng_xmp_private ()
+ : fMeta (NULL)
+ {
+ }
+
+ dng_xmp_private (const dng_xmp_private &xmp);
+
+ ~dng_xmp_private ()
+ {
+ if (fMeta)
+ {
+ delete fMeta;
+ }
+ }
+
+ private:
+
+ // Hidden assignment operator.
+
+ dng_xmp_private & operator= (const dng_xmp_private &xmp);
+
+ };
+
+/*****************************************************************************/
+
+dng_xmp_private::dng_xmp_private (const dng_xmp_private &xmp)
+
+ : fMeta (NULL)
+
+ {
+
+ if (xmp.fMeta)
+ {
+
+ fMeta = new SXMPMeta (xmp.fMeta->Clone (0));
+
+ if (!fMeta)
+ {
+ ThrowMemoryFull ();
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_xmp_sdk::dng_xmp_sdk ()
+
+ : fPrivate (NULL)
+
+ {
+
+ fPrivate = new dng_xmp_private;
+
+ if (!fPrivate)
+ {
+ ThrowMemoryFull ();
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_xmp_sdk::dng_xmp_sdk (const dng_xmp_sdk &sdk)
+
+ : fPrivate (NULL)
+
+ {
+
+ fPrivate = new dng_xmp_private (*sdk.fPrivate);
+
+ if (!fPrivate)
+ {
+ ThrowMemoryFull ();
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_xmp_sdk::~dng_xmp_sdk ()
+ {
+
+ if (fPrivate)
+ {
+ delete fPrivate;
+ }
+
+ }
+
+/*****************************************************************************/
+
+static bool gInitializedXMP = false;
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::InitializeSDK (dng_xmp_namespace * extraNamespaces,
+ const char *software)
+ {
+
+ if (!gInitializedXMP)
+ {
+
+ try
+ {
+
+ if (!SXMPMeta::Initialize ())
+ {
+ ThrowProgramError ();
+ }
+
+ // Register Lightroom beta settings namespace.
+ // We no longer read this but I don't want to cut it out this close
+ // to a release. [bruzenak]
+
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ SXMPMeta::RegisterNamespace (XMP_NS_CRX,
+ "crx",
+ &ss);
+
+ }
+
+ // Register CRSS snapshots namespace
+
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ SXMPMeta::RegisterNamespace (XMP_NS_CRSS,
+ "crss",
+ &ss);
+
+ }
+
+ // Register LCP (lens correction profiles) namespace
+
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ SXMPMeta::RegisterNamespace (XMP_NS_LCP,
+ "stCamera",
+ &ss);
+
+ }
+
+ // Register DNG format metadata namespace
+
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ SXMPMeta::RegisterNamespace (XMP_NS_DNG,
+ "dng",
+ &ss);
+
+ }
+
+ // Register extra namespaces.
+
+ if (extraNamespaces != NULL)
+ {
+
+ for (; extraNamespaces->fullName != NULL; ++extraNamespaces)
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ SXMPMeta::RegisterNamespace (extraNamespaces->fullName,
+ extraNamespaces->shortName,
+ &ss);
+
+ }
+
+ }
+
+ #if qDNGXMPFiles
+
+ #if qLinux
+ if (!SXMPFiles::Initialize (kXMPFiles_IgnoreLocalText))
+ #else
+ if (!SXMPFiles::Initialize ())
+ #endif
+ {
+ ThrowProgramError ();
+ }
+
+ #endif
+
+ #if qDNGXMPDocOps
+
+ if (software)
+ {
+
+ SXMPDocOps::SetAppName (software);
+
+ }
+
+ #else
+
+ (void) software;
+
+ #endif
+
+ }
+
+ CATCH_XMP ("Initialization", true)
+
+ gInitializedXMP = true;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp_sdk::TerminateSDK ()
+ {
+
+ if (gInitializedXMP)
+ {
+
+ try
+ {
+
+ #if qDNGXMPFiles
+
+ SXMPFiles::Terminate ();
+
+ #endif
+
+ SXMPMeta::Terminate ();
+
+ }
+
+ catch (...)
+ {
+
+ }
+
+ gInitializedXMP = false;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+bool dng_xmp_sdk::HasMeta () const
+ {
+
+ if (fPrivate->fMeta)
+ {
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp_sdk::ClearMeta ()
+ {
+
+ if (HasMeta ())
+ {
+
+ delete fPrivate->fMeta;
+
+ fPrivate->fMeta = NULL;
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp_sdk::MakeMeta ()
+ {
+
+ ClearMeta ();
+
+ InitializeSDK ();
+
+ try
+ {
+
+ fPrivate->fMeta = new SXMPMeta;
+
+ if (!fPrivate->fMeta)
+ {
+
+ ThrowMemoryFull ();
+
+ }
+
+ }
+
+ CATCH_XMP ("MakeMeta", true)
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp_sdk::NeedMeta ()
+ {
+
+ if (!HasMeta ())
+ {
+
+ MakeMeta ();
+
+ }
+
+ }
+
+/******************************************************************************/
+
+void * dng_xmp_sdk::GetPrivateMeta ()
+ {
+
+ NeedMeta ();
+
+ return (void *) fPrivate->fMeta;
+
+ }
+
+/******************************************************************************/
+
+void dng_xmp_sdk::Parse (dng_host &host,
+ const char *buffer,
+ uint32 count)
+ {
+
+ MakeMeta ();
+
+ try
+ {
+
+ try
+ {
+
+ fPrivate->fMeta->ParseFromBuffer (buffer, count);
+
+ }
+
+ CATCH_XMP ("ParseFromBuffer", true)
+
+ }
+
+ catch (dng_exception &except)
+ {
+
+ ClearMeta ();
+
+ if (host.IsTransientError (except.ErrorCode ()))
+ {
+
+ throw;
+
+ }
+
+ ThrowBadFormat ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::AppendArrayItem (const char *ns,
+ const char *arrayName,
+ const char *itemValue,
+ bool isBag,
+ bool propIsStruct)
+ {
+
+ NeedMeta();
+
+ try
+ {
+
+ fPrivate->fMeta->AppendArrayItem (ns,
+ arrayName,
+ isBag ? kXMP_PropValueIsArray
+ : kXMP_PropArrayIsOrdered,
+ itemValue,
+ propIsStruct ? kXMP_PropValueIsStruct
+ : 0);
+
+ }
+ CATCH_XMP ("AppendArrayItem", true )
+
+ }
+
+/*****************************************************************************/
+
+int32 dng_xmp_sdk::CountArrayItems (const char *ns,
+ const char *path) const
+ {
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ return fPrivate->fMeta->CountArrayItems (ns, path);
+
+ }
+
+ CATCH_XMP ("CountArrayItems", false)
+
+ }
+
+ return 0;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::Exists (const char *ns,
+ const char *path) const
+ {
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ return fPrivate->fMeta->DoesPropertyExist (ns, path);
+
+ }
+
+ catch (...)
+ {
+
+ // Does not exist...
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::HasNameSpace (const char *ns) const
+ {
+
+ bool result = false;
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ SXMPIterator iter (*fPrivate->fMeta, ns);
+
+ TXMP_STRING_TYPE nsTemp;
+ TXMP_STRING_TYPE prop;
+
+ if (iter.Next (&nsTemp,
+ &prop,
+ NULL,
+ NULL))
+ {
+
+ result = true;
+
+ }
+
+ }
+
+ CATCH_XMP ("HasNameSpace", true)
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::Remove (const char *ns,
+ const char *path)
+ {
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ fPrivate->fMeta->DeleteProperty (ns, path);
+
+ }
+
+ CATCH_XMP ("DeleteProperty", false)
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::RemoveProperties (const char *ns)
+ {
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ SXMPUtils::RemoveProperties (fPrivate->fMeta,
+ ns,
+ NULL,
+ kXMPUtil_DoAllProperties);
+
+ }
+
+ catch (...)
+ {
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::IsEmptyString (const char *ns,
+ const char *path)
+ {
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ XMP_OptionBits options = 0;
+
+ if (fPrivate->fMeta->GetProperty (ns,
+ path,
+ &ss,
+ &options))
+ {
+
+ // Item must be simple.
+
+ if (XMP_PropIsSimple (options))
+ {
+
+ // Check for null strings.
+
+ return (ss.c_str () == 0 ||
+ ss.c_str () [0] == 0);
+
+ }
+
+ }
+
+ }
+
+ CATCH_XMP ("IsEmptyString", false)
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::IsEmptyArray (const char *ns,
+ const char *path)
+ {
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ XMP_OptionBits options = 0;
+
+ if (fPrivate->fMeta->GetProperty (ns,
+ path,
+ &ss,
+ &options))
+ {
+
+ if (XMP_PropIsArray (options))
+ {
+
+ if (fPrivate->fMeta->GetArrayItem (ns,
+ path,
+ 1,
+ &ss,
+ &options))
+ {
+
+ // If the first item is a null string...
+
+ if (XMP_PropIsSimple (options))
+ {
+
+ if ((ss.c_str () == 0 ||
+ ss.c_str () [0] == 0))
+ {
+
+ // And there is no second item.
+
+ if (!fPrivate->fMeta->GetArrayItem (ns,
+ path,
+ 2,
+ &ss,
+ &options))
+ {
+
+ // Then we have an empty array.
+
+ return true;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ else
+ {
+
+ // Unable to get first item, so array is empty.
+
+ return true;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ CATCH_XMP ("IsEmptyArray", false)
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::ComposeArrayItemPath (const char *ns,
+ const char *arrayName,
+ int32 index,
+ dng_string &s) const
+ {
+
+ try
+ {
+
+ std::string ss;
+
+ SXMPUtils::ComposeArrayItemPath (ns, arrayName, index, &ss);
+
+ s.Set (ss.c_str ());
+
+ return;
+
+ }
+
+ CATCH_XMP ("ComposeArrayItemPath", true)
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::ComposeStructFieldPath (const char *ns,
+ const char *structName,
+ const char *fieldNS,
+ const char *fieldName,
+ dng_string &s) const
+ {
+
+ try
+ {
+
+ std::string ss;
+
+ SXMPUtils::ComposeStructFieldPath (ns,
+ structName,
+ fieldNS,
+ fieldName,
+ &ss);
+
+ s.Set (ss.c_str ());
+
+ return;
+
+ }
+
+ CATCH_XMP ("ComposeStructFieldPath", true)
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::GetNamespacePrefix (const char *uri,
+ dng_string &s) const
+ {
+
+ bool result = false;
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ std::string ss;
+
+ fPrivate->fMeta->GetNamespacePrefix (uri, &ss);
+
+ s.Set (ss.c_str ());
+
+ result = true;
+
+ }
+
+ CATCH_XMP ("GetNamespacePrefix", false)
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::GetString (const char *ns,
+ const char *path,
+ dng_string &s) const
+ {
+
+ bool result = false;
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ if (fPrivate->fMeta->GetProperty (ns, path, &ss, NULL))
+ {
+
+ s.Set (ss.c_str ());
+
+ result = true;
+
+ }
+
+ }
+
+ CATCH_XMP ("GetProperty", false)
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::ValidateStringList (const char *ns,
+ const char *path)
+ {
+
+ if (Exists (ns, path))
+ {
+
+ bool bogus = true;
+
+ try
+ {
+
+ XMP_Index index = 1;
+
+ TXMP_STRING_TYPE ss;
+
+ while (fPrivate->fMeta->GetArrayItem (ns,
+ path,
+ index++,
+ &ss,
+ NULL))
+ {
+
+ }
+
+ bogus = false;
+
+ }
+
+ CATCH_XMP ("GetArrayItem", false)
+
+ if (bogus)
+ {
+
+ Remove (ns, path);
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::GetStringList (const char *ns,
+ const char *path,
+ dng_string_list &list) const
+ {
+
+ bool result = false;
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ XMP_Index index = 1;
+
+ TXMP_STRING_TYPE ss;
+
+ while (fPrivate->fMeta->GetArrayItem (ns,
+ path,
+ index++,
+ &ss,
+ NULL))
+ {
+
+ dng_string s;
+
+ s.Set (ss.c_str ());
+
+ list.Append (s);
+
+ result = true;
+
+ }
+
+ }
+
+ CATCH_XMP ("GetArrayItem", false)
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::GetAltLangDefault (const char *ns,
+ const char *path,
+ dng_string &s) const
+ {
+
+ bool result = false;
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ if (fPrivate->fMeta->GetLocalizedText (ns,
+ path,
+ "x-default",
+ "x-default",
+ NULL,
+ &ss,
+ NULL))
+ {
+
+ s.Set (ss.c_str ());
+
+ result = true;
+
+ }
+ //
+ // Special Case: treat the following two representation equivalently.
+ // The first is an empty alt lang array; the second is an array with
+ // an empty item. It seems that xmp lib could be generating both under
+ // some circumstances!
+ //
+ // <dc:description>
+ // <rdf:Alt/>
+ // </dc:description>
+ //
+ // and
+ //
+ // <dc:description>
+ // <rdf:Alt>
+ // <rdf:li xml:lang="x-default"/>
+ // </rdf:Alt>
+ // </dc:description>
+ //
+ else if (fPrivate->fMeta->GetProperty (ns,
+ path,
+ &ss,
+ NULL))
+ {
+
+ if (ss.empty ())
+ {
+
+ s.Clear ();
+
+ result = true;
+
+ }
+
+ }
+
+ }
+
+ CATCH_XMP ("GetLocalizedText", false)
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::GetStructField (const char *ns,
+ const char *path,
+ const char *fieldNS,
+ const char *fieldName,
+ dng_string &s) const
+ {
+
+ bool result = false;
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ TXMP_STRING_TYPE ss;
+
+ if (fPrivate->fMeta->GetStructField (ns,
+ path,
+ fieldNS,
+ fieldName,
+ &ss,
+ NULL))
+ {
+
+ s.Set (ss.c_str ());
+
+ result = true;
+
+ }
+
+ }
+
+ CATCH_XMP ("GetStructField", false)
+
+ }
+
+ return result;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::Set (const char *ns,
+ const char *path,
+ const char *text)
+ {
+
+ NeedMeta ();
+
+ try
+ {
+
+ fPrivate->fMeta->SetProperty (ns, path, text);
+
+ return;
+
+ }
+
+ catch (...)
+ {
+
+ // Failed for some reason.
+
+ }
+
+ // Remove existing value and try again.
+
+ Remove (ns, path);
+
+ try
+ {
+
+ fPrivate->fMeta->SetProperty (ns, path, text);
+
+ }
+
+ CATCH_XMP ("SetProperty", true)
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::SetString (const char *ns,
+ const char *path,
+ const dng_string &s)
+ {
+
+ dng_string ss (s);
+
+ ss.SetLineEndings ('\n');
+
+ ss.StripLowASCII ();
+
+ Set (ns, path, ss.Get ());
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::SetStringList (const char *ns,
+ const char *path,
+ const dng_string_list &list,
+ bool isBag)
+ {
+
+ // Remove any existing structure.
+
+ Remove (ns, path);
+
+ // If list is not empty, add the items.
+
+ if (list.Count ())
+ {
+
+ NeedMeta ();
+
+ for (uint32 index = 0; index < list.Count (); index++)
+ {
+
+ dng_string s (list [index]);
+
+ s.SetLineEndings ('\n');
+
+ s.StripLowASCII ();
+
+ try
+ {
+
+ fPrivate->fMeta->AppendArrayItem (ns,
+ path,
+ isBag ? kXMP_PropValueIsArray
+ : kXMP_PropArrayIsOrdered,
+ s.Get ());
+
+ }
+
+ CATCH_XMP ("AppendArrayItem", true)
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::SetAltLangDefault (const char *ns,
+ const char *path,
+ const dng_string &s)
+ {
+
+ NeedMeta ();
+
+ Remove (ns, path);
+
+ dng_string ss (s);
+
+ ss.SetLineEndings ('\n');
+
+ ss.StripLowASCII ();
+
+ try
+ {
+
+ fPrivate->fMeta->SetLocalizedText (ns,
+ path,
+ "x-default",
+ "x-default",
+ ss.Get ());
+
+ }
+
+ CATCH_XMP ("SetLocalizedText", true)
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::SetStructField (const char *ns,
+ const char *path,
+ const char *fieldNS,
+ const char *fieldName,
+ const char *text)
+ {
+
+ NeedMeta ();
+
+ try
+ {
+
+ fPrivate->fMeta->SetStructField (ns,
+ path,
+ fieldNS,
+ fieldName,
+ text);
+
+ }
+
+ CATCH_XMP ("SetStructField", true)
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::DeleteStructField (const char *ns,
+ const char *structName,
+ const char *fieldNS,
+ const char *fieldName)
+ {
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ fPrivate->fMeta->DeleteStructField (ns, structName, fieldNS, fieldName);
+
+ }
+
+ catch (...)
+ {
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+dng_memory_block * dng_xmp_sdk::Serialize (dng_memory_allocator &allocator,
+ bool asPacket,
+ uint32 targetBytes,
+ uint32 padBytes,
+ bool forJPEG,
+ bool compact) const
+ {
+
+ // The largest XMP packet you can embed in JPEG using normal methods:
+
+ const uint32 kJPEG_XMP_Limit = 65504;
+
+ if (HasMeta ())
+ {
+
+ TXMP_STRING_TYPE s;
+
+ bool havePacket = false;
+
+ // Note that the XMP lib is changing its default to compact format
+ // in the future, so the following line will need to change.
+
+ uint32 formatOption = compact ? kXMP_UseCompactFormat : 0;
+
+ if (asPacket && targetBytes)
+ {
+
+ try
+ {
+
+ fPrivate->fMeta->SerializeToBuffer (&s,
+ formatOption | kXMP_ExactPacketLength,
+ targetBytes,
+ "",
+ " ");
+
+ havePacket = true;
+
+ }
+
+ catch (...)
+ {
+
+ // Most likely the packet cannot fit in the target
+ // byte count. So try again without the limit.
+
+ }
+
+ }
+
+ if (!havePacket)
+ {
+
+ try
+ {
+
+ fPrivate->fMeta->SerializeToBuffer (&s,
+ formatOption |
+ (asPacket ? 0
+ : kXMP_OmitPacketWrapper),
+ (asPacket ? padBytes
+ : 0),
+ "",
+ " ");
+
+ }
+
+ CATCH_XMP ("SerializeToBuffer", true)
+
+ }
+
+ uint32 packetLen = (uint32) s.size ();
+
+ if (forJPEG && asPacket && padBytes > 0 && targetBytes <= kJPEG_XMP_Limit &&
+ packetLen > kJPEG_XMP_Limit)
+ {
+
+ uint32 overLimitCount = packetLen - kJPEG_XMP_Limit;
+
+ if (overLimitCount > padBytes)
+ {
+ padBytes = 0;
+ }
+ else
+ {
+ padBytes -= overLimitCount;
+ }
+
+ try
+ {
+
+ fPrivate->fMeta->SerializeToBuffer (&s,
+ formatOption,
+ padBytes,
+ "",
+ " ");
+
+ }
+
+ CATCH_XMP ("SerializeToBuffer", true)
+
+ packetLen = (uint32) s.size ();
+
+ }
+
+ if (packetLen)
+ {
+
+ AutoPtr<dng_memory_block> buffer (allocator.Allocate (packetLen));
+
+ memcpy (buffer->Buffer (), s.c_str (), packetLen);
+
+ return buffer.Release ();
+
+ }
+
+ }
+
+ return NULL;
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::PackageForJPEG (dng_memory_allocator &allocator,
+ AutoPtr<dng_memory_block> &stdBlock,
+ AutoPtr<dng_memory_block> &extBlock,
+ dng_string &extDigest) const
+ {
+
+ if (HasMeta ())
+ {
+
+ TXMP_STRING_TYPE stdStr;
+ TXMP_STRING_TYPE extStr;
+ TXMP_STRING_TYPE digestStr;
+
+ try
+ {
+
+ SXMPUtils::PackageForJPEG (*fPrivate->fMeta,
+ &stdStr,
+ &extStr,
+ &digestStr);
+
+ }
+
+ CATCH_XMP ("PackageForJPEG", true)
+
+ uint32 stdLen = (uint32) stdStr.size ();
+ uint32 extLen = (uint32) extStr.size ();
+
+ if (stdLen)
+ {
+
+ stdBlock.Reset (allocator.Allocate (stdLen));
+
+ memcpy (stdBlock->Buffer (), stdStr.c_str (), stdLen);
+
+ }
+
+ if (extLen)
+ {
+
+ extBlock.Reset (allocator.Allocate (extLen));
+
+ memcpy (extBlock->Buffer (), extStr.c_str (), extLen);
+
+ if (digestStr.size () != 32)
+ {
+ ThrowProgramError ();
+ }
+
+ extDigest.Set (digestStr.c_str ());
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::MergeFromJPEG (const dng_xmp_sdk *xmp)
+ {
+
+ if (xmp && xmp->HasMeta ())
+ {
+
+ NeedMeta ();
+
+ try
+ {
+
+ SXMPUtils::MergeFromJPEG (fPrivate->fMeta,
+ *xmp->fPrivate->fMeta);
+
+ }
+
+ CATCH_XMP ("MergeFromJPEG", true)
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::ReplaceXMP (dng_xmp_sdk *xmp)
+ {
+
+ ClearMeta ();
+
+ if (xmp && xmp->HasMeta ())
+ {
+
+ fPrivate->fMeta = xmp->fPrivate->fMeta;
+
+ xmp->fPrivate->fMeta = NULL;
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+bool dng_xmp_sdk::IteratePaths (IteratePathsCallback *callback,
+ void *callbackData,
+ const char* startingNS,
+ const char* startingPath)
+ {
+
+ if (HasMeta ())
+ {
+
+ try
+ {
+
+ SXMPIterator iter (*fPrivate->fMeta, startingNS, startingPath);
+
+ TXMP_STRING_TYPE ns;
+ TXMP_STRING_TYPE prop;
+
+ while (iter.Next (&ns,
+ &prop,
+ NULL,
+ NULL))
+ {
+
+ if (!callback (ns .c_str (),
+ prop.c_str (),
+ callbackData))
+ {
+
+ return false;
+
+ }
+
+ }
+
+ }
+
+ CATCH_XMP ("IteratePaths", true)
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+#if qDNGXMPDocOps
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::DocOpsOpenXMP (const char *srcMIMI)
+ {
+
+ if (srcMIMI [0])
+ {
+
+ NeedMeta ();
+
+ try
+ {
+
+ SXMPDocOps docOps;
+
+ docOps.OpenXMP (fPrivate->fMeta,
+ srcMIMI);
+
+ }
+
+ CATCH_XMP ("DocOpsOpenXMP", false)
+
+ Set (XMP_NS_DC,
+ "format",
+ srcMIMI);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::DocOpsPrepareForSave (const char *srcMIMI,
+ const char *dstMIMI,
+ bool newPath)
+ {
+
+ NeedMeta ();
+
+ try
+ {
+
+ SXMPDocOps docOps;
+
+ docOps.OpenXMP (fPrivate->fMeta,
+ srcMIMI,
+ "old path");
+
+ docOps.NoteChange (kXMP_Part_All);
+
+ docOps.PrepareForSave (dstMIMI,
+ newPath ? "new path" : "old path");
+
+ }
+
+ CATCH_XMP ("DocOpsPrepareForSave", false)
+
+ Set (XMP_NS_DC,
+ "format",
+ dstMIMI);
+
+ }
+
+/*****************************************************************************/
+
+void dng_xmp_sdk::DocOpsUpdateMetadata (const char *srcMIMI)
+ {
+
+ NeedMeta ();
+
+ try
+ {
+
+ SXMPDocOps docOps;
+
+ docOps.OpenXMP (fPrivate->fMeta,
+ srcMIMI);
+
+ docOps.NoteChange (kXMP_Part_Metadata);
+
+ docOps.PrepareForSave (srcMIMI);
+
+ }
+
+ CATCH_XMP ("DocOpsUpdateMetadata", false)
+
+ }
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
diff --git a/source/dng_xy_coord.cpp b/source/dng_xy_coord.cpp
index c4fe8f0..5aff58f 100644
--- a/source/dng_xy_coord.cpp
+++ b/source/dng_xy_coord.cpp
@@ -1,89 +1,89 @@
-/*****************************************************************************/
-// Copyright 2006-2007 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_xy_coord.cpp#1 $ */
-/* $DateTime: 2012/05/30 13:28:51 $ */
-/* $Change: 832332 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_xy_coord.h"
-
-#include "dng_matrix.h"
-#include "dng_utils.h"
-
-/******************************************************************************/
-
-dng_xy_coord XYZtoXY (const dng_vector_3 &coord)
- {
-
- real64 X = coord [0];
- real64 Y = coord [1];
- real64 Z = coord [2];
-
- real64 total = X + Y + Z;
-
- if (total > 0.0)
- {
-
- return dng_xy_coord (X / total,
- Y / total);
-
- }
-
- return D50_xy_coord ();
-
- }
-
-/*****************************************************************************/
-
-dng_vector_3 XYtoXYZ (const dng_xy_coord &coord)
- {
-
- dng_xy_coord temp = coord;
-
- // Restrict xy coord to someplace inside the range of real xy coordinates.
- // This prevents math from doing strange things when users specify
- // extreme temperature/tint coordinates.
-
- temp.x = Pin_real64 (0.000001, temp.x, 0.999999);
- temp.y = Pin_real64 (0.000001, temp.y, 0.999999);
-
- if (temp.x + temp.y > 0.999999)
- {
- real64 scale = 0.999999 / (temp.x + temp.y);
- temp.x *= scale;
- temp.y *= scale;
- }
-
- return dng_vector_3 (temp.x / temp.y,
- 1.0,
- (1.0 - temp.x - temp.y) / temp.y);
-
- }
-
-/*****************************************************************************/
-
-dng_xy_coord PCStoXY ()
- {
-
- return D50_xy_coord ();
-
- }
-
-/*****************************************************************************/
-
-dng_vector_3 PCStoXYZ ()
- {
-
- return XYtoXYZ (PCStoXY ());
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006-2007 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_xy_coord.cpp#1 $ */
+/* $DateTime: 2012/05/30 13:28:51 $ */
+/* $Change: 832332 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_xy_coord.h"
+
+#include "dng_matrix.h"
+#include "dng_utils.h"
+
+/******************************************************************************/
+
+dng_xy_coord XYZtoXY (const dng_vector_3 &coord)
+ {
+
+ real64 X = coord [0];
+ real64 Y = coord [1];
+ real64 Z = coord [2];
+
+ real64 total = X + Y + Z;
+
+ if (total > 0.0)
+ {
+
+ return dng_xy_coord (X / total,
+ Y / total);
+
+ }
+
+ return D50_xy_coord ();
+
+ }
+
+/*****************************************************************************/
+
+dng_vector_3 XYtoXYZ (const dng_xy_coord &coord)
+ {
+
+ dng_xy_coord temp = coord;
+
+ // Restrict xy coord to someplace inside the range of real xy coordinates.
+ // This prevents math from doing strange things when users specify
+ // extreme temperature/tint coordinates.
+
+ temp.x = Pin_real64 (0.000001, temp.x, 0.999999);
+ temp.y = Pin_real64 (0.000001, temp.y, 0.999999);
+
+ if (temp.x + temp.y > 0.999999)
+ {
+ real64 scale = 0.999999 / (temp.x + temp.y);
+ temp.x *= scale;
+ temp.y *= scale;
+ }
+
+ return dng_vector_3 (temp.x / temp.y,
+ 1.0,
+ (1.0 - temp.x - temp.y) / temp.y);
+
+ }
+
+/*****************************************************************************/
+
+dng_xy_coord PCStoXY ()
+ {
+
+ return D50_xy_coord ();
+
+ }
+
+/*****************************************************************************/
+
+dng_vector_3 PCStoXYZ ()
+ {
+
+ return XYtoXYZ (PCStoXY ());
+
+ }
+
+/*****************************************************************************/
diff --git a/source/dng_xy_coord.h b/source/dng_xy_coord.h
index daf2125..3ae26a1 100644
--- a/source/dng_xy_coord.h
+++ b/source/dng_xy_coord.h
@@ -1,187 +1,187 @@
-/*****************************************************************************/
-// Copyright 2006 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_xy_coord.h#2 $ */
-/* $DateTime: 2012/07/31 22:04:34 $ */
-/* $Change: 840853 $ */
-/* $Author: tknoll $ */
-
-/** \file
- * Representation of colors in xy and XYZ coordinates.
- */
-
-/*****************************************************************************/
-
-#ifndef __dng_xy_coord__
-#define __dng_xy_coord__
-
-/*****************************************************************************/
-
-#include "dng_classes.h"
-#include "dng_types.h"
-
-/*****************************************************************************/
-
-class dng_xy_coord
- {
-
- public:
-
- real64 x;
- real64 y;
-
- public:
-
- dng_xy_coord ()
- : x (0.0)
- , y (0.0)
- {
- }
-
- dng_xy_coord (real64 xx, real64 yy)
- : x (xx)
- , y (yy)
- {
- }
-
- void Clear ()
- {
- x = 0.0;
- y = 0.0;
- }
-
- bool IsValid () const
- {
- return x > 0.0 &&
- y > 0.0;
- }
-
- bool NotValid () const
- {
- return !IsValid ();
- }
-
- bool operator== (const dng_xy_coord &coord) const
- {
- return coord.x == x &&
- coord.y == y;
- }
-
- bool operator!= (const dng_xy_coord &coord) const
- {
- return !(*this == coord);
- }
-
- };
-
-/*****************************************************************************/
-
-inline dng_xy_coord operator+ (const dng_xy_coord &A,
- const dng_xy_coord &B)
- {
-
- dng_xy_coord C;
-
- C.x = A.x + B.x;
- C.y = A.y + B.y;
-
- return C;
-
- }
-
-/*****************************************************************************/
-
-inline dng_xy_coord operator- (const dng_xy_coord &A,
- const dng_xy_coord &B)
- {
-
- dng_xy_coord C;
-
- C.x = A.x - B.x;
- C.y = A.y - B.y;
-
- return C;
-
- }
-
-/*****************************************************************************/
-
-inline dng_xy_coord operator* (real64 scale,
- const dng_xy_coord &A)
- {
-
- dng_xy_coord B;
-
- B.x = A.x * scale;
- B.y = A.y * scale;
-
- return B;
-
- }
-
-/******************************************************************************/
-
-inline real64 operator* (const dng_xy_coord &A,
- const dng_xy_coord &B)
- {
-
- return A.x * B.x +
- A.y * B.y;
-
- }
-
-/*****************************************************************************/
-
-// Standard xy coordinate constants.
-
-inline dng_xy_coord StdA_xy_coord ()
- {
- return dng_xy_coord (0.4476, 0.4074);
- }
-
-inline dng_xy_coord D50_xy_coord ()
- {
- return dng_xy_coord (0.3457, 0.3585);
- }
-
-inline dng_xy_coord D55_xy_coord ()
- {
- return dng_xy_coord (0.3324, 0.3474);
- }
-
-inline dng_xy_coord D65_xy_coord ()
- {
- return dng_xy_coord (0.3127, 0.3290);
- }
-
-inline dng_xy_coord D75_xy_coord ()
- {
- return dng_xy_coord (0.2990, 0.3149);
- }
-
-/*****************************************************************************/
-
-// Convert between xy coordinates and XYZ coordinates.
-
-dng_xy_coord XYZtoXY (const dng_vector_3 &coord);
-
-dng_vector_3 XYtoXYZ (const dng_xy_coord &coord);
-
-/*****************************************************************************/
-
-// Returns the ICC XYZ profile connection space white point.
-
-dng_xy_coord PCStoXY ();
-
-dng_vector_3 PCStoXYZ ();
-
-/*****************************************************************************/
-
-#endif
-
-/*****************************************************************************/
+/*****************************************************************************/
+// Copyright 2006 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_xy_coord.h#2 $ */
+/* $DateTime: 2012/07/31 22:04:34 $ */
+/* $Change: 840853 $ */
+/* $Author: tknoll $ */
+
+/** \file
+ * Representation of colors in xy and XYZ coordinates.
+ */
+
+/*****************************************************************************/
+
+#ifndef __dng_xy_coord__
+#define __dng_xy_coord__
+
+/*****************************************************************************/
+
+#include "dng_classes.h"
+#include "dng_types.h"
+
+/*****************************************************************************/
+
+class dng_xy_coord
+ {
+
+ public:
+
+ real64 x;
+ real64 y;
+
+ public:
+
+ dng_xy_coord ()
+ : x (0.0)
+ , y (0.0)
+ {
+ }
+
+ dng_xy_coord (real64 xx, real64 yy)
+ : x (xx)
+ , y (yy)
+ {
+ }
+
+ void Clear ()
+ {
+ x = 0.0;
+ y = 0.0;
+ }
+
+ bool IsValid () const
+ {
+ return x > 0.0 &&
+ y > 0.0;
+ }
+
+ bool NotValid () const
+ {
+ return !IsValid ();
+ }
+
+ bool operator== (const dng_xy_coord &coord) const
+ {
+ return coord.x == x &&
+ coord.y == y;
+ }
+
+ bool operator!= (const dng_xy_coord &coord) const
+ {
+ return !(*this == coord);
+ }
+
+ };
+
+/*****************************************************************************/
+
+inline dng_xy_coord operator+ (const dng_xy_coord &A,
+ const dng_xy_coord &B)
+ {
+
+ dng_xy_coord C;
+
+ C.x = A.x + B.x;
+ C.y = A.y + B.y;
+
+ return C;
+
+ }
+
+/*****************************************************************************/
+
+inline dng_xy_coord operator- (const dng_xy_coord &A,
+ const dng_xy_coord &B)
+ {
+
+ dng_xy_coord C;
+
+ C.x = A.x - B.x;
+ C.y = A.y - B.y;
+
+ return C;
+
+ }
+
+/*****************************************************************************/
+
+inline dng_xy_coord operator* (real64 scale,
+ const dng_xy_coord &A)
+ {
+
+ dng_xy_coord B;
+
+ B.x = A.x * scale;
+ B.y = A.y * scale;
+
+ return B;
+
+ }
+
+/******************************************************************************/
+
+inline real64 operator* (const dng_xy_coord &A,
+ const dng_xy_coord &B)
+ {
+
+ return A.x * B.x +
+ A.y * B.y;
+
+ }
+
+/*****************************************************************************/
+
+// Standard xy coordinate constants.
+
+inline dng_xy_coord StdA_xy_coord ()
+ {
+ return dng_xy_coord (0.4476, 0.4074);
+ }
+
+inline dng_xy_coord D50_xy_coord ()
+ {
+ return dng_xy_coord (0.3457, 0.3585);
+ }
+
+inline dng_xy_coord D55_xy_coord ()
+ {
+ return dng_xy_coord (0.3324, 0.3474);
+ }
+
+inline dng_xy_coord D65_xy_coord ()
+ {
+ return dng_xy_coord (0.3127, 0.3290);
+ }
+
+inline dng_xy_coord D75_xy_coord ()
+ {
+ return dng_xy_coord (0.2990, 0.3149);
+ }
+
+/*****************************************************************************/
+
+// Convert between xy coordinates and XYZ coordinates.
+
+dng_xy_coord XYZtoXY (const dng_vector_3 &coord);
+
+dng_vector_3 XYtoXYZ (const dng_xy_coord &coord);
+
+/*****************************************************************************/
+
+// Returns the ICC XYZ profile connection space white point.
+
+dng_xy_coord PCStoXY ();
+
+dng_vector_3 PCStoXYZ ();
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/