summaryrefslogtreecommitdiff
path: root/gpr/source/lib/dng_sdk/dng_camera_profile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gpr/source/lib/dng_sdk/dng_camera_profile.cpp')
-rw-r--r--gpr/source/lib/dng_sdk/dng_camera_profile.cpp1381
1 files changed, 1381 insertions, 0 deletions
diff --git a/gpr/source/lib/dng_sdk/dng_camera_profile.cpp b/gpr/source/lib/dng_sdk/dng_camera_profile.cpp
new file mode 100644
index 0000000..6983b6d
--- /dev/null
+++ b/gpr/source/lib/dng_sdk/dng_camera_profile.cpp
@@ -0,0 +1,1381 @@
+/*****************************************************************************/
+// 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);
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+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;
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/