1 /*****************************************************************************/
2 // Copyright 2006-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 /** \file
10  * Support for writing DNG images to files.
11  */
12 
13 /*****************************************************************************/
14 
15 #ifndef __dng_image_writer__
16 #define __dng_image_writer__
17 
18 /*****************************************************************************/
19 
20 #include "dng_area_task.h"
21 #include "dng_auto_ptr.h"
22 #include "dng_classes.h"
23 #include "dng_fingerprint.h"
24 #include "dng_memory.h"
25 #include "dng_mutex.h"
26 #include "dng_point.h"
27 #include "dng_rational.h"
28 #include "dng_safe_arithmetic.h"
29 #include "dng_sdk_limits.h"
30 #include "dng_string.h"
31 #include "dng_tag_types.h"
32 #include "dng_tag_values.h"
33 #include "dng_types.h"
34 #include "dng_uncopyable.h"
35 
36 #include <atomic>
37 
38 /*****************************************************************************/
39 
40 /// \brief Image resolution.
41 
42 class dng_resolution
43 	{
44 
45 	public:
46 
47 		dng_urational fXResolution;
48 		dng_urational fYResolution;
49 
50 		uint16 fResolutionUnit;
51 
52 	public:
53 
54 		dng_resolution ();
55 
56 	};
57 
58 /*****************************************************************************/
59 
60 class tiff_tag: private dng_uncopyable
61 	{
62 
63 	protected:
64 
65 		uint16 fCode;
66 
67 		uint16 fType;
68 
69 		uint32 fCount;
70 
71 	protected:
72 
tiff_tag(uint16 code,uint16 type,uint32 count)73 		tiff_tag (uint16 code,
74 				  uint16 type,
75 				  uint32 count)
76 
77 			:	fCode  (code)
78 			,	fType  (type)
79 			,	fCount (count)
80 
81 			{
82 			}
83 
84 	public:
85 
~tiff_tag()86 		virtual ~tiff_tag ()
87 			{
88 			}
89 
Code()90 		uint16 Code () const
91 			{
92 			return fCode;
93 			}
94 
Type()95 		uint16 Type () const
96 			{
97 			return fType;
98 			}
99 
Count()100 		uint32 Count () const
101 			{
102 			return fCount;
103 			}
104 
SetCount(uint32 count)105 		void SetCount (uint32 count)
106 			{
107 			fCount = count;
108 			}
109 
Size()110 		uint32 Size () const
111 			{
112 			return TagTypeSize (Type ()) * Count ();
113 			}
114 
115 		virtual void Put (dng_stream &stream) const = 0;
116 
117 	};
118 
119 /******************************************************************************/
120 
121 class tag_data_ptr: public tiff_tag
122 	{
123 
124 	protected:
125 
126 		const void *fData;
127 
128 	public:
129 
tag_data_ptr(uint16 code,uint16 type,uint32 count,const void * data)130 		tag_data_ptr (uint16 code,
131 				      uint16 type,
132 				      uint32 count,
133 				      const void *data)
134 
135 			:	tiff_tag (code, type, count)
136 
137 			,	fData (data)
138 
139 			{
140 			}
141 
SetData(const void * data)142 		void SetData (const void *data)
143 			{
144 			fData = data;
145 			}
146 
147 		virtual void Put (dng_stream &stream) const;
148 
149 	};
150 
151 /******************************************************************************/
152 
153 class tag_string: public tiff_tag
154 	{
155 
156 	protected:
157 
158 		dng_string fString;
159 
160 	public:
161 
162 		tag_string (uint16 code,
163 				    const dng_string &s,
164 				    bool forceASCII = true);
165 
166 		virtual void Put (dng_stream &stream) const;
167 
168 	};
169 
170 /******************************************************************************/
171 
172 class tag_encoded_text: public tiff_tag
173 	{
174 
175 	private:
176 
177 		dng_string fText;
178 
179 		dng_memory_data fUTF16;
180 
181 	public:
182 
183 		tag_encoded_text (uint16 code,
184 						  const dng_string &text);
185 
186 		virtual void Put (dng_stream &stream) const;
187 
188 	};
189 
190 /******************************************************************************/
191 
192 class tag_uint8: public tag_data_ptr
193 	{
194 
195 	private:
196 
197 		uint8 fValue;
198 
199 	public:
200 
201 		tag_uint8 (uint16 code,
202 				   uint8 value = 0)
203 
204 			:	tag_data_ptr (code, ttByte, 1, &fValue)
205 
206 			,	fValue (value)
207 
208 			{
209 			}
210 
Set(uint8 value)211 		void Set (uint8 value)
212 			{
213 			fValue = value;
214 			}
215 
216 	};
217 
218 /******************************************************************************/
219 
220 class tag_uint8_ptr: public tag_data_ptr
221 	{
222 
223 	public:
224 
225 		tag_uint8_ptr (uint16 code,
226 			    	   const uint8 *data,
227 			    	   uint32 count = 1)
228 
tag_data_ptr(code,ttByte,count,data)229 			:	tag_data_ptr (code, ttByte, count, data)
230 
231 			{
232 			}
233 
234 	};
235 
236 /******************************************************************************/
237 
238 class tag_uint16: public tag_data_ptr
239 	{
240 
241 	private:
242 
243 		uint16 fValue;
244 
245 	public:
246 
247 		tag_uint16 (uint16 code,
248 					uint16 value = 0)
249 
250 			:	tag_data_ptr (code, ttShort, 1, &fValue)
251 
252 			,	fValue (value)
253 
254 			{
255 			}
256 
Set(uint16 value)257 		void Set (uint16 value)
258 			{
259 			fValue = value;
260 			}
261 
262 	};
263 
264 /******************************************************************************/
265 
266 class tag_int16_ptr: public tag_data_ptr
267 	{
268 
269 	public:
270 
271 		tag_int16_ptr (uint16 code,
272 				       const int16 *data,
273 				       uint32 count = 1)
274 
tag_data_ptr(code,ttSShort,count,data)275 			:	tag_data_ptr (code, ttSShort, count, data)
276 
277 			{
278 			}
279 
280 	};
281 
282 /******************************************************************************/
283 
284 class tag_uint16_ptr: public tag_data_ptr
285 	{
286 
287 	public:
288 
289 		tag_uint16_ptr (uint16 code,
290 				        const uint16 *data,
291 				        uint32 count = 1)
292 
tag_data_ptr(code,ttShort,count,data)293 			:	tag_data_ptr (code, ttShort, count, data)
294 
295 			{
296 			}
297 
298 	};
299 
300 /******************************************************************************/
301 
302 class tag_uint32: public tag_data_ptr
303 	{
304 
305 	private:
306 
307 		uint32 fValue;
308 
309 	public:
310 
311 		tag_uint32 (uint16 code,
312 				    uint32 value = 0)
313 
314 			:	tag_data_ptr (code, ttLong, 1, &fValue)
315 
316 			,	fValue (value)
317 
318 			{
319 			}
320 
Set(uint32 value)321 		void Set (uint32 value)
322 			{
323 			fValue = value;
324 			}
325 
326 	};
327 
328 /******************************************************************************/
329 
330 class tag_uint32_ptr: public tag_data_ptr
331 	{
332 
333 	public:
334 
335 		tag_uint32_ptr (uint16 code,
336 				 		const uint32 *data,
337 				 		uint32 count = 1)
338 
tag_data_ptr(code,ttLong,count,data)339 			:	tag_data_ptr (code, ttLong, count, data)
340 
341 			{
342 			}
343 
344 	};
345 
346 /******************************************************************************/
347 
348 class tag_urational: public tag_data_ptr
349 	{
350 
351 	private:
352 
353 		const dng_urational fValue;
354 
355 	public:
356 
tag_urational(uint16 code,const dng_urational & value)357 		tag_urational (uint16 code,
358 				       const dng_urational &value)
359 
360 			:	tag_data_ptr (code, ttRational, 1, &fValue)
361 
362 			,	fValue (value)
363 
364 			{
365 			}
366 
367 	};
368 
369 /******************************************************************************/
370 
371 class tag_urational_ptr: public tag_data_ptr
372 	{
373 
374 	public:
375 
376 		tag_urational_ptr (uint16 code,
377 				           const dng_urational *data = NULL,
378 				           uint32 count = 1)
379 
tag_data_ptr(code,ttRational,count,data)380 			:	tag_data_ptr (code, ttRational, count, data)
381 
382 			{
383 			}
384 
385 	};
386 
387 /******************************************************************************/
388 
389 class tag_srational: public tag_data_ptr
390 	{
391 
392 	private:
393 
394 		const dng_srational fValue;
395 
396 	public:
397 
tag_srational(uint16 code,const dng_srational & value)398 		tag_srational (uint16 code,
399 				       const dng_srational &value)
400 
401 			:	tag_data_ptr (code, ttSRational, 1, &fValue)
402 
403 			,	fValue (value)
404 
405 			{
406 			}
407 
408 	};
409 
410 /******************************************************************************/
411 
412 class tag_srational_ptr: public tag_data_ptr
413 	{
414 
415 	public:
416 
417 		tag_srational_ptr (uint16 code,
418 				           const dng_srational *data = NULL,
419 				           uint32 count = 1)
420 
tag_data_ptr(code,ttSRational,count,data)421 			:	tag_data_ptr (code, ttSRational, count, data)
422 
423 			{
424 			}
425 
426 	};
427 
428 /******************************************************************************/
429 
430 class tag_real64: public tag_data_ptr
431 	{
432 
433 	private:
434 
435 		real64 fValue;
436 
437 	public:
438 
439 		tag_real64 (uint16 code,
440 				    real64 value = 0.0)
441 
442 			:	tag_data_ptr (code, ttDouble, 1, &fValue)
443 
444 			,	fValue (value)
445 
446 			{
447 			}
448 
Set(real64 value)449 		void Set (real64 value)
450 			{
451 			fValue = value;
452 			}
453 
454 	};
455 
456 /******************************************************************************/
457 
458 class tag_matrix: public tag_srational_ptr
459 	{
460 
461 	private:
462 
463 		dng_srational fEntry [kMaxColorPlanes *
464 							  kMaxColorPlanes];
465 
466 	public:
467 
468 		tag_matrix (uint16 code,
469 				    const dng_matrix &m);
470 
471 	};
472 
473 /******************************************************************************/
474 
475 class tag_icc_profile: public tag_data_ptr
476 	{
477 
478 	public:
479 
480 		tag_icc_profile (const void *profileData, uint32 profileSize);
481 
482 	};
483 
484 /******************************************************************************/
485 
486 class tag_cfa_pattern: public tiff_tag
487 	{
488 
489 	private:
490 
491 		uint32 fRows;
492 		uint32 fCols;
493 
494 		const uint8 *fPattern;
495 
496 	public:
497 
tag_cfa_pattern(uint16 code,uint32 rows,uint32 cols,const uint8 * pattern)498 		tag_cfa_pattern (uint16 code,
499 					   	 uint32 rows,
500 					     uint32 cols,
501 					   	 const uint8 *pattern)
502 
503 			:	tiff_tag (code, ttUndefined, 4 + rows * cols)
504 
505 			,	fRows    (rows   )
506 			,	fCols    (cols   )
507 			,	fPattern (pattern)
508 
509 			{
510 			}
511 
512 		virtual void Put (dng_stream &stream) const;
513 
514 	};
515 
516 /******************************************************************************/
517 
518 class tag_exif_date_time: public tag_data_ptr
519 	{
520 
521 	private:
522 
523 		char fData [20];
524 
525 	public:
526 
527 		tag_exif_date_time (uint16 code,
528 				            const dng_date_time &dt);
529 
530 	};
531 
532 /******************************************************************************/
533 
534 class tag_iptc: public tiff_tag
535 	{
536 
537 	private:
538 
539 		const void *fData;
540 
541 		uint32 fLength;
542 
543 	public:
544 
545 		tag_iptc (const void *data,
546 				  uint32 length);
547 
548 		virtual void Put (dng_stream &stream) const;
549 
550 	};
551 
552 /******************************************************************************/
553 
554 class tag_xmp: public tag_uint8_ptr
555 	{
556 
557 	private:
558 
559 		AutoPtr<dng_memory_block> fBuffer;
560 
561 	public:
562 
563 		tag_xmp (const dng_xmp *xmp);
564 
565 	};
566 
567 /******************************************************************************/
568 
569 class dng_tiff_directory: private dng_uncopyable
570 	{
571 
572 	private:
573 
574 		enum
575 			{
576 			kMaxEntries = 100
577 			};
578 
579 		uint32 fEntries;
580 
581 		const tiff_tag *fTag [kMaxEntries];
582 
583 		uint32 fChained;
584 
585 	public:
586 
dng_tiff_directory()587 		dng_tiff_directory ()
588 
589 			:	fEntries (0)
590 			,	fChained (0)
591 
592 			{
593 			}
594 
~dng_tiff_directory()595 		virtual ~dng_tiff_directory ()
596 			{
597 			}
598 
599 		void Add (const tiff_tag *tag);
600 
SetChained(uint32 offset)601 		void SetChained (uint32 offset)
602 			{
603 			fChained = offset;
604 			}
605 
606 		uint32 Size () const;
607 
608 		enum OffsetsBase
609 			{
610 			offsetsRelativeToStream			= 0,
611 			offsetsRelativeToExplicitBase	= 1,
612 			offsetsRelativeToIFD			= 2
613 			};
614 
615 		void Put (dng_stream &stream,
616 				  OffsetsBase offsetsBase = offsetsRelativeToStream,
617 				  uint32 explicitBase = 0) const;
618 
619 	};
620 
621 /******************************************************************************/
622 
623 class dng_basic_tag_set: private dng_uncopyable
624 	{
625 
626 	private:
627 
628 		tag_uint32 fNewSubFileType;
629 
630 		tag_uint32 fImageWidth;
631 		tag_uint32 fImageLength;
632 
633 		tag_uint16 fPhotoInterpretation;
634 
635 		tag_uint16 fFillOrder;
636 
637 		tag_uint16 fSamplesPerPixel;
638 
639 		uint16 fBitsPerSampleData [kMaxSamplesPerPixel];
640 
641 		tag_uint16_ptr fBitsPerSample;
642 
643 		bool fStrips;
644 
645 		tag_uint32 fTileWidth;
646 		tag_uint32 fTileLength;
647 
648 		dng_memory_data fTileInfoBuffer;
649 
650 		uint32 *fTileOffsetData;
651 
652 		tag_uint32_ptr fTileOffsets;
653 
654 		uint32 *fTileByteCountData;
655 
656 		tag_uint32_ptr fTileByteCounts;
657 
658 		tag_uint16 fPlanarConfiguration;
659 
660 		tag_uint16 fCompression;
661 
662 		tag_uint16 fPredictor;
663 
664 		uint16 fExtraSamplesData [kMaxSamplesPerPixel];
665 
666 		tag_uint16_ptr fExtraSamples;
667 
668 		uint16 fSampleFormatData [kMaxSamplesPerPixel];
669 
670 		tag_uint16_ptr fSampleFormat;
671 
672 		tag_uint16 fRowInterleaveFactor;
673 
674 		uint16 fSubTileBlockSizeData [2];
675 
676 		tag_uint16_ptr fSubTileBlockSize;
677 
678 	public:
679 
680 		dng_basic_tag_set (dng_tiff_directory &directory,
681 					       const dng_ifd &info);
682 
~dng_basic_tag_set()683 		virtual ~dng_basic_tag_set ()
684 			{
685 			}
686 
SetTileOffset(uint32 index,uint32 offset)687 		void SetTileOffset (uint32 index,
688 							uint32 offset)
689 			{
690 			fTileOffsetData [index] = offset;
691 			}
692 
SetTileByteCount(uint32 index,uint32 count)693 		void SetTileByteCount (uint32 index,
694 							   uint32 count)
695 			{
696 			fTileByteCountData [index] = count;
697 			}
698 
WritingStrips()699 		bool WritingStrips () const
700 			{
701 			return fStrips;
702 			}
703 
704 	};
705 
706 /******************************************************************************/
707 
708 class exif_tag_set: private dng_uncopyable
709 	{
710 
711 	protected:
712 
713 		dng_tiff_directory fExifIFD;
714 		dng_tiff_directory fGPSIFD;
715 
716 	private:
717 
718 		tag_uint32 fExifLink;
719 		tag_uint32 fGPSLink;
720 
721 		bool fAddedExifLink;
722 		bool fAddedGPSLink;
723 
724 		uint8 fExifVersionData [4];
725 
726 		tag_data_ptr fExifVersion;
727 
728 		tag_urational fExposureTime;
729 		tag_srational fShutterSpeedValue;
730 
731 		tag_urational fFNumber;
732 		tag_urational fApertureValue;
733 
734 		tag_srational fBrightnessValue;
735 
736 		tag_srational fExposureBiasValue;
737 
738 		tag_urational fMaxApertureValue;
739 
740 		tag_urational fSubjectDistance;
741 
742 		tag_urational fFocalLength;
743 
744 		tag_uint16 fISOSpeedRatings;
745 
746 		tag_uint16 fSensitivityType;
747 		tag_uint32 fStandardOutputSensitivity;
748 		tag_uint32 fRecommendedExposureIndex;
749 		tag_uint32 fISOSpeed;
750 		tag_uint32 fISOSpeedLatitudeyyy;
751 		tag_uint32 fISOSpeedLatitudezzz;
752 
753 		tag_uint16 fFlash;
754 
755 		tag_uint16 fExposureProgram;
756 
757 		tag_uint16 fMeteringMode;
758 
759 		tag_uint16 fLightSource;
760 
761 		tag_uint16 fSensingMethod;
762 
763 		tag_uint16 fFocalLength35mm;
764 
765 		uint8 fFileSourceData;
766 		tag_data_ptr fFileSource;
767 
768 		uint8 fSceneTypeData;
769 		tag_data_ptr fSceneType;
770 
771 		tag_cfa_pattern fCFAPattern;
772 
773 		tag_uint16 fCustomRendered;
774 		tag_uint16 fExposureMode;
775 		tag_uint16 fWhiteBalance;
776 		tag_uint16 fSceneCaptureType;
777 		tag_uint16 fGainControl;
778 		tag_uint16 fContrast;
779 		tag_uint16 fSaturation;
780 		tag_uint16 fSharpness;
781 		tag_uint16 fSubjectDistanceRange;
782 
783 		tag_urational fDigitalZoomRatio;
784 
785 		tag_urational fExposureIndex;
786 
787 		tag_uint32 fImageNumber;
788 
789 		tag_uint16 fSelfTimerMode;
790 
791 		tag_string    fBatteryLevelA;
792 		tag_urational fBatteryLevelR;
793 
794 		tag_uint16	  fColorSpace;
795 
796 		tag_urational fFocalPlaneXResolution;
797 		tag_urational fFocalPlaneYResolution;
798 
799 		tag_uint16 fFocalPlaneResolutionUnit;
800 
801 		uint16 fSubjectAreaData [4];
802 
803 		tag_uint16_ptr fSubjectArea;
804 
805 		dng_urational fLensInfoData [4];
806 
807 		tag_urational_ptr fLensInfo;
808 
809 		tag_exif_date_time fDateTime;
810 		tag_exif_date_time fDateTimeOriginal;
811 		tag_exif_date_time fDateTimeDigitized;
812 
813 		tag_string fSubsecTime;
814 		tag_string fSubsecTimeOriginal;
815 		tag_string fSubsecTimeDigitized;
816 
817         tag_string fOffsetTime;
818         tag_string fOffsetTimeOriginal;
819         tag_string fOffsetTimeDigitized;
820 
821 		tag_string fMake;
822 		tag_string fModel;
823 		tag_string fArtist;
824 		tag_string fSoftware;
825 		tag_string fCopyright;
826 		tag_string fImageDescription;
827 
828 		tag_string fSerialNumber;
829 
830 		tag_uint16 fMakerNoteSafety;
831 
832 		tag_data_ptr fMakerNote;
833 
834 		tag_encoded_text fUserComment;
835 
836 		char fImageUniqueIDData [33];
837 
838 		tag_data_ptr fImageUniqueID;
839 
840 		// EXIF 2.3 tags.
841 
842 		tag_string fCameraOwnerName;
843 		tag_string fBodySerialNumber;
844 		tag_urational_ptr fLensSpecification;
845 		tag_string fLensMake;
846 		tag_string fLensModel;
847 		tag_string fLensSerialNumber;
848 
849         // EXIF 2.3.1 tags.
850 
851         tag_srational fTemperature;
852         tag_urational fHumidity;
853         tag_urational fPressure;
854         tag_srational fWaterDepth;
855         tag_urational fAcceleration;
856         tag_srational fCameraElevationAngle;
857 
858 		uint8 fGPSVersionData [4];
859 
860 		tag_uint8_ptr fGPSVersionID;
861 
862 		tag_string        fGPSLatitudeRef;
863 		tag_urational_ptr fGPSLatitude;
864 
865 		tag_string        fGPSLongitudeRef;
866 		tag_urational_ptr fGPSLongitude;
867 
868 		tag_uint8     fGPSAltitudeRef;
869 		tag_urational fGPSAltitude;
870 
871 		tag_urational_ptr fGPSTimeStamp;
872 
873 		tag_string fGPSSatellites;
874 		tag_string fGPSStatus;
875 		tag_string fGPSMeasureMode;
876 
877 		tag_urational fGPSDOP;
878 
879 		tag_string    fGPSSpeedRef;
880 		tag_urational fGPSSpeed;
881 
882 		tag_string    fGPSTrackRef;
883 		tag_urational fGPSTrack;
884 
885 		tag_string    fGPSImgDirectionRef;
886 		tag_urational fGPSImgDirection;
887 
888 		tag_string fGPSMapDatum;
889 
890 		tag_string        fGPSDestLatitudeRef;
891 		tag_urational_ptr fGPSDestLatitude;
892 
893 		tag_string         fGPSDestLongitudeRef;
894 		tag_urational_ptr fGPSDestLongitude;
895 
896 		tag_string    fGPSDestBearingRef;
897 		tag_urational fGPSDestBearing;
898 
899 		tag_string    fGPSDestDistanceRef;
900 		tag_urational fGPSDestDistance;
901 
902 		tag_encoded_text fGPSProcessingMethod;
903 		tag_encoded_text fGPSAreaInformation;
904 
905 		tag_string fGPSDateStamp;
906 
907 		tag_uint16 fGPSDifferential;
908 
909 		tag_urational fGPSHPositioningError;
910 
911 	public:
912 
913 		exif_tag_set (dng_tiff_directory &directory,
914 					  const dng_exif &exif,
915 					  bool makerNoteSafe = false,
916 					  const void *makerNoteData = NULL,
917 					  uint32 makerNoteLength = 0,
918 					  bool insideDNG = false);
919 
Locate(uint32 offset)920 		void Locate (uint32 offset)
921 			{
922 			fExifLink.Set (offset);
923 			fGPSLink .Set (offset + fExifIFD.Size ());
924 			}
925 
Size()926 		uint32 Size () const
927 			{
928 			return fExifIFD.Size () +
929 				   fGPSIFD .Size ();
930 			}
931 
Put(dng_stream & stream)932 		void Put (dng_stream &stream) const
933 			{
934 			fExifIFD.Put (stream);
935 			fGPSIFD .Put (stream);
936 			}
937 
938 	protected:
939 
940 		void AddLinks (dng_tiff_directory &directory);
941 
942 	};
943 
944 /******************************************************************************/
945 
946 class tiff_dng_extended_color_profile: private dng_tiff_directory
947 	{
948 
949 	protected:
950 
951 		const dng_camera_profile &fProfile;
952 
953 	public:
954 
955 		tiff_dng_extended_color_profile (const dng_camera_profile &profile);
956 
957 		void Put (dng_stream &stream,
958 				  bool includeModelRestriction = true);
959 
960 	};
961 
962 /*****************************************************************************/
963 
964 class tag_dng_noise_profile: public tag_data_ptr
965 	{
966 
967 	protected:
968 
969 		real64 fValues [2 * kMaxColorPlanes];
970 
971 	public:
972 
973 		explicit tag_dng_noise_profile (const dng_noise_profile &profile);
974 
975 	};
976 
977 /*****************************************************************************/
978 
979 // Enum to control the subset of metadata to save to a file.
980 
981 enum dng_metadata_subset
982 	{
983 
984 	kMetadataSubset_CopyrightOnly = 0,
985 	kMetadataSubset_CopyrightAndContact,
986 	kMetadataSubset_AllExceptCameraInfo,
987 	kMetadataSubset_All,
988 	kMetadataSubset_AllExceptLocationInfo,
989 	kMetadataSubset_AllExceptCameraAndLocation,
990     KMetadataSubset_AllExceptCameraRawInfo,
991 	KMetadataSubset_AllExceptCameraRawInfoAndLocation,
992 
993     kMetadataSubset_Last = KMetadataSubset_AllExceptCameraRawInfoAndLocation
994 
995 	};
996 
997 /*****************************************************************************/
998 
999 /// \brief Support for writing dng_image or dng_negative instances to a
1000 /// dng_stream in TIFF or DNG format.
1001 
1002 class dng_image_writer
1003 	{
1004 
1005 	friend class dng_jpeg_image;
1006 	friend class dng_jpeg_image_encode_task;
1007 	friend class dng_write_tiles_task;
1008 
1009 	protected:
1010 
1011 		enum
1012 			{
1013 
1014 			// Target size for buffer used to copy data to the image.
1015 
1016 			kImageBufferSize = 128 * 1024
1017 
1018 			};
1019 
1020 	public:
1021 
1022 		dng_image_writer ();
1023 
1024 		virtual ~dng_image_writer ();
1025 
1026 		virtual void EncodeJPEGPreview (dng_host &host,
1027 							            const dng_image &image,
1028 							            dng_jpeg_preview &preview,
1029 							            int32 quality = -1);
1030 
1031 		virtual void WriteImage (dng_host &host,
1032 						         const dng_ifd &ifd,
1033 						         dng_basic_tag_set &basic,
1034 						         dng_stream &stream,
1035 						         const dng_image &image,
1036 						         uint32 fakeChannels = 1);
1037 
1038 		/// Write a dng_image to a dng_stream in TIFF format.
1039 		/// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
1040 		/// \param stream The dng_stream on which to write the TIFF.
1041 		/// \param image The actual image data to be written.
1042 		/// \param photometricInterpretation Either piBlackIsZero for monochrome or piRGB for RGB images.
1043 		/// \param compression Must be ccUncompressed.
1044 		/// \param negative or metadata If non-NULL, EXIF, IPTC, and XMP metadata from this negative is written to TIFF.
1045 		/// \param space If non-null and color space has an ICC profile, TIFF will be tagged with this
1046 		/// profile. No color space conversion of image data occurs.
1047 		/// \param resolution If non-NULL, TIFF will be tagged with this resolution.
1048 		/// \param thumbnail If non-NULL, will be stored in TIFF as preview image.
1049 		/// \param imageResources If non-NULL, will image resources be stored in TIFF as well.
1050 		/// \param metadataSubset The subset of metadata (e.g., copyright only) to include in the TIFF.
1051 
1052 		void WriteTIFF (dng_host &host,
1053 						dng_stream &stream,
1054 						const dng_image &image,
1055 						uint32 photometricInterpretation,
1056 						uint32 compression,
1057 						dng_negative *negative,
1058 						const dng_color_space *space = NULL,
1059 						const dng_resolution *resolution = NULL,
1060 						const dng_jpeg_preview *thumbnail = NULL,
1061 						const dng_memory_block *imageResources = NULL,
1062 						dng_metadata_subset metadataSubset = kMetadataSubset_All,
1063                         bool hasTransparency = false);
1064 
1065 		void WriteTIFF (dng_host &host,
1066 						dng_stream &stream,
1067 						const dng_image &image,
1068 						uint32 photometricInterpretation = piBlackIsZero,
1069 						uint32 compression = ccUncompressed,
1070 						const dng_metadata *metadata = NULL,
1071 						const dng_color_space *space = NULL,
1072 						const dng_resolution *resolution = NULL,
1073 						const dng_jpeg_preview *thumbnail = NULL,
1074 						const dng_memory_block *imageResources = NULL,
1075 						dng_metadata_subset metadataSubset = kMetadataSubset_All,
1076                         bool hasTransparency = false);
1077 
1078 		/// Write a dng_image to a dng_stream in TIFF format.
1079 		/// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
1080 		/// \param stream The dng_stream on which to write the TIFF.
1081 		/// \param image The actual image data to be written.
1082 		/// \param photometricInterpretation Either piBlackIsZero for monochrome or piRGB for RGB images.
1083 		/// \param compression Must be ccUncompressed.
1084 		/// \param negative or metadata If non-NULL, EXIF, IPTC, and XMP metadata from this negative is written to TIFF.
1085 		/// \param profileData If non-null, TIFF will be tagged with this profile. No color space conversion
1086 		/// of image data occurs.
1087 		/// \param profileSize The size for the profile data.
1088 		/// \param resolution If non-NULL, TIFF will be tagged with this resolution.
1089 		/// \param thumbnail If non-NULL, will be stored in TIFF as preview image.
1090 		/// \param imageResources If non-NULL, will image resources be stored in TIFF as well.
1091 		/// \param metadataSubset The subset of metadata (e.g., copyright only) to include in the TIFF.
1092 
1093 		void WriteTIFFWithProfile (dng_host &host,
1094 								   dng_stream &stream,
1095 								   const dng_image &image,
1096 								   uint32 photometricInterpretation,
1097 								   uint32 compression,
1098 								   dng_negative *negative,
1099 								   const void *profileData = NULL,
1100 								   uint32 profileSize = 0,
1101 								   const dng_resolution *resolution = NULL,
1102 								   const dng_jpeg_preview *thumbnail = NULL,
1103 								   const dng_memory_block *imageResources = NULL,
1104 								   dng_metadata_subset metadataSubset = kMetadataSubset_All,
1105                                    bool hasTransparency = false);
1106 
1107 		virtual void WriteTIFFWithProfile (dng_host &host,
1108 										   dng_stream &stream,
1109 										   const dng_image &image,
1110 										   uint32 photometricInterpretation = piBlackIsZero,
1111 										   uint32 compression = ccUncompressed,
1112 										   const dng_metadata *metadata = NULL,
1113 										   const void *profileData = NULL,
1114 										   uint32 profileSize = 0,
1115 										   const dng_resolution *resolution = NULL,
1116 										   const dng_jpeg_preview *thumbnail = NULL,
1117 										   const dng_memory_block *imageResources = NULL,
1118 										   dng_metadata_subset metadataSubset = kMetadataSubset_All,
1119                                            bool hasTransparency = false);
1120 
1121 		/// Write a dng_image to a dng_stream in DNG format.
1122 		/// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
1123 		/// \param stream The dng_stream on which to write the TIFF.
1124 		/// \param negative The image data and metadata (EXIF, IPTC, XMP) to be written.
1125 		/// \param previewList List of previews (not counting thumbnail) to write to the file. Defaults to empty.
1126 		/// \param maxBackwardVersion The DNG file should be readable by readers at least back to this version.
1127 		/// \param uncompressed True to force uncompressed images. Otherwise use normal compression.
1128 
1129 		void WriteDNG (dng_host &host,
1130 					   dng_stream &stream,
1131 					   dng_negative &negative,
1132 					   const dng_preview_list *previewList = NULL,
1133 					   uint32 maxBackwardVersion = dngVersion_SaveDefault,
1134 					   bool uncompressed = false);
1135 
1136 		/// Write a dng_image to a dng_stream in DNG format.
1137 		/// \param host Host interface used for progress updates, abort testing, buffer allocation, etc.
1138 		/// \param stream The dng_stream on which to write the TIFF.
1139 		/// \param negative The image data to be written.
1140 		/// \param metadata The metadata (EXIF, IPTC, XMP) to be written.
1141 		/// \param previewList List of previews (not counting thumbnail) to write to the file. Defaults to empty.
1142 		/// \param maxBackwardVersion The DNG file should be readable by readers at least back to this version.
1143 		/// \param uncompressed True to force uncompressed images. Otherwise use normal compression.
1144 
1145 		virtual void WriteDNGWithMetadata (dng_host &host,
1146 										   dng_stream &stream,
1147 										   const dng_negative &negative,
1148 										   const dng_metadata &metadata,
1149 										   const dng_preview_list *previewList = NULL,
1150 										   uint32 maxBackwardVersion = dngVersion_SaveDefault,
1151 										   bool uncompressed = false);
1152 
1153 		/// Resolve metadata conflicts and apply metadata policies in keeping
1154 		/// with Metadata Working Group (MWG) guidelines.
1155 
1156 		virtual void CleanUpMetadata (dng_host &host,
1157 									  dng_metadata &metadata,
1158 									  dng_metadata_subset metadataSubset,
1159 									  const char *dstMIME,
1160 									  const char *software = NULL);
1161 
1162 	protected:
1163 
1164 		virtual void UpdateExifColorSpaceTag (dng_metadata &metadata,
1165 											  const void *profileData,
1166 											  const uint32 profileSize);
1167 
1168 		virtual uint32 CompressedBufferSize (const dng_ifd &ifd,
1169 											 uint32 uncompressedSize);
1170 
1171 		virtual void EncodePredictor (dng_host &host,
1172 									  const dng_ifd &ifd,
1173 						        	  dng_pixel_buffer &buffer,
1174 									  AutoPtr<dng_memory_block> &tempBuffer);
1175 
1176 		virtual void ByteSwapBuffer (dng_host &host,
1177 									 dng_pixel_buffer &buffer);
1178 
1179 		void ReorderSubTileBlocks (const dng_ifd &ifd,
1180 								   dng_pixel_buffer &buffer,
1181 								   AutoPtr<dng_memory_block> &uncompressedBuffer,
1182 								   AutoPtr<dng_memory_block> &subTileBlockBuffer);
1183 
1184 		virtual void WriteData (dng_host &host,
1185 								const dng_ifd &ifd,
1186 						        dng_stream &stream,
1187 						        dng_pixel_buffer &buffer,
1188 								AutoPtr<dng_memory_block> &compressedBuffer,
1189                                 bool usingMultipleThreads);
1190 
1191 		virtual void WriteTile (dng_host &host,
1192 						        const dng_ifd &ifd,
1193 						        dng_stream &stream,
1194 						        const dng_image &image,
1195 						        const dng_rect &tileArea,
1196 						        uint32 fakeChannels,
1197 								AutoPtr<dng_memory_block> &compressedBuffer,
1198 								AutoPtr<dng_memory_block> &uncompressedBuffer,
1199 								AutoPtr<dng_memory_block> &subTileBlockBuffer,
1200 								AutoPtr<dng_memory_block> &tempBuffer,
1201                                 bool usingMultipleThreads);
1202 
1203 		virtual void DoWriteTiles (dng_host &host,
1204 								   const dng_ifd &ifd,
1205 								   dng_basic_tag_set &basic,
1206 								   dng_stream &stream,
1207 								   const dng_image &image,
1208 								   uint32 fakeChannels,
1209 								   uint32 tilesDown,
1210 								   uint32 tilesAcross,
1211 								   uint32 compressedSize,
1212 								   const dng_safe_uint32 &uncompressedSize);
1213 
1214 	};
1215 
1216 /*****************************************************************************/
1217 
1218 class dng_write_tiles_task : public dng_area_task,
1219 							 private dng_uncopyable
1220 	{
1221 
1222 	protected:
1223 
1224 		dng_image_writer &fImageWriter;
1225 
1226 		dng_host &fHost;
1227 
1228 		const dng_ifd &fIFD;
1229 
1230 		dng_basic_tag_set &fBasic;
1231 
1232 		dng_stream &fStream;
1233 
1234 		const dng_image &fImage;
1235 
1236 		uint32 fFakeChannels;
1237 
1238 		uint32 fTilesDown;
1239 
1240 		uint32 fTilesAcross;
1241 
1242 		uint32 fCompressedSize;
1243 
1244 		uint32 fUncompressedSize;
1245 
1246 		std::atomic_uint fNextTileIndex;
1247 
1248 		dng_mutex fMutex;
1249 
1250 		dng_condition fCondition;
1251 
1252 		bool fTaskFailed;
1253 
1254 		uint32 fWriteTileIndex;
1255 
1256 	public:
1257 
1258 		dng_write_tiles_task (dng_image_writer &imageWriter,
1259 							  dng_host &host,
1260 							  const dng_ifd &ifd,
1261 							  dng_basic_tag_set &basic,
1262 							  dng_stream &stream,
1263 							  const dng_image &image,
1264 							  uint32 fakeChannels,
1265 							  uint32 tilesDown,
1266 							  uint32 tilesAcross,
1267 							  uint32 compressedSize,
1268 							  uint32 uncompressedSize);
1269 
1270 		void Process (uint32 threadIndex,
1271 					  const dng_rect &tile,
1272 					  dng_abort_sniffer *sniffer);
1273 
1274 	protected:
1275 
1276 		void ProcessTask (uint32 tileIndex,
1277 						  AutoPtr<dng_memory_block> &compressedBuffer,
1278 						  AutoPtr<dng_memory_block> &uncompressedBuffer,
1279 						  AutoPtr<dng_memory_block> &subTileBlockBuffer,
1280 						  AutoPtr<dng_memory_block> &tempBuffer,
1281 						  uint32 &tileByteCount, // output
1282 						  dng_memory_stream &tileStream, // output
1283 						  dng_abort_sniffer *sniffer);
1284 
1285 		void WriteTask (uint32 tileIndex,
1286 					    uint32 tileByteCount,
1287 					    dng_memory_stream &tileStream,
1288 						dng_abort_sniffer *sniffer);
1289 
1290 	};
1291 
1292 /*****************************************************************************/
1293 
1294 #endif
1295 
1296 /*****************************************************************************/
1297