1 /*****************************************************************************/
2 // Copyright 2015-2019 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 #ifndef __dng_big_table__
10 #define __dng_big_table__
11 
12 /*****************************************************************************/
13 
14 #include "dng_classes.h"
15 #include "dng_camera_profile.h"
16 
17 /*****************************************************************************/
18 
19 class dng_big_table_cache;
20 class dng_big_table_storage;
21 
22 /*****************************************************************************/
23 
24 void dng_big_table_cache_flush ();
25 
26 /*****************************************************************************/
27 
28 class dng_big_table
29     {
30 
31     protected:
32 
33         enum BigTableTypeEnum
34             {
35             btt_LookTable = 0,
36             btt_RGBTable  = 1
37             };
38 
39     private:
40 
41         dng_fingerprint fFingerprint;
42 
43         dng_big_table_cache * fCache;
44 
45         bool fIsMissing;
46 
47     protected:
48 
49         dng_big_table (dng_big_table_cache *cache);
50 
51         dng_big_table (const dng_big_table &table);
52 
53         dng_big_table & operator= (const dng_big_table &table);
54 
55     public:
56 
57         virtual ~dng_big_table ();
58 
IsMissing()59         bool IsMissing () const
60             {
61             return fIsMissing;
62             }
63 
SetMissing()64         void SetMissing ()
65             {
66             fIsMissing = true;
67             }
68 
69         virtual bool IsValid () const = 0;
70 
71         const dng_fingerprint & Fingerprint () const;
72 
73         bool DecodeFromBinary (const uint8 * compressedData,
74                                uint32 compressedSize,
75                                dng_memory_allocator &allocator);
76 
77         bool DecodeFromString (const dng_string &block1,
78                                dng_memory_allocator &allocator);
79 
80         dng_memory_block * EncodeAsBinary (dng_memory_allocator &allocator,
81                                            uint32 &compressedSize) const;
82 
83         dng_memory_block * EncodeAsString (dng_memory_allocator &allocator) const;
84 
85         bool ExtractFromCache (const dng_fingerprint &fingerprint);
86 
87         bool ReadTableFromXMP (const dng_xmp &xmp,
88 							   const char *ns,
89                                const dng_fingerprint &fingerprint);
90 
91         bool ReadFromXMP (const dng_xmp &xmp,
92                           const char *ns,
93                           const char *path,
94                           dng_big_table_storage &storage);
95 
96         void WriteToXMP (dng_xmp &xmp,
97                          const char *ns,
98                          const char *path,
99                          dng_big_table_storage &storage) const;
100 
101     protected:
102 
103         void RecomputeFingerprint ();
104 
105         virtual void GetStream (dng_stream &stream) = 0;
106 
107         virtual void PutStream (dng_stream &stream,
108                                 bool forFingerprint) const = 0;
109 
110     };
111 
112 /*****************************************************************************/
113 
114 class dng_big_table_storage
115     {
116 
117     public:
118 
119         dng_big_table_storage ();
120 
121         virtual ~dng_big_table_storage ();
122 
123         virtual bool ReadTable (dng_big_table &table,
124                                 const dng_fingerprint &fingerprint,
125                                 dng_memory_allocator &allocator);
126 
127         virtual bool WriteTable (const dng_big_table &table,
128                                  const dng_fingerprint &fingerprint,
129                                  dng_memory_allocator &allocator);
130 
131         virtual void MissingTable (const dng_fingerprint &fingerprint);
132 
133     };
134 
135 /*****************************************************************************/
136 
137 class dng_look_table : public dng_big_table
138     {
139 
140     friend class dng_look_table_cache;
141 
142     public:
143 
144         enum
145             {
146 
147             // Tables are are allowed to trade off resolution
148             // between dimensions, but need to keep total
149             // samples below this limit.  This results in
150             // 216K memory footprint (12 byte per sample)
151             // which is similar in size to the RGB table
152             // size limit.
153 
154             kMaxTotalSamples = 36 * 32 * 16,
155 
156             // Also each must be within their own limits.
157 
158             kMaxHueSamples = 360,
159             kMaxSatSamples = 256,
160             kMaxValSamples = 256
161 
162             };
163 
164     private:
165 
166         enum
167             {
168             kLookTableVersion1 = 1,
169             kLookTableVersion2 = 2
170             };
171 
172         // Table data affecting fingerprint and caching.
173 
174         struct table_data
175             {
176 
177             // 3-D hue/sat table to apply a "look".
178 
179             dng_hue_sat_map fMap;
180 
181             // Value (V of HSV) encoding for look table.
182 
183             uint32 fEncoding;
184 
185             // Minimum and maximum scale amounts supported by table.
186 
187             real64 fMinAmount;
188             real64 fMaxAmount;
189 
190 			// Does this table have only monochrome output (when amount is 1.0)?
191 
192 			bool fMonochrome;
193 
194             // Constructor to set defaults.
195 
table_datatable_data196             table_data ()
197 
198                 :   fMap        ()
199                 ,   fEncoding   (encoding_Linear)
200                 ,   fMinAmount  (1.0)
201                 ,   fMaxAmount  (1.0)
202 				,	fMonochrome (false)
203 
204                 {
205                 }
206 
207 			// Compute monchrome flag.
208 
ComputeMonochrometable_data209 			void ComputeMonochrome ()
210 				{
211 
212 				fMonochrome = true;
213 
214 				uint32 count = fMap.DeltasCount ();
215 
216 				dng_hue_sat_map::HSBModify * deltas = fMap.GetDeltas ();
217 
218 				for (uint32 index = 0; index < count; index++)
219 					{
220 
221 					if (deltas [index] . fSatScale != 0.0f)
222 						{
223 
224 						fMonochrome = false;
225 
226 						return;
227 
228 						}
229 
230 					}
231 
232 				}
233 
234             };
235 
236         table_data fData;
237 
238         // Amount to apply at runtime (does not affect fingerprint).
239 
240         real64 fAmount;
241 
242     public:
243 
244         dng_look_table ();
245 
246         dng_look_table (const dng_look_table &table);
247 
248         dng_look_table & operator= (const dng_look_table &table);
249 
250         virtual ~dng_look_table ();
251 
252         bool operator== (const dng_look_table &table) const
253             {
254             return Fingerprint () == table.Fingerprint () &&
255                    Amount      () == table.Amount      () &&
256                    IsMissing   () == table.IsMissing   ();
257             }
258 
259         bool operator!= (const dng_look_table &table) const
260             {
261             return !(*this == table);
262             }
263 
264         void Set (const dng_hue_sat_map &map,
265                   uint32 encoding);
266 
267         virtual bool IsValid () const;
268 
269         void SetInvalid ();
270 
MinAmount()271         real64 MinAmount () const
272             {
273             return fData.fMinAmount;
274             }
275 
MaxAmount()276         real64 MaxAmount () const
277             {
278             return fData.fMaxAmount;
279             }
280 
SetAmountRange(real64 minAmount,real64 maxAmount)281         void SetAmountRange (real64 minAmount,
282                              real64 maxAmount)
283             {
284 
285             fData.fMinAmount = Pin_real64 (0.0,
286 										   Round_int32 (minAmount * 100.0) * 0.01,
287 										   1.0);
288 
289             fData.fMaxAmount = Pin_real64 (1.0,
290 										   Round_int32 (maxAmount * 100.0) * 0.01,
291 										   2.0);
292 
293 			fAmount = Pin_real64 (fData.fMinAmount, fAmount, fData.fMaxAmount);
294 
295             RecomputeFingerprint ();
296 
297             }
298 
Amount()299         real64 Amount () const
300             {
301             return fAmount;
302             }
303 
SetAmount(real64 amount)304         void SetAmount (real64 amount)
305             {
306 
307 			fAmount = Pin_real64 (fData.fMinAmount,
308 								  Round_int32 (amount * 100.0) * 0.01,
309 								  fData.fMaxAmount);
310 
311             // Not part of fingerprint.
312 
313             }
314 
Map()315         const dng_hue_sat_map & Map () const
316             {
317             return fData.fMap;
318             }
319 
Encoding()320         uint32 Encoding () const
321             {
322             return fData.fEncoding;
323             }
324 
Monochrome()325 		bool Monochrome () const
326 			{
327 			return IsValid () && fAmount == 1.0 && fData.fMonochrome;
328 			}
329 
330     protected:
331 
332         virtual void GetStream (dng_stream &stream);
333 
334         virtual void PutStream (dng_stream &stream,
335                                 bool forFingerprint) const;
336 
337     };
338 
339 /*****************************************************************************/
340 
341 class dng_rgb_table : public dng_big_table
342     {
343 
344     friend class dng_rgb_table_cache;
345 
346     public:
347 
348         enum
349             {
350 
351             kMinDivisions1D = 2,
352             kMaxDivisions1D = 4096,
353 
354             kMinDivisions3D = 2,
355             kMaxDivisions3D = 32,
356 
357             kMaxDivisions3D_InMemory = 128
358 
359             };
360 
361         enum primaries_enum
362             {
363 
364             primaries_sRGB = 0,
365             primaries_Adobe,
366             primaries_ProPhoto,
367             primaries_P3,
368             primaries_Rec2020,
369 
370             primaries_count
371 
372             };
373 
374         enum gamma_enum
375             {
376 
377             gamma_Linear = 0,
378             gamma_sRGB,
379             gamma_1_8,
380             gamma_2_2,
381             gamma_Rec2020,
382 
383             gamma_count
384 
385             };
386 
387         enum gamut_enum
388             {
389 
390             gamut_clip = 0,
391             gamut_extend,
392 
393             gamut_count
394 
395             };
396 
397     private:
398 
399         enum
400             {
401             kRGBTableVersion = 1
402             };
403 
404         // Table data affecting fingerprint and caching.
405 
406         struct table_data
407             {
408 
409             // Number of dimensions of the table (1 or 3).
410 
411             uint32 fDimensions;
412 
413             // Number of samples per side of table.
414 
415             uint32 fDivisions;
416 
417             // Sample data.  16-bit unsigned encoding.
418             // Right zero padded to 64 bits per sample (i.e. RGB0).
419 
420             dng_ref_counted_block fSamples;
421 
422             // Color primaries for table.
423 
424             primaries_enum fPrimaries;
425 
426             // Gamma encoding for table.
427 
428             gamma_enum fGamma;
429 
430             // Gamut processing option for table.
431 
432             gamut_enum fGamut;
433 
434             // Minimum and maximum scale amounts supported by table.
435 
436             real64 fMinAmount;
437             real64 fMaxAmount;
438 
439 			// Does this table have only monochrome output (when amount is 1.0)?
440 
441 			bool fMonochrome;
442 
443             // Constructor to set defaults.
444 
table_datatable_data445             table_data ()
446 
447                 :   fDimensions (0)
448                 ,	fDivisions  (0)
449                 ,	fSamples    ()
450                 ,   fPrimaries  (primaries_sRGB)
451                 ,   fGamma      (gamma_sRGB)
452                 ,   fGamut      (gamut_clip)
453                 ,   fMinAmount  (0.0)
454                 ,   fMaxAmount  (2.0)
455 				,	fMonochrome (false)
456 
457                 {
458                 }
459 
460 			// Compute monchrome flag.
461 
ComputeMonochrometable_data462 			void ComputeMonochrome ()
463 				{
464 
465 				if (fPrimaries != primaries_ProPhoto &&
466 					fGamut     != gamut_clip)
467 					{
468 
469 					fMonochrome = false;
470 
471 					return;
472 
473 					}
474 
475 				if (fDimensions != 3)
476 					{
477 
478 					fMonochrome = false;
479 
480 					return;
481 
482 					}
483 
484 				fMonochrome = true;
485 
486 				uint32 count = fDivisions * fDivisions * fDivisions;
487 
488 				const uint16 * sample = fSamples.Buffer_uint16 ();
489 
490 				for (uint32 index = 0; index < count; index++)
491 					{
492 
493 					if (sample [0] != sample [1] ||
494 					    sample [0] != sample [2])
495 						{
496 
497 						fMonochrome = false;
498 
499 						return;
500 
501 						}
502 
503 					sample += 4;
504 
505 					}
506 
507 				}
508 
509             };
510 
511         table_data fData;
512 
513         // Amount to apply at runtime (does not affect fingerprint).
514 
515         real64 fAmount;
516 
517     public:
518 
519         dng_rgb_table ();
520 
521         dng_rgb_table (const dng_rgb_table &table);
522 
523         dng_rgb_table & operator= (const dng_rgb_table &table);
524 
525         virtual ~dng_rgb_table ();
526 
527         bool operator== (const dng_rgb_table &table) const
528             {
529             return Fingerprint () == table.Fingerprint () &&
530                    Amount      () == table.Amount      () &&
531                    IsMissing   () == table.IsMissing   ();
532             }
533 
534         bool operator!= (const dng_rgb_table &table) const
535             {
536             return !(*this == table);
537             }
538 
539         virtual bool IsValid () const;
540 
541         void SetInvalid ();
542 
Primaries()543         primaries_enum Primaries () const
544             {
545             return fData.fPrimaries;
546             }
547 
SetPrimaries(primaries_enum primaries)548         void SetPrimaries (primaries_enum primaries)
549             {
550 
551             fData.fPrimaries = primaries;
552 
553 			fData.ComputeMonochrome ();
554 
555             RecomputeFingerprint ();
556 
557             }
558 
Gamma()559         gamma_enum Gamma () const
560             {
561             return fData.fGamma;
562             }
563 
SetGamma(gamma_enum gamma)564         void SetGamma (gamma_enum gamma)
565             {
566 
567             fData.fGamma = gamma;
568 
569             RecomputeFingerprint ();
570 
571             }
572 
Gamut()573         gamut_enum Gamut () const
574             {
575             return fData.fGamut;
576             }
577 
SetGamut(gamut_enum gamut)578         void SetGamut (gamut_enum gamut)
579             {
580 
581             fData.fGamut = gamut;
582 
583 			fData.ComputeMonochrome ();
584 
585             RecomputeFingerprint ();
586 
587             }
588 
MinAmount()589         real64 MinAmount () const
590             {
591             return fData.fMinAmount;
592             }
593 
MaxAmount()594         real64 MaxAmount () const
595             {
596             return fData.fMaxAmount;
597             }
598 
SetAmountRange(real64 minAmount,real64 maxAmount)599         void SetAmountRange (real64 minAmount,
600                              real64 maxAmount)
601             {
602 
603             fData.fMinAmount = Pin_real64 (0.0,
604 										   Round_int32 (minAmount * 100.0) * 0.01,
605 										   1.0);
606 
607             fData.fMaxAmount = Pin_real64 (1.0,
608 										   Round_int32 (maxAmount * 100.0) * 0.01,
609 										   2.0);
610 
611 			fAmount = Pin_real64 (fData.fMinAmount, fAmount, fData.fMaxAmount);
612 
613             RecomputeFingerprint ();
614 
615             }
616 
Amount()617         real64 Amount () const
618             {
619             return fAmount;
620             }
621 
SetAmount(real64 amount)622         void SetAmount (real64 amount)
623             {
624 
625 			fAmount = Pin_real64 (fData.fMinAmount,
626 								  Round_int32 (amount * 100.0) * 0.01,
627 								  fData.fMaxAmount);
628 
629             // Not part of fingerprint.
630 
631             }
632 
Dimensions()633         uint32 Dimensions () const
634             {
635             return fData.fDimensions;
636             }
637 
Divisions()638         uint32 Divisions () const
639             {
640             return fData.fDivisions;
641             }
642 
Samples()643         const uint16 * Samples () const
644             {
645             return fData.fSamples.Buffer_uint16 ();
646             }
647 
Monochrome()648 		bool Monochrome () const
649 			{
650 			return IsValid () && fAmount == 1.0 && fData.fMonochrome;
651 			}
652 
653         void Set (uint32 dimensions,
654                   uint32 divisions,
655                   dng_ref_counted_block samples);
656 
657     protected:
658 
659         virtual void GetStream (dng_stream &stream);
660 
661         virtual void PutStream (dng_stream &stream,
662                                 bool forFingerprint) const;
663 
664     };
665 
666 /*****************************************************************************/
667 
668 #endif
669 
670 /*****************************************************************************/
671