| /*****************************************************************************/ |
| // Copyright 2007-2022 Adobe Systems Incorporated |
| // All Rights Reserved. |
| // |
| // NOTICE: Adobe permits you to use, modify, and distribute this file in |
| // accordance with the terms of the Adobe license agreement accompanying it. |
| /*****************************************************************************/ |
| |
| #include "dng_preview.h" |
| |
| #include "dng_assertions.h" |
| #include "dng_host.h" |
| #include "dng_image.h" |
| #include "dng_image_writer.h" |
| #include "dng_jxl.h" |
| #include "dng_memory.h" |
| #include "dng_stream.h" |
| #include "dng_tag_codes.h" |
| #include "dng_tag_values.h" |
| |
| /*****************************************************************************/ |
| |
| class dng_preview_tag_set: public dng_basic_tag_set |
| { |
| |
| private: |
| |
| tag_string fApplicationNameTag; |
| |
| tag_string fApplicationVersionTag; |
| |
| tag_string fSettingsNameTag; |
| |
| dng_fingerprint fSettingsDigest; |
| |
| tag_uint8_ptr fSettingsDigestTag; |
| |
| tag_uint32 fColorSpaceTag; |
| |
| tag_string fDateTimeTag; |
| |
| tag_real64 fRawToPreviewGainTag; |
| |
| tag_uint32 fCacheVersionTag; |
| |
| public: |
| |
| dng_preview_tag_set (dng_tiff_directory &directory, |
| const dng_preview &preview, |
| const dng_ifd &ifd); |
| |
| virtual ~dng_preview_tag_set (); |
| |
| }; |
| |
| /*****************************************************************************/ |
| |
| dng_preview_tag_set::dng_preview_tag_set (dng_tiff_directory &directory, |
| const dng_preview &preview, |
| const dng_ifd &ifd) |
| |
| : dng_basic_tag_set (directory, ifd) |
| |
| , fApplicationNameTag (tcPreviewApplicationName, |
| preview.fInfo.fApplicationName, |
| false) |
| |
| , fApplicationVersionTag (tcPreviewApplicationVersion, |
| preview.fInfo.fApplicationVersion, |
| false) |
| |
| , fSettingsNameTag (tcPreviewSettingsName, |
| preview.fInfo.fSettingsName, |
| false) |
| |
| , fSettingsDigest (preview.fInfo.fSettingsDigest) |
| |
| , fSettingsDigestTag (tcPreviewSettingsDigest, |
| fSettingsDigest.data, |
| 16) |
| |
| , fColorSpaceTag (tcPreviewColorSpace, |
| preview.fInfo.fColorSpace) |
| |
| , fDateTimeTag (tcPreviewDateTime, |
| preview.fInfo.fDateTime, |
| true) |
| |
| , fRawToPreviewGainTag (tcRawToPreviewGain, |
| preview.fInfo.fRawToPreviewGain) |
| |
| , fCacheVersionTag (tcCacheVersion, |
| preview.fInfo.fCacheVersion) |
| |
| { |
| |
| if (preview.fInfo.fApplicationName.NotEmpty ()) |
| { |
| |
| directory.Add (&fApplicationNameTag); |
| |
| } |
| |
| if (preview.fInfo.fApplicationVersion.NotEmpty ()) |
| { |
| |
| directory.Add (&fApplicationVersionTag); |
| |
| } |
| |
| if (preview.fInfo.fSettingsName.NotEmpty ()) |
| { |
| |
| directory.Add (&fSettingsNameTag); |
| |
| } |
| |
| if (preview.fInfo.fSettingsDigest.IsValid ()) |
| { |
| |
| directory.Add (&fSettingsDigestTag); |
| |
| } |
| |
| if (preview.fInfo.fColorSpace != previewColorSpace_MaxEnum) |
| { |
| |
| directory.Add (&fColorSpaceTag); |
| |
| } |
| |
| if (preview.fInfo.fDateTime.NotEmpty ()) |
| { |
| |
| directory.Add (&fDateTimeTag); |
| |
| } |
| |
| if (preview.fInfo.fRawToPreviewGain != 1.0) |
| { |
| |
| directory.Add (&fRawToPreviewGainTag); |
| |
| } |
| |
| if (preview.fInfo.fCacheVersion != 0) |
| { |
| |
| directory.Add (&fCacheVersionTag); |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_preview_tag_set::~dng_preview_tag_set () |
| { |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_preview::SetIFDInfo (dng_host & /* host */, |
| const dng_image &image) |
| { |
| |
| fIFD.fNewSubFileType = fInfo.fIsPrimary ? sfPreviewImage |
| : sfAltPreviewImage; |
| |
| fIFD.fImageWidth = image.Width (); |
| fIFD.fImageLength = image.Height (); |
| |
| fIFD.fSamplesPerPixel = image.Planes (); |
| |
| fIFD.fPhotometricInterpretation = fIFD.fSamplesPerPixel == 1 ? piBlackIsZero |
| : piRGB; |
| |
| fIFD.fBitsPerSample [0] = TagTypeSize (image.PixelType ()) * 8; |
| |
| fIFD.fSampleFormat [0] = image.PixelType () == ttFloat |
| ? sfFloatingPoint |
| : sfUnsignedInteger; |
| |
| for (uint32 j = 1; j < fIFD.fSamplesPerPixel; j++) |
| { |
| fIFD.fBitsPerSample [j] = fIFD.fBitsPerSample [0]; |
| fIFD.fSampleFormat [j] = fIFD.fSampleFormat [0]; |
| } |
| |
| fIFD.SetSingleStrip (); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_basic_tag_set * dng_preview::AddTagSet (dng_host & /* host */, |
| dng_tiff_directory &directory) const |
| { |
| |
| return new dng_preview_tag_set (directory, *this, fIFD); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_preview::WriteData (dng_host &host, |
| dng_image_writer &writer, |
| dng_basic_tag_set &basic, |
| dng_stream &stream) const |
| { |
| |
| if (fCompressedImage.get ()) |
| { |
| |
| fCompressedImage->WriteData (stream, |
| basic); |
| |
| } |
| |
| else |
| { |
| |
| writer.WriteImage (host, |
| fIFD, |
| basic, |
| stream, |
| *fImage); |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| uint64 dng_preview::MaxImageDataByteCount () const |
| { |
| |
| if (fCompressedImage.get ()) |
| { |
| |
| return fCompressedImage->NonHeaderSize (); |
| |
| } |
| |
| else |
| { |
| |
| return fIFD.MaxImageDataByteCount (); |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_preview::Compress (dng_host &host, |
| dng_image_writer &writer) |
| { |
| |
| if (fIFD.fCompression == ccJXL || |
| fIFD.fCompression == ccLossyJPEG || |
| fIFD.fCompression == ccDeflate) |
| { |
| |
| AutoPtr<dng_compressed_image_tiles> compressedImage |
| (new dng_compressed_image_tiles); |
| |
| compressedImage->EncodeTiles (host, |
| writer, |
| *fImage, |
| fIFD); |
| |
| fCompressedImage.reset (compressedImage.Release ()); |
| |
| fImage.reset (); |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| class dng_jpeg_preview_tag_set: public dng_preview_tag_set |
| { |
| |
| private: |
| |
| dng_urational fCoefficientsData [3]; |
| |
| tag_urational_ptr fCoefficientsTag; |
| |
| uint16 fSubSamplingData [2]; |
| |
| tag_uint16_ptr fSubSamplingTag; |
| |
| tag_uint16 fPositioningTag; |
| |
| dng_urational fReferenceData [6]; |
| |
| tag_urational_ptr fReferenceTag; |
| |
| public: |
| |
| dng_jpeg_preview_tag_set (dng_tiff_directory &directory, |
| const dng_jpeg_preview &preview, |
| const dng_ifd &ifd); |
| |
| }; |
| |
| /******************************************************************************/ |
| |
| dng_jpeg_preview_tag_set::dng_jpeg_preview_tag_set (dng_tiff_directory &directory, |
| const dng_jpeg_preview &preview, |
| const dng_ifd &ifd) |
| |
| : dng_preview_tag_set (directory, preview, ifd) |
| |
| , fCoefficientsTag (tcYCbCrCoefficients, fCoefficientsData, 3) |
| |
| , fSubSamplingTag (tcYCbCrSubSampling, fSubSamplingData, 2) |
| |
| , fPositioningTag (tcYCbCrPositioning, ifd.fYCbCrPositioning) |
| |
| , fReferenceTag (tcReferenceBlackWhite, fReferenceData, 6) |
| |
| { |
| |
| if (ifd.fPhotometricInterpretation == piYCbCr) |
| { |
| |
| fCoefficientsData [0] = dng_urational (299, 1000); |
| fCoefficientsData [1] = dng_urational (587, 1000); |
| fCoefficientsData [2] = dng_urational (114, 1000); |
| |
| directory.Add (&fCoefficientsTag); |
| |
| fSubSamplingData [0] = (uint16) ifd.fYCbCrSubSampleH; |
| fSubSamplingData [1] = (uint16) ifd.fYCbCrSubSampleV; |
| |
| directory.Add (&fSubSamplingTag); |
| |
| directory.Add (&fPositioningTag); |
| |
| fReferenceData [0] = dng_urational ( 0, 1); |
| fReferenceData [1] = dng_urational (255, 1); |
| fReferenceData [2] = dng_urational (128, 1); |
| fReferenceData [3] = dng_urational (255, 1); |
| fReferenceData [4] = dng_urational (128, 1); |
| fReferenceData [5] = dng_urational (255, 1); |
| |
| directory.Add (&fReferenceTag); |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_jpeg_preview::SetIFDInfo (dng_host &host, |
| const dng_image &image) |
| { |
| |
| dng_preview::SetIFDInfo (host, image); |
| |
| fIFD.fCompression = ccJPEG; // Lossy version |
| |
| if (image.Planes () == 1) |
| { |
| fIFD.fPhotometricInterpretation = piBlackIsZero; |
| } |
| |
| else |
| { |
| SetYCbCr (1, 1); |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_jpeg_preview::SetCompressedData (AutoPtr<dng_memory_block> &compressedData) |
| { |
| |
| fImage.reset (); |
| |
| AutoPtr<dng_compressed_image_tiles> compressedTiles (new dng_compressed_image_tiles); |
| |
| compressedTiles->fData.resize (1); |
| |
| compressedTiles->fData [0].reset (compressedData.Release ()); |
| |
| fCompressedImage.reset (compressedTiles.Release ()); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| const dng_memory_block & dng_jpeg_preview::CompressedData () const |
| { |
| |
| DNG_REQUIRE (fCompressedImage.get () && |
| fCompressedImage->fData.size () == 1, |
| "No compressed data"); |
| |
| return *(fCompressedImage->fData [0]); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_basic_tag_set * dng_jpeg_preview::AddTagSet (dng_host & /* host */, |
| dng_tiff_directory &directory) const |
| { |
| |
| return new dng_jpeg_preview_tag_set (directory, *this, fIFD); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_jpeg_preview::WriteData (dng_host &host, |
| dng_image_writer &writer, |
| dng_basic_tag_set &basic, |
| dng_stream &stream) const |
| { |
| |
| // Force the data to be written using lossy JPEG. |
| |
| fIFD.fCompression = ccLossyJPEG; |
| |
| dng_preview::WriteData (host, |
| writer, |
| basic, |
| stream); |
| |
| // But we still want to use the normal jpeg compression code in the IFD. |
| |
| fIFD.fCompression = ccJPEG; |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| uint64 dng_jpeg_preview::MaxImageDataByteCount () const |
| { |
| |
| fIFD.fCompression = ccLossyJPEG; |
| |
| uint64 result = dng_preview::MaxImageDataByteCount (); |
| |
| fIFD.fCompression = ccJPEG; |
| |
| return result; |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_jpeg_preview::Compress (dng_host &host, |
| dng_image_writer &writer) |
| { |
| |
| fIFD.fCompression = ccLossyJPEG; |
| |
| dng_preview::Compress (host, writer); |
| |
| fIFD.fCompression = ccJPEG; |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_jpeg_preview::SpoolAdobeThumbnail (dng_stream &stream) const |
| { |
| |
| DNG_ASSERT (fIFD.fPhotometricInterpretation == piYCbCr, |
| "SpoolAdobeThumbnail: Non-YCbCr"); |
| |
| uint32 compressedSize = CompressedData ().LogicalSize (); |
| |
| stream.Put_uint32 (DNG_CHAR4 ('8','B','I','M')); |
| stream.Put_uint16 (1036); |
| stream.Put_uint16 (0); |
| |
| stream.Put_uint32 (compressedSize + 28); |
| |
| uint32 widthBytes = (fIFD.fImageWidth * 24 + 31) / 32 * 4; |
| |
| stream.Put_uint32 (1); |
| stream.Put_uint32 (fIFD.fImageWidth); |
| stream.Put_uint32 (fIFD.fImageLength); |
| stream.Put_uint32 (widthBytes); |
| stream.Put_uint32 (widthBytes * fIFD.fImageLength); |
| stream.Put_uint32 (compressedSize); |
| stream.Put_uint16 (24); |
| stream.Put_uint16 (1); |
| |
| stream.Put (CompressedData ().Buffer (), |
| compressedSize); |
| |
| if (compressedSize & 1) |
| { |
| stream.Put_uint8 (0); |
| } |
| |
| } |
| |
| //*****************************************************************************/ |
| |
| void dng_jxl_preview::SetIFDInfo (dng_host &host, |
| const dng_image &image) |
| { |
| |
| dng_preview::SetIFDInfo (host, image); |
| |
| // Store a copy of the preview info so that the writer can get information |
| // about the color space. |
| |
| fIFD.fPreviewInfo = this->fInfo; |
| |
| fIFD.fCompression = ccJXL; |
| fIFD.fPredictor = cpNullPredictor; |
| |
| AutoPtr<dng_jxl_encode_settings> settings (host.MakeJXLEncodeSettings (dng_host::use_case_RenderedPreview, |
| image)); |
| |
| fIFD.fJXLEncodeSettings.reset (settings.Release ()); |
| |
| fIFD.fJXLDistance = fIFD.fJXLEncodeSettings->Distance (); |
| fIFD.fJXLEffort = fIFD.fJXLEncodeSettings->Effort (); |
| fIFD.fJXLDecodeSpeed = fIFD.fJXLEncodeSettings->DecodeSpeed (); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| class dng_raw_preview_tag_set: public dng_preview_tag_set |
| { |
| |
| private: |
| |
| tag_data_ptr fOpcodeList2Tag; |
| |
| tag_uint32_ptr fWhiteLevelTag; |
| |
| uint32 fWhiteLevelData [kMaxColorPlanes]; |
| |
| tag_urational_ptr fBlackLevelTag; |
| |
| dng_urational fBlackLevelData [kMaxColorPlanes]; |
| |
| public: |
| |
| dng_raw_preview_tag_set (dng_tiff_directory &directory, |
| const dng_raw_preview &preview, |
| const dng_ifd &ifd); |
| |
| virtual ~dng_raw_preview_tag_set (); |
| |
| }; |
| |
| /*****************************************************************************/ |
| |
| dng_raw_preview_tag_set::dng_raw_preview_tag_set (dng_tiff_directory &directory, |
| const dng_raw_preview &preview, |
| const dng_ifd &ifd) |
| |
| : dng_preview_tag_set (directory, preview, ifd) |
| |
| , fOpcodeList2Tag (tcOpcodeList2, |
| ttUndefined, |
| 0, |
| NULL) |
| |
| , fWhiteLevelTag (tcWhiteLevel, |
| fWhiteLevelData, |
| preview.SamplesPerPixel ()) |
| |
| , fBlackLevelTag (tcBlackLevel, |
| fBlackLevelData, |
| preview.SamplesPerPixel ()) |
| |
| { |
| |
| if (preview.fOpcodeList2Data.Get ()) |
| { |
| |
| fOpcodeList2Tag.SetData (preview.fOpcodeList2Data->Buffer ()); |
| fOpcodeList2Tag.SetCount (preview.fOpcodeList2Data->LogicalSize ()); |
| |
| directory.Add (&fOpcodeList2Tag); |
| |
| } |
| |
| if (preview.SampleFormat () == sfFloatingPoint) |
| { |
| |
| for (uint32 j = 0; j < kMaxColorPlanes; j++) |
| { |
| fWhiteLevelData [j] = 32768; |
| } |
| |
| directory.Add (&fWhiteLevelTag); |
| |
| } |
| |
| else |
| { |
| |
| bool nonZeroBlack = false; |
| |
| for (uint32 j = 0; j < preview.SamplesPerPixel (); j++) |
| { |
| |
| fBlackLevelData [j].Set_real64 (preview.fBlackLevel [j], 1); |
| |
| nonZeroBlack = nonZeroBlack || (preview.fBlackLevel [j] != 0.0); |
| |
| } |
| |
| if (nonZeroBlack) |
| { |
| |
| directory.Add (&fBlackLevelTag); |
| |
| } |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_raw_preview_tag_set::~dng_raw_preview_tag_set () |
| { |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_raw_preview::dng_raw_preview () |
| { |
| |
| for (uint32 n = 0; n < kMaxColorPlanes; n++) |
| { |
| fBlackLevel [n] = 0.0; |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_raw_preview::SetIFDInfo (dng_host &host, |
| const dng_image &image) |
| { |
| |
| dng_preview::SetIFDInfo (host, image); |
| |
| fIFD.fNewSubFileType = sfPreviewImage; |
| |
| fIFD.fPhotometricInterpretation = piLinearRaw; |
| |
| if (image.PixelType () == ttFloat) |
| { |
| |
| if (fPreferJXL && SupportsJXL (*fImage)) |
| { |
| fIFD.fCompression = ccJXL; |
| fIFD.fPredictor = cpNullPredictor; |
| } |
| |
| else |
| { |
| fIFD.fCompression = ccDeflate; |
| fIFD.fCompressionQuality = fCompressionQuality; |
| fIFD.fPredictor = cpFloatingPoint; |
| } |
| |
| for (uint32 j = 0; j < fIFD.fSamplesPerPixel; j++) |
| { |
| fIFD.fBitsPerSample [j] = 16; |
| } |
| |
| fIFD.FindTileSize (512 * 1024); |
| |
| } |
| |
| else |
| { |
| |
| if (fPreferJXL && SupportsJXL (*fImage)) |
| { |
| fIFD.fCompression = ccJXL; |
| fIFD.fPredictor = cpNullPredictor; |
| } |
| |
| else |
| { |
| fIFD.fCompression = ccLossyJPEG; |
| fIFD.fCompressionQuality = fCompressionQuality; |
| } |
| |
| fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel); |
| |
| } |
| |
| if (fIFD.fCompression == ccJXL) |
| { |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_basic_tag_set * dng_raw_preview::AddTagSet (dng_host & /* host */, |
| dng_tiff_directory &directory) const |
| { |
| |
| return new dng_raw_preview_tag_set (directory, *this, fIFD); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_mask_preview::SetIFDInfo (dng_host &host, |
| const dng_image &image) |
| { |
| |
| dng_preview::SetIFDInfo (host, image); |
| |
| fIFD.fNewSubFileType = sfPreviewMask; |
| |
| fIFD.fPhotometricInterpretation = piTransparencyMask; |
| |
| fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel); |
| |
| if (fPreferJXL && SupportsJXL (*fImage)) |
| { |
| fIFD.fCompression = ccJXL; |
| fIFD.fPredictor = cpNullPredictor; |
| } |
| |
| else |
| { |
| |
| fIFD.fCompression = ccDeflate; |
| fIFD.fPredictor = cpHorizontalDifference; |
| |
| fIFD.fCompressionQuality = fCompressionQuality; |
| |
| } |
| |
| if (fIFD.fCompression == ccJXL) |
| { |
| |
| AutoPtr<dng_jxl_encode_settings> settings (host.MakeJXLEncodeSettings (dng_host::use_case_Transparency, |
| image)); |
| |
| if (fForNegativeCache) |
| { |
| settings->SetEffort (1); |
| } |
| |
| fIFD.fJXLEncodeSettings.reset (settings.Release ()); |
| |
| fIFD.fJXLDistance = fIFD.fJXLEncodeSettings->Distance (); |
| fIFD.fJXLEffort = fIFD.fJXLEncodeSettings->Effort (); |
| fIFD.fJXLDecodeSpeed = fIFD.fJXLEncodeSettings->DecodeSpeed (); |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_basic_tag_set * dng_mask_preview::AddTagSet (dng_host & /* host */, |
| dng_tiff_directory &directory) const |
| { |
| |
| return new dng_basic_tag_set (directory, fIFD); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_semantic_mask_preview::SetIFDInfo (dng_host &host, |
| const dng_image &image) |
| { |
| |
| dng_preview::SetIFDInfo (host, image); |
| |
| fIFD.fNewSubFileType = fOriginalSize ? sfSemanticMask |
| : sfPreviewSemanticMask; |
| |
| fIFD.fPhotometricInterpretation = piPhotometricMask; |
| |
| fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel); |
| |
| if (fPreferJXL && SupportsJXL (*fImage)) |
| { |
| fIFD.fCompression = ccJXL; |
| fIFD.fPredictor = cpNullPredictor; |
| } |
| |
| else |
| { |
| |
| fIFD.fCompression = ccDeflate; |
| fIFD.fPredictor = cpHorizontalDifference; |
| |
| fIFD.fCompressionQuality = fCompressionQuality; |
| |
| } |
| |
| if (fIFD.fCompression == ccJXL) |
| { |
| |
| AutoPtr<dng_jxl_encode_settings> settings (host.MakeJXLEncodeSettings (dng_host::use_case_SemanticMask, |
| image)); |
| |
| if (fForNegativeCache) |
| { |
| settings->SetEffort (1); |
| } |
| |
| fIFD.fJXLEncodeSettings.reset (settings.Release ()); |
| |
| fIFD.fJXLDistance = fIFD.fJXLEncodeSettings->Distance (); |
| fIFD.fJXLEffort = fIFD.fJXLEncodeSettings->Effort (); |
| fIFD.fJXLDecodeSpeed = fIFD.fJXLEncodeSettings->DecodeSpeed (); |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_basic_tag_set * dng_semantic_mask_preview::AddTagSet (dng_host & /* host */, |
| dng_tiff_directory &directory) const |
| { |
| |
| // Need to write the name and instance ID to the directory, too. Otherwise |
| // we won't have corresponding labels when reading the image back in. |
| |
| fTagName.reset (new tag_string (tcSemanticName, |
| fName, |
| false)); |
| |
| fTagInstanceID.reset (new tag_string (tcSemanticInstanceID, |
| fInstanceID, |
| false)); |
| |
| directory.Add (fTagName.get ()); |
| |
| directory.Add (fTagInstanceID.get ()); |
| |
| // Also need to add the MaskSubArea info. |
| |
| fTagMaskSubArea.reset (new tag_uint32_ptr (tcMaskSubArea, |
| & fMaskSubArea [0], |
| 4)); |
| |
| directory.Add (fTagMaskSubArea.get ()); |
| |
| return new dng_basic_tag_set (directory, fIFD); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_depth_preview::SetIFDInfo (dng_host &host, |
| const dng_image &image) |
| { |
| |
| dng_preview::SetIFDInfo (host, image); |
| |
| fIFD.fNewSubFileType = fFullResolution ? sfDepthMap |
| : sfPreviewDepthMap; |
| |
| fIFD.fPhotometricInterpretation = piDepth; |
| |
| fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel); |
| |
| if (fPreferJXL && SupportsJXL (*fImage)) |
| { |
| fIFD.fCompression = ccJXL; |
| fIFD.fPredictor = cpNullPredictor; |
| } |
| |
| else |
| { |
| |
| fIFD.fCompression = ccDeflate; |
| fIFD.fPredictor = cpHorizontalDifference; |
| |
| fIFD.fCompressionQuality = fCompressionQuality; |
| |
| } |
| |
| if (fIFD.fCompression == ccJXL) |
| { |
| |
| AutoPtr<dng_jxl_encode_settings> settings (host.MakeJXLEncodeSettings (dng_host::use_case_Depth, |
| image)); |
| |
| if (fForNegativeCache) |
| { |
| settings->SetEffort (1); |
| } |
| |
| fIFD.fJXLEncodeSettings.reset (settings.Release ()); |
| |
| fIFD.fJXLDistance = fIFD.fJXLEncodeSettings->Distance (); |
| fIFD.fJXLEffort = fIFD.fJXLEncodeSettings->Effort (); |
| fIFD.fJXLDecodeSpeed = fIFD.fJXLEncodeSettings->DecodeSpeed (); |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| dng_basic_tag_set * dng_depth_preview::AddTagSet (dng_host & /* host */, |
| dng_tiff_directory &directory) const |
| { |
| |
| return new dng_basic_tag_set (directory, fIFD); |
| |
| } |
| |
| /*****************************************************************************/ |
| |
| void dng_preview_list::Append (AutoPtr<dng_preview> &preview) |
| { |
| |
| if (preview.Get ()) |
| { |
| |
| std::shared_ptr<const dng_preview> entry (preview.Release ()); |
| |
| fPreview.push_back (entry); |
| |
| } |
| |
| } |
| |
| /*****************************************************************************/ |