Home | History | Annotate | Download | only in source
      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