1 /*****************************************************************************/ 2 // Copyright 2007 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_hue_sat_map.cpp#1 $ */ 10 /* $DateTime: 2012/05/30 13:28:51 $ */ 11 /* $Change: 832332 $ */ 12 /* $Author: tknoll $ */ 13 14 /*****************************************************************************/ 15 16 #include "dng_hue_sat_map.h" 17 18 #include "dng_assertions.h" 19 #include "dng_auto_ptr.h" 20 #include "dng_bottlenecks.h" 21 #include "dng_exceptions.h" 22 #include "dng_host.h" 23 24 /*****************************************************************************/ 25 26 dng_hue_sat_map::dng_hue_sat_map () 27 28 : fHueDivisions (0) 29 , fSatDivisions (0) 30 , fValDivisions (0) 31 , fHueStep (0) 32 , fValStep (0) 33 , fDeltas () 34 35 { 36 37 } 38 39 /*****************************************************************************/ 40 41 dng_hue_sat_map::dng_hue_sat_map (const dng_hue_sat_map &src) 42 43 : fHueDivisions (0) 44 , fSatDivisions (0) 45 , fValDivisions (0) 46 , fHueStep (0) 47 , fValStep (0) 48 , fDeltas () 49 50 { 51 52 *this = src; 53 54 } 55 56 /*****************************************************************************/ 57 58 dng_hue_sat_map &dng_hue_sat_map::operator= (const dng_hue_sat_map &rhs) 59 { 60 61 if (this != &rhs) 62 { 63 64 if (!rhs.IsValid ()) 65 { 66 67 SetInvalid (); 68 69 } 70 71 else 72 { 73 74 fHueDivisions = rhs.fHueDivisions; 75 fSatDivisions = rhs.fSatDivisions; 76 fValDivisions = rhs.fValDivisions; 77 78 fHueStep = rhs.fHueStep; 79 fValStep = rhs.fValStep; 80 81 fDeltas = rhs.fDeltas; 82 83 } 84 85 } 86 87 return *this; 88 89 } 90 91 /*****************************************************************************/ 92 93 dng_hue_sat_map::~dng_hue_sat_map () 94 { 95 96 } 97 98 /*****************************************************************************/ 99 100 void dng_hue_sat_map::SetDivisions (uint32 hueDivisions, 101 uint32 satDivisions, 102 uint32 valDivisions) 103 { 104 105 DNG_ASSERT (hueDivisions >= 1, "Must have at least 1 hue division."); 106 DNG_ASSERT (satDivisions >= 2, "Must have at least 2 sat divisions."); 107 108 if (valDivisions == 0) 109 valDivisions = 1; 110 111 if (hueDivisions == fHueDivisions && 112 satDivisions == fSatDivisions && 113 valDivisions == fValDivisions) 114 { 115 return; 116 } 117 118 fHueDivisions = hueDivisions; 119 fSatDivisions = satDivisions; 120 fValDivisions = valDivisions; 121 122 fHueStep = satDivisions; 123 fValStep = SafeUint32Mult(hueDivisions, fHueStep); 124 125 uint32 size = SafeUint32Mult(DeltasCount (), (uint32) sizeof (HSBModify)); 126 127 fDeltas.Allocate (size); 128 129 DoZeroBytes (fDeltas.Buffer (), size); 130 131 } 132 133 /*****************************************************************************/ 134 135 void dng_hue_sat_map::GetDelta (uint32 hueDiv, 136 uint32 satDiv, 137 uint32 valDiv, 138 HSBModify &modify) const 139 { 140 141 if (hueDiv >= fHueDivisions || 142 satDiv >= fSatDivisions || 143 valDiv >= fValDivisions || 144 fDeltas.Buffer () == NULL) 145 { 146 147 DNG_REPORT ("Bad parameters to dng_hue_sat_map::GetDelta"); 148 149 ThrowProgramError (); 150 151 } 152 153 int32 offset = valDiv * fValStep + 154 hueDiv * fHueStep + 155 satDiv; 156 157 const HSBModify *deltas = GetConstDeltas (); 158 159 modify.fHueShift = deltas [offset].fHueShift; 160 modify.fSatScale = deltas [offset].fSatScale; 161 modify.fValScale = deltas [offset].fValScale; 162 163 } 164 165 /*****************************************************************************/ 166 167 void dng_hue_sat_map::SetDeltaKnownWriteable (uint32 hueDiv, 168 uint32 satDiv, 169 uint32 valDiv, 170 const HSBModify &modify) 171 { 172 173 if (hueDiv >= fHueDivisions || 174 satDiv >= fSatDivisions || 175 valDiv >= fValDivisions || 176 fDeltas.Buffer () == NULL) 177 { 178 179 DNG_REPORT ("Bad parameters to dng_hue_sat_map::SetDelta"); 180 181 ThrowProgramError (); 182 183 } 184 185 // Set this entry. 186 187 int32 offset = valDiv * fValStep + 188 hueDiv * fHueStep + 189 satDiv; 190 191 SafeGetDeltas () [offset] = modify; 192 193 // The zero saturation entry is required to have a value scale 194 // of 1.0f. 195 196 if (satDiv == 0) 197 { 198 199 if (modify.fValScale != 1.0f) 200 { 201 202 #if qDNGValidate 203 204 ReportWarning ("Value scale for zero saturation entries must be 1.0"); 205 206 #endif 207 208 SafeGetDeltas () [offset] . fValScale = 1.0f; 209 210 } 211 212 } 213 214 // If we are settings the first saturation entry and we have not 215 // set the zero saturation entry yet, fill in the zero saturation entry 216 // by extrapolating first saturation entry. 217 218 if (satDiv == 1) 219 { 220 221 HSBModify zeroSatModify; 222 223 GetDelta (hueDiv, 0, valDiv, zeroSatModify); 224 225 if (zeroSatModify.fValScale != 1.0f) 226 { 227 228 zeroSatModify.fHueShift = modify.fHueShift; 229 zeroSatModify.fSatScale = modify.fSatScale; 230 zeroSatModify.fValScale = 1.0f; 231 232 SetDelta (hueDiv, 0, valDiv, zeroSatModify); 233 234 } 235 236 } 237 238 } 239 240 /*****************************************************************************/ 241 242 bool dng_hue_sat_map::operator== (const dng_hue_sat_map &rhs) const 243 { 244 245 if (fHueDivisions != rhs.fHueDivisions || 246 fSatDivisions != rhs.fSatDivisions || 247 fValDivisions != rhs.fValDivisions) 248 return false; 249 250 if (!IsValid ()) 251 return true; 252 253 return memcmp (GetConstDeltas (), 254 rhs.GetConstDeltas (), 255 DeltasCount () * sizeof (HSBModify)) == 0; 256 257 } 258 259 /*****************************************************************************/ 260 261 dng_hue_sat_map * dng_hue_sat_map::Interpolate (const dng_hue_sat_map &map1, 262 const dng_hue_sat_map &map2, 263 real64 weight1) 264 { 265 266 if (weight1 >= 1.0) 267 { 268 269 if (!map1.IsValid ()) 270 { 271 272 DNG_REPORT ("map1 is not valid"); 273 274 ThrowProgramError (); 275 276 } 277 278 return new dng_hue_sat_map (map1); 279 280 } 281 282 if (weight1 <= 0.0) 283 { 284 285 if (!map2.IsValid ()) 286 { 287 DNG_REPORT ("map2 is not valid"); 288 289 ThrowProgramError (); 290 291 } 292 293 return new dng_hue_sat_map (map2); 294 295 } 296 297 // Both maps must be valid if we are using both. 298 299 if (!map1.IsValid () || !map2.IsValid ()) 300 { 301 302 DNG_REPORT ("map1 or map2 is not valid"); 303 304 ThrowProgramError (); 305 306 } 307 308 // Must have the same dimensions. 309 310 if (map1.fHueDivisions != map2.fHueDivisions || 311 map1.fSatDivisions != map2.fSatDivisions || 312 map1.fValDivisions != map2.fValDivisions) 313 { 314 315 DNG_REPORT ("map1 and map2 have different sizes"); 316 317 ThrowProgramError (); 318 319 } 320 321 // Make table to hold interpolated results. 322 323 AutoPtr<dng_hue_sat_map> result (new dng_hue_sat_map); 324 325 result->SetDivisions (map1.fHueDivisions, 326 map1.fSatDivisions, 327 map1.fValDivisions); 328 329 // Interpolate between the tables. 330 331 real32 w1 = (real32) weight1; 332 real32 w2 = 1.0f - w1; 333 334 const HSBModify *data1 = map1.GetConstDeltas (); 335 const HSBModify *data2 = map2.GetConstDeltas (); 336 337 HSBModify *data3 = result->SafeGetDeltas (); 338 339 uint32 count = map1.DeltasCount (); 340 341 for (uint32 index = 0; index < count; index++) 342 { 343 344 data3->fHueShift = w1 * data1->fHueShift + 345 w2 * data2->fHueShift; 346 347 data3->fSatScale = w1 * data1->fSatScale + 348 w2 * data2->fSatScale; 349 350 data3->fValScale = w1 * data1->fValScale + 351 w2 * data2->fValScale; 352 353 data1++; 354 data2++; 355 data3++; 356 357 } 358 359 // Return interpolated tables. 360 361 return result.Release (); 362 363 } 364 365 /*****************************************************************************/ 366