• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dng_preview_tag_set(dng_tiff_directory & directory,const dng_preview & preview,const dng_ifd & ifd)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 
~dng_preview_tag_set()162 dng_preview_tag_set::~dng_preview_tag_set ()
163 	{
164 
165 	}
166 
167 /*****************************************************************************/
168 
dng_preview()169 dng_preview::dng_preview ()
170 
171 	:	fInfo ()
172 
173 	{
174 
175 	}
176 
177 /*****************************************************************************/
178 
~dng_preview()179 dng_preview::~dng_preview ()
180 	{
181 
182 	}
183 
184 /*****************************************************************************/
185 
dng_image_preview()186 dng_image_preview::dng_image_preview ()
187 
188 	:	fImage ()
189 	,	fIFD   ()
190 
191 	{
192 
193 	}
194 
195 /*****************************************************************************/
196 
~dng_image_preview()197 dng_image_preview::~dng_image_preview ()
198 	{
199 
200 	}
201 
202 /*****************************************************************************/
203 
AddTagSet(dng_tiff_directory & directory) const204 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 
WriteData(dng_host & host,dng_image_writer & writer,dng_basic_tag_set & basic,dng_stream & stream) const233 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 
dng_jpeg_preview_tag_set(dng_tiff_directory & directory,const dng_jpeg_preview & preview,const dng_ifd & ifd)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 
~dng_jpeg_preview_tag_set()327 dng_jpeg_preview_tag_set::~dng_jpeg_preview_tag_set ()
328 	{
329 
330 	}
331 
332 /*****************************************************************************/
333 
dng_jpeg_preview()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 
~dng_jpeg_preview()348 dng_jpeg_preview::~dng_jpeg_preview ()
349 	{
350 
351 	}
352 
353 /*****************************************************************************/
354 
AddTagSet(dng_tiff_directory & directory) const355 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 
WriteData(dng_host &,dng_image_writer &,dng_basic_tag_set & basic,dng_stream & stream) const385 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 
SpoolAdobeThumbnail(dng_stream & stream) const407 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 
dng_raw_preview_tag_set(dng_tiff_directory & directory,const dng_raw_preview & preview,const dng_ifd & ifd)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 
~dng_raw_preview_tag_set()513 dng_raw_preview_tag_set::~dng_raw_preview_tag_set ()
514 	{
515 
516 	}
517 
518 /*****************************************************************************/
519 
dng_raw_preview()520 dng_raw_preview::dng_raw_preview ()
521 
522 	:	fImage				()
523 	,	fOpcodeList2Data	()
524 	,	fCompressionQuality (-1)
525 	,	fIFD				()
526 
527 	{
528 
529 	}
530 
531 /*****************************************************************************/
532 
~dng_raw_preview()533 dng_raw_preview::~dng_raw_preview ()
534 	{
535 
536 	}
537 
538 /*****************************************************************************/
539 
AddTagSet(dng_tiff_directory & directory) const540 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 
WriteData(dng_host & host,dng_image_writer & writer,dng_basic_tag_set & basic,dng_stream & stream) const595 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 
dng_mask_preview()611 dng_mask_preview::dng_mask_preview ()
612 
613 	:	fImage				()
614 	,	fCompressionQuality (-1)
615 	,	fIFD				()
616 
617 	{
618 
619 	}
620 
621 /*****************************************************************************/
622 
~dng_mask_preview()623 dng_mask_preview::~dng_mask_preview ()
624 	{
625 
626 	}
627 
628 /*****************************************************************************/
629 
AddTagSet(dng_tiff_directory & directory) const630 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 
WriteData(dng_host & host,dng_image_writer & writer,dng_basic_tag_set & basic,dng_stream & stream) const657 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 
dng_preview_list()673 dng_preview_list::dng_preview_list ()
674 
675 	:	fCount (0)
676 
677 	{
678 
679 	}
680 
681 /*****************************************************************************/
682 
~dng_preview_list()683 dng_preview_list::~dng_preview_list ()
684 	{
685 
686 	}
687 
688 /*****************************************************************************/
689 
Append(AutoPtr<dng_preview> & preview)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