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