Home | History | Annotate | Download | only in source
      1 /*****************************************************************************/
      2 // Copyright 2007-2011 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_preview.cpp#1 $ */
     10 /* $DateTime: 2012/05/30 13:28:51 $ */
     11 /* $Change: 832332 $ */
     12 /* $Author: tknoll $ */
     13 
     14 /*****************************************************************************/
     15 
     16 #include "dng_preview.h"
     17 
     18 #include "dng_assertions.h"
     19 #include "dng_image.h"
     20 #include "dng_image_writer.h"
     21 #include "dng_memory.h"
     22 #include "dng_stream.h"
     23 #include "dng_tag_codes.h"
     24 #include "dng_tag_values.h"
     25 
     26 /*****************************************************************************/
     27 
     28 class dng_preview_tag_set: public dng_basic_tag_set
     29 	{
     30 
     31 	private:
     32 
     33 		tag_string fApplicationNameTag;
     34 
     35 		tag_string fApplicationVersionTag;
     36 
     37 		tag_string fSettingsNameTag;
     38 
     39 		dng_fingerprint fSettingsDigest;
     40 
     41 		tag_uint8_ptr fSettingsDigestTag;
     42 
     43 		tag_uint32 fColorSpaceTag;
     44 
     45 		tag_string fDateTimeTag;
     46 
     47 		tag_real64 fRawToPreviewGainTag;
     48 
     49 		tag_uint32 fCacheVersionTag;
     50 
     51 	public:
     52 
     53 		dng_preview_tag_set (dng_tiff_directory &directory,
     54 							 const dng_preview &preview,
     55 							 const dng_ifd &ifd);
     56 
     57 		virtual ~dng_preview_tag_set ();
     58 
     59 	};
     60 
     61 /*****************************************************************************/
     62 
     63 dng_preview_tag_set::dng_preview_tag_set (dng_tiff_directory &directory,
     64 										  const dng_preview &preview,
     65 										  const dng_ifd &ifd)
     66 
     67 	:	dng_basic_tag_set (directory, ifd)
     68 
     69 	,	fApplicationNameTag (tcPreviewApplicationName,
     70 							 preview.fInfo.fApplicationName,
     71 							 false)
     72 
     73 	,	fApplicationVersionTag (tcPreviewApplicationVersion,
     74 							    preview.fInfo.fApplicationVersion,
     75 								false)
     76 
     77 	,	fSettingsNameTag (tcPreviewSettingsName,
     78 						  preview.fInfo.fSettingsName,
     79 						  false)
     80 
     81 	,	fSettingsDigest (preview.fInfo.fSettingsDigest)
     82 
     83 	,	fSettingsDigestTag (tcPreviewSettingsDigest,
     84 							fSettingsDigest.data,
     85 							16)
     86 
     87 	,	fColorSpaceTag (tcPreviewColorSpace,
     88 						preview.fInfo.fColorSpace)
     89 
     90 	,	fDateTimeTag (tcPreviewDateTime,
     91 					  preview.fInfo.fDateTime,
     92 					  true)
     93 
     94 	,	fRawToPreviewGainTag (tcRawToPreviewGain,
     95 							  preview.fInfo.fRawToPreviewGain)
     96 
     97 	,	fCacheVersionTag (tcCacheVersion,
     98 					      preview.fInfo.fCacheVersion)
     99 
    100 	{
    101 
    102 	if (preview.fInfo.fApplicationName.NotEmpty ())
    103 		{
    104 
    105 		directory.Add (&fApplicationNameTag);
    106 
    107 		}
    108 
    109 	if (preview.fInfo.fApplicationVersion.NotEmpty ())
    110 		{
    111 
    112 		directory.Add (&fApplicationVersionTag);
    113 
    114 		}
    115 
    116 	if (preview.fInfo.fSettingsName.NotEmpty ())
    117 		{
    118 
    119 		directory.Add (&fSettingsNameTag);
    120 
    121 		}
    122 
    123 	if (preview.fInfo.fSettingsDigest.IsValid ())
    124 		{
    125 
    126 		directory.Add (&fSettingsDigestTag);
    127 
    128 		}
    129 
    130 	if (preview.fInfo.fColorSpace != previewColorSpace_MaxEnum)
    131 		{
    132 
    133 		directory.Add (&fColorSpaceTag);
    134 
    135 		}
    136 
    137 	if (preview.fInfo.fDateTime.NotEmpty ())
    138 		{
    139 
    140 		directory.Add (&fDateTimeTag);
    141 
    142 		}
    143 
    144 	if (preview.fInfo.fRawToPreviewGain != 1.0)
    145 		{
    146 
    147 		directory.Add (&fRawToPreviewGainTag);
    148 
    149 		}
    150 
    151 	if (preview.fInfo.fCacheVersion != 0)
    152 		{
    153 
    154 		directory.Add (&fCacheVersionTag);
    155 
    156 		}
    157 
    158 	}
    159 
    160 /*****************************************************************************/
    161 
    162 dng_preview_tag_set::~dng_preview_tag_set ()
    163 	{
    164 
    165 	}
    166 
    167 /*****************************************************************************/
    168 
    169 dng_preview::dng_preview ()
    170 
    171 	:	fInfo ()
    172 
    173 	{
    174 
    175 	}
    176 
    177 /*****************************************************************************/
    178 
    179 dng_preview::~dng_preview ()
    180 	{
    181 
    182 	}
    183 
    184 /*****************************************************************************/
    185 
    186 dng_image_preview::dng_image_preview ()
    187 
    188 	:	fImage ()
    189 	,	fIFD   ()
    190 
    191 	{
    192 
    193 	}
    194 
    195 /*****************************************************************************/
    196 
    197 dng_image_preview::~dng_image_preview ()
    198 	{
    199 
    200 	}
    201 
    202 /*****************************************************************************/
    203 
    204 dng_basic_tag_set * dng_image_preview::AddTagSet (dng_tiff_directory &directory) const
    205 	{
    206 
    207 	fIFD.fNewSubFileType = fInfo.fIsPrimary ? sfPreviewImage
    208 											: sfAltPreviewImage;
    209 
    210 	fIFD.fImageWidth  = fImage->Width  ();
    211 	fIFD.fImageLength = fImage->Height ();
    212 
    213 	fIFD.fSamplesPerPixel = fImage->Planes ();
    214 
    215 	fIFD.fPhotometricInterpretation = fIFD.fSamplesPerPixel == 1 ? piBlackIsZero
    216 																 : piRGB;
    217 
    218 	fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
    219 
    220 	for (uint32 j = 1; j < fIFD.fSamplesPerPixel; j++)
    221 		{
    222 		fIFD.fBitsPerSample [j] = fIFD.fBitsPerSample [0];
    223 		}
    224 
    225 	fIFD.SetSingleStrip ();
    226 
    227 	return new dng_preview_tag_set (directory, *this, fIFD);
    228 
    229 	}
    230 
    231 /*****************************************************************************/
    232 
    233 void dng_image_preview::WriteData (dng_host &host,
    234 								   dng_image_writer &writer,
    235 								   dng_basic_tag_set &basic,
    236 								   dng_stream &stream) const
    237 	{
    238 
    239 	writer.WriteImage (host,
    240 					   fIFD,
    241 					   basic,
    242 					   stream,
    243 				       *fImage.Get ());
    244 
    245 	}
    246 
    247 /*****************************************************************************/
    248 
    249 class dng_jpeg_preview_tag_set: public dng_preview_tag_set
    250 	{
    251 
    252 	private:
    253 
    254 		dng_urational fCoefficientsData [3];
    255 
    256 		tag_urational_ptr fCoefficientsTag;
    257 
    258 		uint16 fSubSamplingData [2];
    259 
    260 		tag_uint16_ptr fSubSamplingTag;
    261 
    262 		tag_uint16 fPositioningTag;
    263 
    264 		dng_urational fReferenceData [6];
    265 
    266 		tag_urational_ptr fReferenceTag;
    267 
    268 	public:
    269 
    270 		dng_jpeg_preview_tag_set (dng_tiff_directory &directory,
    271 								  const dng_jpeg_preview &preview,
    272 								  const dng_ifd &ifd);
    273 
    274 		virtual ~dng_jpeg_preview_tag_set ();
    275 
    276 	};
    277 
    278 /******************************************************************************/
    279 
    280 dng_jpeg_preview_tag_set::dng_jpeg_preview_tag_set (dng_tiff_directory &directory,
    281 													const dng_jpeg_preview &preview,
    282 													const dng_ifd &ifd)
    283 
    284 	:	dng_preview_tag_set (directory, preview, ifd)
    285 
    286 	,	fCoefficientsTag (tcYCbCrCoefficients, fCoefficientsData, 3)
    287 
    288 	,	fSubSamplingTag (tcYCbCrSubSampling, fSubSamplingData, 2)
    289 
    290 	,	fPositioningTag (tcYCbCrPositioning, preview.fYCbCrPositioning)
    291 
    292 	,	fReferenceTag (tcReferenceBlackWhite, fReferenceData, 6)
    293 
    294 	{
    295 
    296 	if (preview.fPhotometricInterpretation == piYCbCr)
    297 		{
    298 
    299 		fCoefficientsData [0] = dng_urational (299, 1000);
    300 		fCoefficientsData [1] = dng_urational (587, 1000);
    301 		fCoefficientsData [2] = dng_urational (114, 1000);
    302 
    303 		directory.Add (&fCoefficientsTag);
    304 
    305 		fSubSamplingData [0] = (uint16) preview.fYCbCrSubSampling.h;
    306 		fSubSamplingData [1] = (uint16) preview.fYCbCrSubSampling.v;
    307 
    308 		directory.Add (&fSubSamplingTag);
    309 
    310 		directory.Add (&fPositioningTag);
    311 
    312 		fReferenceData [0] = dng_urational (  0, 1);
    313 		fReferenceData [1] = dng_urational (255, 1);
    314 		fReferenceData [2] = dng_urational (128, 1);
    315 		fReferenceData [3] = dng_urational (255, 1);
    316 		fReferenceData [4] = dng_urational (128, 1);
    317 		fReferenceData [5] = dng_urational (255, 1);
    318 
    319 		directory.Add (&fReferenceTag);
    320 
    321 		}
    322 
    323 	}
    324 
    325 /*****************************************************************************/
    326 
    327 dng_jpeg_preview_tag_set::~dng_jpeg_preview_tag_set ()
    328 	{
    329 
    330 	}
    331 
    332 /*****************************************************************************/
    333 
    334 dng_jpeg_preview::dng_jpeg_preview ()
    335 
    336 	:	fPreviewSize 			   ()
    337 	,	fPhotometricInterpretation (piYCbCr)
    338 	,	fYCbCrSubSampling 		   (1, 1)
    339 	,	fYCbCrPositioning		   (2)
    340 	,	fCompressedData			   ()
    341 
    342 	{
    343 
    344 	}
    345 
    346 /*****************************************************************************/
    347 
    348 dng_jpeg_preview::~dng_jpeg_preview ()
    349 	{
    350 
    351 	}
    352 
    353 /*****************************************************************************/
    354 
    355 dng_basic_tag_set * dng_jpeg_preview::AddTagSet (dng_tiff_directory &directory) const
    356 	{
    357 
    358 	dng_ifd ifd;
    359 
    360 	ifd.fNewSubFileType = fInfo.fIsPrimary ? sfPreviewImage
    361 										   : sfAltPreviewImage;
    362 
    363 	ifd.fImageWidth  = fPreviewSize.h;
    364 	ifd.fImageLength = fPreviewSize.v;
    365 
    366 	ifd.fPhotometricInterpretation = fPhotometricInterpretation;
    367 
    368 	ifd.fBitsPerSample [0] = 8;
    369 	ifd.fBitsPerSample [1] = 8;
    370 	ifd.fBitsPerSample [2] = 8;
    371 
    372 	ifd.fSamplesPerPixel = (fPhotometricInterpretation == piBlackIsZero ? 1 : 3);
    373 
    374 	ifd.fCompression = ccJPEG;
    375 	ifd.fPredictor   = cpNullPredictor;
    376 
    377 	ifd.SetSingleStrip ();
    378 
    379 	return new dng_jpeg_preview_tag_set (directory, *this, ifd);
    380 
    381 	}
    382 
    383 /*****************************************************************************/
    384 
    385 void dng_jpeg_preview::WriteData (dng_host & /* host */,
    386 								  dng_image_writer & /* writer */,
    387 								  dng_basic_tag_set &basic,
    388 								  dng_stream &stream) const
    389 	{
    390 
    391 	basic.SetTileOffset (0, (uint32) stream.Position ());
    392 
    393 	basic.SetTileByteCount (0, fCompressedData->LogicalSize ());
    394 
    395 	stream.Put (fCompressedData->Buffer      (),
    396 				fCompressedData->LogicalSize ());
    397 
    398 	if (fCompressedData->LogicalSize () & 1)
    399 		{
    400 		stream.Put_uint8 (0);
    401 		}
    402 
    403 	}
    404 
    405 /*****************************************************************************/
    406 
    407 void dng_jpeg_preview::SpoolAdobeThumbnail (dng_stream &stream) const
    408 	{
    409 
    410 	DNG_ASSERT (fCompressedData.Get (),
    411 				"SpoolAdobeThumbnail: no data");
    412 
    413 	DNG_ASSERT (fPhotometricInterpretation == piYCbCr,
    414 				"SpoolAdobeThumbnail: Non-YCbCr");
    415 
    416 	uint32 compressedSize = fCompressedData->LogicalSize ();
    417 
    418 	stream.Put_uint32 (DNG_CHAR4 ('8','B','I','M'));
    419 	stream.Put_uint16 (1036);
    420 	stream.Put_uint16 (0);
    421 
    422 	stream.Put_uint32 (compressedSize + 28);
    423 
    424 	uint32 widthBytes = (fPreviewSize.h * 24 + 31) / 32 * 4;
    425 
    426 	stream.Put_uint32 (1);
    427 	stream.Put_uint32 (fPreviewSize.h);
    428 	stream.Put_uint32 (fPreviewSize.v);
    429 	stream.Put_uint32 (widthBytes);
    430 	stream.Put_uint32 (widthBytes * fPreviewSize.v);
    431 	stream.Put_uint32 (compressedSize);
    432 	stream.Put_uint16 (24);
    433 	stream.Put_uint16 (1);
    434 
    435 	stream.Put (fCompressedData->Buffer (),
    436 			    compressedSize);
    437 
    438 	if (compressedSize & 1)
    439 		{
    440 		stream.Put_uint8 (0);
    441 		}
    442 
    443 	}
    444 
    445 /*****************************************************************************/
    446 
    447 class dng_raw_preview_tag_set: public dng_preview_tag_set
    448 	{
    449 
    450 	private:
    451 
    452 		tag_data_ptr fOpcodeList2Tag;
    453 
    454 		tag_uint32_ptr fWhiteLevelTag;
    455 
    456 		uint32 fWhiteLevelData [kMaxColorPlanes];
    457 
    458 	public:
    459 
    460 		dng_raw_preview_tag_set (dng_tiff_directory &directory,
    461 								 const dng_raw_preview &preview,
    462 								 const dng_ifd &ifd);
    463 
    464 		virtual ~dng_raw_preview_tag_set ();
    465 
    466 	};
    467 
    468 /*****************************************************************************/
    469 
    470 dng_raw_preview_tag_set::dng_raw_preview_tag_set (dng_tiff_directory &directory,
    471 												  const dng_raw_preview &preview,
    472 												  const dng_ifd &ifd)
    473 
    474 	:	dng_preview_tag_set (directory, preview, ifd)
    475 
    476 	,	fOpcodeList2Tag (tcOpcodeList2,
    477 						 ttUndefined,
    478 						 0,
    479 						 NULL)
    480 
    481 	,	fWhiteLevelTag (tcWhiteLevel,
    482 						fWhiteLevelData,
    483 						preview.fImage->Planes ())
    484 
    485 	{
    486 
    487 	if (preview.fOpcodeList2Data.Get ())
    488 		{
    489 
    490 		fOpcodeList2Tag.SetData  (preview.fOpcodeList2Data->Buffer      ());
    491 		fOpcodeList2Tag.SetCount (preview.fOpcodeList2Data->LogicalSize ());
    492 
    493 		directory.Add (&fOpcodeList2Tag);
    494 
    495 		}
    496 
    497 	if (preview.fImage->PixelType () == ttFloat)
    498 		{
    499 
    500 		for (uint32 j = 0; j < kMaxColorPlanes; j++)
    501 			{
    502 			fWhiteLevelData [j] = 32768;
    503 			}
    504 
    505 		directory.Add (&fWhiteLevelTag);
    506 
    507 		}
    508 
    509 	}
    510 
    511 /*****************************************************************************/
    512 
    513 dng_raw_preview_tag_set::~dng_raw_preview_tag_set ()
    514 	{
    515 
    516 	}
    517 
    518 /*****************************************************************************/
    519 
    520 dng_raw_preview::dng_raw_preview ()
    521 
    522 	:	fImage				()
    523 	,	fOpcodeList2Data	()
    524 	,	fCompressionQuality (-1)
    525 	,	fIFD				()
    526 
    527 	{
    528 
    529 	}
    530 
    531 /*****************************************************************************/
    532 
    533 dng_raw_preview::~dng_raw_preview ()
    534 	{
    535 
    536 	}
    537 
    538 /*****************************************************************************/
    539 
    540 dng_basic_tag_set * dng_raw_preview::AddTagSet (dng_tiff_directory &directory) const
    541 	{
    542 
    543 	fIFD.fNewSubFileType = sfPreviewImage;
    544 
    545 	fIFD.fImageWidth  = fImage->Width  ();
    546 	fIFD.fImageLength = fImage->Height ();
    547 
    548 	fIFD.fSamplesPerPixel = fImage->Planes ();
    549 
    550 	fIFD.fPhotometricInterpretation = piLinearRaw;
    551 
    552 	if (fImage->PixelType () == ttFloat)
    553 		{
    554 
    555 		fIFD.fCompression = ccDeflate;
    556 
    557 		fIFD.fCompressionQuality = fCompressionQuality;
    558 
    559 		fIFD.fPredictor = cpFloatingPoint;
    560 
    561 		for (uint32 j = 0; j < fIFD.fSamplesPerPixel; j++)
    562 			{
    563 			fIFD.fBitsPerSample [j] = 16;
    564 			fIFD.fSampleFormat  [j] = sfFloatingPoint;
    565 			}
    566 
    567 		fIFD.FindTileSize (512 * 1024);
    568 
    569 		}
    570 
    571 	else
    572 		{
    573 
    574 		fIFD.fCompression = ccLossyJPEG;
    575 
    576 		fIFD.fCompressionQuality = fCompressionQuality;
    577 
    578 		fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
    579 
    580 		for (uint32 j = 1; j < fIFD.fSamplesPerPixel; j++)
    581 			{
    582 			fIFD.fBitsPerSample [j] = fIFD.fBitsPerSample [0];
    583 			}
    584 
    585 		fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel);
    586 
    587 		}
    588 
    589 	return new dng_raw_preview_tag_set (directory, *this, fIFD);
    590 
    591 	}
    592 
    593 /*****************************************************************************/
    594 
    595 void dng_raw_preview::WriteData (dng_host &host,
    596 								 dng_image_writer &writer,
    597 								 dng_basic_tag_set &basic,
    598 								 dng_stream &stream) const
    599 	{
    600 
    601 	writer.WriteImage (host,
    602 					   fIFD,
    603 					   basic,
    604 					   stream,
    605 				       *fImage.Get ());
    606 
    607 	}
    608 
    609 /*****************************************************************************/
    610 
    611 dng_mask_preview::dng_mask_preview ()
    612 
    613 	:	fImage				()
    614 	,	fCompressionQuality (-1)
    615 	,	fIFD				()
    616 
    617 	{
    618 
    619 	}
    620 
    621 /*****************************************************************************/
    622 
    623 dng_mask_preview::~dng_mask_preview ()
    624 	{
    625 
    626 	}
    627 
    628 /*****************************************************************************/
    629 
    630 dng_basic_tag_set * dng_mask_preview::AddTagSet (dng_tiff_directory &directory) const
    631 	{
    632 
    633 	fIFD.fNewSubFileType = sfPreviewMask;
    634 
    635 	fIFD.fImageWidth  = fImage->Width  ();
    636 	fIFD.fImageLength = fImage->Height ();
    637 
    638 	fIFD.fSamplesPerPixel = 1;
    639 
    640 	fIFD.fPhotometricInterpretation = piTransparencyMask;
    641 
    642 	fIFD.fCompression = ccDeflate;
    643 	fIFD.fPredictor   = cpHorizontalDifference;
    644 
    645 	fIFD.fCompressionQuality = fCompressionQuality;
    646 
    647 	fIFD.fBitsPerSample [0] = TagTypeSize (fImage->PixelType ()) * 8;
    648 
    649 	fIFD.FindTileSize (512 * 512 * fIFD.fSamplesPerPixel);
    650 
    651 	return new dng_basic_tag_set (directory, fIFD);
    652 
    653 	}
    654 
    655 /*****************************************************************************/
    656 
    657 void dng_mask_preview::WriteData (dng_host &host,
    658 								  dng_image_writer &writer,
    659 								  dng_basic_tag_set &basic,
    660 								  dng_stream &stream) const
    661 	{
    662 
    663 	writer.WriteImage (host,
    664 					   fIFD,
    665 					   basic,
    666 					   stream,
    667 				       *fImage.Get ());
    668 
    669 	}
    670 
    671 /*****************************************************************************/
    672 
    673 dng_preview_list::dng_preview_list ()
    674 
    675 	:	fCount (0)
    676 
    677 	{
    678 
    679 	}
    680 
    681 /*****************************************************************************/
    682 
    683 dng_preview_list::~dng_preview_list ()
    684 	{
    685 
    686 	}
    687 
    688 /*****************************************************************************/
    689 
    690 void dng_preview_list::Append (AutoPtr<dng_preview> &preview)
    691 	{
    692 
    693 	if (preview.Get ())
    694 		{
    695 
    696 		DNG_ASSERT (fCount < kMaxDNGPreviews, "DNG preview list overflow");
    697 
    698 		if (fCount < kMaxDNGPreviews)
    699 			{
    700 
    701 			fPreview [fCount++] . Reset (preview.Release ());
    702 
    703 			}
    704 
    705 		}
    706 
    707 	}
    708 
    709 /*****************************************************************************/
    710