1 /*****************************************************************************/ 2 // Copyright 2006 Adobe Systems Incorporated 3 // All Rights Reserved. 4 // 5 // NOTICE: Adobe permits you to use, modify, and distribute this file in 6 // accordance with the terms of the Adobe license agreement accompanying it. 7 /*****************************************************************************/ 8 9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_temperature.cpp#1 $ */ 10 /* $DateTime: 2012/05/30 13:28:51 $ */ 11 /* $Change: 832332 $ */ 12 /* $Author: tknoll $ */ 13 14 #include "dng_temperature.h" 15 16 #include "dng_xy_coord.h" 17 18 /*****************************************************************************/ 19 20 // Scale factor between distances in uv space to a more user friendly "tint" 21 // parameter. 22 23 static const real64 kTintScale = -3000.0; 24 25 /*****************************************************************************/ 26 27 // Table from Wyszecki & Stiles, "Color Science", second edition, page 228. 28 29 struct ruvt 30 { 31 real64 r; 32 real64 u; 33 real64 v; 34 real64 t; 35 }; 36 37 static const ruvt kTempTable [] = 38 { 39 { 0, 0.18006, 0.26352, -0.24341 }, 40 { 10, 0.18066, 0.26589, -0.25479 }, 41 { 20, 0.18133, 0.26846, -0.26876 }, 42 { 30, 0.18208, 0.27119, -0.28539 }, 43 { 40, 0.18293, 0.27407, -0.30470 }, 44 { 50, 0.18388, 0.27709, -0.32675 }, 45 { 60, 0.18494, 0.28021, -0.35156 }, 46 { 70, 0.18611, 0.28342, -0.37915 }, 47 { 80, 0.18740, 0.28668, -0.40955 }, 48 { 90, 0.18880, 0.28997, -0.44278 }, 49 { 100, 0.19032, 0.29326, -0.47888 }, 50 { 125, 0.19462, 0.30141, -0.58204 }, 51 { 150, 0.19962, 0.30921, -0.70471 }, 52 { 175, 0.20525, 0.31647, -0.84901 }, 53 { 200, 0.21142, 0.32312, -1.0182 }, 54 { 225, 0.21807, 0.32909, -1.2168 }, 55 { 250, 0.22511, 0.33439, -1.4512 }, 56 { 275, 0.23247, 0.33904, -1.7298 }, 57 { 300, 0.24010, 0.34308, -2.0637 }, 58 { 325, 0.24702, 0.34655, -2.4681 }, 59 { 350, 0.25591, 0.34951, -2.9641 }, 60 { 375, 0.26400, 0.35200, -3.5814 }, 61 { 400, 0.27218, 0.35407, -4.3633 }, 62 { 425, 0.28039, 0.35577, -5.3762 }, 63 { 450, 0.28863, 0.35714, -6.7262 }, 64 { 475, 0.29685, 0.35823, -8.5955 }, 65 { 500, 0.30505, 0.35907, -11.324 }, 66 { 525, 0.31320, 0.35968, -15.628 }, 67 { 550, 0.32129, 0.36011, -23.325 }, 68 { 575, 0.32931, 0.36038, -40.770 }, 69 { 600, 0.33724, 0.36051, -116.45 } 70 }; 71 72 /*****************************************************************************/ 73 74 void dng_temperature::Set_xy_coord (const dng_xy_coord &xy) 75 { 76 77 // Convert to uv space. 78 79 real64 u = 2.0 * xy.x / (1.5 - xy.x + 6.0 * xy.y); 80 real64 v = 3.0 * xy.y / (1.5 - xy.x + 6.0 * xy.y); 81 82 // Search for line pair coordinate is between. 83 84 real64 last_dt = 0.0; 85 86 real64 last_dv = 0.0; 87 real64 last_du = 0.0; 88 89 for (uint32 index = 1; index <= 30; index++) 90 { 91 92 // Convert slope to delta-u and delta-v, with length 1. 93 94 real64 du = 1.0; 95 real64 dv = kTempTable [index] . t; 96 97 real64 len = sqrt (1.0 + dv * dv); 98 99 du /= len; 100 dv /= len; 101 102 // Find delta from black body point to test coordinate. 103 104 real64 uu = u - kTempTable [index] . u; 105 real64 vv = v - kTempTable [index] . v; 106 107 // Find distance above or below line. 108 109 real64 dt = - uu * dv + vv * du; 110 111 // If below line, we have found line pair. 112 113 if (dt <= 0.0 || index == 30) 114 { 115 116 // Find fractional weight of two lines. 117 118 if (dt > 0.0) 119 dt = 0.0; 120 121 dt = -dt; 122 123 real64 f; 124 125 if (index == 1) 126 { 127 f = 0.0; 128 } 129 else 130 { 131 f = dt / (last_dt + dt); 132 } 133 134 // Interpolate the temperature. 135 136 fTemperature = 1.0E6 / (kTempTable [index - 1] . r * f + 137 kTempTable [index ] . r * (1.0 - f)); 138 139 // Find delta from black body point to test coordinate. 140 141 uu = u - (kTempTable [index - 1] . u * f + 142 kTempTable [index ] . u * (1.0 - f)); 143 144 vv = v - (kTempTable [index - 1] . v * f + 145 kTempTable [index ] . v * (1.0 - f)); 146 147 // Interpolate vectors along slope. 148 149 du = du * (1.0 - f) + last_du * f; 150 dv = dv * (1.0 - f) + last_dv * f; 151 152 len = sqrt (du * du + dv * dv); 153 154 du /= len; 155 dv /= len; 156 157 // Find distance along slope. 158 159 fTint = (uu * du + vv * dv) * kTintScale; 160 161 break; 162 163 } 164 165 // Try next line pair. 166 167 last_dt = dt; 168 169 last_du = du; 170 last_dv = dv; 171 172 } 173 174 } 175 176 /*****************************************************************************/ 177 178 dng_xy_coord dng_temperature::Get_xy_coord () const 179 { 180 181 dng_xy_coord result; 182 183 // Find inverse temperature to use as index. 184 185 real64 r = 1.0E6 / fTemperature; 186 187 // Convert tint to offset is uv space. 188 189 real64 offset = fTint * (1.0 / kTintScale); 190 191 // Search for line pair containing coordinate. 192 193 for (uint32 index = 0; index <= 29; index++) 194 { 195 196 if (r < kTempTable [index + 1] . r || index == 29) 197 { 198 199 // Find relative weight of first line. 200 201 real64 f = (kTempTable [index + 1] . r - r) / 202 (kTempTable [index + 1] . r - kTempTable [index] . r); 203 204 // Interpolate the black body coordinates. 205 206 real64 u = kTempTable [index ] . u * f + 207 kTempTable [index + 1] . u * (1.0 - f); 208 209 real64 v = kTempTable [index ] . v * f + 210 kTempTable [index + 1] . v * (1.0 - f); 211 212 // Find vectors along slope for each line. 213 214 real64 uu1 = 1.0; 215 real64 vv1 = kTempTable [index] . t; 216 217 real64 uu2 = 1.0; 218 real64 vv2 = kTempTable [index + 1] . t; 219 220 real64 len1 = sqrt (1.0 + vv1 * vv1); 221 real64 len2 = sqrt (1.0 + vv2 * vv2); 222 223 uu1 /= len1; 224 vv1 /= len1; 225 226 uu2 /= len2; 227 vv2 /= len2; 228 229 // Find vector from black body point. 230 231 real64 uu3 = uu1 * f + uu2 * (1.0 - f); 232 real64 vv3 = vv1 * f + vv2 * (1.0 - f); 233 234 real64 len3 = sqrt (uu3 * uu3 + vv3 * vv3); 235 236 uu3 /= len3; 237 vv3 /= len3; 238 239 // Adjust coordinate along this vector. 240 241 u += uu3 * offset; 242 v += vv3 * offset; 243 244 // Convert to xy coordinates. 245 246 result.x = 1.5 * u / (u - 4.0 * v + 2.0); 247 result.y = v / (u - 4.0 * v + 2.0); 248 249 break; 250 251 } 252 253 } 254 255 return result; 256 257 } 258 259 /*****************************************************************************/ 260