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 
dng_hue_sat_map()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 
dng_hue_sat_map(const dng_hue_sat_map & src)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 
operator =(const dng_hue_sat_map & rhs)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 
~dng_hue_sat_map()93 dng_hue_sat_map::~dng_hue_sat_map ()
94 	{
95 
96 	}
97 
98 /*****************************************************************************/
99 
SetDivisions(uint32 hueDivisions,uint32 satDivisions,uint32 valDivisions)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 
GetDelta(uint32 hueDiv,uint32 satDiv,uint32 valDiv,HSBModify & modify) const135 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 
SetDeltaKnownWriteable(uint32 hueDiv,uint32 satDiv,uint32 valDiv,const HSBModify & modify)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 
operator ==(const dng_hue_sat_map & rhs) const242 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 
Interpolate(const dng_hue_sat_map & map1,const dng_hue_sat_map & map2,real64 weight1)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