dng_hue_sat_map.cpp revision 29c7498fabe2e3c87a85b487bfe9d783c401e1f0
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 26dng_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 41dng_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 58dng_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 93dng_hue_sat_map::~dng_hue_sat_map () 94 { 95 96 } 97 98/*****************************************************************************/ 99 100#if defined(__clang__) && defined(__has_attribute) 101#if __has_attribute(no_sanitize) 102__attribute__((no_sanitize("unsigned-integer-overflow"))) 103#endif 104#endif 105void dng_hue_sat_map::SetDivisions (uint32 hueDivisions, 106 uint32 satDivisions, 107 uint32 valDivisions) 108 { 109 110 DNG_ASSERT (hueDivisions >= 1, "Must have at least 1 hue division."); 111 DNG_ASSERT (satDivisions >= 2, "Must have at least 2 sat divisions."); 112 113 if (valDivisions == 0) 114 valDivisions = 1; 115 116 if (hueDivisions == fHueDivisions && 117 satDivisions == fSatDivisions && 118 valDivisions == fValDivisions) 119 { 120 return; 121 } 122 123 fHueDivisions = hueDivisions; 124 fSatDivisions = satDivisions; 125 fValDivisions = valDivisions; 126 127 fHueStep = satDivisions; 128 fValStep = hueDivisions * fHueStep; 129 130 uint32 size = DeltasCount () * (uint32) sizeof (HSBModify); 131 132 fDeltas.Allocate (size); 133 134 DoZeroBytes (fDeltas.Buffer (), size); 135 136 } 137 138/*****************************************************************************/ 139 140void dng_hue_sat_map::GetDelta (uint32 hueDiv, 141 uint32 satDiv, 142 uint32 valDiv, 143 HSBModify &modify) const 144 { 145 146 if (hueDiv >= fHueDivisions || 147 satDiv >= fSatDivisions || 148 valDiv >= fValDivisions || 149 fDeltas.Buffer () == NULL) 150 { 151 152 DNG_REPORT ("Bad parameters to dng_hue_sat_map::GetDelta"); 153 154 ThrowProgramError (); 155 156 } 157 158 int32 offset = valDiv * fValStep + 159 hueDiv * fHueStep + 160 satDiv; 161 162 const HSBModify *deltas = GetConstDeltas (); 163 164 modify.fHueShift = deltas [offset].fHueShift; 165 modify.fSatScale = deltas [offset].fSatScale; 166 modify.fValScale = deltas [offset].fValScale; 167 168 } 169 170/*****************************************************************************/ 171 172void dng_hue_sat_map::SetDeltaKnownWriteable (uint32 hueDiv, 173 uint32 satDiv, 174 uint32 valDiv, 175 const HSBModify &modify) 176 { 177 178 if (hueDiv >= fHueDivisions || 179 satDiv >= fSatDivisions || 180 valDiv >= fValDivisions || 181 fDeltas.Buffer () == NULL) 182 { 183 184 DNG_REPORT ("Bad parameters to dng_hue_sat_map::SetDelta"); 185 186 ThrowProgramError (); 187 188 } 189 190 // Set this entry. 191 192 int32 offset = valDiv * fValStep + 193 hueDiv * fHueStep + 194 satDiv; 195 196 SafeGetDeltas () [offset] = modify; 197 198 // The zero saturation entry is required to have a value scale 199 // of 1.0f. 200 201 if (satDiv == 0) 202 { 203 204 if (modify.fValScale != 1.0f) 205 { 206 207 #if qDNGValidate 208 209 ReportWarning ("Value scale for zero saturation entries must be 1.0"); 210 211 #endif 212 213 SafeGetDeltas () [offset] . fValScale = 1.0f; 214 215 } 216 217 } 218 219 // If we are settings the first saturation entry and we have not 220 // set the zero saturation entry yet, fill in the zero saturation entry 221 // by extrapolating first saturation entry. 222 223 if (satDiv == 1) 224 { 225 226 HSBModify zeroSatModify; 227 228 GetDelta (hueDiv, 0, valDiv, zeroSatModify); 229 230 if (zeroSatModify.fValScale != 1.0f) 231 { 232 233 zeroSatModify.fHueShift = modify.fHueShift; 234 zeroSatModify.fSatScale = modify.fSatScale; 235 zeroSatModify.fValScale = 1.0f; 236 237 SetDelta (hueDiv, 0, valDiv, zeroSatModify); 238 239 } 240 241 } 242 243 } 244 245/*****************************************************************************/ 246 247bool dng_hue_sat_map::operator== (const dng_hue_sat_map &rhs) const 248 { 249 250 if (fHueDivisions != rhs.fHueDivisions || 251 fSatDivisions != rhs.fSatDivisions || 252 fValDivisions != rhs.fValDivisions) 253 return false; 254 255 if (!IsValid ()) 256 return true; 257 258 return memcmp (GetConstDeltas (), 259 rhs.GetConstDeltas (), 260 DeltasCount () * sizeof (HSBModify)) == 0; 261 262 } 263 264/*****************************************************************************/ 265 266dng_hue_sat_map * dng_hue_sat_map::Interpolate (const dng_hue_sat_map &map1, 267 const dng_hue_sat_map &map2, 268 real64 weight1) 269 { 270 271 if (weight1 >= 1.0) 272 { 273 274 if (!map1.IsValid ()) 275 { 276 277 DNG_REPORT ("map1 is not valid"); 278 279 ThrowProgramError (); 280 281 } 282 283 return new dng_hue_sat_map (map1); 284 285 } 286 287 if (weight1 <= 0.0) 288 { 289 290 if (!map2.IsValid ()) 291 { 292 DNG_REPORT ("map2 is not valid"); 293 294 ThrowProgramError (); 295 296 } 297 298 return new dng_hue_sat_map (map2); 299 300 } 301 302 // Both maps must be valid if we are using both. 303 304 if (!map1.IsValid () || !map2.IsValid ()) 305 { 306 307 DNG_REPORT ("map1 or map2 is not valid"); 308 309 ThrowProgramError (); 310 311 } 312 313 // Must have the same dimensions. 314 315 if (map1.fHueDivisions != map2.fHueDivisions || 316 map1.fSatDivisions != map2.fSatDivisions || 317 map1.fValDivisions != map2.fValDivisions) 318 { 319 320 DNG_REPORT ("map1 and map2 have different sizes"); 321 322 ThrowProgramError (); 323 324 } 325 326 // Make table to hold interpolated results. 327 328 AutoPtr<dng_hue_sat_map> result (new dng_hue_sat_map); 329 330 result->SetDivisions (map1.fHueDivisions, 331 map1.fSatDivisions, 332 map1.fValDivisions); 333 334 // Interpolate between the tables. 335 336 real32 w1 = (real32) weight1; 337 real32 w2 = 1.0f - w1; 338 339 const HSBModify *data1 = map1.GetConstDeltas (); 340 const HSBModify *data2 = map2.GetConstDeltas (); 341 342 HSBModify *data3 = result->SafeGetDeltas (); 343 344 uint32 count = map1.DeltasCount (); 345 346 for (uint32 index = 0; index < count; index++) 347 { 348 349 data3->fHueShift = w1 * data1->fHueShift + 350 w2 * data2->fHueShift; 351 352 data3->fSatScale = w1 * data1->fSatScale + 353 w2 * data2->fSatScale; 354 355 data3->fValScale = w1 * data1->fValScale + 356 w2 * data2->fValScale; 357 358 data1++; 359 data2++; 360 data3++; 361 362 } 363 364 // Return interpolated tables. 365 366 return result.Release (); 367 368 } 369 370/*****************************************************************************/ 371