18e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 28e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener// Copyright 2006-2008 Adobe Systems Incorporated 38e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener// All Rights Reserved. 48e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener// 58e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener// NOTICE: Adobe permits you to use, modify, and distribute this file in 68e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener// accordance with the terms of the Adobe license agreement accompanying it. 78e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 88e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 98e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_color_spec.cpp#1 $ */ 108e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/* $DateTime: 2012/05/30 13:28:51 $ */ 118e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/* $Change: 832332 $ */ 128e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/* $Author: tknoll $ */ 138e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 148e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener#include "dng_color_spec.h" 158e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 168e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener#include "dng_assertions.h" 178e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener#include "dng_camera_profile.h" 188e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener#include "dng_exceptions.h" 198e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener#include "dng_matrix.h" 208e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener#include "dng_negative.h" 218e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener#include "dng_temperature.h" 228e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener#include "dng_utils.h" 238e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener#include "dng_xy_coord.h" 248e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 258e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 268e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 278e8939fc10ad63576a2785ba1333a23726b7e164Florian Krienerdng_matrix_3by3 MapWhiteMatrix (const dng_xy_coord &white1, 288e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener const dng_xy_coord &white2) 298e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 308e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 318e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Use the linearized Bradford adaptation matrix. 328e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 338e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix_3by3 Mb ( 0.8951, 0.2664, -0.1614, 348e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener -0.7502, 1.7135, 0.0367, 358e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 0.0389, -0.0685, 1.0296); 368e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 378e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_vector_3 w1 = Mb * XYtoXYZ (white1); 388e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_vector_3 w2 = Mb * XYtoXYZ (white2); 398e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 408e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Negative white coordinates are kind of meaningless. 418e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 428e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener w1 [0] = Max_real64 (w1 [0], 0.0); 438e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener w1 [1] = Max_real64 (w1 [1], 0.0); 448e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener w1 [2] = Max_real64 (w1 [2], 0.0); 458e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 468e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener w2 [0] = Max_real64 (w2 [0], 0.0); 478e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener w2 [1] = Max_real64 (w2 [1], 0.0); 488e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener w2 [2] = Max_real64 (w2 [2], 0.0); 498e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 508e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Limit scaling to something reasonable. 518e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 528e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix_3by3 A; 538e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 548e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener A [0] [0] = Pin_real64 (0.1, w1 [0] > 0.0 ? w2 [0] / w1 [0] : 10.0, 10.0); 558e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener A [1] [1] = Pin_real64 (0.1, w1 [1] > 0.0 ? w2 [1] / w1 [1] : 10.0, 10.0); 568e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener A [2] [2] = Pin_real64 (0.1, w1 [2] > 0.0 ? w2 [2] / w1 [2] : 10.0, 10.0); 578e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 588e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix_3by3 B = Invert (Mb) * A * Mb; 598e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 608e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return B; 618e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 628e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 638e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 648e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/******************************************************************************/ 658e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 668e8939fc10ad63576a2785ba1333a23726b7e164Florian Krienerdng_color_spec::dng_color_spec (const dng_negative &negative, 678e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener const dng_camera_profile *profile) 688e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 698e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener : fChannels (negative.ColorChannels ()) 708e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 718e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fTemperature1 (0.0) 728e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fTemperature2 (0.0) 738e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 748e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fColorMatrix1 () 758e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fColorMatrix2 () 768e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 778e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fForwardMatrix1 () 788e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fForwardMatrix2 () 798e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 808e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fReductionMatrix1 () 818e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fReductionMatrix2 () 828e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 838e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fCameraCalibration1 () 848e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fCameraCalibration2 () 858e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 868e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fAnalogBalance () 878e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 888e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fWhiteXY () 898e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 908e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fCameraWhite () 918e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fCameraToPCS () 928e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 938e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener , fPCStoCamera () 948e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 958e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 968e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 978e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (fChannels > 1) 988e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 998e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1008e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (!profile || !profile->IsValid (fChannels)) 1018e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 1028e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener ThrowBadFormat (); 1038e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 1048e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1058e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (profile->WasStubbed ()) 1068e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 1078e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener ThrowProgramError ("Using stubbed profile"); 1088e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 1098e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1108e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fTemperature1 = profile->CalibrationTemperature1 (); 1118e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fTemperature2 = profile->CalibrationTemperature2 (); 1128e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1138e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fColorMatrix1 = profile->ColorMatrix1 (); 1148e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fColorMatrix2 = profile->ColorMatrix2 (); 1158e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1168e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fForwardMatrix1 = profile->ForwardMatrix1 (); 1178e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fForwardMatrix2 = profile->ForwardMatrix2 (); 1188e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1198e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fReductionMatrix1 = profile->ReductionMatrix1 (); 1208e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fReductionMatrix2 = profile->ReductionMatrix2 (); 1218e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1228e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraCalibration1.SetIdentity (fChannels); 1238e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraCalibration2.SetIdentity (fChannels); 1248e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1258e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (negative. CameraCalibrationSignature () == 1268e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener profile->ProfileCalibrationSignature ()) 1278e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 1288e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1298e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (negative.CameraCalibration1 ().Rows () == fChannels && 1308e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener negative.CameraCalibration1 ().Cols () == fChannels) 1318e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 1328e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1338e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraCalibration1 = negative.CameraCalibration1 (); 1348e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1358e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 1368e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1378e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (negative.CameraCalibration2 ().Rows () == fChannels && 1388e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener negative.CameraCalibration2 ().Cols () == fChannels) 1398e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 1408e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1418e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraCalibration2 = negative.CameraCalibration2 (); 1428e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1438e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 1448e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1458e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 1468e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1478e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fAnalogBalance = dng_matrix (fChannels, fChannels); 1488e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1498e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener for (uint32 j = 0; j < fChannels; j++) 1508e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 1518e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1528e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fAnalogBalance [j] [j] = negative.AnalogBalance (j); 1538e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1548e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 1558e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1568e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_camera_profile::NormalizeForwardMatrix (fForwardMatrix1); 1578e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1588e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fColorMatrix1 = fAnalogBalance * fCameraCalibration1 * fColorMatrix1; 1598e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1608e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (!profile->HasColorMatrix2 () || 1618e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fTemperature1 <= 0.0 || 1628e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fTemperature2 <= 0.0 || 1638e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fTemperature1 == fTemperature2) 1648e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 1658e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1668e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fTemperature1 = 5000.0; 1678e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fTemperature2 = 5000.0; 1688e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1698e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fColorMatrix2 = fColorMatrix1; 1708e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fForwardMatrix2 = fForwardMatrix1; 1718e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fReductionMatrix2 = fReductionMatrix1; 1728e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraCalibration2 = fCameraCalibration1; 1738e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1748e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 1758e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1768e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else 1778e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 1788e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1798e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_camera_profile::NormalizeForwardMatrix (fForwardMatrix2); 1808e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1818e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fColorMatrix2 = fAnalogBalance * fCameraCalibration2 * fColorMatrix2; 1828e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1838e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Swap values if temperatures are out of order. 1848e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1858e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (fTemperature1 > fTemperature2) 1868e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 1878e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1888e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener real64 temp = fTemperature1; 1898e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fTemperature1 = fTemperature2; 1908e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fTemperature2 = temp; 1918e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1928e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix T = fColorMatrix1; 1938e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fColorMatrix1 = fColorMatrix2; 1948e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fColorMatrix2 = T; 1958e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1968e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener T = fForwardMatrix1; 1978e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fForwardMatrix1 = fForwardMatrix2; 1988e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fForwardMatrix2 = T; 1998e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2008e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener T = fReductionMatrix1; 2018e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fReductionMatrix1 = fReductionMatrix2; 2028e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fReductionMatrix2 = T; 2038e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2048e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener T = fCameraCalibration1; 2058e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraCalibration1 = fCameraCalibration2; 2068e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraCalibration2 = T; 2078e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2088e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 2098e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2108e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 2118e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2128e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 2138e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2148e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 2158e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2168e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 2178e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2188e8939fc10ad63576a2785ba1333a23726b7e164Florian Krienerdng_matrix dng_color_spec::FindXYZtoCamera (const dng_xy_coord &white, 2198e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix *forwardMatrix, 2208e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix *reductionMatrix, 2218e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix *cameraCalibration) 2228e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 2238e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2248e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Convert to temperature/offset space. 2258e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2268e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_temperature td (white); 2278e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2288e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Find fraction to weight the first calibration. 2298e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2308e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener real64 g; 2318e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2328e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (td.Temperature () <= fTemperature1) 2338e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener g = 1.0; 2348e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2358e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else if (td.Temperature () >= fTemperature2) 2368e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener g = 0.0; 2378e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2388e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else 2398e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 2408e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2418e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener real64 invT = 1.0 / td.Temperature (); 2428e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2438e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener g = (invT - (1.0 / fTemperature2)) / 2448e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener ((1.0 / fTemperature1) - (1.0 / fTemperature2)); 2458e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2468e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 2478e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2488e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Interpolate the color matrix. 2498e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2508e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix colorMatrix; 2518e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2528e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (g >= 1.0) 2538e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener colorMatrix = fColorMatrix1; 2548e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2558e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else if (g <= 0.0) 2568e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener colorMatrix = fColorMatrix2; 2578e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2588e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else 2598e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener colorMatrix = (g ) * fColorMatrix1 + 2608e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener (1.0 - g) * fColorMatrix2; 2618e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2628e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Interpolate forward matrix, if any. 2638e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2648e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (forwardMatrix) 2658e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 2668e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2678e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener bool has1 = fForwardMatrix1.NotEmpty (); 2688e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener bool has2 = fForwardMatrix2.NotEmpty (); 2698e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2708e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (has1 && has2) 2718e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 2728e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2738e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (g >= 1.0) 2748e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *forwardMatrix = fForwardMatrix1; 2758e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2768e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else if (g <= 0.0) 2778e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *forwardMatrix = fForwardMatrix2; 2788e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2798e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else 2808e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *forwardMatrix = (g ) * fForwardMatrix1 + 2818e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener (1.0 - g) * fForwardMatrix2; 2828e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2838e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 2848e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2858e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else if (has1) 2868e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 2878e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2888e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *forwardMatrix = fForwardMatrix1; 2898e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2908e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 2918e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2928e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else if (has2) 2938e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 2948e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2958e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *forwardMatrix = fForwardMatrix2; 2968e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2978e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 2988e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 2998e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else 3008e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 3018e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3028e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener forwardMatrix->Clear (); 3038e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3048e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3058e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3068e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3078e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3088e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Interpolate reduction matrix, if any. 3098e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3108e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (reductionMatrix) 3118e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 3128e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3138e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener bool has1 = fReductionMatrix1.NotEmpty (); 3148e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener bool has2 = fReductionMatrix2.NotEmpty (); 3158e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3168e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (has1 && has2) 3178e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 3188e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3198e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (g >= 1.0) 3208e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *reductionMatrix = fReductionMatrix1; 3218e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3228e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else if (g <= 0.0) 3238e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *reductionMatrix = fReductionMatrix2; 3248e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3258e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else 3268e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *reductionMatrix = (g ) * fReductionMatrix1 + 3278e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener (1.0 - g) * fReductionMatrix2; 3288e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3298e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3308e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3318e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else if (has1) 3328e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 3338e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3348e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *reductionMatrix = fReductionMatrix1; 3358e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3368e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3378e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3388e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else if (has2) 3398e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 3408e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3418e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *reductionMatrix = fReductionMatrix2; 3428e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3438e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3448e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3458e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else 3468e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 3478e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3488e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener reductionMatrix->Clear (); 3498e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3508e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3518e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3528e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3538e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3548e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Interpolate camera calibration matrix. 3558e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3568e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (cameraCalibration) 3578e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 3588e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3598e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (g >= 1.0) 3608e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *cameraCalibration = fCameraCalibration1; 3618e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3628e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else if (g <= 0.0) 3638e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *cameraCalibration = fCameraCalibration2; 3648e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3658e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else 3668e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener *cameraCalibration = (g ) * fCameraCalibration1 + 3678e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener (1.0 - g) * fCameraCalibration2; 3688e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3698e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3708e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3718e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Return the interpolated color matrix. 3728e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3738e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return colorMatrix; 3748e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3758e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3768e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3778e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 3788e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3798e8939fc10ad63576a2785ba1333a23726b7e164Florian Krienervoid dng_color_spec::SetWhiteXY (const dng_xy_coord &white) 3808e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 3818e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3828e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fWhiteXY = white; 3838e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3848e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Deal with monochrome cameras. 3858e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3868e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (fChannels == 1) 3878e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 3888e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3898e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraWhite.SetIdentity (1); 3908e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3918e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraToPCS = PCStoXYZ ().AsColumn (); 3928e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3938e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return; 3948e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3958e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 3968e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3978e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Interpolate an matric values for this white point. 3988e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 3998e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix colorMatrix; 4008e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix forwardMatrix; 4018e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix reductionMatrix; 4028e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix cameraCalibration; 4038e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4048e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener colorMatrix = FindXYZtoCamera (fWhiteXY, 4058e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener &forwardMatrix, 4068e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener &reductionMatrix, 4078e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener &cameraCalibration); 4088e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4098e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Find the camera white values. 4108e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4118e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraWhite = colorMatrix * XYtoXYZ (fWhiteXY); 4127841298310de58d0cddb212ac6295d9a27cf547cFlorian Kriener 4138e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener real64 cameraWhiteMaxEntry = MaxEntry (fCameraWhite); 4148e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (cameraWhiteMaxEntry == 0) 4158e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 4168e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener ThrowBadFormat (); 4178e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 4188e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener real64 whiteScale = 1.0 / cameraWhiteMaxEntry; 4198e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4208e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener for (uint32 j = 0; j < fChannels; j++) 4218e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 4228e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4238e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // We don't support non-positive values for camera neutral values. 4248e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4258e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraWhite [j] = Pin_real64 (0.001, 4268e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener whiteScale * fCameraWhite [j], 4278e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 1.0); 4288e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4298e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 4308e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4318e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Find PCS to Camera transform. Scale matrix so PCS white can just be 4328e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // reached when the first camera channel saturates 4338e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4348e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fPCStoCamera = colorMatrix * MapWhiteMatrix (PCStoXY (), fWhiteXY); 4358e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4368e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener real64 scale = MaxEntry (fPCStoCamera * PCStoXYZ ()); 4377841298310de58d0cddb212ac6295d9a27cf547cFlorian Kriener 4388e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (scale == 0) 4398e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 4408e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener ThrowBadFormat (); 4418e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 4428e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fPCStoCamera = (1.0 / scale) * fPCStoCamera; 4438e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4448e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // If we have a forward matrix, then just use that. 4458e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4468e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (forwardMatrix.NotEmpty ()) 4478e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 4488e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4498e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix individualToReference = Invert (fAnalogBalance * cameraCalibration); 4508e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4518e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_vector refCameraWhite = individualToReference * fCameraWhite; 4528e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4538e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraToPCS = forwardMatrix * 4548e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener Invert (refCameraWhite.AsDiagonal ()) * 4558e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener individualToReference; 4568e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4578e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 4588e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4598e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Else we need to use the adapt in XYZ method. 4608e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4618e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener else 4628e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 4638e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4648e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // Invert this PCS to camera matrix. Note that if there are more than three 4658e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // camera channels, this inversion is non-unique. 4668e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4678e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener fCameraToPCS = Invert (fPCStoCamera, reductionMatrix); 4688e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4698e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 4708e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4718e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 4728e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4738e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 4748e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4758e8939fc10ad63576a2785ba1333a23726b7e164Florian Krienerconst dng_xy_coord & dng_color_spec::WhiteXY () const 4768e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 4778e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4788e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener DNG_ASSERT (fWhiteXY.IsValid (), "Using invalid WhiteXY"); 4798e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4808e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return fWhiteXY; 4818e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4828e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 4838e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4848e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 4858e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4868e8939fc10ad63576a2785ba1333a23726b7e164Florian Krienerconst dng_vector & dng_color_spec::CameraWhite () const 4878e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 4888e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4898e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener DNG_ASSERT (fCameraWhite.NotEmpty (), "Using invalid CameraWhite"); 4908e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4918e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return fCameraWhite; 4928e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4938e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 4948e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4958e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 4968e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 4978e8939fc10ad63576a2785ba1333a23726b7e164Florian Krienerconst dng_matrix & dng_color_spec::CameraToPCS () const 4988e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 4998e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5008e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener DNG_ASSERT (fCameraToPCS.NotEmpty (), "Using invalid CameraToPCS"); 5018e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5028e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return fCameraToPCS; 5038e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5048e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 5058e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5068e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 5078e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5088e8939fc10ad63576a2785ba1333a23726b7e164Florian Krienerconst dng_matrix & dng_color_spec::PCStoCamera () const 5098e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 5108e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5118e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener DNG_ASSERT (fPCStoCamera.NotEmpty (), "Using invalid PCStoCamera"); 5128e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5138e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return fPCStoCamera; 5148e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5158e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 5168e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5178e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 5188e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5198e8939fc10ad63576a2785ba1333a23726b7e164Florian Krienerdng_xy_coord dng_color_spec::NeutralToXY (const dng_vector &neutral) 5208e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 5218e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5228e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener const uint32 kMaxPasses = 30; 5238e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5248e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (fChannels == 1) 5258e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 5268e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5278e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return PCStoXY (); 5288e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5298e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 5308e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5318e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_xy_coord last = D50_xy_coord (); 5328e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5338e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener for (uint32 pass = 0; pass < kMaxPasses; pass++) 5348e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 5358e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5368e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_matrix xyzToCamera = FindXYZtoCamera (last); 5378e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5388e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener dng_xy_coord next = XYZtoXY (Invert (xyzToCamera) * neutral); 5398e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5408e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (Abs_real64 (next.x - last.x) + 5418e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener Abs_real64 (next.y - last.y) < 0.0000001) 5428e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 5438e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5448e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return next; 5458e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5468e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 5478e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5488e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // If we reach the limit without converging, we are most likely 5498e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // in a two value oscillation. So take the average of the last 5508e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener // two estimates and give up. 5518e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5528e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener if (pass == kMaxPasses - 1) 5538e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener { 5548e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5558e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener next.x = (last.x + next.x) * 0.5; 5568e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener next.y = (last.y + next.y) * 0.5; 5578e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5588e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 5598e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5608e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener last = next; 5618e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5628e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 5638e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5648e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener return last; 5658e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5668e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener } 5678e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener 5688e8939fc10ad63576a2785ba1333a23726b7e164Florian Kriener/*****************************************************************************/ 569