xref: /aosp_15_r20/external/dng_sdk/source/dng_image_writer.cpp (revision fd1fabb72dbdf09ea7034f531e6f8e9f57334c8d)
1*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
2*fd1fabb7SAndroid Build Coastguard Worker // Copyright 2006-2012 Adobe Systems Incorporated
3*fd1fabb7SAndroid Build Coastguard Worker // All Rights Reserved.
4*fd1fabb7SAndroid Build Coastguard Worker //
5*fd1fabb7SAndroid Build Coastguard Worker // NOTICE:  Adobe permits you to use, modify, and distribute this file in
6*fd1fabb7SAndroid Build Coastguard Worker // accordance with the terms of the Adobe license agreement accompanying it.
7*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
8*fd1fabb7SAndroid Build Coastguard Worker 
9*fd1fabb7SAndroid Build Coastguard Worker /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_image_writer.cpp#4 $ */
10*fd1fabb7SAndroid Build Coastguard Worker /* $DateTime: 2012/06/14 20:24:41 $ */
11*fd1fabb7SAndroid Build Coastguard Worker /* $Change: 835078 $ */
12*fd1fabb7SAndroid Build Coastguard Worker /* $Author: tknoll $ */
13*fd1fabb7SAndroid Build Coastguard Worker 
14*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
15*fd1fabb7SAndroid Build Coastguard Worker 
16*fd1fabb7SAndroid Build Coastguard Worker #include "dng_image_writer.h"
17*fd1fabb7SAndroid Build Coastguard Worker 
18*fd1fabb7SAndroid Build Coastguard Worker #include "dng_abort_sniffer.h"
19*fd1fabb7SAndroid Build Coastguard Worker #include "dng_area_task.h"
20*fd1fabb7SAndroid Build Coastguard Worker #include "dng_bottlenecks.h"
21*fd1fabb7SAndroid Build Coastguard Worker #include "dng_camera_profile.h"
22*fd1fabb7SAndroid Build Coastguard Worker #include "dng_color_space.h"
23*fd1fabb7SAndroid Build Coastguard Worker #include "dng_exif.h"
24*fd1fabb7SAndroid Build Coastguard Worker #include "dng_flags.h"
25*fd1fabb7SAndroid Build Coastguard Worker #include "dng_exceptions.h"
26*fd1fabb7SAndroid Build Coastguard Worker #include "dng_host.h"
27*fd1fabb7SAndroid Build Coastguard Worker #include "dng_ifd.h"
28*fd1fabb7SAndroid Build Coastguard Worker #include "dng_image.h"
29*fd1fabb7SAndroid Build Coastguard Worker #include "dng_jpeg_image.h"
30*fd1fabb7SAndroid Build Coastguard Worker #include "dng_lossless_jpeg.h"
31*fd1fabb7SAndroid Build Coastguard Worker #include "dng_memory.h"
32*fd1fabb7SAndroid Build Coastguard Worker #include "dng_memory_stream.h"
33*fd1fabb7SAndroid Build Coastguard Worker #include "dng_negative.h"
34*fd1fabb7SAndroid Build Coastguard Worker #include "dng_pixel_buffer.h"
35*fd1fabb7SAndroid Build Coastguard Worker #include "dng_preview.h"
36*fd1fabb7SAndroid Build Coastguard Worker #include "dng_read_image.h"
37*fd1fabb7SAndroid Build Coastguard Worker #include "dng_safe_arithmetic.h"
38*fd1fabb7SAndroid Build Coastguard Worker #include "dng_stream.h"
39*fd1fabb7SAndroid Build Coastguard Worker #include "dng_string_list.h"
40*fd1fabb7SAndroid Build Coastguard Worker #include "dng_tag_codes.h"
41*fd1fabb7SAndroid Build Coastguard Worker #include "dng_tag_values.h"
42*fd1fabb7SAndroid Build Coastguard Worker #include "dng_utils.h"
43*fd1fabb7SAndroid Build Coastguard Worker 
44*fd1fabb7SAndroid Build Coastguard Worker #if qDNGUseXMP
45*fd1fabb7SAndroid Build Coastguard Worker #include "dng_xmp.h"
46*fd1fabb7SAndroid Build Coastguard Worker #endif
47*fd1fabb7SAndroid Build Coastguard Worker 
48*fd1fabb7SAndroid Build Coastguard Worker #include "zlib.h"
49*fd1fabb7SAndroid Build Coastguard Worker 
50*fd1fabb7SAndroid Build Coastguard Worker #if qDNGUseLibJPEG
51*fd1fabb7SAndroid Build Coastguard Worker #include "dng_jpeglib.h"
52*fd1fabb7SAndroid Build Coastguard Worker #endif
53*fd1fabb7SAndroid Build Coastguard Worker 
54*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
55*fd1fabb7SAndroid Build Coastguard Worker 
56*fd1fabb7SAndroid Build Coastguard Worker // Defines for testing DNG 1.2 features.
57*fd1fabb7SAndroid Build Coastguard Worker 
58*fd1fabb7SAndroid Build Coastguard Worker //#define qTestRowInterleave 2
59*fd1fabb7SAndroid Build Coastguard Worker 
60*fd1fabb7SAndroid Build Coastguard Worker //#define qTestSubTileBlockRows 2
61*fd1fabb7SAndroid Build Coastguard Worker //#define qTestSubTileBlockCols 2
62*fd1fabb7SAndroid Build Coastguard Worker 
63*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
64*fd1fabb7SAndroid Build Coastguard Worker 
dng_resolution()65*fd1fabb7SAndroid Build Coastguard Worker dng_resolution::dng_resolution ()
66*fd1fabb7SAndroid Build Coastguard Worker 
67*fd1fabb7SAndroid Build Coastguard Worker 	:	fXResolution ()
68*fd1fabb7SAndroid Build Coastguard Worker 	,	fYResolution ()
69*fd1fabb7SAndroid Build Coastguard Worker 
70*fd1fabb7SAndroid Build Coastguard Worker 	,	fResolutionUnit (0)
71*fd1fabb7SAndroid Build Coastguard Worker 
72*fd1fabb7SAndroid Build Coastguard Worker 	{
73*fd1fabb7SAndroid Build Coastguard Worker 
74*fd1fabb7SAndroid Build Coastguard Worker 	}
75*fd1fabb7SAndroid Build Coastguard Worker 
76*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
77*fd1fabb7SAndroid Build Coastguard Worker 
SpoolAdobeData(dng_stream & stream,const dng_metadata * metadata,const dng_jpeg_preview * preview,const dng_memory_block * imageResources)78*fd1fabb7SAndroid Build Coastguard Worker static void SpoolAdobeData (dng_stream &stream,
79*fd1fabb7SAndroid Build Coastguard Worker 							const dng_metadata *metadata,
80*fd1fabb7SAndroid Build Coastguard Worker 							const dng_jpeg_preview *preview,
81*fd1fabb7SAndroid Build Coastguard Worker 							const dng_memory_block *imageResources)
82*fd1fabb7SAndroid Build Coastguard Worker 	{
83*fd1fabb7SAndroid Build Coastguard Worker 
84*fd1fabb7SAndroid Build Coastguard Worker 	TempBigEndian tempEndian (stream);
85*fd1fabb7SAndroid Build Coastguard Worker 
86*fd1fabb7SAndroid Build Coastguard Worker 	#if qDNGUseXMP
87*fd1fabb7SAndroid Build Coastguard Worker 
88*fd1fabb7SAndroid Build Coastguard Worker 	if (metadata && metadata->GetXMP ())
89*fd1fabb7SAndroid Build Coastguard Worker 		{
90*fd1fabb7SAndroid Build Coastguard Worker 
91*fd1fabb7SAndroid Build Coastguard Worker 		bool marked = false;
92*fd1fabb7SAndroid Build Coastguard Worker 
93*fd1fabb7SAndroid Build Coastguard Worker 		if (metadata->GetXMP ()->GetBoolean (XMP_NS_XAP_RIGHTS,
94*fd1fabb7SAndroid Build Coastguard Worker 											 "Marked",
95*fd1fabb7SAndroid Build Coastguard Worker 											 marked))
96*fd1fabb7SAndroid Build Coastguard Worker 			{
97*fd1fabb7SAndroid Build Coastguard Worker 
98*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint32 (DNG_CHAR4 ('8','B','I','M'));
99*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint16 (1034);
100*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint16 (0);
101*fd1fabb7SAndroid Build Coastguard Worker 
102*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint32 (1);
103*fd1fabb7SAndroid Build Coastguard Worker 
104*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint8 (marked ? 1 : 0);
105*fd1fabb7SAndroid Build Coastguard Worker 
106*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint8 (0);
107*fd1fabb7SAndroid Build Coastguard Worker 
108*fd1fabb7SAndroid Build Coastguard Worker 			}
109*fd1fabb7SAndroid Build Coastguard Worker 
110*fd1fabb7SAndroid Build Coastguard Worker 		dng_string webStatement;
111*fd1fabb7SAndroid Build Coastguard Worker 
112*fd1fabb7SAndroid Build Coastguard Worker 		if (metadata->GetXMP ()->GetString (XMP_NS_XAP_RIGHTS,
113*fd1fabb7SAndroid Build Coastguard Worker 											"WebStatement",
114*fd1fabb7SAndroid Build Coastguard Worker 											webStatement))
115*fd1fabb7SAndroid Build Coastguard Worker 			{
116*fd1fabb7SAndroid Build Coastguard Worker 
117*fd1fabb7SAndroid Build Coastguard Worker 			dng_memory_data buffer;
118*fd1fabb7SAndroid Build Coastguard Worker 
119*fd1fabb7SAndroid Build Coastguard Worker 			uint32 size = webStatement.Get_SystemEncoding (buffer);
120*fd1fabb7SAndroid Build Coastguard Worker 
121*fd1fabb7SAndroid Build Coastguard Worker 			if (size > 0)
122*fd1fabb7SAndroid Build Coastguard Worker 				{
123*fd1fabb7SAndroid Build Coastguard Worker 
124*fd1fabb7SAndroid Build Coastguard Worker 				stream.Put_uint32 (DNG_CHAR4 ('8','B','I','M'));
125*fd1fabb7SAndroid Build Coastguard Worker 				stream.Put_uint16 (1035);
126*fd1fabb7SAndroid Build Coastguard Worker 				stream.Put_uint16 (0);
127*fd1fabb7SAndroid Build Coastguard Worker 
128*fd1fabb7SAndroid Build Coastguard Worker 				stream.Put_uint32 (size);
129*fd1fabb7SAndroid Build Coastguard Worker 
130*fd1fabb7SAndroid Build Coastguard Worker 				stream.Put (buffer.Buffer (), size);
131*fd1fabb7SAndroid Build Coastguard Worker 
132*fd1fabb7SAndroid Build Coastguard Worker 				if (size & 1)
133*fd1fabb7SAndroid Build Coastguard Worker 					stream.Put_uint8 (0);
134*fd1fabb7SAndroid Build Coastguard Worker 
135*fd1fabb7SAndroid Build Coastguard Worker 				}
136*fd1fabb7SAndroid Build Coastguard Worker 
137*fd1fabb7SAndroid Build Coastguard Worker 			}
138*fd1fabb7SAndroid Build Coastguard Worker 
139*fd1fabb7SAndroid Build Coastguard Worker 		}
140*fd1fabb7SAndroid Build Coastguard Worker 
141*fd1fabb7SAndroid Build Coastguard Worker 	#endif
142*fd1fabb7SAndroid Build Coastguard Worker 
143*fd1fabb7SAndroid Build Coastguard Worker 	if (preview)
144*fd1fabb7SAndroid Build Coastguard Worker 		{
145*fd1fabb7SAndroid Build Coastguard Worker 
146*fd1fabb7SAndroid Build Coastguard Worker 		preview->SpoolAdobeThumbnail (stream);
147*fd1fabb7SAndroid Build Coastguard Worker 
148*fd1fabb7SAndroid Build Coastguard Worker 		}
149*fd1fabb7SAndroid Build Coastguard Worker 
150*fd1fabb7SAndroid Build Coastguard Worker 	if (metadata && metadata->IPTCLength ())
151*fd1fabb7SAndroid Build Coastguard Worker 		{
152*fd1fabb7SAndroid Build Coastguard Worker 
153*fd1fabb7SAndroid Build Coastguard Worker 		dng_fingerprint iptcDigest = metadata->IPTCDigest ();
154*fd1fabb7SAndroid Build Coastguard Worker 
155*fd1fabb7SAndroid Build Coastguard Worker 		if (iptcDigest.IsValid ())
156*fd1fabb7SAndroid Build Coastguard Worker 			{
157*fd1fabb7SAndroid Build Coastguard Worker 
158*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint32 (DNG_CHAR4 ('8','B','I','M'));
159*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint16 (1061);
160*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint16 (0);
161*fd1fabb7SAndroid Build Coastguard Worker 
162*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint32 (16);
163*fd1fabb7SAndroid Build Coastguard Worker 
164*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put (iptcDigest.data, 16);
165*fd1fabb7SAndroid Build Coastguard Worker 
166*fd1fabb7SAndroid Build Coastguard Worker 			}
167*fd1fabb7SAndroid Build Coastguard Worker 
168*fd1fabb7SAndroid Build Coastguard Worker 		}
169*fd1fabb7SAndroid Build Coastguard Worker 
170*fd1fabb7SAndroid Build Coastguard Worker 	if (imageResources)
171*fd1fabb7SAndroid Build Coastguard Worker 		{
172*fd1fabb7SAndroid Build Coastguard Worker 
173*fd1fabb7SAndroid Build Coastguard Worker 		uint32 size = imageResources->LogicalSize ();
174*fd1fabb7SAndroid Build Coastguard Worker 
175*fd1fabb7SAndroid Build Coastguard Worker 		stream.Put (imageResources->Buffer (), size);
176*fd1fabb7SAndroid Build Coastguard Worker 
177*fd1fabb7SAndroid Build Coastguard Worker 		if (size & 1)
178*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint8 (0);
179*fd1fabb7SAndroid Build Coastguard Worker 
180*fd1fabb7SAndroid Build Coastguard Worker 		}
181*fd1fabb7SAndroid Build Coastguard Worker 
182*fd1fabb7SAndroid Build Coastguard Worker 	}
183*fd1fabb7SAndroid Build Coastguard Worker 
184*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
185*fd1fabb7SAndroid Build Coastguard Worker 
BuildAdobeData(dng_host & host,const dng_metadata * metadata,const dng_jpeg_preview * preview,const dng_memory_block * imageResources)186*fd1fabb7SAndroid Build Coastguard Worker static dng_memory_block * BuildAdobeData (dng_host &host,
187*fd1fabb7SAndroid Build Coastguard Worker 										  const dng_metadata *metadata,
188*fd1fabb7SAndroid Build Coastguard Worker 										  const dng_jpeg_preview *preview,
189*fd1fabb7SAndroid Build Coastguard Worker 										  const dng_memory_block *imageResources)
190*fd1fabb7SAndroid Build Coastguard Worker 	{
191*fd1fabb7SAndroid Build Coastguard Worker 
192*fd1fabb7SAndroid Build Coastguard Worker 	dng_memory_stream stream (host.Allocator ());
193*fd1fabb7SAndroid Build Coastguard Worker 
194*fd1fabb7SAndroid Build Coastguard Worker 	SpoolAdobeData (stream,
195*fd1fabb7SAndroid Build Coastguard Worker 					metadata,
196*fd1fabb7SAndroid Build Coastguard Worker 					preview,
197*fd1fabb7SAndroid Build Coastguard Worker 					imageResources);
198*fd1fabb7SAndroid Build Coastguard Worker 
199*fd1fabb7SAndroid Build Coastguard Worker 	return stream.AsMemoryBlock (host.Allocator ());
200*fd1fabb7SAndroid Build Coastguard Worker 
201*fd1fabb7SAndroid Build Coastguard Worker 	}
202*fd1fabb7SAndroid Build Coastguard Worker 
203*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
204*fd1fabb7SAndroid Build Coastguard Worker 
tag_string(uint16 code,const dng_string & s,bool forceASCII)205*fd1fabb7SAndroid Build Coastguard Worker tag_string::tag_string (uint16 code,
206*fd1fabb7SAndroid Build Coastguard Worker 				    	const dng_string &s,
207*fd1fabb7SAndroid Build Coastguard Worker 				    	bool forceASCII)
208*fd1fabb7SAndroid Build Coastguard Worker 
209*fd1fabb7SAndroid Build Coastguard Worker 	:	tiff_tag (code, ttAscii, 0)
210*fd1fabb7SAndroid Build Coastguard Worker 
211*fd1fabb7SAndroid Build Coastguard Worker 	,	fString (s)
212*fd1fabb7SAndroid Build Coastguard Worker 
213*fd1fabb7SAndroid Build Coastguard Worker 	{
214*fd1fabb7SAndroid Build Coastguard Worker 
215*fd1fabb7SAndroid Build Coastguard Worker 	if (forceASCII)
216*fd1fabb7SAndroid Build Coastguard Worker 		{
217*fd1fabb7SAndroid Build Coastguard Worker 
218*fd1fabb7SAndroid Build Coastguard Worker 		// Metadata working group recommendation - go ahead
219*fd1fabb7SAndroid Build Coastguard Worker 		// write UTF-8 into ASCII tag strings, rather than
220*fd1fabb7SAndroid Build Coastguard Worker 		// actually force the strings to ASCII.  There is a matching
221*fd1fabb7SAndroid Build Coastguard Worker 		// change on the reading side to assume UTF-8 if the string
222*fd1fabb7SAndroid Build Coastguard Worker 		// contains a valid UTF-8 string.
223*fd1fabb7SAndroid Build Coastguard Worker 		//
224*fd1fabb7SAndroid Build Coastguard Worker 		// fString.ForceASCII ();
225*fd1fabb7SAndroid Build Coastguard Worker 
226*fd1fabb7SAndroid Build Coastguard Worker 		}
227*fd1fabb7SAndroid Build Coastguard Worker 
228*fd1fabb7SAndroid Build Coastguard Worker 	else if (!fString.IsASCII ())
229*fd1fabb7SAndroid Build Coastguard Worker 		{
230*fd1fabb7SAndroid Build Coastguard Worker 
231*fd1fabb7SAndroid Build Coastguard Worker 		fType = ttByte;
232*fd1fabb7SAndroid Build Coastguard Worker 
233*fd1fabb7SAndroid Build Coastguard Worker 		}
234*fd1fabb7SAndroid Build Coastguard Worker 
235*fd1fabb7SAndroid Build Coastguard Worker 	fCount = fString.Length () + 1;
236*fd1fabb7SAndroid Build Coastguard Worker 
237*fd1fabb7SAndroid Build Coastguard Worker 	}
238*fd1fabb7SAndroid Build Coastguard Worker 
239*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
240*fd1fabb7SAndroid Build Coastguard Worker 
Put(dng_stream & stream) const241*fd1fabb7SAndroid Build Coastguard Worker void tag_string::Put (dng_stream &stream) const
242*fd1fabb7SAndroid Build Coastguard Worker 	{
243*fd1fabb7SAndroid Build Coastguard Worker 
244*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put (fString.Get (), Size ());
245*fd1fabb7SAndroid Build Coastguard Worker 
246*fd1fabb7SAndroid Build Coastguard Worker 	}
247*fd1fabb7SAndroid Build Coastguard Worker 
248*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
249*fd1fabb7SAndroid Build Coastguard Worker 
tag_encoded_text(uint16 code,const dng_string & text)250*fd1fabb7SAndroid Build Coastguard Worker tag_encoded_text::tag_encoded_text (uint16 code,
251*fd1fabb7SAndroid Build Coastguard Worker 									const dng_string &text)
252*fd1fabb7SAndroid Build Coastguard Worker 
253*fd1fabb7SAndroid Build Coastguard Worker 	:	tiff_tag (code, ttUndefined, 0)
254*fd1fabb7SAndroid Build Coastguard Worker 
255*fd1fabb7SAndroid Build Coastguard Worker 	,	fText (text)
256*fd1fabb7SAndroid Build Coastguard Worker 
257*fd1fabb7SAndroid Build Coastguard Worker 	,	fUTF16 ()
258*fd1fabb7SAndroid Build Coastguard Worker 
259*fd1fabb7SAndroid Build Coastguard Worker 	{
260*fd1fabb7SAndroid Build Coastguard Worker 
261*fd1fabb7SAndroid Build Coastguard Worker 	if (fText.IsASCII ())
262*fd1fabb7SAndroid Build Coastguard Worker 		{
263*fd1fabb7SAndroid Build Coastguard Worker 
264*fd1fabb7SAndroid Build Coastguard Worker 		fCount = 8 + fText.Length ();
265*fd1fabb7SAndroid Build Coastguard Worker 
266*fd1fabb7SAndroid Build Coastguard Worker 		}
267*fd1fabb7SAndroid Build Coastguard Worker 
268*fd1fabb7SAndroid Build Coastguard Worker 	else
269*fd1fabb7SAndroid Build Coastguard Worker 		{
270*fd1fabb7SAndroid Build Coastguard Worker 
271*fd1fabb7SAndroid Build Coastguard Worker 		fCount = 8 + fText.Get_UTF16 (fUTF16) * 2;
272*fd1fabb7SAndroid Build Coastguard Worker 
273*fd1fabb7SAndroid Build Coastguard Worker 		}
274*fd1fabb7SAndroid Build Coastguard Worker 
275*fd1fabb7SAndroid Build Coastguard Worker 	}
276*fd1fabb7SAndroid Build Coastguard Worker 
277*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
278*fd1fabb7SAndroid Build Coastguard Worker 
Put(dng_stream & stream) const279*fd1fabb7SAndroid Build Coastguard Worker void tag_encoded_text::Put (dng_stream &stream) const
280*fd1fabb7SAndroid Build Coastguard Worker 	{
281*fd1fabb7SAndroid Build Coastguard Worker 
282*fd1fabb7SAndroid Build Coastguard Worker 	if (fUTF16.Buffer ())
283*fd1fabb7SAndroid Build Coastguard Worker 		{
284*fd1fabb7SAndroid Build Coastguard Worker 
285*fd1fabb7SAndroid Build Coastguard Worker 		stream.Put ("UNICODE\000", 8);
286*fd1fabb7SAndroid Build Coastguard Worker 
287*fd1fabb7SAndroid Build Coastguard Worker 		uint32 chars = (fCount - 8) >> 1;
288*fd1fabb7SAndroid Build Coastguard Worker 
289*fd1fabb7SAndroid Build Coastguard Worker 		const uint16 *buf = fUTF16.Buffer_uint16 ();
290*fd1fabb7SAndroid Build Coastguard Worker 
291*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 j = 0; j < chars; j++)
292*fd1fabb7SAndroid Build Coastguard Worker 			{
293*fd1fabb7SAndroid Build Coastguard Worker 
294*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint16 (buf [j]);
295*fd1fabb7SAndroid Build Coastguard Worker 
296*fd1fabb7SAndroid Build Coastguard Worker 			}
297*fd1fabb7SAndroid Build Coastguard Worker 
298*fd1fabb7SAndroid Build Coastguard Worker 		}
299*fd1fabb7SAndroid Build Coastguard Worker 
300*fd1fabb7SAndroid Build Coastguard Worker 	else
301*fd1fabb7SAndroid Build Coastguard Worker 		{
302*fd1fabb7SAndroid Build Coastguard Worker 
303*fd1fabb7SAndroid Build Coastguard Worker 		stream.Put ("ASCII\000\000\000", 8);
304*fd1fabb7SAndroid Build Coastguard Worker 
305*fd1fabb7SAndroid Build Coastguard Worker 		stream.Put (fText.Get (), fCount - 8);
306*fd1fabb7SAndroid Build Coastguard Worker 
307*fd1fabb7SAndroid Build Coastguard Worker 		}
308*fd1fabb7SAndroid Build Coastguard Worker 
309*fd1fabb7SAndroid Build Coastguard Worker 	}
310*fd1fabb7SAndroid Build Coastguard Worker 
311*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
312*fd1fabb7SAndroid Build Coastguard Worker 
Put(dng_stream & stream) const313*fd1fabb7SAndroid Build Coastguard Worker void tag_data_ptr::Put (dng_stream &stream) const
314*fd1fabb7SAndroid Build Coastguard Worker 	{
315*fd1fabb7SAndroid Build Coastguard Worker 
316*fd1fabb7SAndroid Build Coastguard Worker 	// If we are swapping bytes, we need to swap with the right size
317*fd1fabb7SAndroid Build Coastguard Worker 	// entries.
318*fd1fabb7SAndroid Build Coastguard Worker 
319*fd1fabb7SAndroid Build Coastguard Worker 	if (stream.SwapBytes ())
320*fd1fabb7SAndroid Build Coastguard Worker 		{
321*fd1fabb7SAndroid Build Coastguard Worker 
322*fd1fabb7SAndroid Build Coastguard Worker 		switch (Type ())
323*fd1fabb7SAndroid Build Coastguard Worker 			{
324*fd1fabb7SAndroid Build Coastguard Worker 
325*fd1fabb7SAndroid Build Coastguard Worker 			// Two byte entries.
326*fd1fabb7SAndroid Build Coastguard Worker 
327*fd1fabb7SAndroid Build Coastguard Worker 			case ttShort:
328*fd1fabb7SAndroid Build Coastguard Worker 			case ttSShort:
329*fd1fabb7SAndroid Build Coastguard Worker 			case ttUnicode:
330*fd1fabb7SAndroid Build Coastguard Worker 				{
331*fd1fabb7SAndroid Build Coastguard Worker 
332*fd1fabb7SAndroid Build Coastguard Worker 				const uint16 *p = (const uint16 *) fData;
333*fd1fabb7SAndroid Build Coastguard Worker 
334*fd1fabb7SAndroid Build Coastguard Worker 				uint32 entries = (Size () >> 1);
335*fd1fabb7SAndroid Build Coastguard Worker 
336*fd1fabb7SAndroid Build Coastguard Worker 				for (uint32 j = 0; j < entries; j++)
337*fd1fabb7SAndroid Build Coastguard Worker 					{
338*fd1fabb7SAndroid Build Coastguard Worker 
339*fd1fabb7SAndroid Build Coastguard Worker 					stream.Put_uint16 (p [j]);
340*fd1fabb7SAndroid Build Coastguard Worker 
341*fd1fabb7SAndroid Build Coastguard Worker 					}
342*fd1fabb7SAndroid Build Coastguard Worker 
343*fd1fabb7SAndroid Build Coastguard Worker 				return;
344*fd1fabb7SAndroid Build Coastguard Worker 
345*fd1fabb7SAndroid Build Coastguard Worker 				}
346*fd1fabb7SAndroid Build Coastguard Worker 
347*fd1fabb7SAndroid Build Coastguard Worker 			// Four byte entries.
348*fd1fabb7SAndroid Build Coastguard Worker 
349*fd1fabb7SAndroid Build Coastguard Worker 			case ttLong:
350*fd1fabb7SAndroid Build Coastguard Worker 			case ttSLong:
351*fd1fabb7SAndroid Build Coastguard Worker 			case ttRational:
352*fd1fabb7SAndroid Build Coastguard Worker 			case ttSRational:
353*fd1fabb7SAndroid Build Coastguard Worker 			case ttIFD:
354*fd1fabb7SAndroid Build Coastguard Worker 			case ttFloat:
355*fd1fabb7SAndroid Build Coastguard Worker 			case ttComplex:
356*fd1fabb7SAndroid Build Coastguard Worker 				{
357*fd1fabb7SAndroid Build Coastguard Worker 
358*fd1fabb7SAndroid Build Coastguard Worker 				const uint32 *p = (const uint32 *) fData;
359*fd1fabb7SAndroid Build Coastguard Worker 
360*fd1fabb7SAndroid Build Coastguard Worker 				uint32 entries = (Size () >> 2);
361*fd1fabb7SAndroid Build Coastguard Worker 
362*fd1fabb7SAndroid Build Coastguard Worker 				for (uint32 j = 0; j < entries; j++)
363*fd1fabb7SAndroid Build Coastguard Worker 					{
364*fd1fabb7SAndroid Build Coastguard Worker 
365*fd1fabb7SAndroid Build Coastguard Worker 					stream.Put_uint32 (p [j]);
366*fd1fabb7SAndroid Build Coastguard Worker 
367*fd1fabb7SAndroid Build Coastguard Worker 					}
368*fd1fabb7SAndroid Build Coastguard Worker 
369*fd1fabb7SAndroid Build Coastguard Worker 				return;
370*fd1fabb7SAndroid Build Coastguard Worker 
371*fd1fabb7SAndroid Build Coastguard Worker 				}
372*fd1fabb7SAndroid Build Coastguard Worker 
373*fd1fabb7SAndroid Build Coastguard Worker 			// Eight byte entries.
374*fd1fabb7SAndroid Build Coastguard Worker 
375*fd1fabb7SAndroid Build Coastguard Worker 			case ttDouble:
376*fd1fabb7SAndroid Build Coastguard Worker 				{
377*fd1fabb7SAndroid Build Coastguard Worker 
378*fd1fabb7SAndroid Build Coastguard Worker 				const real64 *p = (const real64 *) fData;
379*fd1fabb7SAndroid Build Coastguard Worker 
380*fd1fabb7SAndroid Build Coastguard Worker 				uint32 entries = (Size () >> 3);
381*fd1fabb7SAndroid Build Coastguard Worker 
382*fd1fabb7SAndroid Build Coastguard Worker 				for (uint32 j = 0; j < entries; j++)
383*fd1fabb7SAndroid Build Coastguard Worker 					{
384*fd1fabb7SAndroid Build Coastguard Worker 
385*fd1fabb7SAndroid Build Coastguard Worker 					stream.Put_real64 (p [j]);
386*fd1fabb7SAndroid Build Coastguard Worker 
387*fd1fabb7SAndroid Build Coastguard Worker 					}
388*fd1fabb7SAndroid Build Coastguard Worker 
389*fd1fabb7SAndroid Build Coastguard Worker 				return;
390*fd1fabb7SAndroid Build Coastguard Worker 
391*fd1fabb7SAndroid Build Coastguard Worker 				}
392*fd1fabb7SAndroid Build Coastguard Worker 
393*fd1fabb7SAndroid Build Coastguard Worker 			// Entries don't need to be byte swapped.  Fall through
394*fd1fabb7SAndroid Build Coastguard Worker 			// to non-byte swapped case.
395*fd1fabb7SAndroid Build Coastguard Worker 
396*fd1fabb7SAndroid Build Coastguard Worker 			default:
397*fd1fabb7SAndroid Build Coastguard Worker 				{
398*fd1fabb7SAndroid Build Coastguard Worker 
399*fd1fabb7SAndroid Build Coastguard Worker 				break;
400*fd1fabb7SAndroid Build Coastguard Worker 
401*fd1fabb7SAndroid Build Coastguard Worker 				}
402*fd1fabb7SAndroid Build Coastguard Worker 
403*fd1fabb7SAndroid Build Coastguard Worker 			}
404*fd1fabb7SAndroid Build Coastguard Worker 
405*fd1fabb7SAndroid Build Coastguard Worker 		}
406*fd1fabb7SAndroid Build Coastguard Worker 
407*fd1fabb7SAndroid Build Coastguard Worker 	// Non-byte swapped case.
408*fd1fabb7SAndroid Build Coastguard Worker 
409*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put (fData, Size ());
410*fd1fabb7SAndroid Build Coastguard Worker 
411*fd1fabb7SAndroid Build Coastguard Worker 	}
412*fd1fabb7SAndroid Build Coastguard Worker 
413*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
414*fd1fabb7SAndroid Build Coastguard Worker 
tag_matrix(uint16 code,const dng_matrix & m)415*fd1fabb7SAndroid Build Coastguard Worker tag_matrix::tag_matrix (uint16 code,
416*fd1fabb7SAndroid Build Coastguard Worker 		    			const dng_matrix &m)
417*fd1fabb7SAndroid Build Coastguard Worker 
418*fd1fabb7SAndroid Build Coastguard Worker 	:	tag_srational_ptr (code, fEntry, m.Rows () * m.Cols ())
419*fd1fabb7SAndroid Build Coastguard Worker 
420*fd1fabb7SAndroid Build Coastguard Worker 	{
421*fd1fabb7SAndroid Build Coastguard Worker 
422*fd1fabb7SAndroid Build Coastguard Worker 	uint32 index = 0;
423*fd1fabb7SAndroid Build Coastguard Worker 
424*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 r = 0; r < m.Rows (); r++)
425*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 c = 0; c < m.Cols (); c++)
426*fd1fabb7SAndroid Build Coastguard Worker 			{
427*fd1fabb7SAndroid Build Coastguard Worker 
428*fd1fabb7SAndroid Build Coastguard Worker 			fEntry [index].Set_real64 (m [r] [c], 10000);
429*fd1fabb7SAndroid Build Coastguard Worker 
430*fd1fabb7SAndroid Build Coastguard Worker 			index++;
431*fd1fabb7SAndroid Build Coastguard Worker 
432*fd1fabb7SAndroid Build Coastguard Worker 			}
433*fd1fabb7SAndroid Build Coastguard Worker 
434*fd1fabb7SAndroid Build Coastguard Worker 	}
435*fd1fabb7SAndroid Build Coastguard Worker 
436*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
437*fd1fabb7SAndroid Build Coastguard Worker 
tag_icc_profile(const void * profileData,uint32 profileSize)438*fd1fabb7SAndroid Build Coastguard Worker tag_icc_profile::tag_icc_profile (const void *profileData,
439*fd1fabb7SAndroid Build Coastguard Worker 								  uint32 profileSize)
440*fd1fabb7SAndroid Build Coastguard Worker 
441*fd1fabb7SAndroid Build Coastguard Worker 	:	tag_data_ptr (tcICCProfile,
442*fd1fabb7SAndroid Build Coastguard Worker 					  ttUndefined,
443*fd1fabb7SAndroid Build Coastguard Worker 					  0,
444*fd1fabb7SAndroid Build Coastguard Worker 					  NULL)
445*fd1fabb7SAndroid Build Coastguard Worker 
446*fd1fabb7SAndroid Build Coastguard Worker 	{
447*fd1fabb7SAndroid Build Coastguard Worker 
448*fd1fabb7SAndroid Build Coastguard Worker 	if (profileData && profileSize)
449*fd1fabb7SAndroid Build Coastguard Worker 		{
450*fd1fabb7SAndroid Build Coastguard Worker 
451*fd1fabb7SAndroid Build Coastguard Worker 		SetCount (profileSize);
452*fd1fabb7SAndroid Build Coastguard Worker 		SetData  (profileData);
453*fd1fabb7SAndroid Build Coastguard Worker 
454*fd1fabb7SAndroid Build Coastguard Worker 		}
455*fd1fabb7SAndroid Build Coastguard Worker 
456*fd1fabb7SAndroid Build Coastguard Worker 	}
457*fd1fabb7SAndroid Build Coastguard Worker 
458*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
459*fd1fabb7SAndroid Build Coastguard Worker 
Put(dng_stream & stream) const460*fd1fabb7SAndroid Build Coastguard Worker void tag_cfa_pattern::Put (dng_stream &stream) const
461*fd1fabb7SAndroid Build Coastguard Worker 	{
462*fd1fabb7SAndroid Build Coastguard Worker 
463*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint16 ((uint16) fCols);
464*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint16 ((uint16) fRows);
465*fd1fabb7SAndroid Build Coastguard Worker 
466*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 col = 0; col < fCols; col++)
467*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 row = 0; row < fRows; row++)
468*fd1fabb7SAndroid Build Coastguard Worker 			{
469*fd1fabb7SAndroid Build Coastguard Worker 
470*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint8 (fPattern [row * kMaxCFAPattern + col]);
471*fd1fabb7SAndroid Build Coastguard Worker 
472*fd1fabb7SAndroid Build Coastguard Worker 			}
473*fd1fabb7SAndroid Build Coastguard Worker 
474*fd1fabb7SAndroid Build Coastguard Worker 	}
475*fd1fabb7SAndroid Build Coastguard Worker 
476*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
477*fd1fabb7SAndroid Build Coastguard Worker 
tag_exif_date_time(uint16 code,const dng_date_time & dt)478*fd1fabb7SAndroid Build Coastguard Worker tag_exif_date_time::tag_exif_date_time (uint16 code,
479*fd1fabb7SAndroid Build Coastguard Worker 		            					const dng_date_time &dt)
480*fd1fabb7SAndroid Build Coastguard Worker 
481*fd1fabb7SAndroid Build Coastguard Worker 	:	tag_data_ptr (code, ttAscii, 20, fData)
482*fd1fabb7SAndroid Build Coastguard Worker 
483*fd1fabb7SAndroid Build Coastguard Worker 	{
484*fd1fabb7SAndroid Build Coastguard Worker 
485*fd1fabb7SAndroid Build Coastguard Worker 	if (dt.IsValid ())
486*fd1fabb7SAndroid Build Coastguard Worker 		{
487*fd1fabb7SAndroid Build Coastguard Worker 
488*fd1fabb7SAndroid Build Coastguard Worker 		sprintf (fData,
489*fd1fabb7SAndroid Build Coastguard Worker 				 "%04d:%02d:%02d %02d:%02d:%02d",
490*fd1fabb7SAndroid Build Coastguard Worker 				 (int) dt.fYear,
491*fd1fabb7SAndroid Build Coastguard Worker 				 (int) dt.fMonth,
492*fd1fabb7SAndroid Build Coastguard Worker 				 (int) dt.fDay,
493*fd1fabb7SAndroid Build Coastguard Worker 				 (int) dt.fHour,
494*fd1fabb7SAndroid Build Coastguard Worker 				 (int) dt.fMinute,
495*fd1fabb7SAndroid Build Coastguard Worker 				 (int) dt.fSecond);
496*fd1fabb7SAndroid Build Coastguard Worker 
497*fd1fabb7SAndroid Build Coastguard Worker 		}
498*fd1fabb7SAndroid Build Coastguard Worker 
499*fd1fabb7SAndroid Build Coastguard Worker 	}
500*fd1fabb7SAndroid Build Coastguard Worker 
501*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
502*fd1fabb7SAndroid Build Coastguard Worker 
tag_iptc(const void * data,uint32 length)503*fd1fabb7SAndroid Build Coastguard Worker tag_iptc::tag_iptc (const void *data,
504*fd1fabb7SAndroid Build Coastguard Worker 		  			uint32 length)
505*fd1fabb7SAndroid Build Coastguard Worker 
506*fd1fabb7SAndroid Build Coastguard Worker 	:	tiff_tag (tcIPTC_NAA, ttLong, (length + 3) >> 2)
507*fd1fabb7SAndroid Build Coastguard Worker 
508*fd1fabb7SAndroid Build Coastguard Worker 	,	fData   (data  )
509*fd1fabb7SAndroid Build Coastguard Worker 	,	fLength (length)
510*fd1fabb7SAndroid Build Coastguard Worker 
511*fd1fabb7SAndroid Build Coastguard Worker 	{
512*fd1fabb7SAndroid Build Coastguard Worker 
513*fd1fabb7SAndroid Build Coastguard Worker 	}
514*fd1fabb7SAndroid Build Coastguard Worker 
515*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
516*fd1fabb7SAndroid Build Coastguard Worker 
Put(dng_stream & stream) const517*fd1fabb7SAndroid Build Coastguard Worker void tag_iptc::Put (dng_stream &stream) const
518*fd1fabb7SAndroid Build Coastguard Worker 	{
519*fd1fabb7SAndroid Build Coastguard Worker 
520*fd1fabb7SAndroid Build Coastguard Worker 	// Note: For historical compatiblity reasons, the standard TIFF data
521*fd1fabb7SAndroid Build Coastguard Worker 	// type for IPTC data is ttLong, but without byte swapping.  This really
522*fd1fabb7SAndroid Build Coastguard Worker 	// should be ttUndefined, but doing the right thing would break some
523*fd1fabb7SAndroid Build Coastguard Worker 	// existing readers.
524*fd1fabb7SAndroid Build Coastguard Worker 
525*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put (fData, fLength);
526*fd1fabb7SAndroid Build Coastguard Worker 
527*fd1fabb7SAndroid Build Coastguard Worker 	// Pad with zeros to get to long word boundary.
528*fd1fabb7SAndroid Build Coastguard Worker 
529*fd1fabb7SAndroid Build Coastguard Worker 	uint32 extra = fCount * 4 - fLength;
530*fd1fabb7SAndroid Build Coastguard Worker 
531*fd1fabb7SAndroid Build Coastguard Worker 	while (extra--)
532*fd1fabb7SAndroid Build Coastguard Worker 		{
533*fd1fabb7SAndroid Build Coastguard Worker 		stream.Put_uint8 (0);
534*fd1fabb7SAndroid Build Coastguard Worker 		}
535*fd1fabb7SAndroid Build Coastguard Worker 
536*fd1fabb7SAndroid Build Coastguard Worker 	}
537*fd1fabb7SAndroid Build Coastguard Worker 
538*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
539*fd1fabb7SAndroid Build Coastguard Worker 
tag_xmp(const dng_xmp * xmp)540*fd1fabb7SAndroid Build Coastguard Worker tag_xmp::tag_xmp (const dng_xmp *xmp)
541*fd1fabb7SAndroid Build Coastguard Worker 
542*fd1fabb7SAndroid Build Coastguard Worker 	:	tag_uint8_ptr (tcXMP, NULL, 0)
543*fd1fabb7SAndroid Build Coastguard Worker 
544*fd1fabb7SAndroid Build Coastguard Worker 	,	fBuffer ()
545*fd1fabb7SAndroid Build Coastguard Worker 
546*fd1fabb7SAndroid Build Coastguard Worker 	{
547*fd1fabb7SAndroid Build Coastguard Worker 
548*fd1fabb7SAndroid Build Coastguard Worker 	#if qDNGUseXMP
549*fd1fabb7SAndroid Build Coastguard Worker 
550*fd1fabb7SAndroid Build Coastguard Worker 	if (xmp)
551*fd1fabb7SAndroid Build Coastguard Worker 		{
552*fd1fabb7SAndroid Build Coastguard Worker 
553*fd1fabb7SAndroid Build Coastguard Worker 		fBuffer.Reset (xmp->Serialize (true));
554*fd1fabb7SAndroid Build Coastguard Worker 
555*fd1fabb7SAndroid Build Coastguard Worker 		if (fBuffer.Get ())
556*fd1fabb7SAndroid Build Coastguard Worker 			{
557*fd1fabb7SAndroid Build Coastguard Worker 
558*fd1fabb7SAndroid Build Coastguard Worker 			SetData (fBuffer->Buffer_uint8 ());
559*fd1fabb7SAndroid Build Coastguard Worker 
560*fd1fabb7SAndroid Build Coastguard Worker 			SetCount (fBuffer->LogicalSize ());
561*fd1fabb7SAndroid Build Coastguard Worker 
562*fd1fabb7SAndroid Build Coastguard Worker 			}
563*fd1fabb7SAndroid Build Coastguard Worker 
564*fd1fabb7SAndroid Build Coastguard Worker 		}
565*fd1fabb7SAndroid Build Coastguard Worker 
566*fd1fabb7SAndroid Build Coastguard Worker 	#endif
567*fd1fabb7SAndroid Build Coastguard Worker 
568*fd1fabb7SAndroid Build Coastguard Worker 	}
569*fd1fabb7SAndroid Build Coastguard Worker 
570*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
571*fd1fabb7SAndroid Build Coastguard Worker 
Add(const tiff_tag * tag)572*fd1fabb7SAndroid Build Coastguard Worker void dng_tiff_directory::Add (const tiff_tag *tag)
573*fd1fabb7SAndroid Build Coastguard Worker 	{
574*fd1fabb7SAndroid Build Coastguard Worker 
575*fd1fabb7SAndroid Build Coastguard Worker 	if (fEntries >= kMaxEntries)
576*fd1fabb7SAndroid Build Coastguard Worker 		{
577*fd1fabb7SAndroid Build Coastguard Worker 		ThrowProgramError ();
578*fd1fabb7SAndroid Build Coastguard Worker 		}
579*fd1fabb7SAndroid Build Coastguard Worker 
580*fd1fabb7SAndroid Build Coastguard Worker 	// Tags must be sorted in increasing order of tag code.
581*fd1fabb7SAndroid Build Coastguard Worker 
582*fd1fabb7SAndroid Build Coastguard Worker 	uint32 index = fEntries;
583*fd1fabb7SAndroid Build Coastguard Worker 
584*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 j = 0; j < fEntries; j++)
585*fd1fabb7SAndroid Build Coastguard Worker 		{
586*fd1fabb7SAndroid Build Coastguard Worker 
587*fd1fabb7SAndroid Build Coastguard Worker 		if (tag->Code () < fTag [j]->Code ())
588*fd1fabb7SAndroid Build Coastguard Worker 			{
589*fd1fabb7SAndroid Build Coastguard Worker 			index = j;
590*fd1fabb7SAndroid Build Coastguard Worker 			break;
591*fd1fabb7SAndroid Build Coastguard Worker 			}
592*fd1fabb7SAndroid Build Coastguard Worker 
593*fd1fabb7SAndroid Build Coastguard Worker 		}
594*fd1fabb7SAndroid Build Coastguard Worker 
595*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 k = fEntries; k > index; k--)
596*fd1fabb7SAndroid Build Coastguard Worker 		{
597*fd1fabb7SAndroid Build Coastguard Worker 
598*fd1fabb7SAndroid Build Coastguard Worker 		fTag [k] = fTag [k - 1];
599*fd1fabb7SAndroid Build Coastguard Worker 
600*fd1fabb7SAndroid Build Coastguard Worker 		}
601*fd1fabb7SAndroid Build Coastguard Worker 
602*fd1fabb7SAndroid Build Coastguard Worker 	fTag [index] = tag;
603*fd1fabb7SAndroid Build Coastguard Worker 
604*fd1fabb7SAndroid Build Coastguard Worker 	fEntries++;
605*fd1fabb7SAndroid Build Coastguard Worker 
606*fd1fabb7SAndroid Build Coastguard Worker 	}
607*fd1fabb7SAndroid Build Coastguard Worker 
608*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
609*fd1fabb7SAndroid Build Coastguard Worker 
Size() const610*fd1fabb7SAndroid Build Coastguard Worker uint32 dng_tiff_directory::Size () const
611*fd1fabb7SAndroid Build Coastguard Worker 	{
612*fd1fabb7SAndroid Build Coastguard Worker 
613*fd1fabb7SAndroid Build Coastguard Worker 	if (!fEntries) return 0;
614*fd1fabb7SAndroid Build Coastguard Worker 
615*fd1fabb7SAndroid Build Coastguard Worker 	uint32 size = fEntries * 12 + 6;
616*fd1fabb7SAndroid Build Coastguard Worker 
617*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 index = 0; index < fEntries; index++)
618*fd1fabb7SAndroid Build Coastguard Worker 		{
619*fd1fabb7SAndroid Build Coastguard Worker 
620*fd1fabb7SAndroid Build Coastguard Worker 		uint32 tagSize = fTag [index]->Size ();
621*fd1fabb7SAndroid Build Coastguard Worker 
622*fd1fabb7SAndroid Build Coastguard Worker 		if (tagSize > 4)
623*fd1fabb7SAndroid Build Coastguard Worker 			{
624*fd1fabb7SAndroid Build Coastguard Worker 
625*fd1fabb7SAndroid Build Coastguard Worker 			size += (tagSize + 1) & ~1;
626*fd1fabb7SAndroid Build Coastguard Worker 
627*fd1fabb7SAndroid Build Coastguard Worker 			}
628*fd1fabb7SAndroid Build Coastguard Worker 
629*fd1fabb7SAndroid Build Coastguard Worker 		}
630*fd1fabb7SAndroid Build Coastguard Worker 
631*fd1fabb7SAndroid Build Coastguard Worker 	return size;
632*fd1fabb7SAndroid Build Coastguard Worker 
633*fd1fabb7SAndroid Build Coastguard Worker 	}
634*fd1fabb7SAndroid Build Coastguard Worker 
635*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
636*fd1fabb7SAndroid Build Coastguard Worker 
Put(dng_stream & stream,OffsetsBase offsetsBase,uint32 explicitBase) const637*fd1fabb7SAndroid Build Coastguard Worker void dng_tiff_directory::Put (dng_stream &stream,
638*fd1fabb7SAndroid Build Coastguard Worker 						      OffsetsBase offsetsBase,
639*fd1fabb7SAndroid Build Coastguard Worker 						      uint32 explicitBase) const
640*fd1fabb7SAndroid Build Coastguard Worker 	{
641*fd1fabb7SAndroid Build Coastguard Worker 
642*fd1fabb7SAndroid Build Coastguard Worker 	if (!fEntries) return;
643*fd1fabb7SAndroid Build Coastguard Worker 
644*fd1fabb7SAndroid Build Coastguard Worker 	uint32 index;
645*fd1fabb7SAndroid Build Coastguard Worker 
646*fd1fabb7SAndroid Build Coastguard Worker 	uint32 bigData = fEntries * 12 + 6;
647*fd1fabb7SAndroid Build Coastguard Worker 
648*fd1fabb7SAndroid Build Coastguard Worker 	if (offsetsBase == offsetsRelativeToStream)
649*fd1fabb7SAndroid Build Coastguard Worker 		bigData += (uint32) stream.Position ();
650*fd1fabb7SAndroid Build Coastguard Worker 
651*fd1fabb7SAndroid Build Coastguard Worker 	else if (offsetsBase == offsetsRelativeToExplicitBase)
652*fd1fabb7SAndroid Build Coastguard Worker 		bigData += explicitBase;
653*fd1fabb7SAndroid Build Coastguard Worker 
654*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint16 ((uint16) fEntries);
655*fd1fabb7SAndroid Build Coastguard Worker 
656*fd1fabb7SAndroid Build Coastguard Worker 	for (index = 0; index < fEntries; index++)
657*fd1fabb7SAndroid Build Coastguard Worker 		{
658*fd1fabb7SAndroid Build Coastguard Worker 
659*fd1fabb7SAndroid Build Coastguard Worker 		const tiff_tag &tag = *fTag [index];
660*fd1fabb7SAndroid Build Coastguard Worker 
661*fd1fabb7SAndroid Build Coastguard Worker 		stream.Put_uint16 (tag.Code  ());
662*fd1fabb7SAndroid Build Coastguard Worker 		stream.Put_uint16 (tag.Type  ());
663*fd1fabb7SAndroid Build Coastguard Worker 		stream.Put_uint32 (tag.Count ());
664*fd1fabb7SAndroid Build Coastguard Worker 
665*fd1fabb7SAndroid Build Coastguard Worker 		uint32 size = tag.Size ();
666*fd1fabb7SAndroid Build Coastguard Worker 
667*fd1fabb7SAndroid Build Coastguard Worker 		if (size <= 4)
668*fd1fabb7SAndroid Build Coastguard Worker 			{
669*fd1fabb7SAndroid Build Coastguard Worker 
670*fd1fabb7SAndroid Build Coastguard Worker 			tag.Put (stream);
671*fd1fabb7SAndroid Build Coastguard Worker 
672*fd1fabb7SAndroid Build Coastguard Worker 			while (size < 4)
673*fd1fabb7SAndroid Build Coastguard Worker 				{
674*fd1fabb7SAndroid Build Coastguard Worker 				stream.Put_uint8 (0);
675*fd1fabb7SAndroid Build Coastguard Worker 				size++;
676*fd1fabb7SAndroid Build Coastguard Worker 				}
677*fd1fabb7SAndroid Build Coastguard Worker 
678*fd1fabb7SAndroid Build Coastguard Worker 			}
679*fd1fabb7SAndroid Build Coastguard Worker 
680*fd1fabb7SAndroid Build Coastguard Worker 		else
681*fd1fabb7SAndroid Build Coastguard Worker 			{
682*fd1fabb7SAndroid Build Coastguard Worker 
683*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put_uint32 (bigData);
684*fd1fabb7SAndroid Build Coastguard Worker 
685*fd1fabb7SAndroid Build Coastguard Worker 			bigData += (size + 1) & ~1;
686*fd1fabb7SAndroid Build Coastguard Worker 
687*fd1fabb7SAndroid Build Coastguard Worker 			}
688*fd1fabb7SAndroid Build Coastguard Worker 
689*fd1fabb7SAndroid Build Coastguard Worker 		}
690*fd1fabb7SAndroid Build Coastguard Worker 
691*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint32 (fChained);		// Next IFD offset
692*fd1fabb7SAndroid Build Coastguard Worker 
693*fd1fabb7SAndroid Build Coastguard Worker 	for (index = 0; index < fEntries; index++)
694*fd1fabb7SAndroid Build Coastguard Worker 		{
695*fd1fabb7SAndroid Build Coastguard Worker 
696*fd1fabb7SAndroid Build Coastguard Worker 		const tiff_tag &tag = *fTag [index];
697*fd1fabb7SAndroid Build Coastguard Worker 
698*fd1fabb7SAndroid Build Coastguard Worker 		uint32 size = tag.Size ();
699*fd1fabb7SAndroid Build Coastguard Worker 
700*fd1fabb7SAndroid Build Coastguard Worker 		if (size > 4)
701*fd1fabb7SAndroid Build Coastguard Worker 			{
702*fd1fabb7SAndroid Build Coastguard Worker 
703*fd1fabb7SAndroid Build Coastguard Worker 			tag.Put (stream);
704*fd1fabb7SAndroid Build Coastguard Worker 
705*fd1fabb7SAndroid Build Coastguard Worker 			if (size & 1)
706*fd1fabb7SAndroid Build Coastguard Worker 				stream.Put_uint8 (0);
707*fd1fabb7SAndroid Build Coastguard Worker 
708*fd1fabb7SAndroid Build Coastguard Worker 			}
709*fd1fabb7SAndroid Build Coastguard Worker 
710*fd1fabb7SAndroid Build Coastguard Worker 		}
711*fd1fabb7SAndroid Build Coastguard Worker 
712*fd1fabb7SAndroid Build Coastguard Worker 	}
713*fd1fabb7SAndroid Build Coastguard Worker 
714*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
715*fd1fabb7SAndroid Build Coastguard Worker 
dng_basic_tag_set(dng_tiff_directory & directory,const dng_ifd & info)716*fd1fabb7SAndroid Build Coastguard Worker dng_basic_tag_set::dng_basic_tag_set (dng_tiff_directory &directory,
717*fd1fabb7SAndroid Build Coastguard Worker 									  const dng_ifd &info)
718*fd1fabb7SAndroid Build Coastguard Worker 
719*fd1fabb7SAndroid Build Coastguard Worker 	:	fNewSubFileType (tcNewSubFileType, info.fNewSubFileType)
720*fd1fabb7SAndroid Build Coastguard Worker 
721*fd1fabb7SAndroid Build Coastguard Worker 	,	fImageWidth  (tcImageWidth , info.fImageWidth )
722*fd1fabb7SAndroid Build Coastguard Worker 	,	fImageLength (tcImageLength, info.fImageLength)
723*fd1fabb7SAndroid Build Coastguard Worker 
724*fd1fabb7SAndroid Build Coastguard Worker 	,	fPhotoInterpretation (tcPhotometricInterpretation,
725*fd1fabb7SAndroid Build Coastguard Worker 							  (uint16) info.fPhotometricInterpretation)
726*fd1fabb7SAndroid Build Coastguard Worker 
727*fd1fabb7SAndroid Build Coastguard Worker 	,	fFillOrder (tcFillOrder, 1)
728*fd1fabb7SAndroid Build Coastguard Worker 
729*fd1fabb7SAndroid Build Coastguard Worker 	,	fSamplesPerPixel (tcSamplesPerPixel, (uint16) info.fSamplesPerPixel)
730*fd1fabb7SAndroid Build Coastguard Worker 
731*fd1fabb7SAndroid Build Coastguard Worker 	,	fBitsPerSample (tcBitsPerSample,
732*fd1fabb7SAndroid Build Coastguard Worker 						fBitsPerSampleData,
733*fd1fabb7SAndroid Build Coastguard Worker 						info.fSamplesPerPixel)
734*fd1fabb7SAndroid Build Coastguard Worker 
735*fd1fabb7SAndroid Build Coastguard Worker 	,	fStrips (info.fUsesStrips)
736*fd1fabb7SAndroid Build Coastguard Worker 
737*fd1fabb7SAndroid Build Coastguard Worker 	,	fTileWidth (tcTileWidth, info.fTileWidth)
738*fd1fabb7SAndroid Build Coastguard Worker 
739*fd1fabb7SAndroid Build Coastguard Worker 	,	fTileLength (fStrips ? tcRowsPerStrip : tcTileLength,
740*fd1fabb7SAndroid Build Coastguard Worker 					 info.fTileLength)
741*fd1fabb7SAndroid Build Coastguard Worker 
742*fd1fabb7SAndroid Build Coastguard Worker 	,	fTileInfoBuffer (info.TilesPerImage (), 8)
743*fd1fabb7SAndroid Build Coastguard Worker 
744*fd1fabb7SAndroid Build Coastguard Worker 	,	fTileOffsetData (fTileInfoBuffer.Buffer_uint32 ())
745*fd1fabb7SAndroid Build Coastguard Worker 
746*fd1fabb7SAndroid Build Coastguard Worker 	,	fTileOffsets (fStrips ? tcStripOffsets : tcTileOffsets,
747*fd1fabb7SAndroid Build Coastguard Worker 					  fTileOffsetData,
748*fd1fabb7SAndroid Build Coastguard Worker 					  info.TilesPerImage ())
749*fd1fabb7SAndroid Build Coastguard Worker 
750*fd1fabb7SAndroid Build Coastguard Worker 	,	fTileByteCountData (fTileOffsetData + info.TilesPerImage ())
751*fd1fabb7SAndroid Build Coastguard Worker 
752*fd1fabb7SAndroid Build Coastguard Worker 	,	fTileByteCounts (fStrips ? tcStripByteCounts : tcTileByteCounts,
753*fd1fabb7SAndroid Build Coastguard Worker 						 fTileByteCountData,
754*fd1fabb7SAndroid Build Coastguard Worker 						 info.TilesPerImage ())
755*fd1fabb7SAndroid Build Coastguard Worker 
756*fd1fabb7SAndroid Build Coastguard Worker 	,	fPlanarConfiguration (tcPlanarConfiguration, pcInterleaved)
757*fd1fabb7SAndroid Build Coastguard Worker 
758*fd1fabb7SAndroid Build Coastguard Worker 	,	fCompression (tcCompression, (uint16) info.fCompression)
759*fd1fabb7SAndroid Build Coastguard Worker 	,	fPredictor   (tcPredictor  , (uint16) info.fPredictor  )
760*fd1fabb7SAndroid Build Coastguard Worker 
761*fd1fabb7SAndroid Build Coastguard Worker 	,	fExtraSamples (tcExtraSamples,
762*fd1fabb7SAndroid Build Coastguard Worker 					   fExtraSamplesData,
763*fd1fabb7SAndroid Build Coastguard Worker 					   info.fExtraSamplesCount)
764*fd1fabb7SAndroid Build Coastguard Worker 
765*fd1fabb7SAndroid Build Coastguard Worker 	,	fSampleFormat (tcSampleFormat,
766*fd1fabb7SAndroid Build Coastguard Worker 					   fSampleFormatData,
767*fd1fabb7SAndroid Build Coastguard Worker 					   info.fSamplesPerPixel)
768*fd1fabb7SAndroid Build Coastguard Worker 
769*fd1fabb7SAndroid Build Coastguard Worker 	,	fRowInterleaveFactor (tcRowInterleaveFactor,
770*fd1fabb7SAndroid Build Coastguard Worker 							  (uint16) info.fRowInterleaveFactor)
771*fd1fabb7SAndroid Build Coastguard Worker 
772*fd1fabb7SAndroid Build Coastguard Worker 	,	fSubTileBlockSize (tcSubTileBlockSize,
773*fd1fabb7SAndroid Build Coastguard Worker 						   fSubTileBlockSizeData,
774*fd1fabb7SAndroid Build Coastguard Worker 						   2)
775*fd1fabb7SAndroid Build Coastguard Worker 
776*fd1fabb7SAndroid Build Coastguard Worker 	{
777*fd1fabb7SAndroid Build Coastguard Worker 
778*fd1fabb7SAndroid Build Coastguard Worker 	uint32 j;
779*fd1fabb7SAndroid Build Coastguard Worker 
780*fd1fabb7SAndroid Build Coastguard Worker 	for (j = 0; j < info.fSamplesPerPixel; j++)
781*fd1fabb7SAndroid Build Coastguard Worker 		{
782*fd1fabb7SAndroid Build Coastguard Worker 
783*fd1fabb7SAndroid Build Coastguard Worker 		fBitsPerSampleData [j] = (uint16) info.fBitsPerSample [0];
784*fd1fabb7SAndroid Build Coastguard Worker 
785*fd1fabb7SAndroid Build Coastguard Worker 		}
786*fd1fabb7SAndroid Build Coastguard Worker 
787*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fNewSubFileType);
788*fd1fabb7SAndroid Build Coastguard Worker 
789*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fImageWidth);
790*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fImageLength);
791*fd1fabb7SAndroid Build Coastguard Worker 
792*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fPhotoInterpretation);
793*fd1fabb7SAndroid Build Coastguard Worker 
794*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fSamplesPerPixel);
795*fd1fabb7SAndroid Build Coastguard Worker 
796*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fBitsPerSample);
797*fd1fabb7SAndroid Build Coastguard Worker 
798*fd1fabb7SAndroid Build Coastguard Worker 	if (info.fBitsPerSample [0] !=  8 &&
799*fd1fabb7SAndroid Build Coastguard Worker 	    info.fBitsPerSample [0] != 16 &&
800*fd1fabb7SAndroid Build Coastguard Worker 	    info.fBitsPerSample [0] != 32)
801*fd1fabb7SAndroid Build Coastguard Worker 		{
802*fd1fabb7SAndroid Build Coastguard Worker 
803*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fFillOrder);
804*fd1fabb7SAndroid Build Coastguard Worker 
805*fd1fabb7SAndroid Build Coastguard Worker 		}
806*fd1fabb7SAndroid Build Coastguard Worker 
807*fd1fabb7SAndroid Build Coastguard Worker 	if (!fStrips)
808*fd1fabb7SAndroid Build Coastguard Worker 		{
809*fd1fabb7SAndroid Build Coastguard Worker 
810*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fTileWidth);
811*fd1fabb7SAndroid Build Coastguard Worker 
812*fd1fabb7SAndroid Build Coastguard Worker 		}
813*fd1fabb7SAndroid Build Coastguard Worker 
814*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fTileLength);
815*fd1fabb7SAndroid Build Coastguard Worker 
816*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fTileOffsets);
817*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fTileByteCounts);
818*fd1fabb7SAndroid Build Coastguard Worker 
819*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fPlanarConfiguration);
820*fd1fabb7SAndroid Build Coastguard Worker 
821*fd1fabb7SAndroid Build Coastguard Worker 	directory.Add (&fCompression);
822*fd1fabb7SAndroid Build Coastguard Worker 
823*fd1fabb7SAndroid Build Coastguard Worker 	if (info.fPredictor != cpNullPredictor)
824*fd1fabb7SAndroid Build Coastguard Worker 		{
825*fd1fabb7SAndroid Build Coastguard Worker 
826*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fPredictor);
827*fd1fabb7SAndroid Build Coastguard Worker 
828*fd1fabb7SAndroid Build Coastguard Worker 		}
829*fd1fabb7SAndroid Build Coastguard Worker 
830*fd1fabb7SAndroid Build Coastguard Worker 	if (info.fExtraSamplesCount != 0)
831*fd1fabb7SAndroid Build Coastguard Worker 		{
832*fd1fabb7SAndroid Build Coastguard Worker 
833*fd1fabb7SAndroid Build Coastguard Worker 		for (j = 0; j < info.fExtraSamplesCount; j++)
834*fd1fabb7SAndroid Build Coastguard Worker 			{
835*fd1fabb7SAndroid Build Coastguard Worker 			fExtraSamplesData [j] = (uint16) info.fExtraSamples [j];
836*fd1fabb7SAndroid Build Coastguard Worker 			}
837*fd1fabb7SAndroid Build Coastguard Worker 
838*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fExtraSamples);
839*fd1fabb7SAndroid Build Coastguard Worker 
840*fd1fabb7SAndroid Build Coastguard Worker 		}
841*fd1fabb7SAndroid Build Coastguard Worker 
842*fd1fabb7SAndroid Build Coastguard Worker 	if (info.fSampleFormat [0] != sfUnsignedInteger)
843*fd1fabb7SAndroid Build Coastguard Worker 		{
844*fd1fabb7SAndroid Build Coastguard Worker 
845*fd1fabb7SAndroid Build Coastguard Worker 		for (j = 0; j < info.fSamplesPerPixel; j++)
846*fd1fabb7SAndroid Build Coastguard Worker 			{
847*fd1fabb7SAndroid Build Coastguard Worker 			fSampleFormatData [j] = (uint16) info.fSampleFormat [j];
848*fd1fabb7SAndroid Build Coastguard Worker 			}
849*fd1fabb7SAndroid Build Coastguard Worker 
850*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fSampleFormat);
851*fd1fabb7SAndroid Build Coastguard Worker 
852*fd1fabb7SAndroid Build Coastguard Worker 		}
853*fd1fabb7SAndroid Build Coastguard Worker 
854*fd1fabb7SAndroid Build Coastguard Worker 	if (info.fRowInterleaveFactor != 1)
855*fd1fabb7SAndroid Build Coastguard Worker 		{
856*fd1fabb7SAndroid Build Coastguard Worker 
857*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fRowInterleaveFactor);
858*fd1fabb7SAndroid Build Coastguard Worker 
859*fd1fabb7SAndroid Build Coastguard Worker 		}
860*fd1fabb7SAndroid Build Coastguard Worker 
861*fd1fabb7SAndroid Build Coastguard Worker 	if (info.fSubTileBlockRows != 1 ||
862*fd1fabb7SAndroid Build Coastguard Worker 		info.fSubTileBlockCols != 1)
863*fd1fabb7SAndroid Build Coastguard Worker 		{
864*fd1fabb7SAndroid Build Coastguard Worker 
865*fd1fabb7SAndroid Build Coastguard Worker 		fSubTileBlockSizeData [0] = (uint16) info.fSubTileBlockRows;
866*fd1fabb7SAndroid Build Coastguard Worker 		fSubTileBlockSizeData [1] = (uint16) info.fSubTileBlockCols;
867*fd1fabb7SAndroid Build Coastguard Worker 
868*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fSubTileBlockSize);
869*fd1fabb7SAndroid Build Coastguard Worker 
870*fd1fabb7SAndroid Build Coastguard Worker 		}
871*fd1fabb7SAndroid Build Coastguard Worker 
872*fd1fabb7SAndroid Build Coastguard Worker 	}
873*fd1fabb7SAndroid Build Coastguard Worker 
874*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
875*fd1fabb7SAndroid Build Coastguard Worker 
exif_tag_set(dng_tiff_directory & directory,const dng_exif & exif,bool makerNoteSafe,const void * makerNoteData,uint32 makerNoteLength,bool insideDNG)876*fd1fabb7SAndroid Build Coastguard Worker exif_tag_set::exif_tag_set (dng_tiff_directory &directory,
877*fd1fabb7SAndroid Build Coastguard Worker 					  		const dng_exif &exif,
878*fd1fabb7SAndroid Build Coastguard Worker 							bool makerNoteSafe,
879*fd1fabb7SAndroid Build Coastguard Worker 							const void *makerNoteData,
880*fd1fabb7SAndroid Build Coastguard Worker 							uint32 makerNoteLength,
881*fd1fabb7SAndroid Build Coastguard Worker 					 	    bool insideDNG)
882*fd1fabb7SAndroid Build Coastguard Worker 
883*fd1fabb7SAndroid Build Coastguard Worker 	:	fExifIFD ()
884*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSIFD  ()
885*fd1fabb7SAndroid Build Coastguard Worker 
886*fd1fabb7SAndroid Build Coastguard Worker 	,	fExifLink (tcExifIFD, 0)
887*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSLink  (tcGPSInfo, 0)
888*fd1fabb7SAndroid Build Coastguard Worker 
889*fd1fabb7SAndroid Build Coastguard Worker 	,	fAddedExifLink (false)
890*fd1fabb7SAndroid Build Coastguard Worker 	,	fAddedGPSLink  (false)
891*fd1fabb7SAndroid Build Coastguard Worker 
892*fd1fabb7SAndroid Build Coastguard Worker 	,	fExifVersion (tcExifVersion, ttUndefined, 4, fExifVersionData)
893*fd1fabb7SAndroid Build Coastguard Worker 
894*fd1fabb7SAndroid Build Coastguard Worker 	,	fExposureTime      (tcExposureTime     , exif.fExposureTime     )
895*fd1fabb7SAndroid Build Coastguard Worker 	,	fShutterSpeedValue (tcShutterSpeedValue, exif.fShutterSpeedValue)
896*fd1fabb7SAndroid Build Coastguard Worker 
897*fd1fabb7SAndroid Build Coastguard Worker 	,	fFNumber 	   (tcFNumber      , exif.fFNumber      )
898*fd1fabb7SAndroid Build Coastguard Worker 	,	fApertureValue (tcApertureValue, exif.fApertureValue)
899*fd1fabb7SAndroid Build Coastguard Worker 
900*fd1fabb7SAndroid Build Coastguard Worker 	,	fBrightnessValue (tcBrightnessValue, exif.fBrightnessValue)
901*fd1fabb7SAndroid Build Coastguard Worker 
902*fd1fabb7SAndroid Build Coastguard Worker 	,	fExposureBiasValue (tcExposureBiasValue, exif.fExposureBiasValue)
903*fd1fabb7SAndroid Build Coastguard Worker 
904*fd1fabb7SAndroid Build Coastguard Worker 	,	fMaxApertureValue (tcMaxApertureValue , exif.fMaxApertureValue)
905*fd1fabb7SAndroid Build Coastguard Worker 
906*fd1fabb7SAndroid Build Coastguard Worker 	,	fSubjectDistance (tcSubjectDistance, exif.fSubjectDistance)
907*fd1fabb7SAndroid Build Coastguard Worker 
908*fd1fabb7SAndroid Build Coastguard Worker 	,	fFocalLength (tcFocalLength, exif.fFocalLength)
909*fd1fabb7SAndroid Build Coastguard Worker 
910*fd1fabb7SAndroid Build Coastguard Worker 	// Special case: the EXIF 2.2 standard represents ISO speed ratings with 2 bytes,
911*fd1fabb7SAndroid Build Coastguard Worker 	// which cannot hold ISO speed ratings above 65535 (e.g., 102400). In these
912*fd1fabb7SAndroid Build Coastguard Worker 	// cases, we write the maximum representable ISO speed rating value in the EXIF
913*fd1fabb7SAndroid Build Coastguard Worker 	// tag, i.e., 65535.
914*fd1fabb7SAndroid Build Coastguard Worker 
915*fd1fabb7SAndroid Build Coastguard Worker 	,	fISOSpeedRatings (tcISOSpeedRatings,
916*fd1fabb7SAndroid Build Coastguard Worker 						  (uint16) Min_uint32 (65535,
917*fd1fabb7SAndroid Build Coastguard Worker 											   exif.fISOSpeedRatings [0]))
918*fd1fabb7SAndroid Build Coastguard Worker 
919*fd1fabb7SAndroid Build Coastguard Worker 	,	fSensitivityType (tcSensitivityType, (uint16) exif.fSensitivityType)
920*fd1fabb7SAndroid Build Coastguard Worker 
921*fd1fabb7SAndroid Build Coastguard Worker 	,	fStandardOutputSensitivity (tcStandardOutputSensitivity, exif.fStandardOutputSensitivity)
922*fd1fabb7SAndroid Build Coastguard Worker 
923*fd1fabb7SAndroid Build Coastguard Worker 	,	fRecommendedExposureIndex (tcRecommendedExposureIndex, exif.fRecommendedExposureIndex)
924*fd1fabb7SAndroid Build Coastguard Worker 
925*fd1fabb7SAndroid Build Coastguard Worker 	,	fISOSpeed (tcISOSpeed, exif.fISOSpeed)
926*fd1fabb7SAndroid Build Coastguard Worker 
927*fd1fabb7SAndroid Build Coastguard Worker 	,	fISOSpeedLatitudeyyy (tcISOSpeedLatitudeyyy, exif.fISOSpeedLatitudeyyy)
928*fd1fabb7SAndroid Build Coastguard Worker 
929*fd1fabb7SAndroid Build Coastguard Worker 	,	fISOSpeedLatitudezzz (tcISOSpeedLatitudezzz, exif.fISOSpeedLatitudezzz)
930*fd1fabb7SAndroid Build Coastguard Worker 
931*fd1fabb7SAndroid Build Coastguard Worker 	,	fFlash (tcFlash, (uint16) exif.fFlash)
932*fd1fabb7SAndroid Build Coastguard Worker 
933*fd1fabb7SAndroid Build Coastguard Worker 	,	fExposureProgram (tcExposureProgram, (uint16) exif.fExposureProgram)
934*fd1fabb7SAndroid Build Coastguard Worker 
935*fd1fabb7SAndroid Build Coastguard Worker 	,	fMeteringMode (tcMeteringMode, (uint16) exif.fMeteringMode)
936*fd1fabb7SAndroid Build Coastguard Worker 
937*fd1fabb7SAndroid Build Coastguard Worker 	,	fLightSource (tcLightSource, (uint16) exif.fLightSource)
938*fd1fabb7SAndroid Build Coastguard Worker 
939*fd1fabb7SAndroid Build Coastguard Worker 	,	fSensingMethod (tcSensingMethodExif, (uint16) exif.fSensingMethod)
940*fd1fabb7SAndroid Build Coastguard Worker 
941*fd1fabb7SAndroid Build Coastguard Worker 	,	fFocalLength35mm (tcFocalLengthIn35mmFilm, (uint16) exif.fFocalLengthIn35mmFilm)
942*fd1fabb7SAndroid Build Coastguard Worker 
943*fd1fabb7SAndroid Build Coastguard Worker 	,	fFileSourceData ((uint8) exif.fFileSource)
944*fd1fabb7SAndroid Build Coastguard Worker 	,	fFileSource     (tcFileSource, ttUndefined, 1, &fFileSourceData)
945*fd1fabb7SAndroid Build Coastguard Worker 
946*fd1fabb7SAndroid Build Coastguard Worker 	,	fSceneTypeData ((uint8) exif.fSceneType)
947*fd1fabb7SAndroid Build Coastguard Worker 	,	fSceneType     (tcSceneType, ttUndefined, 1, &fSceneTypeData)
948*fd1fabb7SAndroid Build Coastguard Worker 
949*fd1fabb7SAndroid Build Coastguard Worker 	,	fCFAPattern (tcCFAPatternExif,
950*fd1fabb7SAndroid Build Coastguard Worker 					 exif.fCFARepeatPatternRows,
951*fd1fabb7SAndroid Build Coastguard Worker 					 exif.fCFARepeatPatternCols,
952*fd1fabb7SAndroid Build Coastguard Worker 					 &exif.fCFAPattern [0] [0])
953*fd1fabb7SAndroid Build Coastguard Worker 
954*fd1fabb7SAndroid Build Coastguard Worker 	,	fCustomRendered 	  (tcCustomRendered		 , (uint16) exif.fCustomRendered	  )
955*fd1fabb7SAndroid Build Coastguard Worker 	,	fExposureMode 		  (tcExposureMode		 , (uint16) exif.fExposureMode		  )
956*fd1fabb7SAndroid Build Coastguard Worker 	,	fWhiteBalance 		  (tcWhiteBalance		 , (uint16) exif.fWhiteBalance		  )
957*fd1fabb7SAndroid Build Coastguard Worker 	,	fSceneCaptureType 	  (tcSceneCaptureType	 , (uint16) exif.fSceneCaptureType	  )
958*fd1fabb7SAndroid Build Coastguard Worker 	,	fGainControl 		  (tcGainControl		 , (uint16) exif.fGainControl		  )
959*fd1fabb7SAndroid Build Coastguard Worker 	,	fContrast 			  (tcContrast			 , (uint16) exif.fContrast			  )
960*fd1fabb7SAndroid Build Coastguard Worker 	,	fSaturation 		  (tcSaturation			 , (uint16) exif.fSaturation		  )
961*fd1fabb7SAndroid Build Coastguard Worker 	,	fSharpness 			  (tcSharpness			 , (uint16) exif.fSharpness			  )
962*fd1fabb7SAndroid Build Coastguard Worker 	,	fSubjectDistanceRange (tcSubjectDistanceRange, (uint16) exif.fSubjectDistanceRange)
963*fd1fabb7SAndroid Build Coastguard Worker 
964*fd1fabb7SAndroid Build Coastguard Worker 	,	fDigitalZoomRatio (tcDigitalZoomRatio, exif.fDigitalZoomRatio)
965*fd1fabb7SAndroid Build Coastguard Worker 
966*fd1fabb7SAndroid Build Coastguard Worker 	,	fExposureIndex (tcExposureIndexExif, exif.fExposureIndex)
967*fd1fabb7SAndroid Build Coastguard Worker 
968*fd1fabb7SAndroid Build Coastguard Worker 	,	fImageNumber (tcImageNumber, exif.fImageNumber)
969*fd1fabb7SAndroid Build Coastguard Worker 
970*fd1fabb7SAndroid Build Coastguard Worker 	,	fSelfTimerMode (tcSelfTimerMode, (uint16) exif.fSelfTimerMode)
971*fd1fabb7SAndroid Build Coastguard Worker 
972*fd1fabb7SAndroid Build Coastguard Worker 	,	fBatteryLevelA (tcBatteryLevel, exif.fBatteryLevelA)
973*fd1fabb7SAndroid Build Coastguard Worker 	,	fBatteryLevelR (tcBatteryLevel, exif.fBatteryLevelR)
974*fd1fabb7SAndroid Build Coastguard Worker 
975*fd1fabb7SAndroid Build Coastguard Worker 	,	fFocalPlaneXResolution (tcFocalPlaneXResolutionExif, exif.fFocalPlaneXResolution)
976*fd1fabb7SAndroid Build Coastguard Worker 	,	fFocalPlaneYResolution (tcFocalPlaneYResolutionExif, exif.fFocalPlaneYResolution)
977*fd1fabb7SAndroid Build Coastguard Worker 
978*fd1fabb7SAndroid Build Coastguard Worker 	,	fFocalPlaneResolutionUnit (tcFocalPlaneResolutionUnitExif, (uint16) exif.fFocalPlaneResolutionUnit)
979*fd1fabb7SAndroid Build Coastguard Worker 
980*fd1fabb7SAndroid Build Coastguard Worker 	,	fSubjectArea (tcSubjectArea, fSubjectAreaData, exif.fSubjectAreaCount)
981*fd1fabb7SAndroid Build Coastguard Worker 
982*fd1fabb7SAndroid Build Coastguard Worker 	,	fLensInfo (tcLensInfo, fLensInfoData, 4)
983*fd1fabb7SAndroid Build Coastguard Worker 
984*fd1fabb7SAndroid Build Coastguard Worker 	,	fDateTime		   (tcDateTime		   , exif.fDateTime         .DateTime ())
985*fd1fabb7SAndroid Build Coastguard Worker 	,	fDateTimeOriginal  (tcDateTimeOriginal , exif.fDateTimeOriginal .DateTime ())
986*fd1fabb7SAndroid Build Coastguard Worker 	,	fDateTimeDigitized (tcDateTimeDigitized, exif.fDateTimeDigitized.DateTime ())
987*fd1fabb7SAndroid Build Coastguard Worker 
988*fd1fabb7SAndroid Build Coastguard Worker 	,	fSubsecTime			 (tcSubsecTime, 		 exif.fDateTime         .Subseconds ())
989*fd1fabb7SAndroid Build Coastguard Worker 	,	fSubsecTimeOriginal  (tcSubsecTimeOriginal,  exif.fDateTimeOriginal .Subseconds ())
990*fd1fabb7SAndroid Build Coastguard Worker 	,	fSubsecTimeDigitized (tcSubsecTimeDigitized, exif.fDateTimeDigitized.Subseconds ())
991*fd1fabb7SAndroid Build Coastguard Worker 
992*fd1fabb7SAndroid Build Coastguard Worker 	,	fMake (tcMake, exif.fMake)
993*fd1fabb7SAndroid Build Coastguard Worker 
994*fd1fabb7SAndroid Build Coastguard Worker 	,	fModel (tcModel, exif.fModel)
995*fd1fabb7SAndroid Build Coastguard Worker 
996*fd1fabb7SAndroid Build Coastguard Worker 	,	fArtist (tcArtist, exif.fArtist)
997*fd1fabb7SAndroid Build Coastguard Worker 
998*fd1fabb7SAndroid Build Coastguard Worker 	,	fSoftware (tcSoftware, exif.fSoftware)
999*fd1fabb7SAndroid Build Coastguard Worker 
1000*fd1fabb7SAndroid Build Coastguard Worker 	,	fCopyright (tcCopyright, exif.fCopyright)
1001*fd1fabb7SAndroid Build Coastguard Worker 
1002*fd1fabb7SAndroid Build Coastguard Worker 	,	fMakerNoteSafety (tcMakerNoteSafety, makerNoteSafe ? 1 : 0)
1003*fd1fabb7SAndroid Build Coastguard Worker 
1004*fd1fabb7SAndroid Build Coastguard Worker 	,	fMakerNote (tcMakerNote, ttUndefined, makerNoteLength, makerNoteData)
1005*fd1fabb7SAndroid Build Coastguard Worker 
1006*fd1fabb7SAndroid Build Coastguard Worker 	,	fImageDescription (tcImageDescription, exif.fImageDescription)
1007*fd1fabb7SAndroid Build Coastguard Worker 
1008*fd1fabb7SAndroid Build Coastguard Worker 	,	fSerialNumber (tcCameraSerialNumber, exif.fCameraSerialNumber)
1009*fd1fabb7SAndroid Build Coastguard Worker 
1010*fd1fabb7SAndroid Build Coastguard Worker 	,	fUserComment (tcUserComment, exif.fUserComment)
1011*fd1fabb7SAndroid Build Coastguard Worker 
1012*fd1fabb7SAndroid Build Coastguard Worker 	,	fImageUniqueID (tcImageUniqueID, ttAscii, 33, fImageUniqueIDData)
1013*fd1fabb7SAndroid Build Coastguard Worker 
1014*fd1fabb7SAndroid Build Coastguard Worker 	// EXIF 2.3 tags.
1015*fd1fabb7SAndroid Build Coastguard Worker 
1016*fd1fabb7SAndroid Build Coastguard Worker 	,	fCameraOwnerName   (tcCameraOwnerNameExif,	  exif.fOwnerName		  )
1017*fd1fabb7SAndroid Build Coastguard Worker 	,	fBodySerialNumber  (tcCameraSerialNumberExif, exif.fCameraSerialNumber)
1018*fd1fabb7SAndroid Build Coastguard Worker 	,	fLensSpecification (tcLensSpecificationExif,  fLensInfoData, 4		  )
1019*fd1fabb7SAndroid Build Coastguard Worker 	,	fLensMake		   (tcLensMakeExif,			  exif.fLensMake		  )
1020*fd1fabb7SAndroid Build Coastguard Worker 	,	fLensModel		   (tcLensModelExif,		  exif.fLensName		  )
1021*fd1fabb7SAndroid Build Coastguard Worker 	,	fLensSerialNumber  (tcLensSerialNumberExif,	  exif.fLensSerialNumber  )
1022*fd1fabb7SAndroid Build Coastguard Worker 
1023*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSVersionID (tcGPSVersionID, fGPSVersionData, 4)
1024*fd1fabb7SAndroid Build Coastguard Worker 
1025*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSLatitudeRef (tcGPSLatitudeRef, exif.fGPSLatitudeRef)
1026*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSLatitude    (tcGPSLatitude,    exif.fGPSLatitude, 3)
1027*fd1fabb7SAndroid Build Coastguard Worker 
1028*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSLongitudeRef (tcGPSLongitudeRef, exif.fGPSLongitudeRef)
1029*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSLongitude    (tcGPSLongitude,    exif.fGPSLongitude, 3)
1030*fd1fabb7SAndroid Build Coastguard Worker 
1031*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSAltitudeRef (tcGPSAltitudeRef, (uint8) exif.fGPSAltitudeRef)
1032*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSAltitude    (tcGPSAltitude,            exif.fGPSAltitude   )
1033*fd1fabb7SAndroid Build Coastguard Worker 
1034*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSTimeStamp (tcGPSTimeStamp, exif.fGPSTimeStamp, 3)
1035*fd1fabb7SAndroid Build Coastguard Worker 
1036*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSSatellites  (tcGPSSatellites , exif.fGPSSatellites )
1037*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSStatus      (tcGPSStatus     , exif.fGPSStatus     )
1038*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSMeasureMode (tcGPSMeasureMode, exif.fGPSMeasureMode)
1039*fd1fabb7SAndroid Build Coastguard Worker 
1040*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDOP (tcGPSDOP, exif.fGPSDOP)
1041*fd1fabb7SAndroid Build Coastguard Worker 
1042*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSSpeedRef (tcGPSSpeedRef, exif.fGPSSpeedRef)
1043*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSSpeed    (tcGPSSpeed   , exif.fGPSSpeed   )
1044*fd1fabb7SAndroid Build Coastguard Worker 
1045*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSTrackRef (tcGPSTrackRef, exif.fGPSTrackRef)
1046*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSTrack    (tcGPSTrack   , exif.fGPSTrack   )
1047*fd1fabb7SAndroid Build Coastguard Worker 
1048*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSImgDirectionRef (tcGPSImgDirectionRef, exif.fGPSImgDirectionRef)
1049*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSImgDirection    (tcGPSImgDirection   , exif.fGPSImgDirection   )
1050*fd1fabb7SAndroid Build Coastguard Worker 
1051*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSMapDatum (tcGPSMapDatum, exif.fGPSMapDatum)
1052*fd1fabb7SAndroid Build Coastguard Worker 
1053*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDestLatitudeRef (tcGPSDestLatitudeRef, exif.fGPSDestLatitudeRef)
1054*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDestLatitude    (tcGPSDestLatitude,    exif.fGPSDestLatitude, 3)
1055*fd1fabb7SAndroid Build Coastguard Worker 
1056*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDestLongitudeRef (tcGPSDestLongitudeRef, exif.fGPSDestLongitudeRef)
1057*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDestLongitude    (tcGPSDestLongitude,    exif.fGPSDestLongitude, 3)
1058*fd1fabb7SAndroid Build Coastguard Worker 
1059*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDestBearingRef (tcGPSDestBearingRef, exif.fGPSDestBearingRef)
1060*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDestBearing    (tcGPSDestBearing   , exif.fGPSDestBearing   )
1061*fd1fabb7SAndroid Build Coastguard Worker 
1062*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDestDistanceRef (tcGPSDestDistanceRef, exif.fGPSDestDistanceRef)
1063*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDestDistance    (tcGPSDestDistance   , exif.fGPSDestDistance   )
1064*fd1fabb7SAndroid Build Coastguard Worker 
1065*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSProcessingMethod (tcGPSProcessingMethod, exif.fGPSProcessingMethod)
1066*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSAreaInformation  (tcGPSAreaInformation , exif.fGPSAreaInformation )
1067*fd1fabb7SAndroid Build Coastguard Worker 
1068*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDateStamp (tcGPSDateStamp, exif.fGPSDateStamp)
1069*fd1fabb7SAndroid Build Coastguard Worker 
1070*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSDifferential (tcGPSDifferential, (uint16) exif.fGPSDifferential)
1071*fd1fabb7SAndroid Build Coastguard Worker 
1072*fd1fabb7SAndroid Build Coastguard Worker 	,	fGPSHPositioningError (tcGPSHPositioningError, exif.fGPSHPositioningError)
1073*fd1fabb7SAndroid Build Coastguard Worker 
1074*fd1fabb7SAndroid Build Coastguard Worker 	{
1075*fd1fabb7SAndroid Build Coastguard Worker 
1076*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fExifVersion)
1077*fd1fabb7SAndroid Build Coastguard Worker 		{
1078*fd1fabb7SAndroid Build Coastguard Worker 
1079*fd1fabb7SAndroid Build Coastguard Worker 		fExifVersionData [0] = (uint8) (exif.fExifVersion >> 24);
1080*fd1fabb7SAndroid Build Coastguard Worker 		fExifVersionData [1] = (uint8) (exif.fExifVersion >> 16);
1081*fd1fabb7SAndroid Build Coastguard Worker 		fExifVersionData [2] = (uint8) (exif.fExifVersion >>  8);
1082*fd1fabb7SAndroid Build Coastguard Worker 		fExifVersionData [3] = (uint8) (exif.fExifVersion      );
1083*fd1fabb7SAndroid Build Coastguard Worker 
1084*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fExifVersion);
1085*fd1fabb7SAndroid Build Coastguard Worker 
1086*fd1fabb7SAndroid Build Coastguard Worker 		}
1087*fd1fabb7SAndroid Build Coastguard Worker 
1088*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fExposureTime.IsValid ())
1089*fd1fabb7SAndroid Build Coastguard Worker 		{
1090*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fExposureTime);
1091*fd1fabb7SAndroid Build Coastguard Worker 		}
1092*fd1fabb7SAndroid Build Coastguard Worker 
1093*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fShutterSpeedValue.IsValid ())
1094*fd1fabb7SAndroid Build Coastguard Worker 		{
1095*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fShutterSpeedValue);
1096*fd1fabb7SAndroid Build Coastguard Worker 		}
1097*fd1fabb7SAndroid Build Coastguard Worker 
1098*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fFNumber.IsValid ())
1099*fd1fabb7SAndroid Build Coastguard Worker 		{
1100*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fFNumber);
1101*fd1fabb7SAndroid Build Coastguard Worker 		}
1102*fd1fabb7SAndroid Build Coastguard Worker 
1103*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fApertureValue.IsValid ())
1104*fd1fabb7SAndroid Build Coastguard Worker 		{
1105*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fApertureValue);
1106*fd1fabb7SAndroid Build Coastguard Worker 		}
1107*fd1fabb7SAndroid Build Coastguard Worker 
1108*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fBrightnessValue.IsValid ())
1109*fd1fabb7SAndroid Build Coastguard Worker 		{
1110*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fBrightnessValue);
1111*fd1fabb7SAndroid Build Coastguard Worker 		}
1112*fd1fabb7SAndroid Build Coastguard Worker 
1113*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fExposureBiasValue.IsValid ())
1114*fd1fabb7SAndroid Build Coastguard Worker 		{
1115*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fExposureBiasValue);
1116*fd1fabb7SAndroid Build Coastguard Worker 		}
1117*fd1fabb7SAndroid Build Coastguard Worker 
1118*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fMaxApertureValue.IsValid ())
1119*fd1fabb7SAndroid Build Coastguard Worker 		{
1120*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fMaxApertureValue);
1121*fd1fabb7SAndroid Build Coastguard Worker 		}
1122*fd1fabb7SAndroid Build Coastguard Worker 
1123*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fSubjectDistance.IsValid ())
1124*fd1fabb7SAndroid Build Coastguard Worker 		{
1125*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fSubjectDistance);
1126*fd1fabb7SAndroid Build Coastguard Worker 		}
1127*fd1fabb7SAndroid Build Coastguard Worker 
1128*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fFocalLength.IsValid ())
1129*fd1fabb7SAndroid Build Coastguard Worker 		{
1130*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fFocalLength);
1131*fd1fabb7SAndroid Build Coastguard Worker 		}
1132*fd1fabb7SAndroid Build Coastguard Worker 
1133*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fISOSpeedRatings [0] != 0)
1134*fd1fabb7SAndroid Build Coastguard Worker 		{
1135*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fISOSpeedRatings);
1136*fd1fabb7SAndroid Build Coastguard Worker 		}
1137*fd1fabb7SAndroid Build Coastguard Worker 
1138*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fFlash <= 0x0FFFF)
1139*fd1fabb7SAndroid Build Coastguard Worker 		{
1140*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fFlash);
1141*fd1fabb7SAndroid Build Coastguard Worker 		}
1142*fd1fabb7SAndroid Build Coastguard Worker 
1143*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fExposureProgram <= 0x0FFFF)
1144*fd1fabb7SAndroid Build Coastguard Worker 		{
1145*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fExposureProgram);
1146*fd1fabb7SAndroid Build Coastguard Worker 		}
1147*fd1fabb7SAndroid Build Coastguard Worker 
1148*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fMeteringMode <= 0x0FFFF)
1149*fd1fabb7SAndroid Build Coastguard Worker 		{
1150*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fMeteringMode);
1151*fd1fabb7SAndroid Build Coastguard Worker 		}
1152*fd1fabb7SAndroid Build Coastguard Worker 
1153*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fLightSource <= 0x0FFFF)
1154*fd1fabb7SAndroid Build Coastguard Worker 		{
1155*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fLightSource);
1156*fd1fabb7SAndroid Build Coastguard Worker 		}
1157*fd1fabb7SAndroid Build Coastguard Worker 
1158*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fSensingMethod <= 0x0FFFF)
1159*fd1fabb7SAndroid Build Coastguard Worker 		{
1160*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fSensingMethod);
1161*fd1fabb7SAndroid Build Coastguard Worker 		}
1162*fd1fabb7SAndroid Build Coastguard Worker 
1163*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fFocalLengthIn35mmFilm != 0)
1164*fd1fabb7SAndroid Build Coastguard Worker 		{
1165*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fFocalLength35mm);
1166*fd1fabb7SAndroid Build Coastguard Worker 		}
1167*fd1fabb7SAndroid Build Coastguard Worker 
1168*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fFileSource <= 0x0FF)
1169*fd1fabb7SAndroid Build Coastguard Worker 		{
1170*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fFileSource);
1171*fd1fabb7SAndroid Build Coastguard Worker 		}
1172*fd1fabb7SAndroid Build Coastguard Worker 
1173*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fSceneType <= 0x0FF)
1174*fd1fabb7SAndroid Build Coastguard Worker 		{
1175*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fSceneType);
1176*fd1fabb7SAndroid Build Coastguard Worker 		}
1177*fd1fabb7SAndroid Build Coastguard Worker 
1178*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fCFARepeatPatternRows &&
1179*fd1fabb7SAndroid Build Coastguard Worker 	    exif.fCFARepeatPatternCols)
1180*fd1fabb7SAndroid Build Coastguard Worker 		{
1181*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fCFAPattern);
1182*fd1fabb7SAndroid Build Coastguard Worker 		}
1183*fd1fabb7SAndroid Build Coastguard Worker 
1184*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fCustomRendered <= 0x0FFFF)
1185*fd1fabb7SAndroid Build Coastguard Worker 		{
1186*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fCustomRendered);
1187*fd1fabb7SAndroid Build Coastguard Worker 		}
1188*fd1fabb7SAndroid Build Coastguard Worker 
1189*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fExposureMode <= 0x0FFFF)
1190*fd1fabb7SAndroid Build Coastguard Worker 		{
1191*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fExposureMode);
1192*fd1fabb7SAndroid Build Coastguard Worker 		}
1193*fd1fabb7SAndroid Build Coastguard Worker 
1194*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fWhiteBalance <= 0x0FFFF)
1195*fd1fabb7SAndroid Build Coastguard Worker 		{
1196*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fWhiteBalance);
1197*fd1fabb7SAndroid Build Coastguard Worker 		}
1198*fd1fabb7SAndroid Build Coastguard Worker 
1199*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fSceneCaptureType <= 0x0FFFF)
1200*fd1fabb7SAndroid Build Coastguard Worker 		{
1201*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fSceneCaptureType);
1202*fd1fabb7SAndroid Build Coastguard Worker 		}
1203*fd1fabb7SAndroid Build Coastguard Worker 
1204*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGainControl <= 0x0FFFF)
1205*fd1fabb7SAndroid Build Coastguard Worker 		{
1206*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fGainControl);
1207*fd1fabb7SAndroid Build Coastguard Worker 		}
1208*fd1fabb7SAndroid Build Coastguard Worker 
1209*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fContrast <= 0x0FFFF)
1210*fd1fabb7SAndroid Build Coastguard Worker 		{
1211*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fContrast);
1212*fd1fabb7SAndroid Build Coastguard Worker 		}
1213*fd1fabb7SAndroid Build Coastguard Worker 
1214*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fSaturation <= 0x0FFFF)
1215*fd1fabb7SAndroid Build Coastguard Worker 		{
1216*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fSaturation);
1217*fd1fabb7SAndroid Build Coastguard Worker 		}
1218*fd1fabb7SAndroid Build Coastguard Worker 
1219*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fSharpness <= 0x0FFFF)
1220*fd1fabb7SAndroid Build Coastguard Worker 		{
1221*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fSharpness);
1222*fd1fabb7SAndroid Build Coastguard Worker 		}
1223*fd1fabb7SAndroid Build Coastguard Worker 
1224*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fSubjectDistanceRange <= 0x0FFFF)
1225*fd1fabb7SAndroid Build Coastguard Worker 		{
1226*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fSubjectDistanceRange);
1227*fd1fabb7SAndroid Build Coastguard Worker 		}
1228*fd1fabb7SAndroid Build Coastguard Worker 
1229*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fDigitalZoomRatio.IsValid ())
1230*fd1fabb7SAndroid Build Coastguard Worker 		{
1231*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fDigitalZoomRatio);
1232*fd1fabb7SAndroid Build Coastguard Worker 		}
1233*fd1fabb7SAndroid Build Coastguard Worker 
1234*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fExposureIndex.IsValid ())
1235*fd1fabb7SAndroid Build Coastguard Worker 		{
1236*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fExposureIndex);
1237*fd1fabb7SAndroid Build Coastguard Worker 		}
1238*fd1fabb7SAndroid Build Coastguard Worker 
1239*fd1fabb7SAndroid Build Coastguard Worker 	if (insideDNG)	// TIFF-EP only tags
1240*fd1fabb7SAndroid Build Coastguard Worker 		{
1241*fd1fabb7SAndroid Build Coastguard Worker 
1242*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fImageNumber != 0xFFFFFFFF)
1243*fd1fabb7SAndroid Build Coastguard Worker 			{
1244*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fImageNumber);
1245*fd1fabb7SAndroid Build Coastguard Worker 			}
1246*fd1fabb7SAndroid Build Coastguard Worker 
1247*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fSelfTimerMode <= 0x0FFFF)
1248*fd1fabb7SAndroid Build Coastguard Worker 			{
1249*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fSelfTimerMode);
1250*fd1fabb7SAndroid Build Coastguard Worker 			}
1251*fd1fabb7SAndroid Build Coastguard Worker 
1252*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fBatteryLevelA.NotEmpty ())
1253*fd1fabb7SAndroid Build Coastguard Worker 			{
1254*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fBatteryLevelA);
1255*fd1fabb7SAndroid Build Coastguard Worker 			}
1256*fd1fabb7SAndroid Build Coastguard Worker 
1257*fd1fabb7SAndroid Build Coastguard Worker 		else if (exif.fBatteryLevelR.IsValid ())
1258*fd1fabb7SAndroid Build Coastguard Worker 			{
1259*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fBatteryLevelR);
1260*fd1fabb7SAndroid Build Coastguard Worker 			}
1261*fd1fabb7SAndroid Build Coastguard Worker 
1262*fd1fabb7SAndroid Build Coastguard Worker 		}
1263*fd1fabb7SAndroid Build Coastguard Worker 
1264*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fFocalPlaneXResolution.IsValid ())
1265*fd1fabb7SAndroid Build Coastguard Worker 		{
1266*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fFocalPlaneXResolution);
1267*fd1fabb7SAndroid Build Coastguard Worker 		}
1268*fd1fabb7SAndroid Build Coastguard Worker 
1269*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fFocalPlaneYResolution.IsValid ())
1270*fd1fabb7SAndroid Build Coastguard Worker 		{
1271*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fFocalPlaneYResolution);
1272*fd1fabb7SAndroid Build Coastguard Worker 		}
1273*fd1fabb7SAndroid Build Coastguard Worker 
1274*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fFocalPlaneResolutionUnit <= 0x0FFFF)
1275*fd1fabb7SAndroid Build Coastguard Worker 		{
1276*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fFocalPlaneResolutionUnit);
1277*fd1fabb7SAndroid Build Coastguard Worker 		}
1278*fd1fabb7SAndroid Build Coastguard Worker 
1279*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fSubjectAreaCount)
1280*fd1fabb7SAndroid Build Coastguard Worker 		{
1281*fd1fabb7SAndroid Build Coastguard Worker 
1282*fd1fabb7SAndroid Build Coastguard Worker 		fSubjectAreaData [0] = (uint16) exif.fSubjectArea [0];
1283*fd1fabb7SAndroid Build Coastguard Worker 		fSubjectAreaData [1] = (uint16) exif.fSubjectArea [1];
1284*fd1fabb7SAndroid Build Coastguard Worker 		fSubjectAreaData [2] = (uint16) exif.fSubjectArea [2];
1285*fd1fabb7SAndroid Build Coastguard Worker 		fSubjectAreaData [3] = (uint16) exif.fSubjectArea [3];
1286*fd1fabb7SAndroid Build Coastguard Worker 
1287*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fSubjectArea);
1288*fd1fabb7SAndroid Build Coastguard Worker 
1289*fd1fabb7SAndroid Build Coastguard Worker 		}
1290*fd1fabb7SAndroid Build Coastguard Worker 
1291*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fLensInfo [0].IsValid () &&
1292*fd1fabb7SAndroid Build Coastguard Worker 		exif.fLensInfo [1].IsValid ())
1293*fd1fabb7SAndroid Build Coastguard Worker 		{
1294*fd1fabb7SAndroid Build Coastguard Worker 
1295*fd1fabb7SAndroid Build Coastguard Worker 		fLensInfoData [0] = exif.fLensInfo [0];
1296*fd1fabb7SAndroid Build Coastguard Worker 		fLensInfoData [1] = exif.fLensInfo [1];
1297*fd1fabb7SAndroid Build Coastguard Worker 		fLensInfoData [2] = exif.fLensInfo [2];
1298*fd1fabb7SAndroid Build Coastguard Worker 		fLensInfoData [3] = exif.fLensInfo [3];
1299*fd1fabb7SAndroid Build Coastguard Worker 
1300*fd1fabb7SAndroid Build Coastguard Worker 		if (insideDNG)
1301*fd1fabb7SAndroid Build Coastguard Worker 			{
1302*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fLensInfo);
1303*fd1fabb7SAndroid Build Coastguard Worker 			}
1304*fd1fabb7SAndroid Build Coastguard Worker 
1305*fd1fabb7SAndroid Build Coastguard Worker 		}
1306*fd1fabb7SAndroid Build Coastguard Worker 
1307*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fDateTime.IsValid ())
1308*fd1fabb7SAndroid Build Coastguard Worker 		{
1309*fd1fabb7SAndroid Build Coastguard Worker 
1310*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fDateTime);
1311*fd1fabb7SAndroid Build Coastguard Worker 
1312*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fDateTime.Subseconds ().NotEmpty ())
1313*fd1fabb7SAndroid Build Coastguard Worker 			{
1314*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fSubsecTime);
1315*fd1fabb7SAndroid Build Coastguard Worker 			}
1316*fd1fabb7SAndroid Build Coastguard Worker 
1317*fd1fabb7SAndroid Build Coastguard Worker 		}
1318*fd1fabb7SAndroid Build Coastguard Worker 
1319*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fDateTimeOriginal.IsValid ())
1320*fd1fabb7SAndroid Build Coastguard Worker 		{
1321*fd1fabb7SAndroid Build Coastguard Worker 
1322*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fDateTimeOriginal);
1323*fd1fabb7SAndroid Build Coastguard Worker 
1324*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fDateTimeOriginal.Subseconds ().NotEmpty ())
1325*fd1fabb7SAndroid Build Coastguard Worker 			{
1326*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fSubsecTimeOriginal);
1327*fd1fabb7SAndroid Build Coastguard Worker 			}
1328*fd1fabb7SAndroid Build Coastguard Worker 
1329*fd1fabb7SAndroid Build Coastguard Worker 		}
1330*fd1fabb7SAndroid Build Coastguard Worker 
1331*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fDateTimeDigitized.IsValid ())
1332*fd1fabb7SAndroid Build Coastguard Worker 		{
1333*fd1fabb7SAndroid Build Coastguard Worker 
1334*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fDateTimeDigitized);
1335*fd1fabb7SAndroid Build Coastguard Worker 
1336*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fDateTimeDigitized.Subseconds ().NotEmpty ())
1337*fd1fabb7SAndroid Build Coastguard Worker 			{
1338*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fSubsecTimeDigitized);
1339*fd1fabb7SAndroid Build Coastguard Worker 			}
1340*fd1fabb7SAndroid Build Coastguard Worker 
1341*fd1fabb7SAndroid Build Coastguard Worker 		}
1342*fd1fabb7SAndroid Build Coastguard Worker 
1343*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fMake.NotEmpty ())
1344*fd1fabb7SAndroid Build Coastguard Worker 		{
1345*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fMake);
1346*fd1fabb7SAndroid Build Coastguard Worker 		}
1347*fd1fabb7SAndroid Build Coastguard Worker 
1348*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fModel.NotEmpty ())
1349*fd1fabb7SAndroid Build Coastguard Worker 		{
1350*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fModel);
1351*fd1fabb7SAndroid Build Coastguard Worker 		}
1352*fd1fabb7SAndroid Build Coastguard Worker 
1353*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fArtist.NotEmpty ())
1354*fd1fabb7SAndroid Build Coastguard Worker 		{
1355*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fArtist);
1356*fd1fabb7SAndroid Build Coastguard Worker 		}
1357*fd1fabb7SAndroid Build Coastguard Worker 
1358*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fSoftware.NotEmpty ())
1359*fd1fabb7SAndroid Build Coastguard Worker 		{
1360*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fSoftware);
1361*fd1fabb7SAndroid Build Coastguard Worker 		}
1362*fd1fabb7SAndroid Build Coastguard Worker 
1363*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fCopyright.NotEmpty ())
1364*fd1fabb7SAndroid Build Coastguard Worker 		{
1365*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fCopyright);
1366*fd1fabb7SAndroid Build Coastguard Worker 		}
1367*fd1fabb7SAndroid Build Coastguard Worker 
1368*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fImageDescription.NotEmpty ())
1369*fd1fabb7SAndroid Build Coastguard Worker 		{
1370*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fImageDescription);
1371*fd1fabb7SAndroid Build Coastguard Worker 		}
1372*fd1fabb7SAndroid Build Coastguard Worker 
1373*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fCameraSerialNumber.NotEmpty () && insideDNG)
1374*fd1fabb7SAndroid Build Coastguard Worker 		{
1375*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fSerialNumber);
1376*fd1fabb7SAndroid Build Coastguard Worker 		}
1377*fd1fabb7SAndroid Build Coastguard Worker 
1378*fd1fabb7SAndroid Build Coastguard Worker 	if (makerNoteSafe && makerNoteData)
1379*fd1fabb7SAndroid Build Coastguard Worker 		{
1380*fd1fabb7SAndroid Build Coastguard Worker 
1381*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fMakerNoteSafety);
1382*fd1fabb7SAndroid Build Coastguard Worker 
1383*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fMakerNote);
1384*fd1fabb7SAndroid Build Coastguard Worker 
1385*fd1fabb7SAndroid Build Coastguard Worker 		}
1386*fd1fabb7SAndroid Build Coastguard Worker 
1387*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fUserComment.NotEmpty ())
1388*fd1fabb7SAndroid Build Coastguard Worker 		{
1389*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fUserComment);
1390*fd1fabb7SAndroid Build Coastguard Worker 		}
1391*fd1fabb7SAndroid Build Coastguard Worker 
1392*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fImageUniqueID.IsValid ())
1393*fd1fabb7SAndroid Build Coastguard Worker 		{
1394*fd1fabb7SAndroid Build Coastguard Worker 
1395*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 j = 0; j < 16; j++)
1396*fd1fabb7SAndroid Build Coastguard Worker 			{
1397*fd1fabb7SAndroid Build Coastguard Worker 
1398*fd1fabb7SAndroid Build Coastguard Worker 			sprintf (fImageUniqueIDData + j * 2,
1399*fd1fabb7SAndroid Build Coastguard Worker 					 "%02X",
1400*fd1fabb7SAndroid Build Coastguard Worker 					 (unsigned) exif.fImageUniqueID.data [j]);
1401*fd1fabb7SAndroid Build Coastguard Worker 
1402*fd1fabb7SAndroid Build Coastguard Worker 			}
1403*fd1fabb7SAndroid Build Coastguard Worker 
1404*fd1fabb7SAndroid Build Coastguard Worker 		fExifIFD.Add (&fImageUniqueID);
1405*fd1fabb7SAndroid Build Coastguard Worker 
1406*fd1fabb7SAndroid Build Coastguard Worker 		}
1407*fd1fabb7SAndroid Build Coastguard Worker 
1408*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.AtLeastVersion0230 ())
1409*fd1fabb7SAndroid Build Coastguard Worker 		{
1410*fd1fabb7SAndroid Build Coastguard Worker 
1411*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fSensitivityType != 0)
1412*fd1fabb7SAndroid Build Coastguard Worker 			{
1413*fd1fabb7SAndroid Build Coastguard Worker 
1414*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fSensitivityType);
1415*fd1fabb7SAndroid Build Coastguard Worker 
1416*fd1fabb7SAndroid Build Coastguard Worker 			}
1417*fd1fabb7SAndroid Build Coastguard Worker 
1418*fd1fabb7SAndroid Build Coastguard Worker 		// Sensitivity tags. Do not write these extra tags unless the SensitivityType
1419*fd1fabb7SAndroid Build Coastguard Worker 		// and PhotographicSensitivity (i.e., ISOSpeedRatings) values are valid.
1420*fd1fabb7SAndroid Build Coastguard Worker 
1421*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fSensitivityType	  != 0 &&
1422*fd1fabb7SAndroid Build Coastguard Worker 			exif.fISOSpeedRatings [0] != 0)
1423*fd1fabb7SAndroid Build Coastguard Worker 			{
1424*fd1fabb7SAndroid Build Coastguard Worker 
1425*fd1fabb7SAndroid Build Coastguard Worker 			// Standard Output Sensitivity (SOS).
1426*fd1fabb7SAndroid Build Coastguard Worker 
1427*fd1fabb7SAndroid Build Coastguard Worker 			if (exif.fStandardOutputSensitivity != 0)
1428*fd1fabb7SAndroid Build Coastguard Worker 				{
1429*fd1fabb7SAndroid Build Coastguard Worker 				fExifIFD.Add (&fStandardOutputSensitivity);
1430*fd1fabb7SAndroid Build Coastguard Worker 				}
1431*fd1fabb7SAndroid Build Coastguard Worker 
1432*fd1fabb7SAndroid Build Coastguard Worker 			// Recommended Exposure Index (REI).
1433*fd1fabb7SAndroid Build Coastguard Worker 
1434*fd1fabb7SAndroid Build Coastguard Worker 			if (exif.fRecommendedExposureIndex != 0)
1435*fd1fabb7SAndroid Build Coastguard Worker 				{
1436*fd1fabb7SAndroid Build Coastguard Worker 				fExifIFD.Add (&fRecommendedExposureIndex);
1437*fd1fabb7SAndroid Build Coastguard Worker 				}
1438*fd1fabb7SAndroid Build Coastguard Worker 
1439*fd1fabb7SAndroid Build Coastguard Worker 			// ISO Speed.
1440*fd1fabb7SAndroid Build Coastguard Worker 
1441*fd1fabb7SAndroid Build Coastguard Worker 			if (exif.fISOSpeed != 0)
1442*fd1fabb7SAndroid Build Coastguard Worker 				{
1443*fd1fabb7SAndroid Build Coastguard Worker 
1444*fd1fabb7SAndroid Build Coastguard Worker 				fExifIFD.Add (&fISOSpeed);
1445*fd1fabb7SAndroid Build Coastguard Worker 
1446*fd1fabb7SAndroid Build Coastguard Worker 				if (exif.fISOSpeedLatitudeyyy != 0 &&
1447*fd1fabb7SAndroid Build Coastguard Worker 					exif.fISOSpeedLatitudezzz != 0)
1448*fd1fabb7SAndroid Build Coastguard Worker 					{
1449*fd1fabb7SAndroid Build Coastguard Worker 
1450*fd1fabb7SAndroid Build Coastguard Worker 					fExifIFD.Add (&fISOSpeedLatitudeyyy);
1451*fd1fabb7SAndroid Build Coastguard Worker 					fExifIFD.Add (&fISOSpeedLatitudezzz);
1452*fd1fabb7SAndroid Build Coastguard Worker 
1453*fd1fabb7SAndroid Build Coastguard Worker 					}
1454*fd1fabb7SAndroid Build Coastguard Worker 
1455*fd1fabb7SAndroid Build Coastguard Worker 				}
1456*fd1fabb7SAndroid Build Coastguard Worker 
1457*fd1fabb7SAndroid Build Coastguard Worker 			}
1458*fd1fabb7SAndroid Build Coastguard Worker 
1459*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fOwnerName.NotEmpty ())
1460*fd1fabb7SAndroid Build Coastguard Worker 			{
1461*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fCameraOwnerName);
1462*fd1fabb7SAndroid Build Coastguard Worker 			}
1463*fd1fabb7SAndroid Build Coastguard Worker 
1464*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fCameraSerialNumber.NotEmpty ())
1465*fd1fabb7SAndroid Build Coastguard Worker 			{
1466*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fBodySerialNumber);
1467*fd1fabb7SAndroid Build Coastguard Worker 			}
1468*fd1fabb7SAndroid Build Coastguard Worker 
1469*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fLensInfo [0].IsValid () &&
1470*fd1fabb7SAndroid Build Coastguard Worker 			exif.fLensInfo [1].IsValid ())
1471*fd1fabb7SAndroid Build Coastguard Worker 			{
1472*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fLensSpecification);
1473*fd1fabb7SAndroid Build Coastguard Worker 			}
1474*fd1fabb7SAndroid Build Coastguard Worker 
1475*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fLensMake.NotEmpty ())
1476*fd1fabb7SAndroid Build Coastguard Worker 			{
1477*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fLensMake);
1478*fd1fabb7SAndroid Build Coastguard Worker 			}
1479*fd1fabb7SAndroid Build Coastguard Worker 
1480*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fLensName.NotEmpty ())
1481*fd1fabb7SAndroid Build Coastguard Worker 			{
1482*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fLensModel);
1483*fd1fabb7SAndroid Build Coastguard Worker 			}
1484*fd1fabb7SAndroid Build Coastguard Worker 
1485*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fLensSerialNumber.NotEmpty ())
1486*fd1fabb7SAndroid Build Coastguard Worker 			{
1487*fd1fabb7SAndroid Build Coastguard Worker 			fExifIFD.Add (&fLensSerialNumber);
1488*fd1fabb7SAndroid Build Coastguard Worker 			}
1489*fd1fabb7SAndroid Build Coastguard Worker 
1490*fd1fabb7SAndroid Build Coastguard Worker 		}
1491*fd1fabb7SAndroid Build Coastguard Worker 
1492*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSVersionID)
1493*fd1fabb7SAndroid Build Coastguard Worker 		{
1494*fd1fabb7SAndroid Build Coastguard Worker 
1495*fd1fabb7SAndroid Build Coastguard Worker 		fGPSVersionData [0] = (uint8) (exif.fGPSVersionID >> 24);
1496*fd1fabb7SAndroid Build Coastguard Worker 		fGPSVersionData [1] = (uint8) (exif.fGPSVersionID >> 16);
1497*fd1fabb7SAndroid Build Coastguard Worker 		fGPSVersionData [2] = (uint8) (exif.fGPSVersionID >>  8);
1498*fd1fabb7SAndroid Build Coastguard Worker 		fGPSVersionData [3] = (uint8) (exif.fGPSVersionID      );
1499*fd1fabb7SAndroid Build Coastguard Worker 
1500*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSVersionID);
1501*fd1fabb7SAndroid Build Coastguard Worker 
1502*fd1fabb7SAndroid Build Coastguard Worker 		}
1503*fd1fabb7SAndroid Build Coastguard Worker 
1504*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSLatitudeRef.NotEmpty () &&
1505*fd1fabb7SAndroid Build Coastguard Worker 		exif.fGPSLatitude [0].IsValid ())
1506*fd1fabb7SAndroid Build Coastguard Worker 		{
1507*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSLatitudeRef);
1508*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSLatitude   );
1509*fd1fabb7SAndroid Build Coastguard Worker 		}
1510*fd1fabb7SAndroid Build Coastguard Worker 
1511*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSLongitudeRef.NotEmpty () &&
1512*fd1fabb7SAndroid Build Coastguard Worker 		exif.fGPSLongitude [0].IsValid ())
1513*fd1fabb7SAndroid Build Coastguard Worker 		{
1514*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSLongitudeRef);
1515*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSLongitude   );
1516*fd1fabb7SAndroid Build Coastguard Worker 		}
1517*fd1fabb7SAndroid Build Coastguard Worker 
1518*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSAltitudeRef <= 0x0FF)
1519*fd1fabb7SAndroid Build Coastguard Worker 		{
1520*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSAltitudeRef);
1521*fd1fabb7SAndroid Build Coastguard Worker 		}
1522*fd1fabb7SAndroid Build Coastguard Worker 
1523*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSAltitude.IsValid ())
1524*fd1fabb7SAndroid Build Coastguard Worker 		{
1525*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSAltitude);
1526*fd1fabb7SAndroid Build Coastguard Worker 		}
1527*fd1fabb7SAndroid Build Coastguard Worker 
1528*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSTimeStamp [0].IsValid ())
1529*fd1fabb7SAndroid Build Coastguard Worker 		{
1530*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSTimeStamp);
1531*fd1fabb7SAndroid Build Coastguard Worker 		}
1532*fd1fabb7SAndroid Build Coastguard Worker 
1533*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSSatellites.NotEmpty ())
1534*fd1fabb7SAndroid Build Coastguard Worker 		{
1535*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSSatellites);
1536*fd1fabb7SAndroid Build Coastguard Worker 		}
1537*fd1fabb7SAndroid Build Coastguard Worker 
1538*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSStatus.NotEmpty ())
1539*fd1fabb7SAndroid Build Coastguard Worker 		{
1540*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSStatus);
1541*fd1fabb7SAndroid Build Coastguard Worker 		}
1542*fd1fabb7SAndroid Build Coastguard Worker 
1543*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSMeasureMode.NotEmpty ())
1544*fd1fabb7SAndroid Build Coastguard Worker 		{
1545*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSMeasureMode);
1546*fd1fabb7SAndroid Build Coastguard Worker 		}
1547*fd1fabb7SAndroid Build Coastguard Worker 
1548*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSDOP.IsValid ())
1549*fd1fabb7SAndroid Build Coastguard Worker 		{
1550*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDOP);
1551*fd1fabb7SAndroid Build Coastguard Worker 		}
1552*fd1fabb7SAndroid Build Coastguard Worker 
1553*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSSpeedRef.NotEmpty ())
1554*fd1fabb7SAndroid Build Coastguard Worker 		{
1555*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSSpeedRef);
1556*fd1fabb7SAndroid Build Coastguard Worker 		}
1557*fd1fabb7SAndroid Build Coastguard Worker 
1558*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSSpeed.IsValid ())
1559*fd1fabb7SAndroid Build Coastguard Worker 		{
1560*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSSpeed);
1561*fd1fabb7SAndroid Build Coastguard Worker 		}
1562*fd1fabb7SAndroid Build Coastguard Worker 
1563*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSTrackRef.NotEmpty ())
1564*fd1fabb7SAndroid Build Coastguard Worker 		{
1565*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSTrackRef);
1566*fd1fabb7SAndroid Build Coastguard Worker 		}
1567*fd1fabb7SAndroid Build Coastguard Worker 
1568*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSTrack.IsValid ())
1569*fd1fabb7SAndroid Build Coastguard Worker 		{
1570*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSTrack);
1571*fd1fabb7SAndroid Build Coastguard Worker 		}
1572*fd1fabb7SAndroid Build Coastguard Worker 
1573*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSImgDirectionRef.NotEmpty ())
1574*fd1fabb7SAndroid Build Coastguard Worker 		{
1575*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSImgDirectionRef);
1576*fd1fabb7SAndroid Build Coastguard Worker 		}
1577*fd1fabb7SAndroid Build Coastguard Worker 
1578*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSImgDirection.IsValid ())
1579*fd1fabb7SAndroid Build Coastguard Worker 		{
1580*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSImgDirection);
1581*fd1fabb7SAndroid Build Coastguard Worker 		}
1582*fd1fabb7SAndroid Build Coastguard Worker 
1583*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSMapDatum.NotEmpty ())
1584*fd1fabb7SAndroid Build Coastguard Worker 		{
1585*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSMapDatum);
1586*fd1fabb7SAndroid Build Coastguard Worker 		}
1587*fd1fabb7SAndroid Build Coastguard Worker 
1588*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSDestLatitudeRef.NotEmpty () &&
1589*fd1fabb7SAndroid Build Coastguard Worker 		exif.fGPSDestLatitude [0].IsValid ())
1590*fd1fabb7SAndroid Build Coastguard Worker 		{
1591*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDestLatitudeRef);
1592*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDestLatitude   );
1593*fd1fabb7SAndroid Build Coastguard Worker 		}
1594*fd1fabb7SAndroid Build Coastguard Worker 
1595*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSDestLongitudeRef.NotEmpty () &&
1596*fd1fabb7SAndroid Build Coastguard Worker 		exif.fGPSDestLongitude [0].IsValid ())
1597*fd1fabb7SAndroid Build Coastguard Worker 		{
1598*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDestLongitudeRef);
1599*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDestLongitude   );
1600*fd1fabb7SAndroid Build Coastguard Worker 		}
1601*fd1fabb7SAndroid Build Coastguard Worker 
1602*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSDestBearingRef.NotEmpty ())
1603*fd1fabb7SAndroid Build Coastguard Worker 		{
1604*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDestBearingRef);
1605*fd1fabb7SAndroid Build Coastguard Worker 		}
1606*fd1fabb7SAndroid Build Coastguard Worker 
1607*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSDestBearing.IsValid ())
1608*fd1fabb7SAndroid Build Coastguard Worker 		{
1609*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDestBearing);
1610*fd1fabb7SAndroid Build Coastguard Worker 		}
1611*fd1fabb7SAndroid Build Coastguard Worker 
1612*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSDestDistanceRef.NotEmpty ())
1613*fd1fabb7SAndroid Build Coastguard Worker 		{
1614*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDestDistanceRef);
1615*fd1fabb7SAndroid Build Coastguard Worker 		}
1616*fd1fabb7SAndroid Build Coastguard Worker 
1617*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSDestDistance.IsValid ())
1618*fd1fabb7SAndroid Build Coastguard Worker 		{
1619*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDestDistance);
1620*fd1fabb7SAndroid Build Coastguard Worker 		}
1621*fd1fabb7SAndroid Build Coastguard Worker 
1622*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSProcessingMethod.NotEmpty ())
1623*fd1fabb7SAndroid Build Coastguard Worker 		{
1624*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSProcessingMethod);
1625*fd1fabb7SAndroid Build Coastguard Worker 		}
1626*fd1fabb7SAndroid Build Coastguard Worker 
1627*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSAreaInformation.NotEmpty ())
1628*fd1fabb7SAndroid Build Coastguard Worker 		{
1629*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSAreaInformation);
1630*fd1fabb7SAndroid Build Coastguard Worker 		}
1631*fd1fabb7SAndroid Build Coastguard Worker 
1632*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSDateStamp.NotEmpty ())
1633*fd1fabb7SAndroid Build Coastguard Worker 		{
1634*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDateStamp);
1635*fd1fabb7SAndroid Build Coastguard Worker 		}
1636*fd1fabb7SAndroid Build Coastguard Worker 
1637*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.fGPSDifferential <= 0x0FFFF)
1638*fd1fabb7SAndroid Build Coastguard Worker 		{
1639*fd1fabb7SAndroid Build Coastguard Worker 		fGPSIFD.Add (&fGPSDifferential);
1640*fd1fabb7SAndroid Build Coastguard Worker 		}
1641*fd1fabb7SAndroid Build Coastguard Worker 
1642*fd1fabb7SAndroid Build Coastguard Worker 	if (exif.AtLeastVersion0230 ())
1643*fd1fabb7SAndroid Build Coastguard Worker 		{
1644*fd1fabb7SAndroid Build Coastguard Worker 
1645*fd1fabb7SAndroid Build Coastguard Worker 		if (exif.fGPSHPositioningError.IsValid ())
1646*fd1fabb7SAndroid Build Coastguard Worker 			{
1647*fd1fabb7SAndroid Build Coastguard Worker 			fGPSIFD.Add (&fGPSHPositioningError);
1648*fd1fabb7SAndroid Build Coastguard Worker 			}
1649*fd1fabb7SAndroid Build Coastguard Worker 
1650*fd1fabb7SAndroid Build Coastguard Worker 		}
1651*fd1fabb7SAndroid Build Coastguard Worker 
1652*fd1fabb7SAndroid Build Coastguard Worker 	AddLinks (directory);
1653*fd1fabb7SAndroid Build Coastguard Worker 
1654*fd1fabb7SAndroid Build Coastguard Worker 	}
1655*fd1fabb7SAndroid Build Coastguard Worker 
1656*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
1657*fd1fabb7SAndroid Build Coastguard Worker 
AddLinks(dng_tiff_directory & directory)1658*fd1fabb7SAndroid Build Coastguard Worker void exif_tag_set::AddLinks (dng_tiff_directory &directory)
1659*fd1fabb7SAndroid Build Coastguard Worker 	{
1660*fd1fabb7SAndroid Build Coastguard Worker 
1661*fd1fabb7SAndroid Build Coastguard Worker 	if (fExifIFD.Size () != 0 && !fAddedExifLink)
1662*fd1fabb7SAndroid Build Coastguard Worker 		{
1663*fd1fabb7SAndroid Build Coastguard Worker 
1664*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fExifLink);
1665*fd1fabb7SAndroid Build Coastguard Worker 
1666*fd1fabb7SAndroid Build Coastguard Worker 		fAddedExifLink = true;
1667*fd1fabb7SAndroid Build Coastguard Worker 
1668*fd1fabb7SAndroid Build Coastguard Worker 		}
1669*fd1fabb7SAndroid Build Coastguard Worker 
1670*fd1fabb7SAndroid Build Coastguard Worker 	if (fGPSIFD.Size () != 0 && !fAddedGPSLink)
1671*fd1fabb7SAndroid Build Coastguard Worker 		{
1672*fd1fabb7SAndroid Build Coastguard Worker 
1673*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fGPSLink);
1674*fd1fabb7SAndroid Build Coastguard Worker 
1675*fd1fabb7SAndroid Build Coastguard Worker 		fAddedGPSLink = true;
1676*fd1fabb7SAndroid Build Coastguard Worker 
1677*fd1fabb7SAndroid Build Coastguard Worker 		}
1678*fd1fabb7SAndroid Build Coastguard Worker 
1679*fd1fabb7SAndroid Build Coastguard Worker 	}
1680*fd1fabb7SAndroid Build Coastguard Worker 
1681*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
1682*fd1fabb7SAndroid Build Coastguard Worker 
1683*fd1fabb7SAndroid Build Coastguard Worker class range_tag_set
1684*fd1fabb7SAndroid Build Coastguard Worker 	{
1685*fd1fabb7SAndroid Build Coastguard Worker 
1686*fd1fabb7SAndroid Build Coastguard Worker 	private:
1687*fd1fabb7SAndroid Build Coastguard Worker 
1688*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fActiveAreaData [4];
1689*fd1fabb7SAndroid Build Coastguard Worker 
1690*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32_ptr fActiveArea;
1691*fd1fabb7SAndroid Build Coastguard Worker 
1692*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fMaskedAreaData [kMaxMaskedAreas * 4];
1693*fd1fabb7SAndroid Build Coastguard Worker 
1694*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32_ptr fMaskedAreas;
1695*fd1fabb7SAndroid Build Coastguard Worker 
1696*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint16_ptr fLinearizationTable;
1697*fd1fabb7SAndroid Build Coastguard Worker 
1698*fd1fabb7SAndroid Build Coastguard Worker 		uint16 fBlackLevelRepeatDimData [2];
1699*fd1fabb7SAndroid Build Coastguard Worker 
1700*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint16_ptr fBlackLevelRepeatDim;
1701*fd1fabb7SAndroid Build Coastguard Worker 
1702*fd1fabb7SAndroid Build Coastguard Worker 		dng_urational fBlackLevelData [kMaxBlackPattern *
1703*fd1fabb7SAndroid Build Coastguard Worker 								       kMaxBlackPattern *
1704*fd1fabb7SAndroid Build Coastguard Worker 								       kMaxSamplesPerPixel];
1705*fd1fabb7SAndroid Build Coastguard Worker 
1706*fd1fabb7SAndroid Build Coastguard Worker 		tag_urational_ptr fBlackLevel;
1707*fd1fabb7SAndroid Build Coastguard Worker 
1708*fd1fabb7SAndroid Build Coastguard Worker 		dng_memory_data fBlackLevelDeltaHData;
1709*fd1fabb7SAndroid Build Coastguard Worker 		dng_memory_data fBlackLevelDeltaVData;
1710*fd1fabb7SAndroid Build Coastguard Worker 
1711*fd1fabb7SAndroid Build Coastguard Worker 		tag_srational_ptr fBlackLevelDeltaH;
1712*fd1fabb7SAndroid Build Coastguard Worker 		tag_srational_ptr fBlackLevelDeltaV;
1713*fd1fabb7SAndroid Build Coastguard Worker 
1714*fd1fabb7SAndroid Build Coastguard Worker 		uint16 fWhiteLevelData16 [kMaxSamplesPerPixel];
1715*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fWhiteLevelData32 [kMaxSamplesPerPixel];
1716*fd1fabb7SAndroid Build Coastguard Worker 
1717*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint16_ptr fWhiteLevel16;
1718*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32_ptr fWhiteLevel32;
1719*fd1fabb7SAndroid Build Coastguard Worker 
1720*fd1fabb7SAndroid Build Coastguard Worker 	public:
1721*fd1fabb7SAndroid Build Coastguard Worker 
1722*fd1fabb7SAndroid Build Coastguard Worker 		range_tag_set (dng_tiff_directory &directory,
1723*fd1fabb7SAndroid Build Coastguard Worker 				       const dng_negative &negative);
1724*fd1fabb7SAndroid Build Coastguard Worker 
1725*fd1fabb7SAndroid Build Coastguard Worker 	};
1726*fd1fabb7SAndroid Build Coastguard Worker 
1727*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
1728*fd1fabb7SAndroid Build Coastguard Worker 
range_tag_set(dng_tiff_directory & directory,const dng_negative & negative)1729*fd1fabb7SAndroid Build Coastguard Worker range_tag_set::range_tag_set (dng_tiff_directory &directory,
1730*fd1fabb7SAndroid Build Coastguard Worker 				     	      const dng_negative &negative)
1731*fd1fabb7SAndroid Build Coastguard Worker 
1732*fd1fabb7SAndroid Build Coastguard Worker 	:	fActiveArea (tcActiveArea,
1733*fd1fabb7SAndroid Build Coastguard Worker 					 fActiveAreaData,
1734*fd1fabb7SAndroid Build Coastguard Worker 					 4)
1735*fd1fabb7SAndroid Build Coastguard Worker 
1736*fd1fabb7SAndroid Build Coastguard Worker 	,	fMaskedAreas (tcMaskedAreas,
1737*fd1fabb7SAndroid Build Coastguard Worker 					  fMaskedAreaData,
1738*fd1fabb7SAndroid Build Coastguard Worker 					  0)
1739*fd1fabb7SAndroid Build Coastguard Worker 
1740*fd1fabb7SAndroid Build Coastguard Worker 	,	fLinearizationTable (tcLinearizationTable,
1741*fd1fabb7SAndroid Build Coastguard Worker 							 NULL,
1742*fd1fabb7SAndroid Build Coastguard Worker 							 0)
1743*fd1fabb7SAndroid Build Coastguard Worker 
1744*fd1fabb7SAndroid Build Coastguard Worker 	,	fBlackLevelRepeatDim (tcBlackLevelRepeatDim,
1745*fd1fabb7SAndroid Build Coastguard Worker 							  fBlackLevelRepeatDimData,
1746*fd1fabb7SAndroid Build Coastguard Worker 							  2)
1747*fd1fabb7SAndroid Build Coastguard Worker 
1748*fd1fabb7SAndroid Build Coastguard Worker 	,	fBlackLevel (tcBlackLevel,
1749*fd1fabb7SAndroid Build Coastguard Worker 					 fBlackLevelData)
1750*fd1fabb7SAndroid Build Coastguard Worker 
1751*fd1fabb7SAndroid Build Coastguard Worker 	,	fBlackLevelDeltaHData ()
1752*fd1fabb7SAndroid Build Coastguard Worker 	,	fBlackLevelDeltaVData ()
1753*fd1fabb7SAndroid Build Coastguard Worker 
1754*fd1fabb7SAndroid Build Coastguard Worker 	,	fBlackLevelDeltaH (tcBlackLevelDeltaH)
1755*fd1fabb7SAndroid Build Coastguard Worker 	,	fBlackLevelDeltaV (tcBlackLevelDeltaV)
1756*fd1fabb7SAndroid Build Coastguard Worker 
1757*fd1fabb7SAndroid Build Coastguard Worker 	,	fWhiteLevel16 (tcWhiteLevel,
1758*fd1fabb7SAndroid Build Coastguard Worker 					   fWhiteLevelData16)
1759*fd1fabb7SAndroid Build Coastguard Worker 
1760*fd1fabb7SAndroid Build Coastguard Worker 	,	fWhiteLevel32 (tcWhiteLevel,
1761*fd1fabb7SAndroid Build Coastguard Worker 					   fWhiteLevelData32)
1762*fd1fabb7SAndroid Build Coastguard Worker 
1763*fd1fabb7SAndroid Build Coastguard Worker 	{
1764*fd1fabb7SAndroid Build Coastguard Worker 
1765*fd1fabb7SAndroid Build Coastguard Worker 	const dng_image &rawImage (negative.RawImage ());
1766*fd1fabb7SAndroid Build Coastguard Worker 
1767*fd1fabb7SAndroid Build Coastguard Worker 	const dng_linearization_info *rangeInfo = negative.GetLinearizationInfo ();
1768*fd1fabb7SAndroid Build Coastguard Worker 
1769*fd1fabb7SAndroid Build Coastguard Worker 	if (rangeInfo)
1770*fd1fabb7SAndroid Build Coastguard Worker 		{
1771*fd1fabb7SAndroid Build Coastguard Worker 
1772*fd1fabb7SAndroid Build Coastguard Worker 		// ActiveArea:
1773*fd1fabb7SAndroid Build Coastguard Worker 
1774*fd1fabb7SAndroid Build Coastguard Worker 			{
1775*fd1fabb7SAndroid Build Coastguard Worker 
1776*fd1fabb7SAndroid Build Coastguard Worker 			const dng_rect &r = rangeInfo->fActiveArea;
1777*fd1fabb7SAndroid Build Coastguard Worker 
1778*fd1fabb7SAndroid Build Coastguard Worker 			if (r.NotEmpty ())
1779*fd1fabb7SAndroid Build Coastguard Worker 				{
1780*fd1fabb7SAndroid Build Coastguard Worker 
1781*fd1fabb7SAndroid Build Coastguard Worker 				fActiveAreaData [0] = r.t;
1782*fd1fabb7SAndroid Build Coastguard Worker 				fActiveAreaData [1] = r.l;
1783*fd1fabb7SAndroid Build Coastguard Worker 				fActiveAreaData [2] = r.b;
1784*fd1fabb7SAndroid Build Coastguard Worker 				fActiveAreaData [3] = r.r;
1785*fd1fabb7SAndroid Build Coastguard Worker 
1786*fd1fabb7SAndroid Build Coastguard Worker 				directory.Add (&fActiveArea);
1787*fd1fabb7SAndroid Build Coastguard Worker 
1788*fd1fabb7SAndroid Build Coastguard Worker 				}
1789*fd1fabb7SAndroid Build Coastguard Worker 
1790*fd1fabb7SAndroid Build Coastguard Worker 			}
1791*fd1fabb7SAndroid Build Coastguard Worker 
1792*fd1fabb7SAndroid Build Coastguard Worker 		// MaskedAreas:
1793*fd1fabb7SAndroid Build Coastguard Worker 
1794*fd1fabb7SAndroid Build Coastguard Worker 		if (rangeInfo->fMaskedAreaCount)
1795*fd1fabb7SAndroid Build Coastguard Worker 			{
1796*fd1fabb7SAndroid Build Coastguard Worker 
1797*fd1fabb7SAndroid Build Coastguard Worker 			fMaskedAreas.SetCount (rangeInfo->fMaskedAreaCount * 4);
1798*fd1fabb7SAndroid Build Coastguard Worker 
1799*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 index = 0; index < rangeInfo->fMaskedAreaCount; index++)
1800*fd1fabb7SAndroid Build Coastguard Worker 				{
1801*fd1fabb7SAndroid Build Coastguard Worker 
1802*fd1fabb7SAndroid Build Coastguard Worker 				const dng_rect &r = rangeInfo->fMaskedArea [index];
1803*fd1fabb7SAndroid Build Coastguard Worker 
1804*fd1fabb7SAndroid Build Coastguard Worker 				fMaskedAreaData [index * 4 + 0] = r.t;
1805*fd1fabb7SAndroid Build Coastguard Worker 				fMaskedAreaData [index * 4 + 1] = r.l;
1806*fd1fabb7SAndroid Build Coastguard Worker 				fMaskedAreaData [index * 4 + 2] = r.b;
1807*fd1fabb7SAndroid Build Coastguard Worker 				fMaskedAreaData [index * 4 + 3] = r.r;
1808*fd1fabb7SAndroid Build Coastguard Worker 
1809*fd1fabb7SAndroid Build Coastguard Worker 				}
1810*fd1fabb7SAndroid Build Coastguard Worker 
1811*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fMaskedAreas);
1812*fd1fabb7SAndroid Build Coastguard Worker 
1813*fd1fabb7SAndroid Build Coastguard Worker 			}
1814*fd1fabb7SAndroid Build Coastguard Worker 
1815*fd1fabb7SAndroid Build Coastguard Worker 		// LinearizationTable:
1816*fd1fabb7SAndroid Build Coastguard Worker 
1817*fd1fabb7SAndroid Build Coastguard Worker 		if (rangeInfo->fLinearizationTable.Get ())
1818*fd1fabb7SAndroid Build Coastguard Worker 			{
1819*fd1fabb7SAndroid Build Coastguard Worker 
1820*fd1fabb7SAndroid Build Coastguard Worker 			fLinearizationTable.SetData  (rangeInfo->fLinearizationTable->Buffer_uint16 ()     );
1821*fd1fabb7SAndroid Build Coastguard Worker 			fLinearizationTable.SetCount (rangeInfo->fLinearizationTable->LogicalSize   () >> 1);
1822*fd1fabb7SAndroid Build Coastguard Worker 
1823*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fLinearizationTable);
1824*fd1fabb7SAndroid Build Coastguard Worker 
1825*fd1fabb7SAndroid Build Coastguard Worker 			}
1826*fd1fabb7SAndroid Build Coastguard Worker 
1827*fd1fabb7SAndroid Build Coastguard Worker 		// BlackLevelRepeatDim:
1828*fd1fabb7SAndroid Build Coastguard Worker 
1829*fd1fabb7SAndroid Build Coastguard Worker 			{
1830*fd1fabb7SAndroid Build Coastguard Worker 
1831*fd1fabb7SAndroid Build Coastguard Worker 			fBlackLevelRepeatDimData [0] = (uint16) rangeInfo->fBlackLevelRepeatRows;
1832*fd1fabb7SAndroid Build Coastguard Worker 			fBlackLevelRepeatDimData [1] = (uint16) rangeInfo->fBlackLevelRepeatCols;
1833*fd1fabb7SAndroid Build Coastguard Worker 
1834*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fBlackLevelRepeatDim);
1835*fd1fabb7SAndroid Build Coastguard Worker 
1836*fd1fabb7SAndroid Build Coastguard Worker 			}
1837*fd1fabb7SAndroid Build Coastguard Worker 
1838*fd1fabb7SAndroid Build Coastguard Worker 		// BlackLevel:
1839*fd1fabb7SAndroid Build Coastguard Worker 
1840*fd1fabb7SAndroid Build Coastguard Worker 			{
1841*fd1fabb7SAndroid Build Coastguard Worker 
1842*fd1fabb7SAndroid Build Coastguard Worker 			uint32 index = 0;
1843*fd1fabb7SAndroid Build Coastguard Worker 
1844*fd1fabb7SAndroid Build Coastguard Worker 			for (uint16 v = 0; v < rangeInfo->fBlackLevelRepeatRows; v++)
1845*fd1fabb7SAndroid Build Coastguard Worker 				{
1846*fd1fabb7SAndroid Build Coastguard Worker 
1847*fd1fabb7SAndroid Build Coastguard Worker 				for (uint32 h = 0; h < rangeInfo->fBlackLevelRepeatCols; h++)
1848*fd1fabb7SAndroid Build Coastguard Worker 					{
1849*fd1fabb7SAndroid Build Coastguard Worker 
1850*fd1fabb7SAndroid Build Coastguard Worker 					for (uint32 c = 0; c < rawImage.Planes (); c++)
1851*fd1fabb7SAndroid Build Coastguard Worker 						{
1852*fd1fabb7SAndroid Build Coastguard Worker 
1853*fd1fabb7SAndroid Build Coastguard Worker 						fBlackLevelData [index++] = rangeInfo->BlackLevel (v, h, c);
1854*fd1fabb7SAndroid Build Coastguard Worker 
1855*fd1fabb7SAndroid Build Coastguard Worker 						}
1856*fd1fabb7SAndroid Build Coastguard Worker 
1857*fd1fabb7SAndroid Build Coastguard Worker 					}
1858*fd1fabb7SAndroid Build Coastguard Worker 
1859*fd1fabb7SAndroid Build Coastguard Worker 				}
1860*fd1fabb7SAndroid Build Coastguard Worker 
1861*fd1fabb7SAndroid Build Coastguard Worker 			fBlackLevel.SetCount (rangeInfo->fBlackLevelRepeatRows *
1862*fd1fabb7SAndroid Build Coastguard Worker 								  rangeInfo->fBlackLevelRepeatCols * rawImage.Planes ());
1863*fd1fabb7SAndroid Build Coastguard Worker 
1864*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fBlackLevel);
1865*fd1fabb7SAndroid Build Coastguard Worker 
1866*fd1fabb7SAndroid Build Coastguard Worker 			}
1867*fd1fabb7SAndroid Build Coastguard Worker 
1868*fd1fabb7SAndroid Build Coastguard Worker 		// BlackLevelDeltaH:
1869*fd1fabb7SAndroid Build Coastguard Worker 
1870*fd1fabb7SAndroid Build Coastguard Worker 		if (rangeInfo->ColumnBlackCount ())
1871*fd1fabb7SAndroid Build Coastguard Worker 			{
1872*fd1fabb7SAndroid Build Coastguard Worker 
1873*fd1fabb7SAndroid Build Coastguard Worker 			uint32 count = rangeInfo->ColumnBlackCount ();
1874*fd1fabb7SAndroid Build Coastguard Worker 
1875*fd1fabb7SAndroid Build Coastguard Worker 			fBlackLevelDeltaHData.Allocate (count, sizeof (dng_srational));
1876*fd1fabb7SAndroid Build Coastguard Worker 
1877*fd1fabb7SAndroid Build Coastguard Worker 			dng_srational *blacks = (dng_srational *) fBlackLevelDeltaHData.Buffer ();
1878*fd1fabb7SAndroid Build Coastguard Worker 
1879*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 col = 0; col < count; col++)
1880*fd1fabb7SAndroid Build Coastguard Worker 				{
1881*fd1fabb7SAndroid Build Coastguard Worker 
1882*fd1fabb7SAndroid Build Coastguard Worker 				blacks [col] = rangeInfo->ColumnBlack (col);
1883*fd1fabb7SAndroid Build Coastguard Worker 
1884*fd1fabb7SAndroid Build Coastguard Worker 				}
1885*fd1fabb7SAndroid Build Coastguard Worker 
1886*fd1fabb7SAndroid Build Coastguard Worker 			fBlackLevelDeltaH.SetData  (blacks);
1887*fd1fabb7SAndroid Build Coastguard Worker 			fBlackLevelDeltaH.SetCount (count );
1888*fd1fabb7SAndroid Build Coastguard Worker 
1889*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fBlackLevelDeltaH);
1890*fd1fabb7SAndroid Build Coastguard Worker 
1891*fd1fabb7SAndroid Build Coastguard Worker 			}
1892*fd1fabb7SAndroid Build Coastguard Worker 
1893*fd1fabb7SAndroid Build Coastguard Worker 		// BlackLevelDeltaV:
1894*fd1fabb7SAndroid Build Coastguard Worker 
1895*fd1fabb7SAndroid Build Coastguard Worker 		if (rangeInfo->RowBlackCount ())
1896*fd1fabb7SAndroid Build Coastguard Worker 			{
1897*fd1fabb7SAndroid Build Coastguard Worker 
1898*fd1fabb7SAndroid Build Coastguard Worker 			uint32 count = rangeInfo->RowBlackCount ();
1899*fd1fabb7SAndroid Build Coastguard Worker 
1900*fd1fabb7SAndroid Build Coastguard Worker 			fBlackLevelDeltaVData.Allocate (count, sizeof (dng_srational));
1901*fd1fabb7SAndroid Build Coastguard Worker 
1902*fd1fabb7SAndroid Build Coastguard Worker 			dng_srational *blacks = (dng_srational *) fBlackLevelDeltaVData.Buffer ();
1903*fd1fabb7SAndroid Build Coastguard Worker 
1904*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 row = 0; row < count; row++)
1905*fd1fabb7SAndroid Build Coastguard Worker 				{
1906*fd1fabb7SAndroid Build Coastguard Worker 
1907*fd1fabb7SAndroid Build Coastguard Worker 				blacks [row] = rangeInfo->RowBlack (row);
1908*fd1fabb7SAndroid Build Coastguard Worker 
1909*fd1fabb7SAndroid Build Coastguard Worker 				}
1910*fd1fabb7SAndroid Build Coastguard Worker 
1911*fd1fabb7SAndroid Build Coastguard Worker 			fBlackLevelDeltaV.SetData  (blacks);
1912*fd1fabb7SAndroid Build Coastguard Worker 			fBlackLevelDeltaV.SetCount (count );
1913*fd1fabb7SAndroid Build Coastguard Worker 
1914*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fBlackLevelDeltaV);
1915*fd1fabb7SAndroid Build Coastguard Worker 
1916*fd1fabb7SAndroid Build Coastguard Worker 			}
1917*fd1fabb7SAndroid Build Coastguard Worker 
1918*fd1fabb7SAndroid Build Coastguard Worker 		}
1919*fd1fabb7SAndroid Build Coastguard Worker 
1920*fd1fabb7SAndroid Build Coastguard Worker 	// WhiteLevel:
1921*fd1fabb7SAndroid Build Coastguard Worker 
1922*fd1fabb7SAndroid Build Coastguard Worker 	// Only use the 32-bit data type if we must use it since there
1923*fd1fabb7SAndroid Build Coastguard Worker 	// are some lazy (non-Adobe) DNG readers out there.
1924*fd1fabb7SAndroid Build Coastguard Worker 
1925*fd1fabb7SAndroid Build Coastguard Worker 	bool needs32 = false;
1926*fd1fabb7SAndroid Build Coastguard Worker 
1927*fd1fabb7SAndroid Build Coastguard Worker 	fWhiteLevel16.SetCount (rawImage.Planes ());
1928*fd1fabb7SAndroid Build Coastguard Worker 	fWhiteLevel32.SetCount (rawImage.Planes ());
1929*fd1fabb7SAndroid Build Coastguard Worker 
1930*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 c = 0; c < fWhiteLevel16.Count (); c++)
1931*fd1fabb7SAndroid Build Coastguard Worker 		{
1932*fd1fabb7SAndroid Build Coastguard Worker 
1933*fd1fabb7SAndroid Build Coastguard Worker 		fWhiteLevelData32 [c] = negative.WhiteLevel (c);
1934*fd1fabb7SAndroid Build Coastguard Worker 
1935*fd1fabb7SAndroid Build Coastguard Worker 		if (fWhiteLevelData32 [c] > 0x0FFFF)
1936*fd1fabb7SAndroid Build Coastguard Worker 			{
1937*fd1fabb7SAndroid Build Coastguard Worker 			needs32 = true;
1938*fd1fabb7SAndroid Build Coastguard Worker 			}
1939*fd1fabb7SAndroid Build Coastguard Worker 
1940*fd1fabb7SAndroid Build Coastguard Worker 		fWhiteLevelData16 [c] = (uint16) fWhiteLevelData32 [c];
1941*fd1fabb7SAndroid Build Coastguard Worker 
1942*fd1fabb7SAndroid Build Coastguard Worker 		}
1943*fd1fabb7SAndroid Build Coastguard Worker 
1944*fd1fabb7SAndroid Build Coastguard Worker 	if (needs32)
1945*fd1fabb7SAndroid Build Coastguard Worker 		{
1946*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fWhiteLevel32);
1947*fd1fabb7SAndroid Build Coastguard Worker 		}
1948*fd1fabb7SAndroid Build Coastguard Worker 
1949*fd1fabb7SAndroid Build Coastguard Worker 	else
1950*fd1fabb7SAndroid Build Coastguard Worker 		{
1951*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fWhiteLevel16);
1952*fd1fabb7SAndroid Build Coastguard Worker 		}
1953*fd1fabb7SAndroid Build Coastguard Worker 
1954*fd1fabb7SAndroid Build Coastguard Worker 	}
1955*fd1fabb7SAndroid Build Coastguard Worker 
1956*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
1957*fd1fabb7SAndroid Build Coastguard Worker 
1958*fd1fabb7SAndroid Build Coastguard Worker class mosaic_tag_set
1959*fd1fabb7SAndroid Build Coastguard Worker 	{
1960*fd1fabb7SAndroid Build Coastguard Worker 
1961*fd1fabb7SAndroid Build Coastguard Worker 	private:
1962*fd1fabb7SAndroid Build Coastguard Worker 
1963*fd1fabb7SAndroid Build Coastguard Worker 		uint16 fCFARepeatPatternDimData [2];
1964*fd1fabb7SAndroid Build Coastguard Worker 
1965*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint16_ptr fCFARepeatPatternDim;
1966*fd1fabb7SAndroid Build Coastguard Worker 
1967*fd1fabb7SAndroid Build Coastguard Worker 		uint8 fCFAPatternData [kMaxCFAPattern *
1968*fd1fabb7SAndroid Build Coastguard Worker 							   kMaxCFAPattern];
1969*fd1fabb7SAndroid Build Coastguard Worker 
1970*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint8_ptr fCFAPattern;
1971*fd1fabb7SAndroid Build Coastguard Worker 
1972*fd1fabb7SAndroid Build Coastguard Worker 		uint8 fCFAPlaneColorData [kMaxColorPlanes];
1973*fd1fabb7SAndroid Build Coastguard Worker 
1974*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint8_ptr fCFAPlaneColor;
1975*fd1fabb7SAndroid Build Coastguard Worker 
1976*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint16 fCFALayout;
1977*fd1fabb7SAndroid Build Coastguard Worker 
1978*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32 fGreenSplit;
1979*fd1fabb7SAndroid Build Coastguard Worker 
1980*fd1fabb7SAndroid Build Coastguard Worker 	public:
1981*fd1fabb7SAndroid Build Coastguard Worker 
1982*fd1fabb7SAndroid Build Coastguard Worker 		mosaic_tag_set (dng_tiff_directory &directory,
1983*fd1fabb7SAndroid Build Coastguard Worker 				        const dng_mosaic_info &info);
1984*fd1fabb7SAndroid Build Coastguard Worker 
1985*fd1fabb7SAndroid Build Coastguard Worker 	};
1986*fd1fabb7SAndroid Build Coastguard Worker 
1987*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
1988*fd1fabb7SAndroid Build Coastguard Worker 
mosaic_tag_set(dng_tiff_directory & directory,const dng_mosaic_info & info)1989*fd1fabb7SAndroid Build Coastguard Worker mosaic_tag_set::mosaic_tag_set (dng_tiff_directory &directory,
1990*fd1fabb7SAndroid Build Coastguard Worker 					            const dng_mosaic_info &info)
1991*fd1fabb7SAndroid Build Coastguard Worker 
1992*fd1fabb7SAndroid Build Coastguard Worker 	:	fCFARepeatPatternDim (tcCFARepeatPatternDim,
1993*fd1fabb7SAndroid Build Coastguard Worker 						  	  fCFARepeatPatternDimData,
1994*fd1fabb7SAndroid Build Coastguard Worker 						  	  2)
1995*fd1fabb7SAndroid Build Coastguard Worker 
1996*fd1fabb7SAndroid Build Coastguard Worker 	,	fCFAPattern (tcCFAPattern,
1997*fd1fabb7SAndroid Build Coastguard Worker 					 fCFAPatternData)
1998*fd1fabb7SAndroid Build Coastguard Worker 
1999*fd1fabb7SAndroid Build Coastguard Worker 	,	fCFAPlaneColor (tcCFAPlaneColor,
2000*fd1fabb7SAndroid Build Coastguard Worker 						fCFAPlaneColorData)
2001*fd1fabb7SAndroid Build Coastguard Worker 
2002*fd1fabb7SAndroid Build Coastguard Worker 	,	fCFALayout (tcCFALayout,
2003*fd1fabb7SAndroid Build Coastguard Worker 					(uint16) info.fCFALayout)
2004*fd1fabb7SAndroid Build Coastguard Worker 
2005*fd1fabb7SAndroid Build Coastguard Worker 	,	fGreenSplit (tcBayerGreenSplit,
2006*fd1fabb7SAndroid Build Coastguard Worker 					 info.fBayerGreenSplit)
2007*fd1fabb7SAndroid Build Coastguard Worker 
2008*fd1fabb7SAndroid Build Coastguard Worker 	{
2009*fd1fabb7SAndroid Build Coastguard Worker 
2010*fd1fabb7SAndroid Build Coastguard Worker 	if (info.IsColorFilterArray ())
2011*fd1fabb7SAndroid Build Coastguard Worker 		{
2012*fd1fabb7SAndroid Build Coastguard Worker 
2013*fd1fabb7SAndroid Build Coastguard Worker 		// CFARepeatPatternDim:
2014*fd1fabb7SAndroid Build Coastguard Worker 
2015*fd1fabb7SAndroid Build Coastguard Worker 		fCFARepeatPatternDimData [0] = (uint16) info.fCFAPatternSize.v;
2016*fd1fabb7SAndroid Build Coastguard Worker 		fCFARepeatPatternDimData [1] = (uint16) info.fCFAPatternSize.h;
2017*fd1fabb7SAndroid Build Coastguard Worker 
2018*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fCFARepeatPatternDim);
2019*fd1fabb7SAndroid Build Coastguard Worker 
2020*fd1fabb7SAndroid Build Coastguard Worker 		// CFAPattern:
2021*fd1fabb7SAndroid Build Coastguard Worker 
2022*fd1fabb7SAndroid Build Coastguard Worker 		fCFAPattern.SetCount (info.fCFAPatternSize.v *
2023*fd1fabb7SAndroid Build Coastguard Worker 							  info.fCFAPatternSize.h);
2024*fd1fabb7SAndroid Build Coastguard Worker 
2025*fd1fabb7SAndroid Build Coastguard Worker 		for (int32 r = 0; r < info.fCFAPatternSize.v; r++)
2026*fd1fabb7SAndroid Build Coastguard Worker 			{
2027*fd1fabb7SAndroid Build Coastguard Worker 
2028*fd1fabb7SAndroid Build Coastguard Worker 			for (int32 c = 0; c < info.fCFAPatternSize.h; c++)
2029*fd1fabb7SAndroid Build Coastguard Worker 				{
2030*fd1fabb7SAndroid Build Coastguard Worker 
2031*fd1fabb7SAndroid Build Coastguard Worker 				fCFAPatternData [r * info.fCFAPatternSize.h + c] = info.fCFAPattern [r] [c];
2032*fd1fabb7SAndroid Build Coastguard Worker 
2033*fd1fabb7SAndroid Build Coastguard Worker 				}
2034*fd1fabb7SAndroid Build Coastguard Worker 
2035*fd1fabb7SAndroid Build Coastguard Worker 			}
2036*fd1fabb7SAndroid Build Coastguard Worker 
2037*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fCFAPattern);
2038*fd1fabb7SAndroid Build Coastguard Worker 
2039*fd1fabb7SAndroid Build Coastguard Worker 		// CFAPlaneColor:
2040*fd1fabb7SAndroid Build Coastguard Worker 
2041*fd1fabb7SAndroid Build Coastguard Worker 		fCFAPlaneColor.SetCount (info.fColorPlanes);
2042*fd1fabb7SAndroid Build Coastguard Worker 
2043*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 j = 0; j < info.fColorPlanes; j++)
2044*fd1fabb7SAndroid Build Coastguard Worker 			{
2045*fd1fabb7SAndroid Build Coastguard Worker 
2046*fd1fabb7SAndroid Build Coastguard Worker 			fCFAPlaneColorData [j] = info.fCFAPlaneColor [j];
2047*fd1fabb7SAndroid Build Coastguard Worker 
2048*fd1fabb7SAndroid Build Coastguard Worker 			}
2049*fd1fabb7SAndroid Build Coastguard Worker 
2050*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fCFAPlaneColor);
2051*fd1fabb7SAndroid Build Coastguard Worker 
2052*fd1fabb7SAndroid Build Coastguard Worker 		// CFALayout:
2053*fd1fabb7SAndroid Build Coastguard Worker 
2054*fd1fabb7SAndroid Build Coastguard Worker 		fCFALayout.Set ((uint16) info.fCFALayout);
2055*fd1fabb7SAndroid Build Coastguard Worker 
2056*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fCFALayout);
2057*fd1fabb7SAndroid Build Coastguard Worker 
2058*fd1fabb7SAndroid Build Coastguard Worker 		// BayerGreenSplit:  (only include if the pattern is a Bayer pattern)
2059*fd1fabb7SAndroid Build Coastguard Worker 
2060*fd1fabb7SAndroid Build Coastguard Worker 		if (info.fCFAPatternSize == dng_point (2, 2) &&
2061*fd1fabb7SAndroid Build Coastguard Worker 			info.fColorPlanes    == 3)
2062*fd1fabb7SAndroid Build Coastguard Worker 			{
2063*fd1fabb7SAndroid Build Coastguard Worker 
2064*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fGreenSplit);
2065*fd1fabb7SAndroid Build Coastguard Worker 
2066*fd1fabb7SAndroid Build Coastguard Worker 			}
2067*fd1fabb7SAndroid Build Coastguard Worker 
2068*fd1fabb7SAndroid Build Coastguard Worker 		}
2069*fd1fabb7SAndroid Build Coastguard Worker 
2070*fd1fabb7SAndroid Build Coastguard Worker 	}
2071*fd1fabb7SAndroid Build Coastguard Worker 
2072*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
2073*fd1fabb7SAndroid Build Coastguard Worker 
2074*fd1fabb7SAndroid Build Coastguard Worker class color_tag_set
2075*fd1fabb7SAndroid Build Coastguard Worker 	{
2076*fd1fabb7SAndroid Build Coastguard Worker 
2077*fd1fabb7SAndroid Build Coastguard Worker 	private:
2078*fd1fabb7SAndroid Build Coastguard Worker 
2079*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fColorChannels;
2080*fd1fabb7SAndroid Build Coastguard Worker 
2081*fd1fabb7SAndroid Build Coastguard Worker 		tag_matrix fCameraCalibration1;
2082*fd1fabb7SAndroid Build Coastguard Worker 		tag_matrix fCameraCalibration2;
2083*fd1fabb7SAndroid Build Coastguard Worker 
2084*fd1fabb7SAndroid Build Coastguard Worker 		tag_string fCameraCalibrationSignature;
2085*fd1fabb7SAndroid Build Coastguard Worker 
2086*fd1fabb7SAndroid Build Coastguard Worker 		tag_string fAsShotProfileName;
2087*fd1fabb7SAndroid Build Coastguard Worker 
2088*fd1fabb7SAndroid Build Coastguard Worker 		dng_urational fAnalogBalanceData [4];
2089*fd1fabb7SAndroid Build Coastguard Worker 
2090*fd1fabb7SAndroid Build Coastguard Worker 		tag_urational_ptr fAnalogBalance;
2091*fd1fabb7SAndroid Build Coastguard Worker 
2092*fd1fabb7SAndroid Build Coastguard Worker 		dng_urational fAsShotNeutralData [4];
2093*fd1fabb7SAndroid Build Coastguard Worker 
2094*fd1fabb7SAndroid Build Coastguard Worker 		tag_urational_ptr fAsShotNeutral;
2095*fd1fabb7SAndroid Build Coastguard Worker 
2096*fd1fabb7SAndroid Build Coastguard Worker 		dng_urational fAsShotWhiteXYData [2];
2097*fd1fabb7SAndroid Build Coastguard Worker 
2098*fd1fabb7SAndroid Build Coastguard Worker 		tag_urational_ptr fAsShotWhiteXY;
2099*fd1fabb7SAndroid Build Coastguard Worker 
2100*fd1fabb7SAndroid Build Coastguard Worker 		tag_urational fLinearResponseLimit;
2101*fd1fabb7SAndroid Build Coastguard Worker 
2102*fd1fabb7SAndroid Build Coastguard Worker 	public:
2103*fd1fabb7SAndroid Build Coastguard Worker 
2104*fd1fabb7SAndroid Build Coastguard Worker 		color_tag_set (dng_tiff_directory &directory,
2105*fd1fabb7SAndroid Build Coastguard Worker 				       const dng_negative &negative);
2106*fd1fabb7SAndroid Build Coastguard Worker 
2107*fd1fabb7SAndroid Build Coastguard Worker 	};
2108*fd1fabb7SAndroid Build Coastguard Worker 
2109*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
2110*fd1fabb7SAndroid Build Coastguard Worker 
color_tag_set(dng_tiff_directory & directory,const dng_negative & negative)2111*fd1fabb7SAndroid Build Coastguard Worker color_tag_set::color_tag_set (dng_tiff_directory &directory,
2112*fd1fabb7SAndroid Build Coastguard Worker 				     	  	  const dng_negative &negative)
2113*fd1fabb7SAndroid Build Coastguard Worker 
2114*fd1fabb7SAndroid Build Coastguard Worker 	:	fColorChannels (negative.ColorChannels ())
2115*fd1fabb7SAndroid Build Coastguard Worker 
2116*fd1fabb7SAndroid Build Coastguard Worker 	,	fCameraCalibration1 (tcCameraCalibration1,
2117*fd1fabb7SAndroid Build Coastguard Worker 						     negative.CameraCalibration1 ())
2118*fd1fabb7SAndroid Build Coastguard Worker 
2119*fd1fabb7SAndroid Build Coastguard Worker 	,	fCameraCalibration2 (tcCameraCalibration2,
2120*fd1fabb7SAndroid Build Coastguard Worker 						     negative.CameraCalibration2 ())
2121*fd1fabb7SAndroid Build Coastguard Worker 
2122*fd1fabb7SAndroid Build Coastguard Worker 	,	fCameraCalibrationSignature (tcCameraCalibrationSignature,
2123*fd1fabb7SAndroid Build Coastguard Worker 									 negative.CameraCalibrationSignature ())
2124*fd1fabb7SAndroid Build Coastguard Worker 
2125*fd1fabb7SAndroid Build Coastguard Worker 	,	fAsShotProfileName (tcAsShotProfileName,
2126*fd1fabb7SAndroid Build Coastguard Worker 							negative.AsShotProfileName ())
2127*fd1fabb7SAndroid Build Coastguard Worker 
2128*fd1fabb7SAndroid Build Coastguard Worker 	,	fAnalogBalance (tcAnalogBalance,
2129*fd1fabb7SAndroid Build Coastguard Worker 						fAnalogBalanceData,
2130*fd1fabb7SAndroid Build Coastguard Worker 						fColorChannels)
2131*fd1fabb7SAndroid Build Coastguard Worker 
2132*fd1fabb7SAndroid Build Coastguard Worker 	,	fAsShotNeutral (tcAsShotNeutral,
2133*fd1fabb7SAndroid Build Coastguard Worker 						fAsShotNeutralData,
2134*fd1fabb7SAndroid Build Coastguard Worker 						fColorChannels)
2135*fd1fabb7SAndroid Build Coastguard Worker 
2136*fd1fabb7SAndroid Build Coastguard Worker 	,	fAsShotWhiteXY (tcAsShotWhiteXY,
2137*fd1fabb7SAndroid Build Coastguard Worker 						fAsShotWhiteXYData,
2138*fd1fabb7SAndroid Build Coastguard Worker 						2)
2139*fd1fabb7SAndroid Build Coastguard Worker 
2140*fd1fabb7SAndroid Build Coastguard Worker 	,	fLinearResponseLimit (tcLinearResponseLimit,
2141*fd1fabb7SAndroid Build Coastguard Worker 						      negative.LinearResponseLimitR ())
2142*fd1fabb7SAndroid Build Coastguard Worker 
2143*fd1fabb7SAndroid Build Coastguard Worker 	{
2144*fd1fabb7SAndroid Build Coastguard Worker 
2145*fd1fabb7SAndroid Build Coastguard Worker 	if (fColorChannels > 1)
2146*fd1fabb7SAndroid Build Coastguard Worker 		{
2147*fd1fabb7SAndroid Build Coastguard Worker 
2148*fd1fabb7SAndroid Build Coastguard Worker 		uint32 channels2 = fColorChannels * fColorChannels;
2149*fd1fabb7SAndroid Build Coastguard Worker 
2150*fd1fabb7SAndroid Build Coastguard Worker 		if (fCameraCalibration1.Count () == channels2)
2151*fd1fabb7SAndroid Build Coastguard Worker 			{
2152*fd1fabb7SAndroid Build Coastguard Worker 
2153*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fCameraCalibration1);
2154*fd1fabb7SAndroid Build Coastguard Worker 
2155*fd1fabb7SAndroid Build Coastguard Worker 			}
2156*fd1fabb7SAndroid Build Coastguard Worker 
2157*fd1fabb7SAndroid Build Coastguard Worker 		if (fCameraCalibration2.Count () == channels2)
2158*fd1fabb7SAndroid Build Coastguard Worker 			{
2159*fd1fabb7SAndroid Build Coastguard Worker 
2160*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fCameraCalibration2);
2161*fd1fabb7SAndroid Build Coastguard Worker 
2162*fd1fabb7SAndroid Build Coastguard Worker 			}
2163*fd1fabb7SAndroid Build Coastguard Worker 
2164*fd1fabb7SAndroid Build Coastguard Worker 		if (fCameraCalibration1.Count () == channels2 ||
2165*fd1fabb7SAndroid Build Coastguard Worker 			fCameraCalibration2.Count () == channels2)
2166*fd1fabb7SAndroid Build Coastguard Worker 			{
2167*fd1fabb7SAndroid Build Coastguard Worker 
2168*fd1fabb7SAndroid Build Coastguard Worker 			if (negative.CameraCalibrationSignature ().NotEmpty ())
2169*fd1fabb7SAndroid Build Coastguard Worker 				{
2170*fd1fabb7SAndroid Build Coastguard Worker 
2171*fd1fabb7SAndroid Build Coastguard Worker 				directory.Add (&fCameraCalibrationSignature);
2172*fd1fabb7SAndroid Build Coastguard Worker 
2173*fd1fabb7SAndroid Build Coastguard Worker 				}
2174*fd1fabb7SAndroid Build Coastguard Worker 
2175*fd1fabb7SAndroid Build Coastguard Worker 			}
2176*fd1fabb7SAndroid Build Coastguard Worker 
2177*fd1fabb7SAndroid Build Coastguard Worker 		if (negative.AsShotProfileName ().NotEmpty ())
2178*fd1fabb7SAndroid Build Coastguard Worker 			{
2179*fd1fabb7SAndroid Build Coastguard Worker 
2180*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fAsShotProfileName);
2181*fd1fabb7SAndroid Build Coastguard Worker 
2182*fd1fabb7SAndroid Build Coastguard Worker 			}
2183*fd1fabb7SAndroid Build Coastguard Worker 
2184*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 j = 0; j < fColorChannels; j++)
2185*fd1fabb7SAndroid Build Coastguard Worker 			{
2186*fd1fabb7SAndroid Build Coastguard Worker 
2187*fd1fabb7SAndroid Build Coastguard Worker 			fAnalogBalanceData [j] = negative.AnalogBalanceR (j);
2188*fd1fabb7SAndroid Build Coastguard Worker 
2189*fd1fabb7SAndroid Build Coastguard Worker 			}
2190*fd1fabb7SAndroid Build Coastguard Worker 
2191*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fAnalogBalance);
2192*fd1fabb7SAndroid Build Coastguard Worker 
2193*fd1fabb7SAndroid Build Coastguard Worker 		if (negative.HasCameraNeutral ())
2194*fd1fabb7SAndroid Build Coastguard Worker 			{
2195*fd1fabb7SAndroid Build Coastguard Worker 
2196*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 k = 0; k < fColorChannels; k++)
2197*fd1fabb7SAndroid Build Coastguard Worker 				{
2198*fd1fabb7SAndroid Build Coastguard Worker 
2199*fd1fabb7SAndroid Build Coastguard Worker 				fAsShotNeutralData [k] = negative.CameraNeutralR (k);
2200*fd1fabb7SAndroid Build Coastguard Worker 
2201*fd1fabb7SAndroid Build Coastguard Worker 				}
2202*fd1fabb7SAndroid Build Coastguard Worker 
2203*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fAsShotNeutral);
2204*fd1fabb7SAndroid Build Coastguard Worker 
2205*fd1fabb7SAndroid Build Coastguard Worker 			}
2206*fd1fabb7SAndroid Build Coastguard Worker 
2207*fd1fabb7SAndroid Build Coastguard Worker 		else if (negative.HasCameraWhiteXY ())
2208*fd1fabb7SAndroid Build Coastguard Worker 			{
2209*fd1fabb7SAndroid Build Coastguard Worker 
2210*fd1fabb7SAndroid Build Coastguard Worker 			negative.GetCameraWhiteXY (fAsShotWhiteXYData [0],
2211*fd1fabb7SAndroid Build Coastguard Worker 									   fAsShotWhiteXYData [1]);
2212*fd1fabb7SAndroid Build Coastguard Worker 
2213*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fAsShotWhiteXY);
2214*fd1fabb7SAndroid Build Coastguard Worker 
2215*fd1fabb7SAndroid Build Coastguard Worker 			}
2216*fd1fabb7SAndroid Build Coastguard Worker 
2217*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fLinearResponseLimit);
2218*fd1fabb7SAndroid Build Coastguard Worker 
2219*fd1fabb7SAndroid Build Coastguard Worker 		}
2220*fd1fabb7SAndroid Build Coastguard Worker 
2221*fd1fabb7SAndroid Build Coastguard Worker 	}
2222*fd1fabb7SAndroid Build Coastguard Worker 
2223*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
2224*fd1fabb7SAndroid Build Coastguard Worker 
2225*fd1fabb7SAndroid Build Coastguard Worker class profile_tag_set
2226*fd1fabb7SAndroid Build Coastguard Worker 	{
2227*fd1fabb7SAndroid Build Coastguard Worker 
2228*fd1fabb7SAndroid Build Coastguard Worker 	private:
2229*fd1fabb7SAndroid Build Coastguard Worker 
2230*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint16 fCalibrationIlluminant1;
2231*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint16 fCalibrationIlluminant2;
2232*fd1fabb7SAndroid Build Coastguard Worker 
2233*fd1fabb7SAndroid Build Coastguard Worker 		tag_matrix fColorMatrix1;
2234*fd1fabb7SAndroid Build Coastguard Worker 		tag_matrix fColorMatrix2;
2235*fd1fabb7SAndroid Build Coastguard Worker 
2236*fd1fabb7SAndroid Build Coastguard Worker 		tag_matrix fForwardMatrix1;
2237*fd1fabb7SAndroid Build Coastguard Worker 		tag_matrix fForwardMatrix2;
2238*fd1fabb7SAndroid Build Coastguard Worker 
2239*fd1fabb7SAndroid Build Coastguard Worker 		tag_matrix fReductionMatrix1;
2240*fd1fabb7SAndroid Build Coastguard Worker 		tag_matrix fReductionMatrix2;
2241*fd1fabb7SAndroid Build Coastguard Worker 
2242*fd1fabb7SAndroid Build Coastguard Worker 		tag_string fProfileName;
2243*fd1fabb7SAndroid Build Coastguard Worker 
2244*fd1fabb7SAndroid Build Coastguard Worker 		tag_string fProfileCalibrationSignature;
2245*fd1fabb7SAndroid Build Coastguard Worker 
2246*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32 fEmbedPolicyTag;
2247*fd1fabb7SAndroid Build Coastguard Worker 
2248*fd1fabb7SAndroid Build Coastguard Worker 		tag_string fCopyrightTag;
2249*fd1fabb7SAndroid Build Coastguard Worker 
2250*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fHueSatMapDimData [3];
2251*fd1fabb7SAndroid Build Coastguard Worker 
2252*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32_ptr fHueSatMapDims;
2253*fd1fabb7SAndroid Build Coastguard Worker 
2254*fd1fabb7SAndroid Build Coastguard Worker 		tag_data_ptr fHueSatData1;
2255*fd1fabb7SAndroid Build Coastguard Worker 		tag_data_ptr fHueSatData2;
2256*fd1fabb7SAndroid Build Coastguard Worker 
2257*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32 fHueSatMapEncodingTag;
2258*fd1fabb7SAndroid Build Coastguard Worker 
2259*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fLookTableDimData [3];
2260*fd1fabb7SAndroid Build Coastguard Worker 
2261*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32_ptr fLookTableDims;
2262*fd1fabb7SAndroid Build Coastguard Worker 
2263*fd1fabb7SAndroid Build Coastguard Worker 		tag_data_ptr fLookTableData;
2264*fd1fabb7SAndroid Build Coastguard Worker 
2265*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32 fLookTableEncodingTag;
2266*fd1fabb7SAndroid Build Coastguard Worker 
2267*fd1fabb7SAndroid Build Coastguard Worker 		tag_srational fBaselineExposureOffsetTag;
2268*fd1fabb7SAndroid Build Coastguard Worker 
2269*fd1fabb7SAndroid Build Coastguard Worker 		tag_uint32 fDefaultBlackRenderTag;
2270*fd1fabb7SAndroid Build Coastguard Worker 
2271*fd1fabb7SAndroid Build Coastguard Worker 		dng_memory_data fToneCurveBuffer;
2272*fd1fabb7SAndroid Build Coastguard Worker 
2273*fd1fabb7SAndroid Build Coastguard Worker 		tag_data_ptr fToneCurveTag;
2274*fd1fabb7SAndroid Build Coastguard Worker 
2275*fd1fabb7SAndroid Build Coastguard Worker 	public:
2276*fd1fabb7SAndroid Build Coastguard Worker 
2277*fd1fabb7SAndroid Build Coastguard Worker 		profile_tag_set (dng_tiff_directory &directory,
2278*fd1fabb7SAndroid Build Coastguard Worker 						 const dng_camera_profile &profile);
2279*fd1fabb7SAndroid Build Coastguard Worker 
2280*fd1fabb7SAndroid Build Coastguard Worker 	};
2281*fd1fabb7SAndroid Build Coastguard Worker 
2282*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
2283*fd1fabb7SAndroid Build Coastguard Worker 
profile_tag_set(dng_tiff_directory & directory,const dng_camera_profile & profile)2284*fd1fabb7SAndroid Build Coastguard Worker profile_tag_set::profile_tag_set (dng_tiff_directory &directory,
2285*fd1fabb7SAndroid Build Coastguard Worker 				     	  	      const dng_camera_profile &profile)
2286*fd1fabb7SAndroid Build Coastguard Worker 
2287*fd1fabb7SAndroid Build Coastguard Worker 	:	fCalibrationIlluminant1 (tcCalibrationIlluminant1,
2288*fd1fabb7SAndroid Build Coastguard Worker 								 (uint16) profile.CalibrationIlluminant1 ())
2289*fd1fabb7SAndroid Build Coastguard Worker 
2290*fd1fabb7SAndroid Build Coastguard Worker 	,	fCalibrationIlluminant2 (tcCalibrationIlluminant2,
2291*fd1fabb7SAndroid Build Coastguard Worker 								 (uint16) profile.CalibrationIlluminant2 ())
2292*fd1fabb7SAndroid Build Coastguard Worker 
2293*fd1fabb7SAndroid Build Coastguard Worker 	,	fColorMatrix1 (tcColorMatrix1,
2294*fd1fabb7SAndroid Build Coastguard Worker 					   profile.ColorMatrix1 ())
2295*fd1fabb7SAndroid Build Coastguard Worker 
2296*fd1fabb7SAndroid Build Coastguard Worker 	,	fColorMatrix2 (tcColorMatrix2,
2297*fd1fabb7SAndroid Build Coastguard Worker 					   profile.ColorMatrix2 ())
2298*fd1fabb7SAndroid Build Coastguard Worker 
2299*fd1fabb7SAndroid Build Coastguard Worker 	,	fForwardMatrix1 (tcForwardMatrix1,
2300*fd1fabb7SAndroid Build Coastguard Worker 						 profile.ForwardMatrix1 ())
2301*fd1fabb7SAndroid Build Coastguard Worker 
2302*fd1fabb7SAndroid Build Coastguard Worker 	,	fForwardMatrix2 (tcForwardMatrix2,
2303*fd1fabb7SAndroid Build Coastguard Worker 						 profile.ForwardMatrix2 ())
2304*fd1fabb7SAndroid Build Coastguard Worker 
2305*fd1fabb7SAndroid Build Coastguard Worker 	,	fReductionMatrix1 (tcReductionMatrix1,
2306*fd1fabb7SAndroid Build Coastguard Worker 						   profile.ReductionMatrix1 ())
2307*fd1fabb7SAndroid Build Coastguard Worker 
2308*fd1fabb7SAndroid Build Coastguard Worker 	,	fReductionMatrix2 (tcReductionMatrix2,
2309*fd1fabb7SAndroid Build Coastguard Worker 						   profile.ReductionMatrix2 ())
2310*fd1fabb7SAndroid Build Coastguard Worker 
2311*fd1fabb7SAndroid Build Coastguard Worker 	,	fProfileName (tcProfileName,
2312*fd1fabb7SAndroid Build Coastguard Worker 					  profile.Name (),
2313*fd1fabb7SAndroid Build Coastguard Worker 					  false)
2314*fd1fabb7SAndroid Build Coastguard Worker 
2315*fd1fabb7SAndroid Build Coastguard Worker 	,	fProfileCalibrationSignature (tcProfileCalibrationSignature,
2316*fd1fabb7SAndroid Build Coastguard Worker 									  profile.ProfileCalibrationSignature (),
2317*fd1fabb7SAndroid Build Coastguard Worker 									  false)
2318*fd1fabb7SAndroid Build Coastguard Worker 
2319*fd1fabb7SAndroid Build Coastguard Worker 	,	fEmbedPolicyTag (tcProfileEmbedPolicy,
2320*fd1fabb7SAndroid Build Coastguard Worker 						 profile.EmbedPolicy ())
2321*fd1fabb7SAndroid Build Coastguard Worker 
2322*fd1fabb7SAndroid Build Coastguard Worker 	,	fCopyrightTag (tcProfileCopyright,
2323*fd1fabb7SAndroid Build Coastguard Worker 					   profile.Copyright (),
2324*fd1fabb7SAndroid Build Coastguard Worker 					   false)
2325*fd1fabb7SAndroid Build Coastguard Worker 
2326*fd1fabb7SAndroid Build Coastguard Worker 	,	fHueSatMapDims (tcProfileHueSatMapDims,
2327*fd1fabb7SAndroid Build Coastguard Worker 						fHueSatMapDimData,
2328*fd1fabb7SAndroid Build Coastguard Worker 						3)
2329*fd1fabb7SAndroid Build Coastguard Worker 
2330*fd1fabb7SAndroid Build Coastguard Worker 	,	fHueSatData1 (tcProfileHueSatMapData1,
2331*fd1fabb7SAndroid Build Coastguard Worker 					  ttFloat,
2332*fd1fabb7SAndroid Build Coastguard Worker 					  profile.HueSatDeltas1 ().DeltasCount () * 3,
2333*fd1fabb7SAndroid Build Coastguard Worker 					  profile.HueSatDeltas1 ().GetConstDeltas ())
2334*fd1fabb7SAndroid Build Coastguard Worker 
2335*fd1fabb7SAndroid Build Coastguard Worker 	,	fHueSatData2 (tcProfileHueSatMapData2,
2336*fd1fabb7SAndroid Build Coastguard Worker 					  ttFloat,
2337*fd1fabb7SAndroid Build Coastguard Worker 					  profile.HueSatDeltas2 ().DeltasCount () * 3,
2338*fd1fabb7SAndroid Build Coastguard Worker 					  profile.HueSatDeltas2 ().GetConstDeltas ())
2339*fd1fabb7SAndroid Build Coastguard Worker 
2340*fd1fabb7SAndroid Build Coastguard Worker 	,	fHueSatMapEncodingTag (tcProfileHueSatMapEncoding,
2341*fd1fabb7SAndroid Build Coastguard Worker 							   profile.HueSatMapEncoding ())
2342*fd1fabb7SAndroid Build Coastguard Worker 
2343*fd1fabb7SAndroid Build Coastguard Worker 	,	fLookTableDims (tcProfileLookTableDims,
2344*fd1fabb7SAndroid Build Coastguard Worker 						fLookTableDimData,
2345*fd1fabb7SAndroid Build Coastguard Worker 						3)
2346*fd1fabb7SAndroid Build Coastguard Worker 
2347*fd1fabb7SAndroid Build Coastguard Worker 	,	fLookTableData (tcProfileLookTableData,
2348*fd1fabb7SAndroid Build Coastguard Worker 						ttFloat,
2349*fd1fabb7SAndroid Build Coastguard Worker 						profile.LookTable ().DeltasCount () * 3,
2350*fd1fabb7SAndroid Build Coastguard Worker 					    profile.LookTable ().GetConstDeltas ())
2351*fd1fabb7SAndroid Build Coastguard Worker 
2352*fd1fabb7SAndroid Build Coastguard Worker 	,	fLookTableEncodingTag (tcProfileLookTableEncoding,
2353*fd1fabb7SAndroid Build Coastguard Worker 							   profile.LookTableEncoding ())
2354*fd1fabb7SAndroid Build Coastguard Worker 
2355*fd1fabb7SAndroid Build Coastguard Worker 	,	fBaselineExposureOffsetTag (tcBaselineExposureOffset,
2356*fd1fabb7SAndroid Build Coastguard Worker 									profile.BaselineExposureOffset ())
2357*fd1fabb7SAndroid Build Coastguard Worker 
2358*fd1fabb7SAndroid Build Coastguard Worker 	,	fDefaultBlackRenderTag (tcDefaultBlackRender,
2359*fd1fabb7SAndroid Build Coastguard Worker 								profile.DefaultBlackRender ())
2360*fd1fabb7SAndroid Build Coastguard Worker 
2361*fd1fabb7SAndroid Build Coastguard Worker 	,	fToneCurveBuffer ()
2362*fd1fabb7SAndroid Build Coastguard Worker 
2363*fd1fabb7SAndroid Build Coastguard Worker 	,	fToneCurveTag (tcProfileToneCurve,
2364*fd1fabb7SAndroid Build Coastguard Worker 					   ttFloat,
2365*fd1fabb7SAndroid Build Coastguard Worker 					   0,
2366*fd1fabb7SAndroid Build Coastguard Worker 					   NULL)
2367*fd1fabb7SAndroid Build Coastguard Worker 
2368*fd1fabb7SAndroid Build Coastguard Worker 	{
2369*fd1fabb7SAndroid Build Coastguard Worker 
2370*fd1fabb7SAndroid Build Coastguard Worker 	if (profile.HasColorMatrix1 ())
2371*fd1fabb7SAndroid Build Coastguard Worker 		{
2372*fd1fabb7SAndroid Build Coastguard Worker 
2373*fd1fabb7SAndroid Build Coastguard Worker 		uint32 colorChannels = profile.ColorMatrix1 ().Rows ();
2374*fd1fabb7SAndroid Build Coastguard Worker 
2375*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fCalibrationIlluminant1);
2376*fd1fabb7SAndroid Build Coastguard Worker 
2377*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fColorMatrix1);
2378*fd1fabb7SAndroid Build Coastguard Worker 
2379*fd1fabb7SAndroid Build Coastguard Worker 		if (fForwardMatrix1.Count () == colorChannels * 3)
2380*fd1fabb7SAndroid Build Coastguard Worker 			{
2381*fd1fabb7SAndroid Build Coastguard Worker 
2382*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fForwardMatrix1);
2383*fd1fabb7SAndroid Build Coastguard Worker 
2384*fd1fabb7SAndroid Build Coastguard Worker 			}
2385*fd1fabb7SAndroid Build Coastguard Worker 
2386*fd1fabb7SAndroid Build Coastguard Worker 		if (colorChannels > 3 && fReductionMatrix1.Count () == colorChannels * 3)
2387*fd1fabb7SAndroid Build Coastguard Worker 			{
2388*fd1fabb7SAndroid Build Coastguard Worker 
2389*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fReductionMatrix1);
2390*fd1fabb7SAndroid Build Coastguard Worker 
2391*fd1fabb7SAndroid Build Coastguard Worker 			}
2392*fd1fabb7SAndroid Build Coastguard Worker 
2393*fd1fabb7SAndroid Build Coastguard Worker 		if (profile.HasColorMatrix2 ())
2394*fd1fabb7SAndroid Build Coastguard Worker 			{
2395*fd1fabb7SAndroid Build Coastguard Worker 
2396*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fCalibrationIlluminant2);
2397*fd1fabb7SAndroid Build Coastguard Worker 
2398*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fColorMatrix2);
2399*fd1fabb7SAndroid Build Coastguard Worker 
2400*fd1fabb7SAndroid Build Coastguard Worker 			if (fForwardMatrix2.Count () == colorChannels * 3)
2401*fd1fabb7SAndroid Build Coastguard Worker 				{
2402*fd1fabb7SAndroid Build Coastguard Worker 
2403*fd1fabb7SAndroid Build Coastguard Worker 				directory.Add (&fForwardMatrix2);
2404*fd1fabb7SAndroid Build Coastguard Worker 
2405*fd1fabb7SAndroid Build Coastguard Worker 				}
2406*fd1fabb7SAndroid Build Coastguard Worker 
2407*fd1fabb7SAndroid Build Coastguard Worker 			if (colorChannels > 3 && fReductionMatrix2.Count () == colorChannels * 3)
2408*fd1fabb7SAndroid Build Coastguard Worker 				{
2409*fd1fabb7SAndroid Build Coastguard Worker 
2410*fd1fabb7SAndroid Build Coastguard Worker 				directory.Add (&fReductionMatrix2);
2411*fd1fabb7SAndroid Build Coastguard Worker 
2412*fd1fabb7SAndroid Build Coastguard Worker 				}
2413*fd1fabb7SAndroid Build Coastguard Worker 
2414*fd1fabb7SAndroid Build Coastguard Worker 			}
2415*fd1fabb7SAndroid Build Coastguard Worker 
2416*fd1fabb7SAndroid Build Coastguard Worker 		if (profile.Name ().NotEmpty ())
2417*fd1fabb7SAndroid Build Coastguard Worker 			{
2418*fd1fabb7SAndroid Build Coastguard Worker 
2419*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fProfileName);
2420*fd1fabb7SAndroid Build Coastguard Worker 
2421*fd1fabb7SAndroid Build Coastguard Worker 			}
2422*fd1fabb7SAndroid Build Coastguard Worker 
2423*fd1fabb7SAndroid Build Coastguard Worker 		if (profile.ProfileCalibrationSignature ().NotEmpty ())
2424*fd1fabb7SAndroid Build Coastguard Worker 			{
2425*fd1fabb7SAndroid Build Coastguard Worker 
2426*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fProfileCalibrationSignature);
2427*fd1fabb7SAndroid Build Coastguard Worker 
2428*fd1fabb7SAndroid Build Coastguard Worker 			}
2429*fd1fabb7SAndroid Build Coastguard Worker 
2430*fd1fabb7SAndroid Build Coastguard Worker 		directory.Add (&fEmbedPolicyTag);
2431*fd1fabb7SAndroid Build Coastguard Worker 
2432*fd1fabb7SAndroid Build Coastguard Worker 		if (profile.Copyright ().NotEmpty ())
2433*fd1fabb7SAndroid Build Coastguard Worker 			{
2434*fd1fabb7SAndroid Build Coastguard Worker 
2435*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fCopyrightTag);
2436*fd1fabb7SAndroid Build Coastguard Worker 
2437*fd1fabb7SAndroid Build Coastguard Worker 			}
2438*fd1fabb7SAndroid Build Coastguard Worker 
2439*fd1fabb7SAndroid Build Coastguard Worker 		bool haveHueSat1 = profile.HueSatDeltas1 ().IsValid ();
2440*fd1fabb7SAndroid Build Coastguard Worker 
2441*fd1fabb7SAndroid Build Coastguard Worker 		bool haveHueSat2 = profile.HueSatDeltas2 ().IsValid () &&
2442*fd1fabb7SAndroid Build Coastguard Worker 						   profile.HasColorMatrix2 ();
2443*fd1fabb7SAndroid Build Coastguard Worker 
2444*fd1fabb7SAndroid Build Coastguard Worker 		if (haveHueSat1 || haveHueSat2)
2445*fd1fabb7SAndroid Build Coastguard Worker 			{
2446*fd1fabb7SAndroid Build Coastguard Worker 
2447*fd1fabb7SAndroid Build Coastguard Worker 			uint32 hueDivs = 0;
2448*fd1fabb7SAndroid Build Coastguard Worker 			uint32 satDivs = 0;
2449*fd1fabb7SAndroid Build Coastguard Worker 			uint32 valDivs = 0;
2450*fd1fabb7SAndroid Build Coastguard Worker 
2451*fd1fabb7SAndroid Build Coastguard Worker 			if (haveHueSat1)
2452*fd1fabb7SAndroid Build Coastguard Worker 				{
2453*fd1fabb7SAndroid Build Coastguard Worker 
2454*fd1fabb7SAndroid Build Coastguard Worker 				profile.HueSatDeltas1 ().GetDivisions (hueDivs,
2455*fd1fabb7SAndroid Build Coastguard Worker 													   satDivs,
2456*fd1fabb7SAndroid Build Coastguard Worker 													   valDivs);
2457*fd1fabb7SAndroid Build Coastguard Worker 
2458*fd1fabb7SAndroid Build Coastguard Worker 				}
2459*fd1fabb7SAndroid Build Coastguard Worker 
2460*fd1fabb7SAndroid Build Coastguard Worker 			else
2461*fd1fabb7SAndroid Build Coastguard Worker 				{
2462*fd1fabb7SAndroid Build Coastguard Worker 
2463*fd1fabb7SAndroid Build Coastguard Worker 				profile.HueSatDeltas2 ().GetDivisions (hueDivs,
2464*fd1fabb7SAndroid Build Coastguard Worker 													   satDivs,
2465*fd1fabb7SAndroid Build Coastguard Worker 													   valDivs);
2466*fd1fabb7SAndroid Build Coastguard Worker 
2467*fd1fabb7SAndroid Build Coastguard Worker 				}
2468*fd1fabb7SAndroid Build Coastguard Worker 
2469*fd1fabb7SAndroid Build Coastguard Worker 			fHueSatMapDimData [0] = hueDivs;
2470*fd1fabb7SAndroid Build Coastguard Worker 			fHueSatMapDimData [1] = satDivs;
2471*fd1fabb7SAndroid Build Coastguard Worker 			fHueSatMapDimData [2] = valDivs;
2472*fd1fabb7SAndroid Build Coastguard Worker 
2473*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fHueSatMapDims);
2474*fd1fabb7SAndroid Build Coastguard Worker 
2475*fd1fabb7SAndroid Build Coastguard Worker 			// Don't bother including the ProfileHueSatMapEncoding tag unless it's
2476*fd1fabb7SAndroid Build Coastguard Worker 			// non-linear.
2477*fd1fabb7SAndroid Build Coastguard Worker 
2478*fd1fabb7SAndroid Build Coastguard Worker 			if (profile.HueSatMapEncoding () != encoding_Linear)
2479*fd1fabb7SAndroid Build Coastguard Worker 				{
2480*fd1fabb7SAndroid Build Coastguard Worker 
2481*fd1fabb7SAndroid Build Coastguard Worker 				directory.Add (&fHueSatMapEncodingTag);
2482*fd1fabb7SAndroid Build Coastguard Worker 
2483*fd1fabb7SAndroid Build Coastguard Worker 				}
2484*fd1fabb7SAndroid Build Coastguard Worker 
2485*fd1fabb7SAndroid Build Coastguard Worker 			}
2486*fd1fabb7SAndroid Build Coastguard Worker 
2487*fd1fabb7SAndroid Build Coastguard Worker 		if (haveHueSat1)
2488*fd1fabb7SAndroid Build Coastguard Worker 			{
2489*fd1fabb7SAndroid Build Coastguard Worker 
2490*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fHueSatData1);
2491*fd1fabb7SAndroid Build Coastguard Worker 
2492*fd1fabb7SAndroid Build Coastguard Worker 			}
2493*fd1fabb7SAndroid Build Coastguard Worker 
2494*fd1fabb7SAndroid Build Coastguard Worker 		if (haveHueSat2)
2495*fd1fabb7SAndroid Build Coastguard Worker 			{
2496*fd1fabb7SAndroid Build Coastguard Worker 
2497*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fHueSatData2);
2498*fd1fabb7SAndroid Build Coastguard Worker 
2499*fd1fabb7SAndroid Build Coastguard Worker 			}
2500*fd1fabb7SAndroid Build Coastguard Worker 
2501*fd1fabb7SAndroid Build Coastguard Worker 		if (profile.HasLookTable ())
2502*fd1fabb7SAndroid Build Coastguard Worker 			{
2503*fd1fabb7SAndroid Build Coastguard Worker 
2504*fd1fabb7SAndroid Build Coastguard Worker 			uint32 hueDivs = 0;
2505*fd1fabb7SAndroid Build Coastguard Worker 			uint32 satDivs = 0;
2506*fd1fabb7SAndroid Build Coastguard Worker 			uint32 valDivs = 0;
2507*fd1fabb7SAndroid Build Coastguard Worker 
2508*fd1fabb7SAndroid Build Coastguard Worker 			profile.LookTable ().GetDivisions (hueDivs,
2509*fd1fabb7SAndroid Build Coastguard Worker 											   satDivs,
2510*fd1fabb7SAndroid Build Coastguard Worker 											   valDivs);
2511*fd1fabb7SAndroid Build Coastguard Worker 
2512*fd1fabb7SAndroid Build Coastguard Worker 			fLookTableDimData [0] = hueDivs;
2513*fd1fabb7SAndroid Build Coastguard Worker 			fLookTableDimData [1] = satDivs;
2514*fd1fabb7SAndroid Build Coastguard Worker 			fLookTableDimData [2] = valDivs;
2515*fd1fabb7SAndroid Build Coastguard Worker 
2516*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fLookTableDims);
2517*fd1fabb7SAndroid Build Coastguard Worker 
2518*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fLookTableData);
2519*fd1fabb7SAndroid Build Coastguard Worker 
2520*fd1fabb7SAndroid Build Coastguard Worker 			// Don't bother including the ProfileLookTableEncoding tag unless it's
2521*fd1fabb7SAndroid Build Coastguard Worker 			// non-linear.
2522*fd1fabb7SAndroid Build Coastguard Worker 
2523*fd1fabb7SAndroid Build Coastguard Worker 			if (profile.LookTableEncoding () != encoding_Linear)
2524*fd1fabb7SAndroid Build Coastguard Worker 				{
2525*fd1fabb7SAndroid Build Coastguard Worker 
2526*fd1fabb7SAndroid Build Coastguard Worker 				directory.Add (&fLookTableEncodingTag);
2527*fd1fabb7SAndroid Build Coastguard Worker 
2528*fd1fabb7SAndroid Build Coastguard Worker 				}
2529*fd1fabb7SAndroid Build Coastguard Worker 
2530*fd1fabb7SAndroid Build Coastguard Worker 			}
2531*fd1fabb7SAndroid Build Coastguard Worker 
2532*fd1fabb7SAndroid Build Coastguard Worker 		// Don't bother including the BaselineExposureOffset tag unless it's both
2533*fd1fabb7SAndroid Build Coastguard Worker 		// valid and non-zero.
2534*fd1fabb7SAndroid Build Coastguard Worker 
2535*fd1fabb7SAndroid Build Coastguard Worker 		if (profile.BaselineExposureOffset ().IsValid ())
2536*fd1fabb7SAndroid Build Coastguard Worker 			{
2537*fd1fabb7SAndroid Build Coastguard Worker 
2538*fd1fabb7SAndroid Build Coastguard Worker 			if (profile.BaselineExposureOffset ().As_real64 () != 0.0)
2539*fd1fabb7SAndroid Build Coastguard Worker 				{
2540*fd1fabb7SAndroid Build Coastguard Worker 
2541*fd1fabb7SAndroid Build Coastguard Worker 				directory.Add (&fBaselineExposureOffsetTag);
2542*fd1fabb7SAndroid Build Coastguard Worker 
2543*fd1fabb7SAndroid Build Coastguard Worker 				}
2544*fd1fabb7SAndroid Build Coastguard Worker 
2545*fd1fabb7SAndroid Build Coastguard Worker 			}
2546*fd1fabb7SAndroid Build Coastguard Worker 
2547*fd1fabb7SAndroid Build Coastguard Worker 		if (profile.DefaultBlackRender () != defaultBlackRender_Auto)
2548*fd1fabb7SAndroid Build Coastguard Worker 			{
2549*fd1fabb7SAndroid Build Coastguard Worker 
2550*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fDefaultBlackRenderTag);
2551*fd1fabb7SAndroid Build Coastguard Worker 
2552*fd1fabb7SAndroid Build Coastguard Worker 			}
2553*fd1fabb7SAndroid Build Coastguard Worker 
2554*fd1fabb7SAndroid Build Coastguard Worker 		if (profile.ToneCurve ().IsValid ())
2555*fd1fabb7SAndroid Build Coastguard Worker 			{
2556*fd1fabb7SAndroid Build Coastguard Worker 
2557*fd1fabb7SAndroid Build Coastguard Worker 			// Tone curve stored as pairs of 32-bit coordinates.  Probably could do with
2558*fd1fabb7SAndroid Build Coastguard Worker 			// 16-bits here, but should be small number of points so...
2559*fd1fabb7SAndroid Build Coastguard Worker 
2560*fd1fabb7SAndroid Build Coastguard Worker 			uint32 toneCurvePoints = (uint32) (profile.ToneCurve ().fCoord.size ());
2561*fd1fabb7SAndroid Build Coastguard Worker 
2562*fd1fabb7SAndroid Build Coastguard Worker 			fToneCurveBuffer.Allocate (SafeUint32Mult(toneCurvePoints, 2),
2563*fd1fabb7SAndroid Build Coastguard Worker 									   sizeof (real32));
2564*fd1fabb7SAndroid Build Coastguard Worker 
2565*fd1fabb7SAndroid Build Coastguard Worker 			real32 *points = fToneCurveBuffer.Buffer_real32 ();
2566*fd1fabb7SAndroid Build Coastguard Worker 
2567*fd1fabb7SAndroid Build Coastguard Worker 			fToneCurveTag.SetCount (toneCurvePoints * 2);
2568*fd1fabb7SAndroid Build Coastguard Worker 			fToneCurveTag.SetData  (points);
2569*fd1fabb7SAndroid Build Coastguard Worker 
2570*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 i = 0; i < toneCurvePoints; i++)
2571*fd1fabb7SAndroid Build Coastguard Worker 				{
2572*fd1fabb7SAndroid Build Coastguard Worker 
2573*fd1fabb7SAndroid Build Coastguard Worker 				// Transpose coordinates so they are in a more expected
2574*fd1fabb7SAndroid Build Coastguard Worker 				// order (domain -> range).
2575*fd1fabb7SAndroid Build Coastguard Worker 
2576*fd1fabb7SAndroid Build Coastguard Worker 				points [i * 2    ] = (real32) profile.ToneCurve ().fCoord [i].h;
2577*fd1fabb7SAndroid Build Coastguard Worker 				points [i * 2 + 1] = (real32) profile.ToneCurve ().fCoord [i].v;
2578*fd1fabb7SAndroid Build Coastguard Worker 
2579*fd1fabb7SAndroid Build Coastguard Worker 				}
2580*fd1fabb7SAndroid Build Coastguard Worker 
2581*fd1fabb7SAndroid Build Coastguard Worker 			directory.Add (&fToneCurveTag);
2582*fd1fabb7SAndroid Build Coastguard Worker 
2583*fd1fabb7SAndroid Build Coastguard Worker 			}
2584*fd1fabb7SAndroid Build Coastguard Worker 
2585*fd1fabb7SAndroid Build Coastguard Worker 		}
2586*fd1fabb7SAndroid Build Coastguard Worker 
2587*fd1fabb7SAndroid Build Coastguard Worker 	}
2588*fd1fabb7SAndroid Build Coastguard Worker 
2589*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
2590*fd1fabb7SAndroid Build Coastguard Worker 
tiff_dng_extended_color_profile(const dng_camera_profile & profile)2591*fd1fabb7SAndroid Build Coastguard Worker tiff_dng_extended_color_profile::tiff_dng_extended_color_profile
2592*fd1fabb7SAndroid Build Coastguard Worker 								 (const dng_camera_profile &profile)
2593*fd1fabb7SAndroid Build Coastguard Worker 
2594*fd1fabb7SAndroid Build Coastguard Worker 	:	fProfile (profile)
2595*fd1fabb7SAndroid Build Coastguard Worker 
2596*fd1fabb7SAndroid Build Coastguard Worker 	{
2597*fd1fabb7SAndroid Build Coastguard Worker 
2598*fd1fabb7SAndroid Build Coastguard Worker 	}
2599*fd1fabb7SAndroid Build Coastguard Worker 
2600*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
2601*fd1fabb7SAndroid Build Coastguard Worker 
Put(dng_stream & stream,bool includeModelRestriction)2602*fd1fabb7SAndroid Build Coastguard Worker void tiff_dng_extended_color_profile::Put (dng_stream &stream,
2603*fd1fabb7SAndroid Build Coastguard Worker 										   bool includeModelRestriction)
2604*fd1fabb7SAndroid Build Coastguard Worker 	{
2605*fd1fabb7SAndroid Build Coastguard Worker 
2606*fd1fabb7SAndroid Build Coastguard Worker 	// Profile header.
2607*fd1fabb7SAndroid Build Coastguard Worker 
2608*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint16 (stream.BigEndian () ? byteOrderMM : byteOrderII);
2609*fd1fabb7SAndroid Build Coastguard Worker 
2610*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint16 (magicExtendedProfile);
2611*fd1fabb7SAndroid Build Coastguard Worker 
2612*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint32 (8);
2613*fd1fabb7SAndroid Build Coastguard Worker 
2614*fd1fabb7SAndroid Build Coastguard Worker 	// Profile tags.
2615*fd1fabb7SAndroid Build Coastguard Worker 
2616*fd1fabb7SAndroid Build Coastguard Worker 	profile_tag_set tagSet (*this, fProfile);
2617*fd1fabb7SAndroid Build Coastguard Worker 
2618*fd1fabb7SAndroid Build Coastguard Worker 	// Camera this profile is for.
2619*fd1fabb7SAndroid Build Coastguard Worker 
2620*fd1fabb7SAndroid Build Coastguard Worker 	tag_string cameraModelTag (tcUniqueCameraModel,
2621*fd1fabb7SAndroid Build Coastguard Worker 							   fProfile.UniqueCameraModelRestriction ());
2622*fd1fabb7SAndroid Build Coastguard Worker 
2623*fd1fabb7SAndroid Build Coastguard Worker 	if (includeModelRestriction)
2624*fd1fabb7SAndroid Build Coastguard Worker 		{
2625*fd1fabb7SAndroid Build Coastguard Worker 
2626*fd1fabb7SAndroid Build Coastguard Worker 		if (fProfile.UniqueCameraModelRestriction ().NotEmpty ())
2627*fd1fabb7SAndroid Build Coastguard Worker 			{
2628*fd1fabb7SAndroid Build Coastguard Worker 
2629*fd1fabb7SAndroid Build Coastguard Worker 			Add (&cameraModelTag);
2630*fd1fabb7SAndroid Build Coastguard Worker 
2631*fd1fabb7SAndroid Build Coastguard Worker 			}
2632*fd1fabb7SAndroid Build Coastguard Worker 
2633*fd1fabb7SAndroid Build Coastguard Worker 		}
2634*fd1fabb7SAndroid Build Coastguard Worker 
2635*fd1fabb7SAndroid Build Coastguard Worker 	// Write it all out.
2636*fd1fabb7SAndroid Build Coastguard Worker 
2637*fd1fabb7SAndroid Build Coastguard Worker 	dng_tiff_directory::Put (stream, offsetsRelativeToExplicitBase, 8);
2638*fd1fabb7SAndroid Build Coastguard Worker 
2639*fd1fabb7SAndroid Build Coastguard Worker 	}
2640*fd1fabb7SAndroid Build Coastguard Worker 
2641*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
2642*fd1fabb7SAndroid Build Coastguard Worker 
tag_dng_noise_profile(const dng_noise_profile & profile)2643*fd1fabb7SAndroid Build Coastguard Worker tag_dng_noise_profile::tag_dng_noise_profile (const dng_noise_profile &profile)
2644*fd1fabb7SAndroid Build Coastguard Worker 
2645*fd1fabb7SAndroid Build Coastguard Worker 	:	tag_data_ptr (tcNoiseProfile,
2646*fd1fabb7SAndroid Build Coastguard Worker 					  ttDouble,
2647*fd1fabb7SAndroid Build Coastguard Worker 					  2 * profile.NumFunctions (),
2648*fd1fabb7SAndroid Build Coastguard Worker 					  fValues)
2649*fd1fabb7SAndroid Build Coastguard Worker 
2650*fd1fabb7SAndroid Build Coastguard Worker 	{
2651*fd1fabb7SAndroid Build Coastguard Worker 
2652*fd1fabb7SAndroid Build Coastguard Worker 	DNG_REQUIRE (profile.NumFunctions () <= kMaxColorPlanes,
2653*fd1fabb7SAndroid Build Coastguard Worker 				 "Too many noise functions in tag_dng_noise_profile.");
2654*fd1fabb7SAndroid Build Coastguard Worker 
2655*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 i = 0; i < profile.NumFunctions (); i++)
2656*fd1fabb7SAndroid Build Coastguard Worker 		{
2657*fd1fabb7SAndroid Build Coastguard Worker 
2658*fd1fabb7SAndroid Build Coastguard Worker 		fValues [(2 * i)	] = profile.NoiseFunction (i).Scale	 ();
2659*fd1fabb7SAndroid Build Coastguard Worker 		fValues [(2 * i) + 1] = profile.NoiseFunction (i).Offset ();
2660*fd1fabb7SAndroid Build Coastguard Worker 
2661*fd1fabb7SAndroid Build Coastguard Worker 		}
2662*fd1fabb7SAndroid Build Coastguard Worker 
2663*fd1fabb7SAndroid Build Coastguard Worker 	}
2664*fd1fabb7SAndroid Build Coastguard Worker 
2665*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
2666*fd1fabb7SAndroid Build Coastguard Worker 
dng_image_writer()2667*fd1fabb7SAndroid Build Coastguard Worker dng_image_writer::dng_image_writer ()
2668*fd1fabb7SAndroid Build Coastguard Worker 	{
2669*fd1fabb7SAndroid Build Coastguard Worker 
2670*fd1fabb7SAndroid Build Coastguard Worker 	}
2671*fd1fabb7SAndroid Build Coastguard Worker 
2672*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
2673*fd1fabb7SAndroid Build Coastguard Worker 
~dng_image_writer()2674*fd1fabb7SAndroid Build Coastguard Worker dng_image_writer::~dng_image_writer ()
2675*fd1fabb7SAndroid Build Coastguard Worker 	{
2676*fd1fabb7SAndroid Build Coastguard Worker 
2677*fd1fabb7SAndroid Build Coastguard Worker 	}
2678*fd1fabb7SAndroid Build Coastguard Worker 
2679*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
2680*fd1fabb7SAndroid Build Coastguard Worker 
CompressedBufferSize(const dng_ifd & ifd,uint32 uncompressedSize)2681*fd1fabb7SAndroid Build Coastguard Worker uint32 dng_image_writer::CompressedBufferSize (const dng_ifd &ifd,
2682*fd1fabb7SAndroid Build Coastguard Worker 											   uint32 uncompressedSize)
2683*fd1fabb7SAndroid Build Coastguard Worker 	{
2684*fd1fabb7SAndroid Build Coastguard Worker 
2685*fd1fabb7SAndroid Build Coastguard Worker 	switch (ifd.fCompression)
2686*fd1fabb7SAndroid Build Coastguard Worker 		{
2687*fd1fabb7SAndroid Build Coastguard Worker 
2688*fd1fabb7SAndroid Build Coastguard Worker 		case ccLZW:
2689*fd1fabb7SAndroid Build Coastguard Worker 			{
2690*fd1fabb7SAndroid Build Coastguard Worker 
2691*fd1fabb7SAndroid Build Coastguard Worker 			// Add lots of slop for LZW to expand data.
2692*fd1fabb7SAndroid Build Coastguard Worker 
2693*fd1fabb7SAndroid Build Coastguard Worker 			return SafeUint32Add (SafeUint32Mult (uncompressedSize, 2), 1024);
2694*fd1fabb7SAndroid Build Coastguard Worker 
2695*fd1fabb7SAndroid Build Coastguard Worker 			}
2696*fd1fabb7SAndroid Build Coastguard Worker 
2697*fd1fabb7SAndroid Build Coastguard Worker 		case ccDeflate:
2698*fd1fabb7SAndroid Build Coastguard Worker 			{
2699*fd1fabb7SAndroid Build Coastguard Worker 
2700*fd1fabb7SAndroid Build Coastguard Worker 			// ZLib says maximum is source size + 0.1% + 12 bytes.
2701*fd1fabb7SAndroid Build Coastguard Worker 
2702*fd1fabb7SAndroid Build Coastguard Worker 			return SafeUint32Add (SafeUint32Add (uncompressedSize,
2703*fd1fabb7SAndroid Build Coastguard Worker 												 uncompressedSize >> 8), 64);
2704*fd1fabb7SAndroid Build Coastguard Worker 
2705*fd1fabb7SAndroid Build Coastguard Worker 			}
2706*fd1fabb7SAndroid Build Coastguard Worker 
2707*fd1fabb7SAndroid Build Coastguard Worker 		case ccJPEG:
2708*fd1fabb7SAndroid Build Coastguard Worker 			{
2709*fd1fabb7SAndroid Build Coastguard Worker 
2710*fd1fabb7SAndroid Build Coastguard Worker 			// If we are saving lossless JPEG from an 8-bit image, reserve
2711*fd1fabb7SAndroid Build Coastguard Worker 			// space to pad the data out to 16-bits.
2712*fd1fabb7SAndroid Build Coastguard Worker 
2713*fd1fabb7SAndroid Build Coastguard Worker 			if (ifd.fBitsPerSample [0] <= 8)
2714*fd1fabb7SAndroid Build Coastguard Worker 				{
2715*fd1fabb7SAndroid Build Coastguard Worker 
2716*fd1fabb7SAndroid Build Coastguard Worker 				return SafeUint32Mult (uncompressedSize, 2);
2717*fd1fabb7SAndroid Build Coastguard Worker 
2718*fd1fabb7SAndroid Build Coastguard Worker 				}
2719*fd1fabb7SAndroid Build Coastguard Worker 
2720*fd1fabb7SAndroid Build Coastguard Worker 			break;
2721*fd1fabb7SAndroid Build Coastguard Worker 
2722*fd1fabb7SAndroid Build Coastguard Worker 			}
2723*fd1fabb7SAndroid Build Coastguard Worker 
2724*fd1fabb7SAndroid Build Coastguard Worker 		default:
2725*fd1fabb7SAndroid Build Coastguard Worker 			break;
2726*fd1fabb7SAndroid Build Coastguard Worker 
2727*fd1fabb7SAndroid Build Coastguard Worker 		}
2728*fd1fabb7SAndroid Build Coastguard Worker 
2729*fd1fabb7SAndroid Build Coastguard Worker 	return 0;
2730*fd1fabb7SAndroid Build Coastguard Worker 
2731*fd1fabb7SAndroid Build Coastguard Worker 	}
2732*fd1fabb7SAndroid Build Coastguard Worker 
2733*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
2734*fd1fabb7SAndroid Build Coastguard Worker 
EncodeDelta8(uint8 * dPtr,uint32 rows,uint32 cols,uint32 channels)2735*fd1fabb7SAndroid Build Coastguard Worker static void EncodeDelta8 (uint8 *dPtr,
2736*fd1fabb7SAndroid Build Coastguard Worker 						  uint32 rows,
2737*fd1fabb7SAndroid Build Coastguard Worker 						  uint32 cols,
2738*fd1fabb7SAndroid Build Coastguard Worker 						  uint32 channels)
2739*fd1fabb7SAndroid Build Coastguard Worker 	{
2740*fd1fabb7SAndroid Build Coastguard Worker 
2741*fd1fabb7SAndroid Build Coastguard Worker 	const uint32 dRowStep = cols * channels;
2742*fd1fabb7SAndroid Build Coastguard Worker 
2743*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 row = 0; row < rows; row++)
2744*fd1fabb7SAndroid Build Coastguard Worker 		{
2745*fd1fabb7SAndroid Build Coastguard Worker 
2746*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 col = cols - 1; col > 0; col--)
2747*fd1fabb7SAndroid Build Coastguard Worker 			{
2748*fd1fabb7SAndroid Build Coastguard Worker 
2749*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 channel = 0; channel < channels; channel++)
2750*fd1fabb7SAndroid Build Coastguard Worker 				{
2751*fd1fabb7SAndroid Build Coastguard Worker 
2752*fd1fabb7SAndroid Build Coastguard Worker 				dPtr [col * channels + channel] -= dPtr [(col - 1) * channels + channel];
2753*fd1fabb7SAndroid Build Coastguard Worker 
2754*fd1fabb7SAndroid Build Coastguard Worker 				}
2755*fd1fabb7SAndroid Build Coastguard Worker 
2756*fd1fabb7SAndroid Build Coastguard Worker 			}
2757*fd1fabb7SAndroid Build Coastguard Worker 
2758*fd1fabb7SAndroid Build Coastguard Worker 		dPtr += dRowStep;
2759*fd1fabb7SAndroid Build Coastguard Worker 
2760*fd1fabb7SAndroid Build Coastguard Worker 		}
2761*fd1fabb7SAndroid Build Coastguard Worker 
2762*fd1fabb7SAndroid Build Coastguard Worker 	}
2763*fd1fabb7SAndroid Build Coastguard Worker 
2764*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
2765*fd1fabb7SAndroid Build Coastguard Worker 
EncodeDelta16(uint16 * dPtr,uint32 rows,uint32 cols,uint32 channels)2766*fd1fabb7SAndroid Build Coastguard Worker static void EncodeDelta16 (uint16 *dPtr,
2767*fd1fabb7SAndroid Build Coastguard Worker 						   uint32 rows,
2768*fd1fabb7SAndroid Build Coastguard Worker 						   uint32 cols,
2769*fd1fabb7SAndroid Build Coastguard Worker 						   uint32 channels)
2770*fd1fabb7SAndroid Build Coastguard Worker 	{
2771*fd1fabb7SAndroid Build Coastguard Worker 
2772*fd1fabb7SAndroid Build Coastguard Worker 	const uint32 dRowStep = cols * channels;
2773*fd1fabb7SAndroid Build Coastguard Worker 
2774*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 row = 0; row < rows; row++)
2775*fd1fabb7SAndroid Build Coastguard Worker 		{
2776*fd1fabb7SAndroid Build Coastguard Worker 
2777*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 col = cols - 1; col > 0; col--)
2778*fd1fabb7SAndroid Build Coastguard Worker 			{
2779*fd1fabb7SAndroid Build Coastguard Worker 
2780*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 channel = 0; channel < channels; channel++)
2781*fd1fabb7SAndroid Build Coastguard Worker 				{
2782*fd1fabb7SAndroid Build Coastguard Worker 
2783*fd1fabb7SAndroid Build Coastguard Worker 				dPtr [col * channels + channel] -= dPtr [(col - 1) * channels + channel];
2784*fd1fabb7SAndroid Build Coastguard Worker 
2785*fd1fabb7SAndroid Build Coastguard Worker 				}
2786*fd1fabb7SAndroid Build Coastguard Worker 
2787*fd1fabb7SAndroid Build Coastguard Worker 			}
2788*fd1fabb7SAndroid Build Coastguard Worker 
2789*fd1fabb7SAndroid Build Coastguard Worker 		dPtr += dRowStep;
2790*fd1fabb7SAndroid Build Coastguard Worker 
2791*fd1fabb7SAndroid Build Coastguard Worker 		}
2792*fd1fabb7SAndroid Build Coastguard Worker 
2793*fd1fabb7SAndroid Build Coastguard Worker 	}
2794*fd1fabb7SAndroid Build Coastguard Worker 
2795*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
2796*fd1fabb7SAndroid Build Coastguard Worker 
EncodeDelta32(uint32 * dPtr,uint32 rows,uint32 cols,uint32 channels)2797*fd1fabb7SAndroid Build Coastguard Worker static void EncodeDelta32 (uint32 *dPtr,
2798*fd1fabb7SAndroid Build Coastguard Worker 						   uint32 rows,
2799*fd1fabb7SAndroid Build Coastguard Worker 						   uint32 cols,
2800*fd1fabb7SAndroid Build Coastguard Worker 						   uint32 channels)
2801*fd1fabb7SAndroid Build Coastguard Worker 	{
2802*fd1fabb7SAndroid Build Coastguard Worker 
2803*fd1fabb7SAndroid Build Coastguard Worker 	const uint32 dRowStep = cols * channels;
2804*fd1fabb7SAndroid Build Coastguard Worker 
2805*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 row = 0; row < rows; row++)
2806*fd1fabb7SAndroid Build Coastguard Worker 		{
2807*fd1fabb7SAndroid Build Coastguard Worker 
2808*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 col = cols - 1; col > 0; col--)
2809*fd1fabb7SAndroid Build Coastguard Worker 			{
2810*fd1fabb7SAndroid Build Coastguard Worker 
2811*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 channel = 0; channel < channels; channel++)
2812*fd1fabb7SAndroid Build Coastguard Worker 				{
2813*fd1fabb7SAndroid Build Coastguard Worker 
2814*fd1fabb7SAndroid Build Coastguard Worker 				dPtr [col * channels + channel] -= dPtr [(col - 1) * channels + channel];
2815*fd1fabb7SAndroid Build Coastguard Worker 
2816*fd1fabb7SAndroid Build Coastguard Worker 				}
2817*fd1fabb7SAndroid Build Coastguard Worker 
2818*fd1fabb7SAndroid Build Coastguard Worker 			}
2819*fd1fabb7SAndroid Build Coastguard Worker 
2820*fd1fabb7SAndroid Build Coastguard Worker 		dPtr += dRowStep;
2821*fd1fabb7SAndroid Build Coastguard Worker 
2822*fd1fabb7SAndroid Build Coastguard Worker 		}
2823*fd1fabb7SAndroid Build Coastguard Worker 
2824*fd1fabb7SAndroid Build Coastguard Worker 	}
2825*fd1fabb7SAndroid Build Coastguard Worker 
2826*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
2827*fd1fabb7SAndroid Build Coastguard Worker 
EncodeDeltaBytes(uint8 * bytePtr,int32 cols,int32 channels)2828*fd1fabb7SAndroid Build Coastguard Worker inline void EncodeDeltaBytes (uint8 *bytePtr, int32 cols, int32 channels)
2829*fd1fabb7SAndroid Build Coastguard Worker 	{
2830*fd1fabb7SAndroid Build Coastguard Worker 
2831*fd1fabb7SAndroid Build Coastguard Worker 	if (channels == 1)
2832*fd1fabb7SAndroid Build Coastguard Worker 		{
2833*fd1fabb7SAndroid Build Coastguard Worker 
2834*fd1fabb7SAndroid Build Coastguard Worker 		bytePtr += (cols - 1);
2835*fd1fabb7SAndroid Build Coastguard Worker 
2836*fd1fabb7SAndroid Build Coastguard Worker 		uint8 this0 = bytePtr [0];
2837*fd1fabb7SAndroid Build Coastguard Worker 
2838*fd1fabb7SAndroid Build Coastguard Worker 		for (int32 col = 1; col < cols; col++)
2839*fd1fabb7SAndroid Build Coastguard Worker 			{
2840*fd1fabb7SAndroid Build Coastguard Worker 
2841*fd1fabb7SAndroid Build Coastguard Worker 			uint8 prev0 = bytePtr [-1];
2842*fd1fabb7SAndroid Build Coastguard Worker 
2843*fd1fabb7SAndroid Build Coastguard Worker 			this0 -= prev0;
2844*fd1fabb7SAndroid Build Coastguard Worker 
2845*fd1fabb7SAndroid Build Coastguard Worker 			bytePtr [0] = this0;
2846*fd1fabb7SAndroid Build Coastguard Worker 
2847*fd1fabb7SAndroid Build Coastguard Worker 			this0 = prev0;
2848*fd1fabb7SAndroid Build Coastguard Worker 
2849*fd1fabb7SAndroid Build Coastguard Worker 			bytePtr -= 1;
2850*fd1fabb7SAndroid Build Coastguard Worker 
2851*fd1fabb7SAndroid Build Coastguard Worker 			}
2852*fd1fabb7SAndroid Build Coastguard Worker 
2853*fd1fabb7SAndroid Build Coastguard Worker 		}
2854*fd1fabb7SAndroid Build Coastguard Worker 
2855*fd1fabb7SAndroid Build Coastguard Worker 	else if (channels == 3)
2856*fd1fabb7SAndroid Build Coastguard Worker 		{
2857*fd1fabb7SAndroid Build Coastguard Worker 
2858*fd1fabb7SAndroid Build Coastguard Worker 		bytePtr += (cols - 1) * 3;
2859*fd1fabb7SAndroid Build Coastguard Worker 
2860*fd1fabb7SAndroid Build Coastguard Worker 		uint8 this0 = bytePtr [0];
2861*fd1fabb7SAndroid Build Coastguard Worker 		uint8 this1 = bytePtr [1];
2862*fd1fabb7SAndroid Build Coastguard Worker 		uint8 this2 = bytePtr [2];
2863*fd1fabb7SAndroid Build Coastguard Worker 
2864*fd1fabb7SAndroid Build Coastguard Worker 		for (int32 col = 1; col < cols; col++)
2865*fd1fabb7SAndroid Build Coastguard Worker 			{
2866*fd1fabb7SAndroid Build Coastguard Worker 
2867*fd1fabb7SAndroid Build Coastguard Worker 			uint8 prev0 = bytePtr [-3];
2868*fd1fabb7SAndroid Build Coastguard Worker 			uint8 prev1 = bytePtr [-2];
2869*fd1fabb7SAndroid Build Coastguard Worker 			uint8 prev2 = bytePtr [-1];
2870*fd1fabb7SAndroid Build Coastguard Worker 
2871*fd1fabb7SAndroid Build Coastguard Worker 			this0 -= prev0;
2872*fd1fabb7SAndroid Build Coastguard Worker 			this1 -= prev1;
2873*fd1fabb7SAndroid Build Coastguard Worker 			this2 -= prev2;
2874*fd1fabb7SAndroid Build Coastguard Worker 
2875*fd1fabb7SAndroid Build Coastguard Worker 			bytePtr [0] = this0;
2876*fd1fabb7SAndroid Build Coastguard Worker 			bytePtr [1] = this1;
2877*fd1fabb7SAndroid Build Coastguard Worker 			bytePtr [2] = this2;
2878*fd1fabb7SAndroid Build Coastguard Worker 
2879*fd1fabb7SAndroid Build Coastguard Worker 			this0 = prev0;
2880*fd1fabb7SAndroid Build Coastguard Worker 			this1 = prev1;
2881*fd1fabb7SAndroid Build Coastguard Worker 			this2 = prev2;
2882*fd1fabb7SAndroid Build Coastguard Worker 
2883*fd1fabb7SAndroid Build Coastguard Worker 			bytePtr -= 3;
2884*fd1fabb7SAndroid Build Coastguard Worker 
2885*fd1fabb7SAndroid Build Coastguard Worker 			}
2886*fd1fabb7SAndroid Build Coastguard Worker 
2887*fd1fabb7SAndroid Build Coastguard Worker 		}
2888*fd1fabb7SAndroid Build Coastguard Worker 
2889*fd1fabb7SAndroid Build Coastguard Worker 	else
2890*fd1fabb7SAndroid Build Coastguard Worker 		{
2891*fd1fabb7SAndroid Build Coastguard Worker 
2892*fd1fabb7SAndroid Build Coastguard Worker 		uint32 rowBytes = cols * channels;
2893*fd1fabb7SAndroid Build Coastguard Worker 
2894*fd1fabb7SAndroid Build Coastguard Worker 		bytePtr += rowBytes - 1;
2895*fd1fabb7SAndroid Build Coastguard Worker 
2896*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 col = channels; col < rowBytes; col++)
2897*fd1fabb7SAndroid Build Coastguard Worker 			{
2898*fd1fabb7SAndroid Build Coastguard Worker 
2899*fd1fabb7SAndroid Build Coastguard Worker 			bytePtr [0] -= bytePtr [-channels];
2900*fd1fabb7SAndroid Build Coastguard Worker 
2901*fd1fabb7SAndroid Build Coastguard Worker 			bytePtr--;
2902*fd1fabb7SAndroid Build Coastguard Worker 
2903*fd1fabb7SAndroid Build Coastguard Worker 			}
2904*fd1fabb7SAndroid Build Coastguard Worker 
2905*fd1fabb7SAndroid Build Coastguard Worker 		}
2906*fd1fabb7SAndroid Build Coastguard Worker 
2907*fd1fabb7SAndroid Build Coastguard Worker 	}
2908*fd1fabb7SAndroid Build Coastguard Worker 
2909*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
2910*fd1fabb7SAndroid Build Coastguard Worker 
EncodeFPDelta(uint8 * buffer,uint8 * temp,int32 cols,int32 channels,int32 bytesPerSample)2911*fd1fabb7SAndroid Build Coastguard Worker static void EncodeFPDelta (uint8 *buffer,
2912*fd1fabb7SAndroid Build Coastguard Worker 						   uint8 *temp,
2913*fd1fabb7SAndroid Build Coastguard Worker 						   int32 cols,
2914*fd1fabb7SAndroid Build Coastguard Worker 						   int32 channels,
2915*fd1fabb7SAndroid Build Coastguard Worker 						   int32 bytesPerSample)
2916*fd1fabb7SAndroid Build Coastguard Worker 	{
2917*fd1fabb7SAndroid Build Coastguard Worker 
2918*fd1fabb7SAndroid Build Coastguard Worker 	int32 rowIncrement = cols * channels;
2919*fd1fabb7SAndroid Build Coastguard Worker 
2920*fd1fabb7SAndroid Build Coastguard Worker 	if (bytesPerSample == 2)
2921*fd1fabb7SAndroid Build Coastguard Worker 		{
2922*fd1fabb7SAndroid Build Coastguard Worker 
2923*fd1fabb7SAndroid Build Coastguard Worker 		const uint8 *src = buffer;
2924*fd1fabb7SAndroid Build Coastguard Worker 
2925*fd1fabb7SAndroid Build Coastguard Worker 		#if qDNGBigEndian
2926*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst0 = temp;
2927*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst1 = temp + rowIncrement;
2928*fd1fabb7SAndroid Build Coastguard Worker 		#else
2929*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst1 = temp;
2930*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst0 = temp + rowIncrement;
2931*fd1fabb7SAndroid Build Coastguard Worker 		#endif
2932*fd1fabb7SAndroid Build Coastguard Worker 
2933*fd1fabb7SAndroid Build Coastguard Worker 		for (int32 col = 0; col < rowIncrement; ++col)
2934*fd1fabb7SAndroid Build Coastguard Worker 			{
2935*fd1fabb7SAndroid Build Coastguard Worker 
2936*fd1fabb7SAndroid Build Coastguard Worker 			dst0 [col] = src [0];
2937*fd1fabb7SAndroid Build Coastguard Worker 			dst1 [col] = src [1];
2938*fd1fabb7SAndroid Build Coastguard Worker 
2939*fd1fabb7SAndroid Build Coastguard Worker 			src += 2;
2940*fd1fabb7SAndroid Build Coastguard Worker 
2941*fd1fabb7SAndroid Build Coastguard Worker 			}
2942*fd1fabb7SAndroid Build Coastguard Worker 
2943*fd1fabb7SAndroid Build Coastguard Worker 		}
2944*fd1fabb7SAndroid Build Coastguard Worker 
2945*fd1fabb7SAndroid Build Coastguard Worker 	else if (bytesPerSample == 3)
2946*fd1fabb7SAndroid Build Coastguard Worker 		{
2947*fd1fabb7SAndroid Build Coastguard Worker 
2948*fd1fabb7SAndroid Build Coastguard Worker 		const uint8 *src = buffer;
2949*fd1fabb7SAndroid Build Coastguard Worker 
2950*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst0 = temp;
2951*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst1 = temp + rowIncrement;
2952*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst2 = temp + rowIncrement * 2;
2953*fd1fabb7SAndroid Build Coastguard Worker 
2954*fd1fabb7SAndroid Build Coastguard Worker 		for (int32 col = 0; col < rowIncrement; ++col)
2955*fd1fabb7SAndroid Build Coastguard Worker 			{
2956*fd1fabb7SAndroid Build Coastguard Worker 
2957*fd1fabb7SAndroid Build Coastguard Worker 			dst0 [col] = src [0];
2958*fd1fabb7SAndroid Build Coastguard Worker 			dst1 [col] = src [1];
2959*fd1fabb7SAndroid Build Coastguard Worker 			dst2 [col] = src [2];
2960*fd1fabb7SAndroid Build Coastguard Worker 
2961*fd1fabb7SAndroid Build Coastguard Worker 			src += 3;
2962*fd1fabb7SAndroid Build Coastguard Worker 
2963*fd1fabb7SAndroid Build Coastguard Worker 			}
2964*fd1fabb7SAndroid Build Coastguard Worker 
2965*fd1fabb7SAndroid Build Coastguard Worker 		}
2966*fd1fabb7SAndroid Build Coastguard Worker 
2967*fd1fabb7SAndroid Build Coastguard Worker 	else
2968*fd1fabb7SAndroid Build Coastguard Worker 		{
2969*fd1fabb7SAndroid Build Coastguard Worker 
2970*fd1fabb7SAndroid Build Coastguard Worker 		const uint8 *src = buffer;
2971*fd1fabb7SAndroid Build Coastguard Worker 
2972*fd1fabb7SAndroid Build Coastguard Worker 		#if qDNGBigEndian
2973*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst0 = temp;
2974*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst1 = temp + rowIncrement;
2975*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst2 = temp + rowIncrement * 2;
2976*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst3 = temp + rowIncrement * 3;
2977*fd1fabb7SAndroid Build Coastguard Worker 		#else
2978*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst3 = temp;
2979*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst2 = temp + rowIncrement;
2980*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst1 = temp + rowIncrement * 2;
2981*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dst0 = temp + rowIncrement * 3;
2982*fd1fabb7SAndroid Build Coastguard Worker 		#endif
2983*fd1fabb7SAndroid Build Coastguard Worker 
2984*fd1fabb7SAndroid Build Coastguard Worker 		for (int32 col = 0; col < rowIncrement; ++col)
2985*fd1fabb7SAndroid Build Coastguard Worker 			{
2986*fd1fabb7SAndroid Build Coastguard Worker 
2987*fd1fabb7SAndroid Build Coastguard Worker 			dst0 [col] = src [0];
2988*fd1fabb7SAndroid Build Coastguard Worker 			dst1 [col] = src [1];
2989*fd1fabb7SAndroid Build Coastguard Worker 			dst2 [col] = src [2];
2990*fd1fabb7SAndroid Build Coastguard Worker 			dst3 [col] = src [3];
2991*fd1fabb7SAndroid Build Coastguard Worker 
2992*fd1fabb7SAndroid Build Coastguard Worker 			src += 4;
2993*fd1fabb7SAndroid Build Coastguard Worker 
2994*fd1fabb7SAndroid Build Coastguard Worker 			}
2995*fd1fabb7SAndroid Build Coastguard Worker 
2996*fd1fabb7SAndroid Build Coastguard Worker 		}
2997*fd1fabb7SAndroid Build Coastguard Worker 
2998*fd1fabb7SAndroid Build Coastguard Worker 	EncodeDeltaBytes (temp, cols*bytesPerSample, channels);
2999*fd1fabb7SAndroid Build Coastguard Worker 
3000*fd1fabb7SAndroid Build Coastguard Worker 	memcpy (buffer, temp, cols*bytesPerSample*channels);
3001*fd1fabb7SAndroid Build Coastguard Worker 
3002*fd1fabb7SAndroid Build Coastguard Worker 	}
3003*fd1fabb7SAndroid Build Coastguard Worker 
3004*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3005*fd1fabb7SAndroid Build Coastguard Worker 
EncodePredictor(dng_host & host,const dng_ifd & ifd,dng_pixel_buffer & buffer,AutoPtr<dng_memory_block> & tempBuffer)3006*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::EncodePredictor (dng_host &host,
3007*fd1fabb7SAndroid Build Coastguard Worker 									    const dng_ifd &ifd,
3008*fd1fabb7SAndroid Build Coastguard Worker 						        	    dng_pixel_buffer &buffer,
3009*fd1fabb7SAndroid Build Coastguard Worker 										AutoPtr<dng_memory_block> &tempBuffer)
3010*fd1fabb7SAndroid Build Coastguard Worker 	{
3011*fd1fabb7SAndroid Build Coastguard Worker 
3012*fd1fabb7SAndroid Build Coastguard Worker 	switch (ifd.fPredictor)
3013*fd1fabb7SAndroid Build Coastguard Worker 		{
3014*fd1fabb7SAndroid Build Coastguard Worker 
3015*fd1fabb7SAndroid Build Coastguard Worker 		case cpHorizontalDifference:
3016*fd1fabb7SAndroid Build Coastguard Worker 		case cpHorizontalDifferenceX2:
3017*fd1fabb7SAndroid Build Coastguard Worker 		case cpHorizontalDifferenceX4:
3018*fd1fabb7SAndroid Build Coastguard Worker 			{
3019*fd1fabb7SAndroid Build Coastguard Worker 
3020*fd1fabb7SAndroid Build Coastguard Worker 			int32 xFactor = 1;
3021*fd1fabb7SAndroid Build Coastguard Worker 
3022*fd1fabb7SAndroid Build Coastguard Worker 			if (ifd.fPredictor == cpHorizontalDifferenceX2)
3023*fd1fabb7SAndroid Build Coastguard Worker 				{
3024*fd1fabb7SAndroid Build Coastguard Worker 				xFactor = 2;
3025*fd1fabb7SAndroid Build Coastguard Worker 				}
3026*fd1fabb7SAndroid Build Coastguard Worker 
3027*fd1fabb7SAndroid Build Coastguard Worker 			else if (ifd.fPredictor == cpHorizontalDifferenceX4)
3028*fd1fabb7SAndroid Build Coastguard Worker 				{
3029*fd1fabb7SAndroid Build Coastguard Worker 				xFactor = 4;
3030*fd1fabb7SAndroid Build Coastguard Worker 				}
3031*fd1fabb7SAndroid Build Coastguard Worker 
3032*fd1fabb7SAndroid Build Coastguard Worker 			switch (buffer.fPixelType)
3033*fd1fabb7SAndroid Build Coastguard Worker 				{
3034*fd1fabb7SAndroid Build Coastguard Worker 
3035*fd1fabb7SAndroid Build Coastguard Worker 				case ttByte:
3036*fd1fabb7SAndroid Build Coastguard Worker 					{
3037*fd1fabb7SAndroid Build Coastguard Worker 
3038*fd1fabb7SAndroid Build Coastguard Worker 					EncodeDelta8 ((uint8 *) buffer.fData,
3039*fd1fabb7SAndroid Build Coastguard Worker 								  buffer.fArea.H (),
3040*fd1fabb7SAndroid Build Coastguard Worker 								  buffer.fArea.W () / xFactor,
3041*fd1fabb7SAndroid Build Coastguard Worker 								  buffer.fPlanes    * xFactor);
3042*fd1fabb7SAndroid Build Coastguard Worker 
3043*fd1fabb7SAndroid Build Coastguard Worker 					return;
3044*fd1fabb7SAndroid Build Coastguard Worker 
3045*fd1fabb7SAndroid Build Coastguard Worker 					}
3046*fd1fabb7SAndroid Build Coastguard Worker 
3047*fd1fabb7SAndroid Build Coastguard Worker 				case ttShort:
3048*fd1fabb7SAndroid Build Coastguard Worker 					{
3049*fd1fabb7SAndroid Build Coastguard Worker 
3050*fd1fabb7SAndroid Build Coastguard Worker 					EncodeDelta16 ((uint16 *) buffer.fData,
3051*fd1fabb7SAndroid Build Coastguard Worker 								   buffer.fArea.H (),
3052*fd1fabb7SAndroid Build Coastguard Worker 								   buffer.fArea.W () / xFactor,
3053*fd1fabb7SAndroid Build Coastguard Worker 								   buffer.fPlanes    * xFactor);
3054*fd1fabb7SAndroid Build Coastguard Worker 
3055*fd1fabb7SAndroid Build Coastguard Worker 					return;
3056*fd1fabb7SAndroid Build Coastguard Worker 
3057*fd1fabb7SAndroid Build Coastguard Worker 					}
3058*fd1fabb7SAndroid Build Coastguard Worker 
3059*fd1fabb7SAndroid Build Coastguard Worker 				case ttLong:
3060*fd1fabb7SAndroid Build Coastguard Worker 					{
3061*fd1fabb7SAndroid Build Coastguard Worker 
3062*fd1fabb7SAndroid Build Coastguard Worker 					EncodeDelta32 ((uint32 *) buffer.fData,
3063*fd1fabb7SAndroid Build Coastguard Worker 								   buffer.fArea.H (),
3064*fd1fabb7SAndroid Build Coastguard Worker 								   buffer.fArea.W () / xFactor,
3065*fd1fabb7SAndroid Build Coastguard Worker 								   buffer.fPlanes    * xFactor);
3066*fd1fabb7SAndroid Build Coastguard Worker 
3067*fd1fabb7SAndroid Build Coastguard Worker 					return;
3068*fd1fabb7SAndroid Build Coastguard Worker 
3069*fd1fabb7SAndroid Build Coastguard Worker 					}
3070*fd1fabb7SAndroid Build Coastguard Worker 
3071*fd1fabb7SAndroid Build Coastguard Worker 				default:
3072*fd1fabb7SAndroid Build Coastguard Worker 					break;
3073*fd1fabb7SAndroid Build Coastguard Worker 
3074*fd1fabb7SAndroid Build Coastguard Worker 				}
3075*fd1fabb7SAndroid Build Coastguard Worker 
3076*fd1fabb7SAndroid Build Coastguard Worker 			break;
3077*fd1fabb7SAndroid Build Coastguard Worker 
3078*fd1fabb7SAndroid Build Coastguard Worker 			}
3079*fd1fabb7SAndroid Build Coastguard Worker 
3080*fd1fabb7SAndroid Build Coastguard Worker 		case cpFloatingPoint:
3081*fd1fabb7SAndroid Build Coastguard Worker 		case cpFloatingPointX2:
3082*fd1fabb7SAndroid Build Coastguard Worker 		case cpFloatingPointX4:
3083*fd1fabb7SAndroid Build Coastguard Worker 			{
3084*fd1fabb7SAndroid Build Coastguard Worker 
3085*fd1fabb7SAndroid Build Coastguard Worker 			int32 xFactor = 1;
3086*fd1fabb7SAndroid Build Coastguard Worker 
3087*fd1fabb7SAndroid Build Coastguard Worker 			if (ifd.fPredictor == cpFloatingPointX2)
3088*fd1fabb7SAndroid Build Coastguard Worker 				{
3089*fd1fabb7SAndroid Build Coastguard Worker 				xFactor = 2;
3090*fd1fabb7SAndroid Build Coastguard Worker 				}
3091*fd1fabb7SAndroid Build Coastguard Worker 
3092*fd1fabb7SAndroid Build Coastguard Worker 			else if (ifd.fPredictor == cpFloatingPointX4)
3093*fd1fabb7SAndroid Build Coastguard Worker 				{
3094*fd1fabb7SAndroid Build Coastguard Worker 				xFactor = 4;
3095*fd1fabb7SAndroid Build Coastguard Worker 				}
3096*fd1fabb7SAndroid Build Coastguard Worker 
3097*fd1fabb7SAndroid Build Coastguard Worker 			if (buffer.fRowStep < 0)
3098*fd1fabb7SAndroid Build Coastguard Worker 				{
3099*fd1fabb7SAndroid Build Coastguard Worker 				ThrowProgramError ("Row step may not be negative");
3100*fd1fabb7SAndroid Build Coastguard Worker 				}
3101*fd1fabb7SAndroid Build Coastguard Worker 			uint32 tempBufferSize = SafeUint32Mult (
3102*fd1fabb7SAndroid Build Coastguard Worker 				static_cast<uint32>(buffer.fRowStep),
3103*fd1fabb7SAndroid Build Coastguard Worker 				buffer.fPixelSize);
3104*fd1fabb7SAndroid Build Coastguard Worker 
3105*fd1fabb7SAndroid Build Coastguard Worker 			if (!tempBuffer.Get () || tempBuffer->LogicalSize () < tempBufferSize)
3106*fd1fabb7SAndroid Build Coastguard Worker 				{
3107*fd1fabb7SAndroid Build Coastguard Worker 
3108*fd1fabb7SAndroid Build Coastguard Worker 				tempBuffer.Reset (host.Allocate (tempBufferSize));
3109*fd1fabb7SAndroid Build Coastguard Worker 
3110*fd1fabb7SAndroid Build Coastguard Worker 				}
3111*fd1fabb7SAndroid Build Coastguard Worker 
3112*fd1fabb7SAndroid Build Coastguard Worker 			for (int32 row = buffer.fArea.t; row < buffer.fArea.b; row++)
3113*fd1fabb7SAndroid Build Coastguard Worker 				{
3114*fd1fabb7SAndroid Build Coastguard Worker 
3115*fd1fabb7SAndroid Build Coastguard Worker 				EncodeFPDelta ((uint8 *) buffer.DirtyPixel (row, buffer.fArea.l, buffer.fPlane),
3116*fd1fabb7SAndroid Build Coastguard Worker 							   tempBuffer->Buffer_uint8 (),
3117*fd1fabb7SAndroid Build Coastguard Worker 							   buffer.fArea.W () / xFactor,
3118*fd1fabb7SAndroid Build Coastguard Worker 							   buffer.fPlanes    * xFactor,
3119*fd1fabb7SAndroid Build Coastguard Worker 							   buffer.fPixelSize);
3120*fd1fabb7SAndroid Build Coastguard Worker 
3121*fd1fabb7SAndroid Build Coastguard Worker 				}
3122*fd1fabb7SAndroid Build Coastguard Worker 
3123*fd1fabb7SAndroid Build Coastguard Worker 			return;
3124*fd1fabb7SAndroid Build Coastguard Worker 
3125*fd1fabb7SAndroid Build Coastguard Worker 			}
3126*fd1fabb7SAndroid Build Coastguard Worker 
3127*fd1fabb7SAndroid Build Coastguard Worker 		default:
3128*fd1fabb7SAndroid Build Coastguard Worker 			break;
3129*fd1fabb7SAndroid Build Coastguard Worker 
3130*fd1fabb7SAndroid Build Coastguard Worker 		}
3131*fd1fabb7SAndroid Build Coastguard Worker 
3132*fd1fabb7SAndroid Build Coastguard Worker 	if (ifd.fPredictor != cpNullPredictor)
3133*fd1fabb7SAndroid Build Coastguard Worker 		{
3134*fd1fabb7SAndroid Build Coastguard Worker 
3135*fd1fabb7SAndroid Build Coastguard Worker 		ThrowProgramError ();
3136*fd1fabb7SAndroid Build Coastguard Worker 
3137*fd1fabb7SAndroid Build Coastguard Worker 		}
3138*fd1fabb7SAndroid Build Coastguard Worker 
3139*fd1fabb7SAndroid Build Coastguard Worker 	}
3140*fd1fabb7SAndroid Build Coastguard Worker 
3141*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3142*fd1fabb7SAndroid Build Coastguard Worker 
ByteSwapBuffer(dng_host &,dng_pixel_buffer & buffer)3143*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::ByteSwapBuffer (dng_host & /* host */,
3144*fd1fabb7SAndroid Build Coastguard Worker 									   dng_pixel_buffer &buffer)
3145*fd1fabb7SAndroid Build Coastguard Worker 	{
3146*fd1fabb7SAndroid Build Coastguard Worker 
3147*fd1fabb7SAndroid Build Coastguard Worker 	uint32 pixels = buffer.fRowStep * buffer.fArea.H ();
3148*fd1fabb7SAndroid Build Coastguard Worker 
3149*fd1fabb7SAndroid Build Coastguard Worker 	switch (buffer.fPixelSize)
3150*fd1fabb7SAndroid Build Coastguard Worker 		{
3151*fd1fabb7SAndroid Build Coastguard Worker 
3152*fd1fabb7SAndroid Build Coastguard Worker 		case 2:
3153*fd1fabb7SAndroid Build Coastguard Worker 			{
3154*fd1fabb7SAndroid Build Coastguard Worker 
3155*fd1fabb7SAndroid Build Coastguard Worker 			DoSwapBytes16 ((uint16 *) buffer.fData,
3156*fd1fabb7SAndroid Build Coastguard Worker 						   pixels);
3157*fd1fabb7SAndroid Build Coastguard Worker 
3158*fd1fabb7SAndroid Build Coastguard Worker 			break;
3159*fd1fabb7SAndroid Build Coastguard Worker 
3160*fd1fabb7SAndroid Build Coastguard Worker 			}
3161*fd1fabb7SAndroid Build Coastguard Worker 
3162*fd1fabb7SAndroid Build Coastguard Worker 		case 4:
3163*fd1fabb7SAndroid Build Coastguard Worker 			{
3164*fd1fabb7SAndroid Build Coastguard Worker 
3165*fd1fabb7SAndroid Build Coastguard Worker 			DoSwapBytes32 ((uint32 *) buffer.fData,
3166*fd1fabb7SAndroid Build Coastguard Worker 						   pixels);
3167*fd1fabb7SAndroid Build Coastguard Worker 
3168*fd1fabb7SAndroid Build Coastguard Worker 			break;
3169*fd1fabb7SAndroid Build Coastguard Worker 
3170*fd1fabb7SAndroid Build Coastguard Worker 			}
3171*fd1fabb7SAndroid Build Coastguard Worker 
3172*fd1fabb7SAndroid Build Coastguard Worker 		default:
3173*fd1fabb7SAndroid Build Coastguard Worker 			break;
3174*fd1fabb7SAndroid Build Coastguard Worker 
3175*fd1fabb7SAndroid Build Coastguard Worker 		}
3176*fd1fabb7SAndroid Build Coastguard Worker 
3177*fd1fabb7SAndroid Build Coastguard Worker 	}
3178*fd1fabb7SAndroid Build Coastguard Worker 
3179*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3180*fd1fabb7SAndroid Build Coastguard Worker 
ReorderSubTileBlocks(const dng_ifd & ifd,dng_pixel_buffer & buffer,AutoPtr<dng_memory_block> & uncompressedBuffer,AutoPtr<dng_memory_block> & subTileBlockBuffer)3181*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::ReorderSubTileBlocks (const dng_ifd &ifd,
3182*fd1fabb7SAndroid Build Coastguard Worker 											 dng_pixel_buffer &buffer,
3183*fd1fabb7SAndroid Build Coastguard Worker 											 AutoPtr<dng_memory_block> &uncompressedBuffer,
3184*fd1fabb7SAndroid Build Coastguard Worker 											 AutoPtr<dng_memory_block> &subTileBlockBuffer)
3185*fd1fabb7SAndroid Build Coastguard Worker 	{
3186*fd1fabb7SAndroid Build Coastguard Worker 
3187*fd1fabb7SAndroid Build Coastguard Worker 	uint32 blockRows = ifd.fSubTileBlockRows;
3188*fd1fabb7SAndroid Build Coastguard Worker 	uint32 blockCols = ifd.fSubTileBlockCols;
3189*fd1fabb7SAndroid Build Coastguard Worker 
3190*fd1fabb7SAndroid Build Coastguard Worker 	uint32 rowBlocks = buffer.fArea.H () / blockRows;
3191*fd1fabb7SAndroid Build Coastguard Worker 	uint32 colBlocks = buffer.fArea.W () / blockCols;
3192*fd1fabb7SAndroid Build Coastguard Worker 
3193*fd1fabb7SAndroid Build Coastguard Worker 	int32 rowStep = buffer.fRowStep * buffer.fPixelSize;
3194*fd1fabb7SAndroid Build Coastguard Worker 	int32 colStep = buffer.fColStep * buffer.fPixelSize;
3195*fd1fabb7SAndroid Build Coastguard Worker 
3196*fd1fabb7SAndroid Build Coastguard Worker 	int32 rowBlockStep = rowStep * blockRows;
3197*fd1fabb7SAndroid Build Coastguard Worker 	int32 colBlockStep = colStep * blockCols;
3198*fd1fabb7SAndroid Build Coastguard Worker 
3199*fd1fabb7SAndroid Build Coastguard Worker 	uint32 blockColBytes = blockCols * buffer.fPlanes * buffer.fPixelSize;
3200*fd1fabb7SAndroid Build Coastguard Worker 
3201*fd1fabb7SAndroid Build Coastguard Worker 	const uint8 *s0 = uncompressedBuffer->Buffer_uint8 ();
3202*fd1fabb7SAndroid Build Coastguard Worker 	      uint8 *d0 = subTileBlockBuffer->Buffer_uint8 ();
3203*fd1fabb7SAndroid Build Coastguard Worker 
3204*fd1fabb7SAndroid Build Coastguard Worker 	for (uint32 rowBlock = 0; rowBlock < rowBlocks; rowBlock++)
3205*fd1fabb7SAndroid Build Coastguard Worker 		{
3206*fd1fabb7SAndroid Build Coastguard Worker 
3207*fd1fabb7SAndroid Build Coastguard Worker 		const uint8 *s1 = s0;
3208*fd1fabb7SAndroid Build Coastguard Worker 
3209*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 colBlock = 0; colBlock < colBlocks; colBlock++)
3210*fd1fabb7SAndroid Build Coastguard Worker 			{
3211*fd1fabb7SAndroid Build Coastguard Worker 
3212*fd1fabb7SAndroid Build Coastguard Worker 			const uint8 *s2 = s1;
3213*fd1fabb7SAndroid Build Coastguard Worker 
3214*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 blockRow = 0; blockRow < blockRows; blockRow++)
3215*fd1fabb7SAndroid Build Coastguard Worker 				{
3216*fd1fabb7SAndroid Build Coastguard Worker 
3217*fd1fabb7SAndroid Build Coastguard Worker 				for (uint32 j = 0; j < blockColBytes; j++)
3218*fd1fabb7SAndroid Build Coastguard Worker 					{
3219*fd1fabb7SAndroid Build Coastguard Worker 
3220*fd1fabb7SAndroid Build Coastguard Worker 					d0 [j] = s2 [j];
3221*fd1fabb7SAndroid Build Coastguard Worker 
3222*fd1fabb7SAndroid Build Coastguard Worker 					}
3223*fd1fabb7SAndroid Build Coastguard Worker 
3224*fd1fabb7SAndroid Build Coastguard Worker 				d0 += blockColBytes;
3225*fd1fabb7SAndroid Build Coastguard Worker 
3226*fd1fabb7SAndroid Build Coastguard Worker 				s2 += rowStep;
3227*fd1fabb7SAndroid Build Coastguard Worker 
3228*fd1fabb7SAndroid Build Coastguard Worker 				}
3229*fd1fabb7SAndroid Build Coastguard Worker 
3230*fd1fabb7SAndroid Build Coastguard Worker 			s1 += colBlockStep;
3231*fd1fabb7SAndroid Build Coastguard Worker 
3232*fd1fabb7SAndroid Build Coastguard Worker 			}
3233*fd1fabb7SAndroid Build Coastguard Worker 
3234*fd1fabb7SAndroid Build Coastguard Worker 		s0 += rowBlockStep;
3235*fd1fabb7SAndroid Build Coastguard Worker 
3236*fd1fabb7SAndroid Build Coastguard Worker 		}
3237*fd1fabb7SAndroid Build Coastguard Worker 
3238*fd1fabb7SAndroid Build Coastguard Worker 	// Copy back reordered pixels.
3239*fd1fabb7SAndroid Build Coastguard Worker 
3240*fd1fabb7SAndroid Build Coastguard Worker 	DoCopyBytes (subTileBlockBuffer->Buffer      (),
3241*fd1fabb7SAndroid Build Coastguard Worker 				 uncompressedBuffer->Buffer      (),
3242*fd1fabb7SAndroid Build Coastguard Worker 				 uncompressedBuffer->LogicalSize ());
3243*fd1fabb7SAndroid Build Coastguard Worker 
3244*fd1fabb7SAndroid Build Coastguard Worker 	}
3245*fd1fabb7SAndroid Build Coastguard Worker 
3246*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
3247*fd1fabb7SAndroid Build Coastguard Worker 
3248*fd1fabb7SAndroid Build Coastguard Worker class dng_lzw_compressor
3249*fd1fabb7SAndroid Build Coastguard Worker 	{
3250*fd1fabb7SAndroid Build Coastguard Worker 
3251*fd1fabb7SAndroid Build Coastguard Worker 	private:
3252*fd1fabb7SAndroid Build Coastguard Worker 
3253*fd1fabb7SAndroid Build Coastguard Worker 		enum
3254*fd1fabb7SAndroid Build Coastguard Worker 			{
3255*fd1fabb7SAndroid Build Coastguard Worker 			kResetCode = 256,
3256*fd1fabb7SAndroid Build Coastguard Worker 			kEndCode   = 257,
3257*fd1fabb7SAndroid Build Coastguard Worker 			kTableSize = 4096
3258*fd1fabb7SAndroid Build Coastguard Worker 			};
3259*fd1fabb7SAndroid Build Coastguard Worker 
3260*fd1fabb7SAndroid Build Coastguard Worker 		// Compressor nodes have two son pointers.  The low order bit of
3261*fd1fabb7SAndroid Build Coastguard Worker 		// the next code determines which pointer is used.  This cuts the
3262*fd1fabb7SAndroid Build Coastguard Worker 		// number of nodes searched for the next code by two on average.
3263*fd1fabb7SAndroid Build Coastguard Worker 
3264*fd1fabb7SAndroid Build Coastguard Worker 		struct LZWCompressorNode
3265*fd1fabb7SAndroid Build Coastguard Worker 			{
3266*fd1fabb7SAndroid Build Coastguard Worker 			int16 final;
3267*fd1fabb7SAndroid Build Coastguard Worker 			int16 son0;
3268*fd1fabb7SAndroid Build Coastguard Worker 			int16 son1;
3269*fd1fabb7SAndroid Build Coastguard Worker 			int16 brother;
3270*fd1fabb7SAndroid Build Coastguard Worker 			};
3271*fd1fabb7SAndroid Build Coastguard Worker 
3272*fd1fabb7SAndroid Build Coastguard Worker 		dng_memory_data fBuffer;
3273*fd1fabb7SAndroid Build Coastguard Worker 
3274*fd1fabb7SAndroid Build Coastguard Worker 		LZWCompressorNode *fTable;
3275*fd1fabb7SAndroid Build Coastguard Worker 
3276*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *fDstPtr;
3277*fd1fabb7SAndroid Build Coastguard Worker 
3278*fd1fabb7SAndroid Build Coastguard Worker 		int32 fDstCount;
3279*fd1fabb7SAndroid Build Coastguard Worker 
3280*fd1fabb7SAndroid Build Coastguard Worker 		int32 fBitOffset;
3281*fd1fabb7SAndroid Build Coastguard Worker 
3282*fd1fabb7SAndroid Build Coastguard Worker 		int32 fNextCode;
3283*fd1fabb7SAndroid Build Coastguard Worker 
3284*fd1fabb7SAndroid Build Coastguard Worker 		int32 fCodeSize;
3285*fd1fabb7SAndroid Build Coastguard Worker 
3286*fd1fabb7SAndroid Build Coastguard Worker 	public:
3287*fd1fabb7SAndroid Build Coastguard Worker 
3288*fd1fabb7SAndroid Build Coastguard Worker 		dng_lzw_compressor ();
3289*fd1fabb7SAndroid Build Coastguard Worker 
3290*fd1fabb7SAndroid Build Coastguard Worker 		void Compress (const uint8 *sPtr,
3291*fd1fabb7SAndroid Build Coastguard Worker 					   uint8 *dPtr,
3292*fd1fabb7SAndroid Build Coastguard Worker 					   uint32 sCount,
3293*fd1fabb7SAndroid Build Coastguard Worker 					   uint32 &dCount);
3294*fd1fabb7SAndroid Build Coastguard Worker 
3295*fd1fabb7SAndroid Build Coastguard Worker 	private:
3296*fd1fabb7SAndroid Build Coastguard Worker 
3297*fd1fabb7SAndroid Build Coastguard Worker 		void InitTable ();
3298*fd1fabb7SAndroid Build Coastguard Worker 
SearchTable(int32 w,int32 k) const3299*fd1fabb7SAndroid Build Coastguard Worker 		int32 SearchTable (int32 w, int32 k) const
3300*fd1fabb7SAndroid Build Coastguard Worker 			{
3301*fd1fabb7SAndroid Build Coastguard Worker 
3302*fd1fabb7SAndroid Build Coastguard Worker 			DNG_ASSERT ((w >= 0) && (w <= kTableSize),
3303*fd1fabb7SAndroid Build Coastguard Worker 						"Bad w value in dng_lzw_compressor::SearchTable");
3304*fd1fabb7SAndroid Build Coastguard Worker 
3305*fd1fabb7SAndroid Build Coastguard Worker 			int32 son0 = fTable [w] . son0;
3306*fd1fabb7SAndroid Build Coastguard Worker 			int32 son1 = fTable [w] . son1;
3307*fd1fabb7SAndroid Build Coastguard Worker 
3308*fd1fabb7SAndroid Build Coastguard Worker 			// Branchless version of:
3309*fd1fabb7SAndroid Build Coastguard Worker 			// int32 code = (k & 1) ? son1 : son0;
3310*fd1fabb7SAndroid Build Coastguard Worker 
3311*fd1fabb7SAndroid Build Coastguard Worker 			int32 code = son0 + ((-((int32) (k & 1))) & (son1 - son0));
3312*fd1fabb7SAndroid Build Coastguard Worker 
3313*fd1fabb7SAndroid Build Coastguard Worker 			while (code > 0 && fTable [code].final != k)
3314*fd1fabb7SAndroid Build Coastguard Worker 				{
3315*fd1fabb7SAndroid Build Coastguard Worker 				code = fTable [code].brother;
3316*fd1fabb7SAndroid Build Coastguard Worker 				}
3317*fd1fabb7SAndroid Build Coastguard Worker 
3318*fd1fabb7SAndroid Build Coastguard Worker 			return code;
3319*fd1fabb7SAndroid Build Coastguard Worker 
3320*fd1fabb7SAndroid Build Coastguard Worker 			}
3321*fd1fabb7SAndroid Build Coastguard Worker 
3322*fd1fabb7SAndroid Build Coastguard Worker 		void AddTable (int32 w, int32 k);
3323*fd1fabb7SAndroid Build Coastguard Worker 
3324*fd1fabb7SAndroid Build Coastguard Worker 		void PutCodeWord (int32 code);
3325*fd1fabb7SAndroid Build Coastguard Worker 
3326*fd1fabb7SAndroid Build Coastguard Worker 		// Hidden copy constructor and assignment operator.
3327*fd1fabb7SAndroid Build Coastguard Worker 
3328*fd1fabb7SAndroid Build Coastguard Worker 		dng_lzw_compressor (const dng_lzw_compressor &compressor);
3329*fd1fabb7SAndroid Build Coastguard Worker 
3330*fd1fabb7SAndroid Build Coastguard Worker 		dng_lzw_compressor & operator= (const dng_lzw_compressor &compressor);
3331*fd1fabb7SAndroid Build Coastguard Worker 
3332*fd1fabb7SAndroid Build Coastguard Worker 	};
3333*fd1fabb7SAndroid Build Coastguard Worker 
3334*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
3335*fd1fabb7SAndroid Build Coastguard Worker 
dng_lzw_compressor()3336*fd1fabb7SAndroid Build Coastguard Worker dng_lzw_compressor::dng_lzw_compressor ()
3337*fd1fabb7SAndroid Build Coastguard Worker 
3338*fd1fabb7SAndroid Build Coastguard Worker 	:	fBuffer    ()
3339*fd1fabb7SAndroid Build Coastguard Worker 	,	fTable     (NULL)
3340*fd1fabb7SAndroid Build Coastguard Worker 	,	fDstPtr    (NULL)
3341*fd1fabb7SAndroid Build Coastguard Worker 	,	fDstCount  (0)
3342*fd1fabb7SAndroid Build Coastguard Worker 	,	fBitOffset (0)
3343*fd1fabb7SAndroid Build Coastguard Worker 	,	fNextCode  (0)
3344*fd1fabb7SAndroid Build Coastguard Worker 	,	fCodeSize  (0)
3345*fd1fabb7SAndroid Build Coastguard Worker 
3346*fd1fabb7SAndroid Build Coastguard Worker 	{
3347*fd1fabb7SAndroid Build Coastguard Worker 
3348*fd1fabb7SAndroid Build Coastguard Worker 	fBuffer.Allocate (kTableSize, sizeof (LZWCompressorNode));
3349*fd1fabb7SAndroid Build Coastguard Worker 
3350*fd1fabb7SAndroid Build Coastguard Worker 	fTable = (LZWCompressorNode *) fBuffer.Buffer ();
3351*fd1fabb7SAndroid Build Coastguard Worker 
3352*fd1fabb7SAndroid Build Coastguard Worker 	}
3353*fd1fabb7SAndroid Build Coastguard Worker 
3354*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
3355*fd1fabb7SAndroid Build Coastguard Worker 
InitTable()3356*fd1fabb7SAndroid Build Coastguard Worker void dng_lzw_compressor::InitTable ()
3357*fd1fabb7SAndroid Build Coastguard Worker 	{
3358*fd1fabb7SAndroid Build Coastguard Worker 
3359*fd1fabb7SAndroid Build Coastguard Worker 	fCodeSize = 9;
3360*fd1fabb7SAndroid Build Coastguard Worker 
3361*fd1fabb7SAndroid Build Coastguard Worker 	fNextCode = 258;
3362*fd1fabb7SAndroid Build Coastguard Worker 
3363*fd1fabb7SAndroid Build Coastguard Worker 	LZWCompressorNode *node = &fTable [0];
3364*fd1fabb7SAndroid Build Coastguard Worker 
3365*fd1fabb7SAndroid Build Coastguard Worker 	for (int32 code = 0; code < 256; ++code)
3366*fd1fabb7SAndroid Build Coastguard Worker 		{
3367*fd1fabb7SAndroid Build Coastguard Worker 
3368*fd1fabb7SAndroid Build Coastguard Worker 		node->final   = (int16) code;
3369*fd1fabb7SAndroid Build Coastguard Worker 		node->son0    = -1;
3370*fd1fabb7SAndroid Build Coastguard Worker 		node->son1    = -1;
3371*fd1fabb7SAndroid Build Coastguard Worker 		node->brother = -1;
3372*fd1fabb7SAndroid Build Coastguard Worker 
3373*fd1fabb7SAndroid Build Coastguard Worker 		node++;
3374*fd1fabb7SAndroid Build Coastguard Worker 
3375*fd1fabb7SAndroid Build Coastguard Worker 		}
3376*fd1fabb7SAndroid Build Coastguard Worker 
3377*fd1fabb7SAndroid Build Coastguard Worker 	}
3378*fd1fabb7SAndroid Build Coastguard Worker 
3379*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
3380*fd1fabb7SAndroid Build Coastguard Worker 
AddTable(int32 w,int32 k)3381*fd1fabb7SAndroid Build Coastguard Worker void dng_lzw_compressor::AddTable (int32 w, int32 k)
3382*fd1fabb7SAndroid Build Coastguard Worker 	{
3383*fd1fabb7SAndroid Build Coastguard Worker 
3384*fd1fabb7SAndroid Build Coastguard Worker 	DNG_ASSERT ((w >= 0) && (w <= kTableSize),
3385*fd1fabb7SAndroid Build Coastguard Worker 				"Bad w value in dng_lzw_compressor::AddTable");
3386*fd1fabb7SAndroid Build Coastguard Worker 
3387*fd1fabb7SAndroid Build Coastguard Worker 	LZWCompressorNode *node = &fTable [w];
3388*fd1fabb7SAndroid Build Coastguard Worker 
3389*fd1fabb7SAndroid Build Coastguard Worker 	int32 nextCode = fNextCode;
3390*fd1fabb7SAndroid Build Coastguard Worker 
3391*fd1fabb7SAndroid Build Coastguard Worker 	DNG_ASSERT ((nextCode >= 0) && (nextCode <= kTableSize),
3392*fd1fabb7SAndroid Build Coastguard Worker 				"Bad fNextCode value in dng_lzw_compressor::AddTable");
3393*fd1fabb7SAndroid Build Coastguard Worker 
3394*fd1fabb7SAndroid Build Coastguard Worker 	LZWCompressorNode *node2 = &fTable [nextCode];
3395*fd1fabb7SAndroid Build Coastguard Worker 
3396*fd1fabb7SAndroid Build Coastguard Worker 	fNextCode++;
3397*fd1fabb7SAndroid Build Coastguard Worker 
3398*fd1fabb7SAndroid Build Coastguard Worker 	int32 oldSon;
3399*fd1fabb7SAndroid Build Coastguard Worker 
3400*fd1fabb7SAndroid Build Coastguard Worker 	if( k&1 )
3401*fd1fabb7SAndroid Build Coastguard Worker 		{
3402*fd1fabb7SAndroid Build Coastguard Worker 		oldSon = node->son1;
3403*fd1fabb7SAndroid Build Coastguard Worker 		node->son1 = (int16) nextCode;
3404*fd1fabb7SAndroid Build Coastguard Worker 		}
3405*fd1fabb7SAndroid Build Coastguard Worker 	else
3406*fd1fabb7SAndroid Build Coastguard Worker 		{
3407*fd1fabb7SAndroid Build Coastguard Worker 		oldSon = node->son0;
3408*fd1fabb7SAndroid Build Coastguard Worker 		node->son0 = (int16) nextCode;
3409*fd1fabb7SAndroid Build Coastguard Worker 		}
3410*fd1fabb7SAndroid Build Coastguard Worker 
3411*fd1fabb7SAndroid Build Coastguard Worker 	node2->final   = (int16) k;
3412*fd1fabb7SAndroid Build Coastguard Worker 	node2->son0    = -1;
3413*fd1fabb7SAndroid Build Coastguard Worker 	node2->son1    = -1;
3414*fd1fabb7SAndroid Build Coastguard Worker 	node2->brother = (int16) oldSon;
3415*fd1fabb7SAndroid Build Coastguard Worker 
3416*fd1fabb7SAndroid Build Coastguard Worker 	if (nextCode == (1 << fCodeSize) - 1)
3417*fd1fabb7SAndroid Build Coastguard Worker 		{
3418*fd1fabb7SAndroid Build Coastguard Worker 		if (fCodeSize != 12)
3419*fd1fabb7SAndroid Build Coastguard Worker 			fCodeSize++;
3420*fd1fabb7SAndroid Build Coastguard Worker 		}
3421*fd1fabb7SAndroid Build Coastguard Worker 
3422*fd1fabb7SAndroid Build Coastguard Worker 	}
3423*fd1fabb7SAndroid Build Coastguard Worker 
3424*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
3425*fd1fabb7SAndroid Build Coastguard Worker 
PutCodeWord(int32 code)3426*fd1fabb7SAndroid Build Coastguard Worker void dng_lzw_compressor::PutCodeWord (int32 code)
3427*fd1fabb7SAndroid Build Coastguard Worker 	{
3428*fd1fabb7SAndroid Build Coastguard Worker 
3429*fd1fabb7SAndroid Build Coastguard Worker 	int32 bit = (int32) (fBitOffset & 7);
3430*fd1fabb7SAndroid Build Coastguard Worker 
3431*fd1fabb7SAndroid Build Coastguard Worker 	int32 offset1 = fBitOffset >> 3;
3432*fd1fabb7SAndroid Build Coastguard Worker 	int32 offset2 = (fBitOffset + fCodeSize - 1) >> 3;
3433*fd1fabb7SAndroid Build Coastguard Worker 
3434*fd1fabb7SAndroid Build Coastguard Worker 	int32 shift1 = (fCodeSize + bit) -  8;
3435*fd1fabb7SAndroid Build Coastguard Worker 	int32 shift2 = (fCodeSize + bit) - 16;
3436*fd1fabb7SAndroid Build Coastguard Worker 
3437*fd1fabb7SAndroid Build Coastguard Worker 	uint8 byte1 = (uint8) (code >> shift1);
3438*fd1fabb7SAndroid Build Coastguard Worker 
3439*fd1fabb7SAndroid Build Coastguard Worker 	uint8 *dstPtr1 = fDstPtr + offset1;
3440*fd1fabb7SAndroid Build Coastguard Worker 	uint8 *dstPtr3 = fDstPtr + offset2;
3441*fd1fabb7SAndroid Build Coastguard Worker 
3442*fd1fabb7SAndroid Build Coastguard Worker 	if (offset1 + 1 == offset2)
3443*fd1fabb7SAndroid Build Coastguard Worker 		{
3444*fd1fabb7SAndroid Build Coastguard Worker 
3445*fd1fabb7SAndroid Build Coastguard Worker 		uint8 byte2 = (uint8) (code << (-shift2));
3446*fd1fabb7SAndroid Build Coastguard Worker 
3447*fd1fabb7SAndroid Build Coastguard Worker 		if (bit)
3448*fd1fabb7SAndroid Build Coastguard Worker 			*dstPtr1 |= byte1;
3449*fd1fabb7SAndroid Build Coastguard Worker 		else
3450*fd1fabb7SAndroid Build Coastguard Worker 			*dstPtr1 = byte1;
3451*fd1fabb7SAndroid Build Coastguard Worker 
3452*fd1fabb7SAndroid Build Coastguard Worker 		*dstPtr3 = byte2;
3453*fd1fabb7SAndroid Build Coastguard Worker 
3454*fd1fabb7SAndroid Build Coastguard Worker 		}
3455*fd1fabb7SAndroid Build Coastguard Worker 
3456*fd1fabb7SAndroid Build Coastguard Worker 	else
3457*fd1fabb7SAndroid Build Coastguard Worker 		{
3458*fd1fabb7SAndroid Build Coastguard Worker 
3459*fd1fabb7SAndroid Build Coastguard Worker 		int32 shift3 = (fCodeSize + bit) - 24;
3460*fd1fabb7SAndroid Build Coastguard Worker 
3461*fd1fabb7SAndroid Build Coastguard Worker 		uint8 byte2 = (uint8) (code >> shift2);
3462*fd1fabb7SAndroid Build Coastguard Worker 		uint8 byte3 = (uint8) (code << (-shift3));
3463*fd1fabb7SAndroid Build Coastguard Worker 
3464*fd1fabb7SAndroid Build Coastguard Worker 		uint8 *dstPtr2 = fDstPtr + (offset1 + 1);
3465*fd1fabb7SAndroid Build Coastguard Worker 
3466*fd1fabb7SAndroid Build Coastguard Worker 		if (bit)
3467*fd1fabb7SAndroid Build Coastguard Worker 			*dstPtr1 |= byte1;
3468*fd1fabb7SAndroid Build Coastguard Worker 		else
3469*fd1fabb7SAndroid Build Coastguard Worker 			*dstPtr1 = byte1;
3470*fd1fabb7SAndroid Build Coastguard Worker 
3471*fd1fabb7SAndroid Build Coastguard Worker 		*dstPtr2 = byte2;
3472*fd1fabb7SAndroid Build Coastguard Worker 
3473*fd1fabb7SAndroid Build Coastguard Worker 		*dstPtr3 = byte3;
3474*fd1fabb7SAndroid Build Coastguard Worker 
3475*fd1fabb7SAndroid Build Coastguard Worker 		}
3476*fd1fabb7SAndroid Build Coastguard Worker 
3477*fd1fabb7SAndroid Build Coastguard Worker 	fBitOffset += fCodeSize;
3478*fd1fabb7SAndroid Build Coastguard Worker 
3479*fd1fabb7SAndroid Build Coastguard Worker 	}
3480*fd1fabb7SAndroid Build Coastguard Worker 
3481*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
3482*fd1fabb7SAndroid Build Coastguard Worker 
Compress(const uint8 * sPtr,uint8 * dPtr,uint32 sCount,uint32 & dCount)3483*fd1fabb7SAndroid Build Coastguard Worker void dng_lzw_compressor::Compress (const uint8 *sPtr,
3484*fd1fabb7SAndroid Build Coastguard Worker 						           uint8 *dPtr,
3485*fd1fabb7SAndroid Build Coastguard Worker 						           uint32 sCount,
3486*fd1fabb7SAndroid Build Coastguard Worker 						           uint32 &dCount)
3487*fd1fabb7SAndroid Build Coastguard Worker 	{
3488*fd1fabb7SAndroid Build Coastguard Worker 
3489*fd1fabb7SAndroid Build Coastguard Worker 	fDstPtr = dPtr;
3490*fd1fabb7SAndroid Build Coastguard Worker 
3491*fd1fabb7SAndroid Build Coastguard Worker 	fBitOffset = 0;
3492*fd1fabb7SAndroid Build Coastguard Worker 
3493*fd1fabb7SAndroid Build Coastguard Worker 	InitTable ();
3494*fd1fabb7SAndroid Build Coastguard Worker 
3495*fd1fabb7SAndroid Build Coastguard Worker 	PutCodeWord (kResetCode);
3496*fd1fabb7SAndroid Build Coastguard Worker 
3497*fd1fabb7SAndroid Build Coastguard Worker 	int32 code = -1;
3498*fd1fabb7SAndroid Build Coastguard Worker 
3499*fd1fabb7SAndroid Build Coastguard Worker 	int32 pixel;
3500*fd1fabb7SAndroid Build Coastguard Worker 
3501*fd1fabb7SAndroid Build Coastguard Worker 	if (sCount > 0)
3502*fd1fabb7SAndroid Build Coastguard Worker 		{
3503*fd1fabb7SAndroid Build Coastguard Worker 
3504*fd1fabb7SAndroid Build Coastguard Worker 		pixel = *sPtr;
3505*fd1fabb7SAndroid Build Coastguard Worker 		sPtr = sPtr + 1;
3506*fd1fabb7SAndroid Build Coastguard Worker 		code = pixel;
3507*fd1fabb7SAndroid Build Coastguard Worker 
3508*fd1fabb7SAndroid Build Coastguard Worker 		sCount--;
3509*fd1fabb7SAndroid Build Coastguard Worker 
3510*fd1fabb7SAndroid Build Coastguard Worker 		while (sCount--)
3511*fd1fabb7SAndroid Build Coastguard Worker 			{
3512*fd1fabb7SAndroid Build Coastguard Worker 
3513*fd1fabb7SAndroid Build Coastguard Worker 			pixel = *sPtr;
3514*fd1fabb7SAndroid Build Coastguard Worker 			sPtr = sPtr + 1;
3515*fd1fabb7SAndroid Build Coastguard Worker 
3516*fd1fabb7SAndroid Build Coastguard Worker 			int32 newCode = SearchTable (code, pixel);
3517*fd1fabb7SAndroid Build Coastguard Worker 
3518*fd1fabb7SAndroid Build Coastguard Worker 			if (newCode == -1)
3519*fd1fabb7SAndroid Build Coastguard Worker 				{
3520*fd1fabb7SAndroid Build Coastguard Worker 
3521*fd1fabb7SAndroid Build Coastguard Worker 				PutCodeWord (code);
3522*fd1fabb7SAndroid Build Coastguard Worker 
3523*fd1fabb7SAndroid Build Coastguard Worker 				if (fNextCode < 4093)
3524*fd1fabb7SAndroid Build Coastguard Worker 					{
3525*fd1fabb7SAndroid Build Coastguard Worker 					AddTable (code, pixel);
3526*fd1fabb7SAndroid Build Coastguard Worker 					}
3527*fd1fabb7SAndroid Build Coastguard Worker 				else
3528*fd1fabb7SAndroid Build Coastguard Worker 					{
3529*fd1fabb7SAndroid Build Coastguard Worker 					PutCodeWord (kResetCode);
3530*fd1fabb7SAndroid Build Coastguard Worker 					InitTable ();
3531*fd1fabb7SAndroid Build Coastguard Worker 					}
3532*fd1fabb7SAndroid Build Coastguard Worker 
3533*fd1fabb7SAndroid Build Coastguard Worker 				code = pixel;
3534*fd1fabb7SAndroid Build Coastguard Worker 
3535*fd1fabb7SAndroid Build Coastguard Worker 				}
3536*fd1fabb7SAndroid Build Coastguard Worker 
3537*fd1fabb7SAndroid Build Coastguard Worker 			else
3538*fd1fabb7SAndroid Build Coastguard Worker 				code = newCode;
3539*fd1fabb7SAndroid Build Coastguard Worker 
3540*fd1fabb7SAndroid Build Coastguard Worker 			}
3541*fd1fabb7SAndroid Build Coastguard Worker 
3542*fd1fabb7SAndroid Build Coastguard Worker 		}
3543*fd1fabb7SAndroid Build Coastguard Worker 
3544*fd1fabb7SAndroid Build Coastguard Worker 	if (code != -1)
3545*fd1fabb7SAndroid Build Coastguard Worker 		{
3546*fd1fabb7SAndroid Build Coastguard Worker 		PutCodeWord (code);
3547*fd1fabb7SAndroid Build Coastguard Worker 		AddTable (code, 0);
3548*fd1fabb7SAndroid Build Coastguard Worker 		}
3549*fd1fabb7SAndroid Build Coastguard Worker 
3550*fd1fabb7SAndroid Build Coastguard Worker 	PutCodeWord (kEndCode);
3551*fd1fabb7SAndroid Build Coastguard Worker 
3552*fd1fabb7SAndroid Build Coastguard Worker 	dCount = (fBitOffset + 7) >> 3;
3553*fd1fabb7SAndroid Build Coastguard Worker 
3554*fd1fabb7SAndroid Build Coastguard Worker 	}
3555*fd1fabb7SAndroid Build Coastguard Worker 
3556*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3557*fd1fabb7SAndroid Build Coastguard Worker 
3558*fd1fabb7SAndroid Build Coastguard Worker #if qDNGUseLibJPEG
3559*fd1fabb7SAndroid Build Coastguard Worker 
3560*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3561*fd1fabb7SAndroid Build Coastguard Worker 
dng_error_exit(j_common_ptr cinfo)3562*fd1fabb7SAndroid Build Coastguard Worker static void dng_error_exit (j_common_ptr cinfo)
3563*fd1fabb7SAndroid Build Coastguard Worker 	{
3564*fd1fabb7SAndroid Build Coastguard Worker 
3565*fd1fabb7SAndroid Build Coastguard Worker 	// Output message.
3566*fd1fabb7SAndroid Build Coastguard Worker 
3567*fd1fabb7SAndroid Build Coastguard Worker 	(*cinfo->err->output_message) (cinfo);
3568*fd1fabb7SAndroid Build Coastguard Worker 
3569*fd1fabb7SAndroid Build Coastguard Worker 	// Convert to a dng_exception.
3570*fd1fabb7SAndroid Build Coastguard Worker 
3571*fd1fabb7SAndroid Build Coastguard Worker 	switch (cinfo->err->msg_code)
3572*fd1fabb7SAndroid Build Coastguard Worker 		{
3573*fd1fabb7SAndroid Build Coastguard Worker 
3574*fd1fabb7SAndroid Build Coastguard Worker 		case JERR_OUT_OF_MEMORY:
3575*fd1fabb7SAndroid Build Coastguard Worker 			{
3576*fd1fabb7SAndroid Build Coastguard Worker 			ThrowMemoryFull ();
3577*fd1fabb7SAndroid Build Coastguard Worker 			break;
3578*fd1fabb7SAndroid Build Coastguard Worker 			}
3579*fd1fabb7SAndroid Build Coastguard Worker 
3580*fd1fabb7SAndroid Build Coastguard Worker 		default:
3581*fd1fabb7SAndroid Build Coastguard Worker 			{
3582*fd1fabb7SAndroid Build Coastguard Worker 			ThrowBadFormat ();
3583*fd1fabb7SAndroid Build Coastguard Worker 			}
3584*fd1fabb7SAndroid Build Coastguard Worker 
3585*fd1fabb7SAndroid Build Coastguard Worker 		}
3586*fd1fabb7SAndroid Build Coastguard Worker 
3587*fd1fabb7SAndroid Build Coastguard Worker 	}
3588*fd1fabb7SAndroid Build Coastguard Worker 
3589*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3590*fd1fabb7SAndroid Build Coastguard Worker 
dng_output_message(j_common_ptr cinfo)3591*fd1fabb7SAndroid Build Coastguard Worker static void dng_output_message (j_common_ptr cinfo)
3592*fd1fabb7SAndroid Build Coastguard Worker 	{
3593*fd1fabb7SAndroid Build Coastguard Worker 
3594*fd1fabb7SAndroid Build Coastguard Worker 	// Format message to string.
3595*fd1fabb7SAndroid Build Coastguard Worker 
3596*fd1fabb7SAndroid Build Coastguard Worker 	char buffer [JMSG_LENGTH_MAX];
3597*fd1fabb7SAndroid Build Coastguard Worker 
3598*fd1fabb7SAndroid Build Coastguard Worker 	(*cinfo->err->format_message) (cinfo, buffer);
3599*fd1fabb7SAndroid Build Coastguard Worker 
3600*fd1fabb7SAndroid Build Coastguard Worker 	// Report the libjpeg message as a warning.
3601*fd1fabb7SAndroid Build Coastguard Worker 
3602*fd1fabb7SAndroid Build Coastguard Worker 	ReportWarning ("libjpeg", buffer);
3603*fd1fabb7SAndroid Build Coastguard Worker 
3604*fd1fabb7SAndroid Build Coastguard Worker 	}
3605*fd1fabb7SAndroid Build Coastguard Worker 
3606*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3607*fd1fabb7SAndroid Build Coastguard Worker 
3608*fd1fabb7SAndroid Build Coastguard Worker struct dng_jpeg_stream_dest
3609*fd1fabb7SAndroid Build Coastguard Worker 	{
3610*fd1fabb7SAndroid Build Coastguard Worker 
3611*fd1fabb7SAndroid Build Coastguard Worker 	struct jpeg_destination_mgr pub;
3612*fd1fabb7SAndroid Build Coastguard Worker 
3613*fd1fabb7SAndroid Build Coastguard Worker 	dng_stream *fStream;
3614*fd1fabb7SAndroid Build Coastguard Worker 
3615*fd1fabb7SAndroid Build Coastguard Worker 	uint8 fBuffer [4096];
3616*fd1fabb7SAndroid Build Coastguard Worker 
3617*fd1fabb7SAndroid Build Coastguard Worker 	};
3618*fd1fabb7SAndroid Build Coastguard Worker 
3619*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3620*fd1fabb7SAndroid Build Coastguard Worker 
dng_init_destination(j_compress_ptr cinfo)3621*fd1fabb7SAndroid Build Coastguard Worker static void dng_init_destination (j_compress_ptr cinfo)
3622*fd1fabb7SAndroid Build Coastguard Worker 	{
3623*fd1fabb7SAndroid Build Coastguard Worker 
3624*fd1fabb7SAndroid Build Coastguard Worker 	dng_jpeg_stream_dest *dest = (dng_jpeg_stream_dest *) cinfo->dest;
3625*fd1fabb7SAndroid Build Coastguard Worker 
3626*fd1fabb7SAndroid Build Coastguard Worker 	dest->pub.next_output_byte = dest->fBuffer;
3627*fd1fabb7SAndroid Build Coastguard Worker 	dest->pub.free_in_buffer   = sizeof (dest->fBuffer);
3628*fd1fabb7SAndroid Build Coastguard Worker 
3629*fd1fabb7SAndroid Build Coastguard Worker 	}
3630*fd1fabb7SAndroid Build Coastguard Worker 
3631*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3632*fd1fabb7SAndroid Build Coastguard Worker 
dng_empty_output_buffer(j_compress_ptr cinfo)3633*fd1fabb7SAndroid Build Coastguard Worker static boolean dng_empty_output_buffer (j_compress_ptr cinfo)
3634*fd1fabb7SAndroid Build Coastguard Worker 	{
3635*fd1fabb7SAndroid Build Coastguard Worker 
3636*fd1fabb7SAndroid Build Coastguard Worker 	dng_jpeg_stream_dest *dest = (dng_jpeg_stream_dest *) cinfo->dest;
3637*fd1fabb7SAndroid Build Coastguard Worker 
3638*fd1fabb7SAndroid Build Coastguard Worker 	dest->fStream->Put (dest->fBuffer, sizeof (dest->fBuffer));
3639*fd1fabb7SAndroid Build Coastguard Worker 
3640*fd1fabb7SAndroid Build Coastguard Worker 	dest->pub.next_output_byte = dest->fBuffer;
3641*fd1fabb7SAndroid Build Coastguard Worker 	dest->pub.free_in_buffer   = sizeof (dest->fBuffer);
3642*fd1fabb7SAndroid Build Coastguard Worker 
3643*fd1fabb7SAndroid Build Coastguard Worker 	return TRUE;
3644*fd1fabb7SAndroid Build Coastguard Worker 
3645*fd1fabb7SAndroid Build Coastguard Worker 	}
3646*fd1fabb7SAndroid Build Coastguard Worker 
3647*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3648*fd1fabb7SAndroid Build Coastguard Worker 
dng_term_destination(j_compress_ptr cinfo)3649*fd1fabb7SAndroid Build Coastguard Worker static void dng_term_destination (j_compress_ptr cinfo)
3650*fd1fabb7SAndroid Build Coastguard Worker 	{
3651*fd1fabb7SAndroid Build Coastguard Worker 
3652*fd1fabb7SAndroid Build Coastguard Worker 	dng_jpeg_stream_dest *dest = (dng_jpeg_stream_dest *) cinfo->dest;
3653*fd1fabb7SAndroid Build Coastguard Worker 
3654*fd1fabb7SAndroid Build Coastguard Worker 	uint32 datacount = sizeof (dest->fBuffer) -
3655*fd1fabb7SAndroid Build Coastguard Worker 					   (uint32) dest->pub.free_in_buffer;
3656*fd1fabb7SAndroid Build Coastguard Worker 
3657*fd1fabb7SAndroid Build Coastguard Worker 	if (datacount)
3658*fd1fabb7SAndroid Build Coastguard Worker 		{
3659*fd1fabb7SAndroid Build Coastguard Worker 		dest->fStream->Put (dest->fBuffer, datacount);
3660*fd1fabb7SAndroid Build Coastguard Worker 		}
3661*fd1fabb7SAndroid Build Coastguard Worker 
3662*fd1fabb7SAndroid Build Coastguard Worker 	}
3663*fd1fabb7SAndroid Build Coastguard Worker 
3664*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3665*fd1fabb7SAndroid Build Coastguard Worker 
jpeg_set_adobe_quality(struct jpeg_compress_struct * cinfo,int32 quality)3666*fd1fabb7SAndroid Build Coastguard Worker static void jpeg_set_adobe_quality (struct jpeg_compress_struct *cinfo,
3667*fd1fabb7SAndroid Build Coastguard Worker 									int32 quality)
3668*fd1fabb7SAndroid Build Coastguard Worker 	{
3669*fd1fabb7SAndroid Build Coastguard Worker 
3670*fd1fabb7SAndroid Build Coastguard Worker 	// If out of range, map to default.
3671*fd1fabb7SAndroid Build Coastguard Worker 
3672*fd1fabb7SAndroid Build Coastguard Worker 	if (quality < 0 || quality > 12)
3673*fd1fabb7SAndroid Build Coastguard Worker 		{
3674*fd1fabb7SAndroid Build Coastguard Worker 		quality = 10;
3675*fd1fabb7SAndroid Build Coastguard Worker 		}
3676*fd1fabb7SAndroid Build Coastguard Worker 
3677*fd1fabb7SAndroid Build Coastguard Worker 	// Adobe turns off chroma downsampling at high quality levels.
3678*fd1fabb7SAndroid Build Coastguard Worker 
3679*fd1fabb7SAndroid Build Coastguard Worker 	bool useChromaDownsampling = (quality <= 6);
3680*fd1fabb7SAndroid Build Coastguard Worker 
3681*fd1fabb7SAndroid Build Coastguard Worker 	// Approximate mapping from Adobe quality levels to LibJPEG levels.
3682*fd1fabb7SAndroid Build Coastguard Worker 
3683*fd1fabb7SAndroid Build Coastguard Worker 	const int kLibJPEGQuality [13] =
3684*fd1fabb7SAndroid Build Coastguard Worker 		{
3685*fd1fabb7SAndroid Build Coastguard Worker 		5, 11, 23, 34, 46, 63, 76, 77, 86, 90, 94, 97, 99
3686*fd1fabb7SAndroid Build Coastguard Worker 		};
3687*fd1fabb7SAndroid Build Coastguard Worker 
3688*fd1fabb7SAndroid Build Coastguard Worker 	quality = kLibJPEGQuality [quality];
3689*fd1fabb7SAndroid Build Coastguard Worker 
3690*fd1fabb7SAndroid Build Coastguard Worker 	jpeg_set_quality (cinfo, quality, TRUE);
3691*fd1fabb7SAndroid Build Coastguard Worker 
3692*fd1fabb7SAndroid Build Coastguard Worker 	// LibJPEG defaults to always using chroma downsampling.  Turn if off
3693*fd1fabb7SAndroid Build Coastguard Worker 	// if we need it off to match Adobe.
3694*fd1fabb7SAndroid Build Coastguard Worker 
3695*fd1fabb7SAndroid Build Coastguard Worker 	if (!useChromaDownsampling)
3696*fd1fabb7SAndroid Build Coastguard Worker 		{
3697*fd1fabb7SAndroid Build Coastguard Worker 
3698*fd1fabb7SAndroid Build Coastguard Worker 		cinfo->comp_info [0].h_samp_factor = 1;
3699*fd1fabb7SAndroid Build Coastguard Worker 		cinfo->comp_info [0].h_samp_factor = 1;
3700*fd1fabb7SAndroid Build Coastguard Worker 
3701*fd1fabb7SAndroid Build Coastguard Worker 		}
3702*fd1fabb7SAndroid Build Coastguard Worker 
3703*fd1fabb7SAndroid Build Coastguard Worker 	}
3704*fd1fabb7SAndroid Build Coastguard Worker 
3705*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3706*fd1fabb7SAndroid Build Coastguard Worker 
3707*fd1fabb7SAndroid Build Coastguard Worker #endif
3708*fd1fabb7SAndroid Build Coastguard Worker 
3709*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
3710*fd1fabb7SAndroid Build Coastguard Worker 
WriteData(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_pixel_buffer & buffer,AutoPtr<dng_memory_block> & compressedBuffer)3711*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::WriteData (dng_host &host,
3712*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_ifd &ifd,
3713*fd1fabb7SAndroid Build Coastguard Worker 						          dng_stream &stream,
3714*fd1fabb7SAndroid Build Coastguard Worker 						          dng_pixel_buffer &buffer,
3715*fd1fabb7SAndroid Build Coastguard Worker 								  AutoPtr<dng_memory_block> &compressedBuffer)
3716*fd1fabb7SAndroid Build Coastguard Worker 	{
3717*fd1fabb7SAndroid Build Coastguard Worker 
3718*fd1fabb7SAndroid Build Coastguard Worker 	switch (ifd.fCompression)
3719*fd1fabb7SAndroid Build Coastguard Worker 		{
3720*fd1fabb7SAndroid Build Coastguard Worker 
3721*fd1fabb7SAndroid Build Coastguard Worker 		case ccUncompressed:
3722*fd1fabb7SAndroid Build Coastguard Worker 			{
3723*fd1fabb7SAndroid Build Coastguard Worker 
3724*fd1fabb7SAndroid Build Coastguard Worker 			// Special case support for when we save to 8-bits from
3725*fd1fabb7SAndroid Build Coastguard Worker 			// 16-bit data.
3726*fd1fabb7SAndroid Build Coastguard Worker 
3727*fd1fabb7SAndroid Build Coastguard Worker 			if (ifd.fBitsPerSample [0] == 8 && buffer.fPixelType == ttShort)
3728*fd1fabb7SAndroid Build Coastguard Worker 				{
3729*fd1fabb7SAndroid Build Coastguard Worker 
3730*fd1fabb7SAndroid Build Coastguard Worker 				uint32 count = buffer.fRowStep *
3731*fd1fabb7SAndroid Build Coastguard Worker 							   buffer.fArea.H ();
3732*fd1fabb7SAndroid Build Coastguard Worker 
3733*fd1fabb7SAndroid Build Coastguard Worker 				const uint16 *sPtr = (const uint16 *) buffer.fData;
3734*fd1fabb7SAndroid Build Coastguard Worker 
3735*fd1fabb7SAndroid Build Coastguard Worker 				for (uint32 j = 0; j < count; j++)
3736*fd1fabb7SAndroid Build Coastguard Worker 					{
3737*fd1fabb7SAndroid Build Coastguard Worker 
3738*fd1fabb7SAndroid Build Coastguard Worker 					stream.Put_uint8 ((uint8) sPtr [j]);
3739*fd1fabb7SAndroid Build Coastguard Worker 
3740*fd1fabb7SAndroid Build Coastguard Worker 					}
3741*fd1fabb7SAndroid Build Coastguard Worker 
3742*fd1fabb7SAndroid Build Coastguard Worker 				}
3743*fd1fabb7SAndroid Build Coastguard Worker 
3744*fd1fabb7SAndroid Build Coastguard Worker 			else
3745*fd1fabb7SAndroid Build Coastguard Worker 				{
3746*fd1fabb7SAndroid Build Coastguard Worker 
3747*fd1fabb7SAndroid Build Coastguard Worker 				// Swap bytes if required.
3748*fd1fabb7SAndroid Build Coastguard Worker 
3749*fd1fabb7SAndroid Build Coastguard Worker 				if (stream.SwapBytes ())
3750*fd1fabb7SAndroid Build Coastguard Worker 					{
3751*fd1fabb7SAndroid Build Coastguard Worker 
3752*fd1fabb7SAndroid Build Coastguard Worker 					ByteSwapBuffer (host, buffer);
3753*fd1fabb7SAndroid Build Coastguard Worker 
3754*fd1fabb7SAndroid Build Coastguard Worker 					}
3755*fd1fabb7SAndroid Build Coastguard Worker 
3756*fd1fabb7SAndroid Build Coastguard Worker 				// Write the bytes.
3757*fd1fabb7SAndroid Build Coastguard Worker 
3758*fd1fabb7SAndroid Build Coastguard Worker 				stream.Put (buffer.fData, buffer.fRowStep *
3759*fd1fabb7SAndroid Build Coastguard Worker 										  buffer.fArea.H () *
3760*fd1fabb7SAndroid Build Coastguard Worker 										  buffer.fPixelSize);
3761*fd1fabb7SAndroid Build Coastguard Worker 
3762*fd1fabb7SAndroid Build Coastguard Worker 				}
3763*fd1fabb7SAndroid Build Coastguard Worker 
3764*fd1fabb7SAndroid Build Coastguard Worker 			break;
3765*fd1fabb7SAndroid Build Coastguard Worker 
3766*fd1fabb7SAndroid Build Coastguard Worker 			}
3767*fd1fabb7SAndroid Build Coastguard Worker 
3768*fd1fabb7SAndroid Build Coastguard Worker 		case ccLZW:
3769*fd1fabb7SAndroid Build Coastguard Worker 		case ccDeflate:
3770*fd1fabb7SAndroid Build Coastguard Worker 			{
3771*fd1fabb7SAndroid Build Coastguard Worker 
3772*fd1fabb7SAndroid Build Coastguard Worker 			// Both these compression algorithms are byte based.  The floating
3773*fd1fabb7SAndroid Build Coastguard Worker 			// point predictor already does byte ordering, so don't ever swap
3774*fd1fabb7SAndroid Build Coastguard Worker 			// when using it.
3775*fd1fabb7SAndroid Build Coastguard Worker 
3776*fd1fabb7SAndroid Build Coastguard Worker 			if (stream.SwapBytes () && ifd.fPredictor != cpFloatingPoint)
3777*fd1fabb7SAndroid Build Coastguard Worker 				{
3778*fd1fabb7SAndroid Build Coastguard Worker 
3779*fd1fabb7SAndroid Build Coastguard Worker 				ByteSwapBuffer (host,
3780*fd1fabb7SAndroid Build Coastguard Worker 								buffer);
3781*fd1fabb7SAndroid Build Coastguard Worker 
3782*fd1fabb7SAndroid Build Coastguard Worker 				}
3783*fd1fabb7SAndroid Build Coastguard Worker 
3784*fd1fabb7SAndroid Build Coastguard Worker 			// Run the compression algorithm.
3785*fd1fabb7SAndroid Build Coastguard Worker 
3786*fd1fabb7SAndroid Build Coastguard Worker 			uint32 sBytes = buffer.fRowStep *
3787*fd1fabb7SAndroid Build Coastguard Worker 							buffer.fArea.H () *
3788*fd1fabb7SAndroid Build Coastguard Worker 							buffer.fPixelSize;
3789*fd1fabb7SAndroid Build Coastguard Worker 
3790*fd1fabb7SAndroid Build Coastguard Worker 			uint8 *sBuffer = (uint8 *) buffer.fData;
3791*fd1fabb7SAndroid Build Coastguard Worker 
3792*fd1fabb7SAndroid Build Coastguard Worker 			uint32 dBytes = 0;
3793*fd1fabb7SAndroid Build Coastguard Worker 
3794*fd1fabb7SAndroid Build Coastguard Worker 			uint8 *dBuffer = compressedBuffer->Buffer_uint8 ();
3795*fd1fabb7SAndroid Build Coastguard Worker 
3796*fd1fabb7SAndroid Build Coastguard Worker 			if (ifd.fCompression == ccLZW)
3797*fd1fabb7SAndroid Build Coastguard Worker 				{
3798*fd1fabb7SAndroid Build Coastguard Worker 
3799*fd1fabb7SAndroid Build Coastguard Worker 				dng_lzw_compressor lzwCompressor;
3800*fd1fabb7SAndroid Build Coastguard Worker 
3801*fd1fabb7SAndroid Build Coastguard Worker 				lzwCompressor.Compress (sBuffer,
3802*fd1fabb7SAndroid Build Coastguard Worker 										dBuffer,
3803*fd1fabb7SAndroid Build Coastguard Worker 										sBytes,
3804*fd1fabb7SAndroid Build Coastguard Worker 										dBytes);
3805*fd1fabb7SAndroid Build Coastguard Worker 
3806*fd1fabb7SAndroid Build Coastguard Worker 				}
3807*fd1fabb7SAndroid Build Coastguard Worker 
3808*fd1fabb7SAndroid Build Coastguard Worker 			else
3809*fd1fabb7SAndroid Build Coastguard Worker 				{
3810*fd1fabb7SAndroid Build Coastguard Worker 
3811*fd1fabb7SAndroid Build Coastguard Worker 				uLongf dCount = compressedBuffer->LogicalSize ();
3812*fd1fabb7SAndroid Build Coastguard Worker 
3813*fd1fabb7SAndroid Build Coastguard Worker 				int32 level = Z_DEFAULT_COMPRESSION;
3814*fd1fabb7SAndroid Build Coastguard Worker 
3815*fd1fabb7SAndroid Build Coastguard Worker 				if (ifd.fCompressionQuality >= Z_BEST_SPEED &&
3816*fd1fabb7SAndroid Build Coastguard Worker 					ifd.fCompressionQuality <= Z_BEST_COMPRESSION)
3817*fd1fabb7SAndroid Build Coastguard Worker 					{
3818*fd1fabb7SAndroid Build Coastguard Worker 
3819*fd1fabb7SAndroid Build Coastguard Worker 					level = ifd.fCompressionQuality;
3820*fd1fabb7SAndroid Build Coastguard Worker 
3821*fd1fabb7SAndroid Build Coastguard Worker 					}
3822*fd1fabb7SAndroid Build Coastguard Worker 
3823*fd1fabb7SAndroid Build Coastguard Worker 				int zResult = ::compress2 (dBuffer,
3824*fd1fabb7SAndroid Build Coastguard Worker 										   &dCount,
3825*fd1fabb7SAndroid Build Coastguard Worker 										   sBuffer,
3826*fd1fabb7SAndroid Build Coastguard Worker 										   sBytes,
3827*fd1fabb7SAndroid Build Coastguard Worker 										   level);
3828*fd1fabb7SAndroid Build Coastguard Worker 
3829*fd1fabb7SAndroid Build Coastguard Worker 				if (zResult != Z_OK)
3830*fd1fabb7SAndroid Build Coastguard Worker 					{
3831*fd1fabb7SAndroid Build Coastguard Worker 
3832*fd1fabb7SAndroid Build Coastguard Worker 					ThrowMemoryFull ();
3833*fd1fabb7SAndroid Build Coastguard Worker 
3834*fd1fabb7SAndroid Build Coastguard Worker 					}
3835*fd1fabb7SAndroid Build Coastguard Worker 
3836*fd1fabb7SAndroid Build Coastguard Worker 				dBytes = (uint32) dCount;
3837*fd1fabb7SAndroid Build Coastguard Worker 
3838*fd1fabb7SAndroid Build Coastguard Worker 				}
3839*fd1fabb7SAndroid Build Coastguard Worker 
3840*fd1fabb7SAndroid Build Coastguard Worker 			if (dBytes > compressedBuffer->LogicalSize ())
3841*fd1fabb7SAndroid Build Coastguard Worker 				{
3842*fd1fabb7SAndroid Build Coastguard Worker 
3843*fd1fabb7SAndroid Build Coastguard Worker 				DNG_REPORT ("Compression output buffer overflow");
3844*fd1fabb7SAndroid Build Coastguard Worker 
3845*fd1fabb7SAndroid Build Coastguard Worker 				ThrowProgramError ();
3846*fd1fabb7SAndroid Build Coastguard Worker 
3847*fd1fabb7SAndroid Build Coastguard Worker 				}
3848*fd1fabb7SAndroid Build Coastguard Worker 
3849*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put (dBuffer, dBytes);
3850*fd1fabb7SAndroid Build Coastguard Worker 
3851*fd1fabb7SAndroid Build Coastguard Worker 			return;
3852*fd1fabb7SAndroid Build Coastguard Worker 
3853*fd1fabb7SAndroid Build Coastguard Worker 			}
3854*fd1fabb7SAndroid Build Coastguard Worker 
3855*fd1fabb7SAndroid Build Coastguard Worker 		case ccJPEG:
3856*fd1fabb7SAndroid Build Coastguard Worker 			{
3857*fd1fabb7SAndroid Build Coastguard Worker 
3858*fd1fabb7SAndroid Build Coastguard Worker 			dng_pixel_buffer temp (buffer);
3859*fd1fabb7SAndroid Build Coastguard Worker 
3860*fd1fabb7SAndroid Build Coastguard Worker 			if (buffer.fPixelType == ttByte)
3861*fd1fabb7SAndroid Build Coastguard Worker 				{
3862*fd1fabb7SAndroid Build Coastguard Worker 
3863*fd1fabb7SAndroid Build Coastguard Worker 				// The lossless JPEG encoder needs 16-bit data, so if we are
3864*fd1fabb7SAndroid Build Coastguard Worker 				// are saving 8 bit data, we need to pad it out to 16-bits.
3865*fd1fabb7SAndroid Build Coastguard Worker 
3866*fd1fabb7SAndroid Build Coastguard Worker 				temp.fData = compressedBuffer->Buffer ();
3867*fd1fabb7SAndroid Build Coastguard Worker 
3868*fd1fabb7SAndroid Build Coastguard Worker 				temp.fPixelType = ttShort;
3869*fd1fabb7SAndroid Build Coastguard Worker 				temp.fPixelSize = 2;
3870*fd1fabb7SAndroid Build Coastguard Worker 
3871*fd1fabb7SAndroid Build Coastguard Worker 				temp.CopyArea (buffer,
3872*fd1fabb7SAndroid Build Coastguard Worker 							   buffer.fArea,
3873*fd1fabb7SAndroid Build Coastguard Worker 							   buffer.fPlane,
3874*fd1fabb7SAndroid Build Coastguard Worker 							   buffer.fPlanes);
3875*fd1fabb7SAndroid Build Coastguard Worker 
3876*fd1fabb7SAndroid Build Coastguard Worker 				}
3877*fd1fabb7SAndroid Build Coastguard Worker 
3878*fd1fabb7SAndroid Build Coastguard Worker 			EncodeLosslessJPEG ((const uint16 *) temp.fData,
3879*fd1fabb7SAndroid Build Coastguard Worker 								temp.fArea.H (),
3880*fd1fabb7SAndroid Build Coastguard Worker 								temp.fArea.W (),
3881*fd1fabb7SAndroid Build Coastguard Worker 								temp.fPlanes,
3882*fd1fabb7SAndroid Build Coastguard Worker 								ifd.fBitsPerSample [0],
3883*fd1fabb7SAndroid Build Coastguard Worker 								temp.fRowStep,
3884*fd1fabb7SAndroid Build Coastguard Worker 								temp.fColStep,
3885*fd1fabb7SAndroid Build Coastguard Worker 								stream);
3886*fd1fabb7SAndroid Build Coastguard Worker 
3887*fd1fabb7SAndroid Build Coastguard Worker 			break;
3888*fd1fabb7SAndroid Build Coastguard Worker 
3889*fd1fabb7SAndroid Build Coastguard Worker 			}
3890*fd1fabb7SAndroid Build Coastguard Worker 
3891*fd1fabb7SAndroid Build Coastguard Worker 		#if qDNGUseLibJPEG
3892*fd1fabb7SAndroid Build Coastguard Worker 
3893*fd1fabb7SAndroid Build Coastguard Worker 		case ccLossyJPEG:
3894*fd1fabb7SAndroid Build Coastguard Worker 			{
3895*fd1fabb7SAndroid Build Coastguard Worker 
3896*fd1fabb7SAndroid Build Coastguard Worker 			struct jpeg_compress_struct cinfo;
3897*fd1fabb7SAndroid Build Coastguard Worker 
3898*fd1fabb7SAndroid Build Coastguard Worker 			// Setup the error manager.
3899*fd1fabb7SAndroid Build Coastguard Worker 
3900*fd1fabb7SAndroid Build Coastguard Worker 			struct jpeg_error_mgr jerr;
3901*fd1fabb7SAndroid Build Coastguard Worker 
3902*fd1fabb7SAndroid Build Coastguard Worker 			cinfo.err = jpeg_std_error (&jerr);
3903*fd1fabb7SAndroid Build Coastguard Worker 
3904*fd1fabb7SAndroid Build Coastguard Worker 			jerr.error_exit     = dng_error_exit;
3905*fd1fabb7SAndroid Build Coastguard Worker 			jerr.output_message = dng_output_message;
3906*fd1fabb7SAndroid Build Coastguard Worker 
3907*fd1fabb7SAndroid Build Coastguard Worker 			try
3908*fd1fabb7SAndroid Build Coastguard Worker 				{
3909*fd1fabb7SAndroid Build Coastguard Worker 
3910*fd1fabb7SAndroid Build Coastguard Worker 				// Create the compression context.
3911*fd1fabb7SAndroid Build Coastguard Worker 
3912*fd1fabb7SAndroid Build Coastguard Worker 				jpeg_create_compress (&cinfo);
3913*fd1fabb7SAndroid Build Coastguard Worker 
3914*fd1fabb7SAndroid Build Coastguard Worker 				// Setup the destination manager to write to stream.
3915*fd1fabb7SAndroid Build Coastguard Worker 
3916*fd1fabb7SAndroid Build Coastguard Worker 				dng_jpeg_stream_dest dest;
3917*fd1fabb7SAndroid Build Coastguard Worker 
3918*fd1fabb7SAndroid Build Coastguard Worker 				dest.fStream = &stream;
3919*fd1fabb7SAndroid Build Coastguard Worker 
3920*fd1fabb7SAndroid Build Coastguard Worker 				dest.pub.init_destination    = dng_init_destination;
3921*fd1fabb7SAndroid Build Coastguard Worker 				dest.pub.empty_output_buffer = dng_empty_output_buffer;
3922*fd1fabb7SAndroid Build Coastguard Worker 				dest.pub.term_destination    = dng_term_destination;
3923*fd1fabb7SAndroid Build Coastguard Worker 
3924*fd1fabb7SAndroid Build Coastguard Worker 				cinfo.dest = &dest.pub;
3925*fd1fabb7SAndroid Build Coastguard Worker 
3926*fd1fabb7SAndroid Build Coastguard Worker 				// Setup basic image info.
3927*fd1fabb7SAndroid Build Coastguard Worker 
3928*fd1fabb7SAndroid Build Coastguard Worker 				cinfo.image_width      = buffer.fArea.W ();
3929*fd1fabb7SAndroid Build Coastguard Worker 				cinfo.image_height     = buffer.fArea.H ();
3930*fd1fabb7SAndroid Build Coastguard Worker 				cinfo.input_components = buffer.fPlanes;
3931*fd1fabb7SAndroid Build Coastguard Worker 
3932*fd1fabb7SAndroid Build Coastguard Worker 				switch (buffer.fPlanes)
3933*fd1fabb7SAndroid Build Coastguard Worker 					{
3934*fd1fabb7SAndroid Build Coastguard Worker 
3935*fd1fabb7SAndroid Build Coastguard Worker 					case 1:
3936*fd1fabb7SAndroid Build Coastguard Worker 						cinfo.in_color_space = JCS_GRAYSCALE;
3937*fd1fabb7SAndroid Build Coastguard Worker 						break;
3938*fd1fabb7SAndroid Build Coastguard Worker 
3939*fd1fabb7SAndroid Build Coastguard Worker 					case 3:
3940*fd1fabb7SAndroid Build Coastguard Worker 						cinfo.in_color_space = JCS_RGB;
3941*fd1fabb7SAndroid Build Coastguard Worker 						break;
3942*fd1fabb7SAndroid Build Coastguard Worker 
3943*fd1fabb7SAndroid Build Coastguard Worker 					case 4:
3944*fd1fabb7SAndroid Build Coastguard Worker 						cinfo.in_color_space = JCS_CMYK;
3945*fd1fabb7SAndroid Build Coastguard Worker 						break;
3946*fd1fabb7SAndroid Build Coastguard Worker 
3947*fd1fabb7SAndroid Build Coastguard Worker 					default:
3948*fd1fabb7SAndroid Build Coastguard Worker 						ThrowProgramError ();
3949*fd1fabb7SAndroid Build Coastguard Worker 
3950*fd1fabb7SAndroid Build Coastguard Worker 					}
3951*fd1fabb7SAndroid Build Coastguard Worker 
3952*fd1fabb7SAndroid Build Coastguard Worker 				// Setup the compression parameters.
3953*fd1fabb7SAndroid Build Coastguard Worker 
3954*fd1fabb7SAndroid Build Coastguard Worker 				jpeg_set_defaults (&cinfo);
3955*fd1fabb7SAndroid Build Coastguard Worker 
3956*fd1fabb7SAndroid Build Coastguard Worker 				jpeg_set_adobe_quality (&cinfo, ifd.fCompressionQuality);
3957*fd1fabb7SAndroid Build Coastguard Worker 
3958*fd1fabb7SAndroid Build Coastguard Worker 				// Write the JPEG header.
3959*fd1fabb7SAndroid Build Coastguard Worker 
3960*fd1fabb7SAndroid Build Coastguard Worker 				jpeg_start_compress (&cinfo, TRUE);
3961*fd1fabb7SAndroid Build Coastguard Worker 
3962*fd1fabb7SAndroid Build Coastguard Worker 				// Write the scanlines.
3963*fd1fabb7SAndroid Build Coastguard Worker 
3964*fd1fabb7SAndroid Build Coastguard Worker 				for (int32 row = buffer.fArea.t; row < buffer.fArea.b; row++)
3965*fd1fabb7SAndroid Build Coastguard Worker 					{
3966*fd1fabb7SAndroid Build Coastguard Worker 
3967*fd1fabb7SAndroid Build Coastguard Worker 					uint8 *sampArray [1];
3968*fd1fabb7SAndroid Build Coastguard Worker 
3969*fd1fabb7SAndroid Build Coastguard Worker 					sampArray [0] = buffer.DirtyPixel_uint8 (row,
3970*fd1fabb7SAndroid Build Coastguard Worker 															 buffer.fArea.l,
3971*fd1fabb7SAndroid Build Coastguard Worker 															 0);
3972*fd1fabb7SAndroid Build Coastguard Worker 
3973*fd1fabb7SAndroid Build Coastguard Worker 					jpeg_write_scanlines (&cinfo, sampArray, 1);
3974*fd1fabb7SAndroid Build Coastguard Worker 
3975*fd1fabb7SAndroid Build Coastguard Worker 					}
3976*fd1fabb7SAndroid Build Coastguard Worker 
3977*fd1fabb7SAndroid Build Coastguard Worker 				// Cleanup.
3978*fd1fabb7SAndroid Build Coastguard Worker 
3979*fd1fabb7SAndroid Build Coastguard Worker 				jpeg_finish_compress (&cinfo);
3980*fd1fabb7SAndroid Build Coastguard Worker 
3981*fd1fabb7SAndroid Build Coastguard Worker 				jpeg_destroy_compress (&cinfo);
3982*fd1fabb7SAndroid Build Coastguard Worker 
3983*fd1fabb7SAndroid Build Coastguard Worker 				}
3984*fd1fabb7SAndroid Build Coastguard Worker 
3985*fd1fabb7SAndroid Build Coastguard Worker 			catch (...)
3986*fd1fabb7SAndroid Build Coastguard Worker 				{
3987*fd1fabb7SAndroid Build Coastguard Worker 
3988*fd1fabb7SAndroid Build Coastguard Worker 				jpeg_destroy_compress (&cinfo);
3989*fd1fabb7SAndroid Build Coastguard Worker 
3990*fd1fabb7SAndroid Build Coastguard Worker 				throw;
3991*fd1fabb7SAndroid Build Coastguard Worker 
3992*fd1fabb7SAndroid Build Coastguard Worker 				}
3993*fd1fabb7SAndroid Build Coastguard Worker 
3994*fd1fabb7SAndroid Build Coastguard Worker 			return;
3995*fd1fabb7SAndroid Build Coastguard Worker 
3996*fd1fabb7SAndroid Build Coastguard Worker 			}
3997*fd1fabb7SAndroid Build Coastguard Worker 
3998*fd1fabb7SAndroid Build Coastguard Worker 		#endif
3999*fd1fabb7SAndroid Build Coastguard Worker 
4000*fd1fabb7SAndroid Build Coastguard Worker 		default:
4001*fd1fabb7SAndroid Build Coastguard Worker 			{
4002*fd1fabb7SAndroid Build Coastguard Worker 
4003*fd1fabb7SAndroid Build Coastguard Worker 			ThrowProgramError ();
4004*fd1fabb7SAndroid Build Coastguard Worker 
4005*fd1fabb7SAndroid Build Coastguard Worker 			}
4006*fd1fabb7SAndroid Build Coastguard Worker 
4007*fd1fabb7SAndroid Build Coastguard Worker 		}
4008*fd1fabb7SAndroid Build Coastguard Worker 
4009*fd1fabb7SAndroid Build Coastguard Worker 	}
4010*fd1fabb7SAndroid Build Coastguard Worker 
4011*fd1fabb7SAndroid Build Coastguard Worker /******************************************************************************/
4012*fd1fabb7SAndroid Build Coastguard Worker 
EncodeJPEGPreview(dng_host & host,const dng_image & image,dng_jpeg_preview & preview,int32 quality)4013*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::EncodeJPEGPreview (dng_host &host,
4014*fd1fabb7SAndroid Build Coastguard Worker 										  const dng_image &image,
4015*fd1fabb7SAndroid Build Coastguard Worker 										  dng_jpeg_preview &preview,
4016*fd1fabb7SAndroid Build Coastguard Worker 										  int32 quality)
4017*fd1fabb7SAndroid Build Coastguard Worker 	{
4018*fd1fabb7SAndroid Build Coastguard Worker 
4019*fd1fabb7SAndroid Build Coastguard Worker 	#if qDNGUseLibJPEG
4020*fd1fabb7SAndroid Build Coastguard Worker 
4021*fd1fabb7SAndroid Build Coastguard Worker 	dng_memory_stream stream (host.Allocator ());
4022*fd1fabb7SAndroid Build Coastguard Worker 
4023*fd1fabb7SAndroid Build Coastguard Worker 	struct jpeg_compress_struct cinfo;
4024*fd1fabb7SAndroid Build Coastguard Worker 
4025*fd1fabb7SAndroid Build Coastguard Worker 	// Setup the error manager.
4026*fd1fabb7SAndroid Build Coastguard Worker 
4027*fd1fabb7SAndroid Build Coastguard Worker 	struct jpeg_error_mgr jerr;
4028*fd1fabb7SAndroid Build Coastguard Worker 
4029*fd1fabb7SAndroid Build Coastguard Worker 	cinfo.err = jpeg_std_error (&jerr);
4030*fd1fabb7SAndroid Build Coastguard Worker 
4031*fd1fabb7SAndroid Build Coastguard Worker 	jerr.error_exit     = dng_error_exit;
4032*fd1fabb7SAndroid Build Coastguard Worker 	jerr.output_message = dng_output_message;
4033*fd1fabb7SAndroid Build Coastguard Worker 
4034*fd1fabb7SAndroid Build Coastguard Worker 	try
4035*fd1fabb7SAndroid Build Coastguard Worker 		{
4036*fd1fabb7SAndroid Build Coastguard Worker 
4037*fd1fabb7SAndroid Build Coastguard Worker 		// Create the compression context.
4038*fd1fabb7SAndroid Build Coastguard Worker 
4039*fd1fabb7SAndroid Build Coastguard Worker 		jpeg_create_compress (&cinfo);
4040*fd1fabb7SAndroid Build Coastguard Worker 
4041*fd1fabb7SAndroid Build Coastguard Worker 		// Setup the destination manager to write to stream.
4042*fd1fabb7SAndroid Build Coastguard Worker 
4043*fd1fabb7SAndroid Build Coastguard Worker 		dng_jpeg_stream_dest dest;
4044*fd1fabb7SAndroid Build Coastguard Worker 
4045*fd1fabb7SAndroid Build Coastguard Worker 		dest.fStream = &stream;
4046*fd1fabb7SAndroid Build Coastguard Worker 
4047*fd1fabb7SAndroid Build Coastguard Worker 		dest.pub.init_destination    = dng_init_destination;
4048*fd1fabb7SAndroid Build Coastguard Worker 		dest.pub.empty_output_buffer = dng_empty_output_buffer;
4049*fd1fabb7SAndroid Build Coastguard Worker 		dest.pub.term_destination    = dng_term_destination;
4050*fd1fabb7SAndroid Build Coastguard Worker 
4051*fd1fabb7SAndroid Build Coastguard Worker 		cinfo.dest = &dest.pub;
4052*fd1fabb7SAndroid Build Coastguard Worker 
4053*fd1fabb7SAndroid Build Coastguard Worker 		// Setup basic image info.
4054*fd1fabb7SAndroid Build Coastguard Worker 
4055*fd1fabb7SAndroid Build Coastguard Worker 		cinfo.image_width      = image.Bounds ().W ();
4056*fd1fabb7SAndroid Build Coastguard Worker 		cinfo.image_height     = image.Bounds ().H ();
4057*fd1fabb7SAndroid Build Coastguard Worker 		cinfo.input_components = image.Planes ();
4058*fd1fabb7SAndroid Build Coastguard Worker 
4059*fd1fabb7SAndroid Build Coastguard Worker 		switch (image.Planes ())
4060*fd1fabb7SAndroid Build Coastguard Worker 			{
4061*fd1fabb7SAndroid Build Coastguard Worker 
4062*fd1fabb7SAndroid Build Coastguard Worker 			case 1:
4063*fd1fabb7SAndroid Build Coastguard Worker 				cinfo.in_color_space = JCS_GRAYSCALE;
4064*fd1fabb7SAndroid Build Coastguard Worker 				break;
4065*fd1fabb7SAndroid Build Coastguard Worker 
4066*fd1fabb7SAndroid Build Coastguard Worker 			case 3:
4067*fd1fabb7SAndroid Build Coastguard Worker 				cinfo.in_color_space = JCS_RGB;
4068*fd1fabb7SAndroid Build Coastguard Worker 				break;
4069*fd1fabb7SAndroid Build Coastguard Worker 
4070*fd1fabb7SAndroid Build Coastguard Worker 			default:
4071*fd1fabb7SAndroid Build Coastguard Worker 				ThrowProgramError ();
4072*fd1fabb7SAndroid Build Coastguard Worker 
4073*fd1fabb7SAndroid Build Coastguard Worker 			}
4074*fd1fabb7SAndroid Build Coastguard Worker 
4075*fd1fabb7SAndroid Build Coastguard Worker 		// Setup the compression parameters.
4076*fd1fabb7SAndroid Build Coastguard Worker 
4077*fd1fabb7SAndroid Build Coastguard Worker 		jpeg_set_defaults (&cinfo);
4078*fd1fabb7SAndroid Build Coastguard Worker 
4079*fd1fabb7SAndroid Build Coastguard Worker 		jpeg_set_adobe_quality (&cinfo, quality);
4080*fd1fabb7SAndroid Build Coastguard Worker 
4081*fd1fabb7SAndroid Build Coastguard Worker 		// Find some preview information based on the compression settings.
4082*fd1fabb7SAndroid Build Coastguard Worker 
4083*fd1fabb7SAndroid Build Coastguard Worker 		preview.fPreviewSize = image.Size ();
4084*fd1fabb7SAndroid Build Coastguard Worker 
4085*fd1fabb7SAndroid Build Coastguard Worker 		if (image.Planes () == 1)
4086*fd1fabb7SAndroid Build Coastguard Worker 			{
4087*fd1fabb7SAndroid Build Coastguard Worker 
4088*fd1fabb7SAndroid Build Coastguard Worker 			preview.fPhotometricInterpretation = piBlackIsZero;
4089*fd1fabb7SAndroid Build Coastguard Worker 
4090*fd1fabb7SAndroid Build Coastguard Worker 			}
4091*fd1fabb7SAndroid Build Coastguard Worker 
4092*fd1fabb7SAndroid Build Coastguard Worker 		else
4093*fd1fabb7SAndroid Build Coastguard Worker 			{
4094*fd1fabb7SAndroid Build Coastguard Worker 
4095*fd1fabb7SAndroid Build Coastguard Worker 			preview.fPhotometricInterpretation = piYCbCr;
4096*fd1fabb7SAndroid Build Coastguard Worker 
4097*fd1fabb7SAndroid Build Coastguard Worker 			preview.fYCbCrSubSampling.h  = cinfo.comp_info [0].h_samp_factor;
4098*fd1fabb7SAndroid Build Coastguard Worker 			preview.fYCbCrSubSampling.v  = cinfo.comp_info [0].v_samp_factor;
4099*fd1fabb7SAndroid Build Coastguard Worker 
4100*fd1fabb7SAndroid Build Coastguard Worker 			}
4101*fd1fabb7SAndroid Build Coastguard Worker 
4102*fd1fabb7SAndroid Build Coastguard Worker 		// Write the JPEG header.
4103*fd1fabb7SAndroid Build Coastguard Worker 
4104*fd1fabb7SAndroid Build Coastguard Worker 		jpeg_start_compress (&cinfo, TRUE);
4105*fd1fabb7SAndroid Build Coastguard Worker 
4106*fd1fabb7SAndroid Build Coastguard Worker 		// Write the scanlines.
4107*fd1fabb7SAndroid Build Coastguard Worker 
4108*fd1fabb7SAndroid Build Coastguard Worker 		dng_pixel_buffer buffer (image.Bounds (), 0, image.Planes (), ttByte,
4109*fd1fabb7SAndroid Build Coastguard Worker 			 pcInterleaved, NULL);
4110*fd1fabb7SAndroid Build Coastguard Worker 
4111*fd1fabb7SAndroid Build Coastguard Worker 		AutoPtr<dng_memory_block> bufferData (host.Allocate (buffer.fRowStep));
4112*fd1fabb7SAndroid Build Coastguard Worker 
4113*fd1fabb7SAndroid Build Coastguard Worker 		buffer.fData = bufferData->Buffer ();
4114*fd1fabb7SAndroid Build Coastguard Worker 
4115*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 row = 0; row < cinfo.image_height; row++)
4116*fd1fabb7SAndroid Build Coastguard Worker 			{
4117*fd1fabb7SAndroid Build Coastguard Worker 
4118*fd1fabb7SAndroid Build Coastguard Worker 			buffer.fArea.t = row;
4119*fd1fabb7SAndroid Build Coastguard Worker 			buffer.fArea.b = row + 1;
4120*fd1fabb7SAndroid Build Coastguard Worker 
4121*fd1fabb7SAndroid Build Coastguard Worker 			image.Get (buffer);
4122*fd1fabb7SAndroid Build Coastguard Worker 
4123*fd1fabb7SAndroid Build Coastguard Worker 			uint8 *sampArray [1];
4124*fd1fabb7SAndroid Build Coastguard Worker 
4125*fd1fabb7SAndroid Build Coastguard Worker 			sampArray [0] = buffer.DirtyPixel_uint8 (row,
4126*fd1fabb7SAndroid Build Coastguard Worker 													 buffer.fArea.l,
4127*fd1fabb7SAndroid Build Coastguard Worker 													 0);
4128*fd1fabb7SAndroid Build Coastguard Worker 
4129*fd1fabb7SAndroid Build Coastguard Worker 			jpeg_write_scanlines (&cinfo, sampArray, 1);
4130*fd1fabb7SAndroid Build Coastguard Worker 
4131*fd1fabb7SAndroid Build Coastguard Worker 			}
4132*fd1fabb7SAndroid Build Coastguard Worker 
4133*fd1fabb7SAndroid Build Coastguard Worker 		// Cleanup.
4134*fd1fabb7SAndroid Build Coastguard Worker 
4135*fd1fabb7SAndroid Build Coastguard Worker 		jpeg_finish_compress (&cinfo);
4136*fd1fabb7SAndroid Build Coastguard Worker 
4137*fd1fabb7SAndroid Build Coastguard Worker 		jpeg_destroy_compress (&cinfo);
4138*fd1fabb7SAndroid Build Coastguard Worker 
4139*fd1fabb7SAndroid Build Coastguard Worker 		}
4140*fd1fabb7SAndroid Build Coastguard Worker 
4141*fd1fabb7SAndroid Build Coastguard Worker 	catch (...)
4142*fd1fabb7SAndroid Build Coastguard Worker 		{
4143*fd1fabb7SAndroid Build Coastguard Worker 
4144*fd1fabb7SAndroid Build Coastguard Worker 		jpeg_destroy_compress (&cinfo);
4145*fd1fabb7SAndroid Build Coastguard Worker 
4146*fd1fabb7SAndroid Build Coastguard Worker 		throw;
4147*fd1fabb7SAndroid Build Coastguard Worker 
4148*fd1fabb7SAndroid Build Coastguard Worker 		}
4149*fd1fabb7SAndroid Build Coastguard Worker 
4150*fd1fabb7SAndroid Build Coastguard Worker 	preview.fCompressedData.Reset (stream.AsMemoryBlock (host.Allocator ()));
4151*fd1fabb7SAndroid Build Coastguard Worker 
4152*fd1fabb7SAndroid Build Coastguard Worker 	#else
4153*fd1fabb7SAndroid Build Coastguard Worker 
4154*fd1fabb7SAndroid Build Coastguard Worker 	(void) host;
4155*fd1fabb7SAndroid Build Coastguard Worker 	(void) image;
4156*fd1fabb7SAndroid Build Coastguard Worker 	(void) preview;
4157*fd1fabb7SAndroid Build Coastguard Worker 	(void) quality;
4158*fd1fabb7SAndroid Build Coastguard Worker 
4159*fd1fabb7SAndroid Build Coastguard Worker 	ThrowProgramError ("No JPEG encoder");
4160*fd1fabb7SAndroid Build Coastguard Worker 
4161*fd1fabb7SAndroid Build Coastguard Worker 	#endif
4162*fd1fabb7SAndroid Build Coastguard Worker 
4163*fd1fabb7SAndroid Build Coastguard Worker 	}
4164*fd1fabb7SAndroid Build Coastguard Worker 
4165*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
4166*fd1fabb7SAndroid Build Coastguard Worker 
WriteTile(dng_host & host,const dng_ifd & ifd,dng_stream & stream,const dng_image & image,const dng_rect & tileArea,uint32 fakeChannels,AutoPtr<dng_memory_block> & compressedBuffer,AutoPtr<dng_memory_block> & uncompressedBuffer,AutoPtr<dng_memory_block> & subTileBlockBuffer,AutoPtr<dng_memory_block> & tempBuffer)4167*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::WriteTile (dng_host &host,
4168*fd1fabb7SAndroid Build Coastguard Worker 						          const dng_ifd &ifd,
4169*fd1fabb7SAndroid Build Coastguard Worker 						          dng_stream &stream,
4170*fd1fabb7SAndroid Build Coastguard Worker 						          const dng_image &image,
4171*fd1fabb7SAndroid Build Coastguard Worker 						          const dng_rect &tileArea,
4172*fd1fabb7SAndroid Build Coastguard Worker 						          uint32 fakeChannels,
4173*fd1fabb7SAndroid Build Coastguard Worker 								  AutoPtr<dng_memory_block> &compressedBuffer,
4174*fd1fabb7SAndroid Build Coastguard Worker 								  AutoPtr<dng_memory_block> &uncompressedBuffer,
4175*fd1fabb7SAndroid Build Coastguard Worker 								  AutoPtr<dng_memory_block> &subTileBlockBuffer,
4176*fd1fabb7SAndroid Build Coastguard Worker 								  AutoPtr<dng_memory_block> &tempBuffer)
4177*fd1fabb7SAndroid Build Coastguard Worker 	{
4178*fd1fabb7SAndroid Build Coastguard Worker 
4179*fd1fabb7SAndroid Build Coastguard Worker 	// Create pixel buffer to hold uncompressed tile.
4180*fd1fabb7SAndroid Build Coastguard Worker 
4181*fd1fabb7SAndroid Build Coastguard Worker 	dng_pixel_buffer buffer (tileArea, 0, ifd.fSamplesPerPixel,
4182*fd1fabb7SAndroid Build Coastguard Worker 		 image.PixelType(), pcInterleaved, uncompressedBuffer->Buffer());
4183*fd1fabb7SAndroid Build Coastguard Worker 
4184*fd1fabb7SAndroid Build Coastguard Worker 	// Get the uncompressed data.
4185*fd1fabb7SAndroid Build Coastguard Worker 
4186*fd1fabb7SAndroid Build Coastguard Worker 	image.Get (buffer, dng_image::edge_zero);
4187*fd1fabb7SAndroid Build Coastguard Worker 
4188*fd1fabb7SAndroid Build Coastguard Worker 	// Deal with sub-tile blocks.
4189*fd1fabb7SAndroid Build Coastguard Worker 
4190*fd1fabb7SAndroid Build Coastguard Worker 	if (ifd.fSubTileBlockRows > 1)
4191*fd1fabb7SAndroid Build Coastguard Worker 		{
4192*fd1fabb7SAndroid Build Coastguard Worker 
4193*fd1fabb7SAndroid Build Coastguard Worker 		ReorderSubTileBlocks (ifd,
4194*fd1fabb7SAndroid Build Coastguard Worker 							  buffer,
4195*fd1fabb7SAndroid Build Coastguard Worker 							  uncompressedBuffer,
4196*fd1fabb7SAndroid Build Coastguard Worker 							  subTileBlockBuffer);
4197*fd1fabb7SAndroid Build Coastguard Worker 
4198*fd1fabb7SAndroid Build Coastguard Worker 		}
4199*fd1fabb7SAndroid Build Coastguard Worker 
4200*fd1fabb7SAndroid Build Coastguard Worker 	// Floating point depth conversion.
4201*fd1fabb7SAndroid Build Coastguard Worker 
4202*fd1fabb7SAndroid Build Coastguard Worker 	if (ifd.fSampleFormat [0] == sfFloatingPoint)
4203*fd1fabb7SAndroid Build Coastguard Worker 		{
4204*fd1fabb7SAndroid Build Coastguard Worker 
4205*fd1fabb7SAndroid Build Coastguard Worker 		if (ifd.fBitsPerSample [0] == 16)
4206*fd1fabb7SAndroid Build Coastguard Worker 			{
4207*fd1fabb7SAndroid Build Coastguard Worker 
4208*fd1fabb7SAndroid Build Coastguard Worker 			uint32 *srcPtr = (uint32 *) buffer.fData;
4209*fd1fabb7SAndroid Build Coastguard Worker 			uint16 *dstPtr = (uint16 *) buffer.fData;
4210*fd1fabb7SAndroid Build Coastguard Worker 
4211*fd1fabb7SAndroid Build Coastguard Worker 			uint32 pixels = tileArea.W () * tileArea.H () * buffer.fPlanes;
4212*fd1fabb7SAndroid Build Coastguard Worker 
4213*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 j = 0; j < pixels; j++)
4214*fd1fabb7SAndroid Build Coastguard Worker 				{
4215*fd1fabb7SAndroid Build Coastguard Worker 
4216*fd1fabb7SAndroid Build Coastguard Worker 				dstPtr [j] = DNG_FloatToHalf (srcPtr [j]);
4217*fd1fabb7SAndroid Build Coastguard Worker 
4218*fd1fabb7SAndroid Build Coastguard Worker 				}
4219*fd1fabb7SAndroid Build Coastguard Worker 
4220*fd1fabb7SAndroid Build Coastguard Worker 			buffer.fPixelSize = 2;
4221*fd1fabb7SAndroid Build Coastguard Worker 
4222*fd1fabb7SAndroid Build Coastguard Worker 			}
4223*fd1fabb7SAndroid Build Coastguard Worker 
4224*fd1fabb7SAndroid Build Coastguard Worker 		if (ifd.fBitsPerSample [0] == 24)
4225*fd1fabb7SAndroid Build Coastguard Worker 			{
4226*fd1fabb7SAndroid Build Coastguard Worker 
4227*fd1fabb7SAndroid Build Coastguard Worker 			uint32 *srcPtr = (uint32 *) buffer.fData;
4228*fd1fabb7SAndroid Build Coastguard Worker 			uint8  *dstPtr = (uint8  *) buffer.fData;
4229*fd1fabb7SAndroid Build Coastguard Worker 
4230*fd1fabb7SAndroid Build Coastguard Worker 			uint32 pixels = tileArea.W () * tileArea.H () * buffer.fPlanes;
4231*fd1fabb7SAndroid Build Coastguard Worker 
4232*fd1fabb7SAndroid Build Coastguard Worker 			if (stream.BigEndian () || ifd.fPredictor == cpFloatingPoint   ||
4233*fd1fabb7SAndroid Build Coastguard Worker 									   ifd.fPredictor == cpFloatingPointX2 ||
4234*fd1fabb7SAndroid Build Coastguard Worker 									   ifd.fPredictor == cpFloatingPointX4)
4235*fd1fabb7SAndroid Build Coastguard Worker 				{
4236*fd1fabb7SAndroid Build Coastguard Worker 
4237*fd1fabb7SAndroid Build Coastguard Worker 				for (uint32 j = 0; j < pixels; j++)
4238*fd1fabb7SAndroid Build Coastguard Worker 					{
4239*fd1fabb7SAndroid Build Coastguard Worker 
4240*fd1fabb7SAndroid Build Coastguard Worker 					DNG_FloatToFP24 (srcPtr [j], dstPtr);
4241*fd1fabb7SAndroid Build Coastguard Worker 
4242*fd1fabb7SAndroid Build Coastguard Worker 					dstPtr += 3;
4243*fd1fabb7SAndroid Build Coastguard Worker 
4244*fd1fabb7SAndroid Build Coastguard Worker 					}
4245*fd1fabb7SAndroid Build Coastguard Worker 
4246*fd1fabb7SAndroid Build Coastguard Worker 				}
4247*fd1fabb7SAndroid Build Coastguard Worker 
4248*fd1fabb7SAndroid Build Coastguard Worker 			else
4249*fd1fabb7SAndroid Build Coastguard Worker 				{
4250*fd1fabb7SAndroid Build Coastguard Worker 
4251*fd1fabb7SAndroid Build Coastguard Worker 				for (uint32 j = 0; j < pixels; j++)
4252*fd1fabb7SAndroid Build Coastguard Worker 					{
4253*fd1fabb7SAndroid Build Coastguard Worker 
4254*fd1fabb7SAndroid Build Coastguard Worker 					uint8 output [3];
4255*fd1fabb7SAndroid Build Coastguard Worker 
4256*fd1fabb7SAndroid Build Coastguard Worker 					DNG_FloatToFP24 (srcPtr [j], output);
4257*fd1fabb7SAndroid Build Coastguard Worker 
4258*fd1fabb7SAndroid Build Coastguard Worker 					dstPtr [0] = output [2];
4259*fd1fabb7SAndroid Build Coastguard Worker 					dstPtr [1] = output [1];
4260*fd1fabb7SAndroid Build Coastguard Worker 					dstPtr [2] = output [0];
4261*fd1fabb7SAndroid Build Coastguard Worker 
4262*fd1fabb7SAndroid Build Coastguard Worker 					dstPtr += 3;
4263*fd1fabb7SAndroid Build Coastguard Worker 
4264*fd1fabb7SAndroid Build Coastguard Worker 					}
4265*fd1fabb7SAndroid Build Coastguard Worker 
4266*fd1fabb7SAndroid Build Coastguard Worker 				}
4267*fd1fabb7SAndroid Build Coastguard Worker 
4268*fd1fabb7SAndroid Build Coastguard Worker 			buffer.fPixelSize = 3;
4269*fd1fabb7SAndroid Build Coastguard Worker 
4270*fd1fabb7SAndroid Build Coastguard Worker 			}
4271*fd1fabb7SAndroid Build Coastguard Worker 
4272*fd1fabb7SAndroid Build Coastguard Worker 		}
4273*fd1fabb7SAndroid Build Coastguard Worker 
4274*fd1fabb7SAndroid Build Coastguard Worker 	// Run predictor.
4275*fd1fabb7SAndroid Build Coastguard Worker 
4276*fd1fabb7SAndroid Build Coastguard Worker 	EncodePredictor (host,
4277*fd1fabb7SAndroid Build Coastguard Worker 					 ifd,
4278*fd1fabb7SAndroid Build Coastguard Worker 					 buffer,
4279*fd1fabb7SAndroid Build Coastguard Worker 					 tempBuffer);
4280*fd1fabb7SAndroid Build Coastguard Worker 
4281*fd1fabb7SAndroid Build Coastguard Worker 	// Adjust pixel buffer for fake channels.
4282*fd1fabb7SAndroid Build Coastguard Worker 
4283*fd1fabb7SAndroid Build Coastguard Worker 	if (fakeChannels > 1)
4284*fd1fabb7SAndroid Build Coastguard Worker 		{
4285*fd1fabb7SAndroid Build Coastguard Worker 
4286*fd1fabb7SAndroid Build Coastguard Worker 		buffer.fPlanes  *= fakeChannels;
4287*fd1fabb7SAndroid Build Coastguard Worker 		buffer.fColStep *= fakeChannels;
4288*fd1fabb7SAndroid Build Coastguard Worker 
4289*fd1fabb7SAndroid Build Coastguard Worker 		buffer.fArea.r = buffer.fArea.l + (buffer.fArea.W () / fakeChannels);
4290*fd1fabb7SAndroid Build Coastguard Worker 
4291*fd1fabb7SAndroid Build Coastguard Worker 		}
4292*fd1fabb7SAndroid Build Coastguard Worker 
4293*fd1fabb7SAndroid Build Coastguard Worker 	// Compress (if required) and write out the data.
4294*fd1fabb7SAndroid Build Coastguard Worker 
4295*fd1fabb7SAndroid Build Coastguard Worker 	WriteData (host,
4296*fd1fabb7SAndroid Build Coastguard Worker 			   ifd,
4297*fd1fabb7SAndroid Build Coastguard Worker 			   stream,
4298*fd1fabb7SAndroid Build Coastguard Worker 			   buffer,
4299*fd1fabb7SAndroid Build Coastguard Worker 			   compressedBuffer);
4300*fd1fabb7SAndroid Build Coastguard Worker 
4301*fd1fabb7SAndroid Build Coastguard Worker 	}
4302*fd1fabb7SAndroid Build Coastguard Worker 
4303*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
4304*fd1fabb7SAndroid Build Coastguard Worker 
4305*fd1fabb7SAndroid Build Coastguard Worker class dng_write_tiles_task : public dng_area_task
4306*fd1fabb7SAndroid Build Coastguard Worker 	{
4307*fd1fabb7SAndroid Build Coastguard Worker 
4308*fd1fabb7SAndroid Build Coastguard Worker 	private:
4309*fd1fabb7SAndroid Build Coastguard Worker 
4310*fd1fabb7SAndroid Build Coastguard Worker 		dng_image_writer &fImageWriter;
4311*fd1fabb7SAndroid Build Coastguard Worker 
4312*fd1fabb7SAndroid Build Coastguard Worker 		dng_host &fHost;
4313*fd1fabb7SAndroid Build Coastguard Worker 
4314*fd1fabb7SAndroid Build Coastguard Worker 		const dng_ifd &fIFD;
4315*fd1fabb7SAndroid Build Coastguard Worker 
4316*fd1fabb7SAndroid Build Coastguard Worker 		dng_basic_tag_set &fBasic;
4317*fd1fabb7SAndroid Build Coastguard Worker 
4318*fd1fabb7SAndroid Build Coastguard Worker 		dng_stream &fStream;
4319*fd1fabb7SAndroid Build Coastguard Worker 
4320*fd1fabb7SAndroid Build Coastguard Worker 		const dng_image &fImage;
4321*fd1fabb7SAndroid Build Coastguard Worker 
4322*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fFakeChannels;
4323*fd1fabb7SAndroid Build Coastguard Worker 
4324*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fTilesDown;
4325*fd1fabb7SAndroid Build Coastguard Worker 
4326*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fTilesAcross;
4327*fd1fabb7SAndroid Build Coastguard Worker 
4328*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fCompressedSize;
4329*fd1fabb7SAndroid Build Coastguard Worker 
4330*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fUncompressedSize;
4331*fd1fabb7SAndroid Build Coastguard Worker 
4332*fd1fabb7SAndroid Build Coastguard Worker 		dng_mutex fMutex1;
4333*fd1fabb7SAndroid Build Coastguard Worker 
4334*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fNextTileIndex;
4335*fd1fabb7SAndroid Build Coastguard Worker 
4336*fd1fabb7SAndroid Build Coastguard Worker 		dng_mutex fMutex2;
4337*fd1fabb7SAndroid Build Coastguard Worker 
4338*fd1fabb7SAndroid Build Coastguard Worker 		dng_condition fCondition;
4339*fd1fabb7SAndroid Build Coastguard Worker 
4340*fd1fabb7SAndroid Build Coastguard Worker 		bool fTaskFailed;
4341*fd1fabb7SAndroid Build Coastguard Worker 
4342*fd1fabb7SAndroid Build Coastguard Worker 		uint32 fWriteTileIndex;
4343*fd1fabb7SAndroid Build Coastguard Worker 
4344*fd1fabb7SAndroid Build Coastguard Worker 	public:
4345*fd1fabb7SAndroid Build Coastguard Worker 
dng_write_tiles_task(dng_image_writer & imageWriter,dng_host & host,const dng_ifd & ifd,dng_basic_tag_set & basic,dng_stream & stream,const dng_image & image,uint32 fakeChannels,uint32 tilesDown,uint32 tilesAcross,uint32 compressedSize,uint32 uncompressedSize)4346*fd1fabb7SAndroid Build Coastguard Worker 		dng_write_tiles_task (dng_image_writer &imageWriter,
4347*fd1fabb7SAndroid Build Coastguard Worker 							  dng_host &host,
4348*fd1fabb7SAndroid Build Coastguard Worker 							  const dng_ifd &ifd,
4349*fd1fabb7SAndroid Build Coastguard Worker 							  dng_basic_tag_set &basic,
4350*fd1fabb7SAndroid Build Coastguard Worker 							  dng_stream &stream,
4351*fd1fabb7SAndroid Build Coastguard Worker 							  const dng_image &image,
4352*fd1fabb7SAndroid Build Coastguard Worker 							  uint32 fakeChannels,
4353*fd1fabb7SAndroid Build Coastguard Worker 							  uint32 tilesDown,
4354*fd1fabb7SAndroid Build Coastguard Worker 							  uint32 tilesAcross,
4355*fd1fabb7SAndroid Build Coastguard Worker 							  uint32 compressedSize,
4356*fd1fabb7SAndroid Build Coastguard Worker 							  uint32 uncompressedSize)
4357*fd1fabb7SAndroid Build Coastguard Worker 
4358*fd1fabb7SAndroid Build Coastguard Worker 			:	fImageWriter      (imageWriter)
4359*fd1fabb7SAndroid Build Coastguard Worker 			,	fHost		      (host)
4360*fd1fabb7SAndroid Build Coastguard Worker 			,	fIFD		      (ifd)
4361*fd1fabb7SAndroid Build Coastguard Worker 			,	fBasic			  (basic)
4362*fd1fabb7SAndroid Build Coastguard Worker 			,	fStream		      (stream)
4363*fd1fabb7SAndroid Build Coastguard Worker 			,	fImage		      (image)
4364*fd1fabb7SAndroid Build Coastguard Worker 			,	fFakeChannels	  (fakeChannels)
4365*fd1fabb7SAndroid Build Coastguard Worker 			,	fTilesDown        (tilesDown)
4366*fd1fabb7SAndroid Build Coastguard Worker 			,	fTilesAcross	  (tilesAcross)
4367*fd1fabb7SAndroid Build Coastguard Worker 			,	fCompressedSize   (compressedSize)
4368*fd1fabb7SAndroid Build Coastguard Worker 			,	fUncompressedSize (uncompressedSize)
4369*fd1fabb7SAndroid Build Coastguard Worker 			,	fMutex1			  ("dng_write_tiles_task_1")
4370*fd1fabb7SAndroid Build Coastguard Worker 			,	fNextTileIndex	  (0)
4371*fd1fabb7SAndroid Build Coastguard Worker 			,	fMutex2			  ("dng_write_tiles_task_2")
4372*fd1fabb7SAndroid Build Coastguard Worker 			,	fCondition		  ()
4373*fd1fabb7SAndroid Build Coastguard Worker 			,	fTaskFailed		  (false)
4374*fd1fabb7SAndroid Build Coastguard Worker 			,	fWriteTileIndex	  (0)
4375*fd1fabb7SAndroid Build Coastguard Worker 
4376*fd1fabb7SAndroid Build Coastguard Worker 			{
4377*fd1fabb7SAndroid Build Coastguard Worker 
4378*fd1fabb7SAndroid Build Coastguard Worker 			fMinTaskArea = 16 * 16;
4379*fd1fabb7SAndroid Build Coastguard Worker 			fUnitCell    = dng_point (16, 16);
4380*fd1fabb7SAndroid Build Coastguard Worker 			fMaxTileSize = dng_point (16, 16);
4381*fd1fabb7SAndroid Build Coastguard Worker 
4382*fd1fabb7SAndroid Build Coastguard Worker 			}
4383*fd1fabb7SAndroid Build Coastguard Worker 
Process(uint32,const dng_rect &,dng_abort_sniffer * sniffer)4384*fd1fabb7SAndroid Build Coastguard Worker 		void Process (uint32 /* threadIndex */,
4385*fd1fabb7SAndroid Build Coastguard Worker 					  const dng_rect & /* tile */,
4386*fd1fabb7SAndroid Build Coastguard Worker 					  dng_abort_sniffer *sniffer)
4387*fd1fabb7SAndroid Build Coastguard Worker 			{
4388*fd1fabb7SAndroid Build Coastguard Worker 
4389*fd1fabb7SAndroid Build Coastguard Worker 			try
4390*fd1fabb7SAndroid Build Coastguard Worker 				{
4391*fd1fabb7SAndroid Build Coastguard Worker 
4392*fd1fabb7SAndroid Build Coastguard Worker 				AutoPtr<dng_memory_block> compressedBuffer;
4393*fd1fabb7SAndroid Build Coastguard Worker 				AutoPtr<dng_memory_block> uncompressedBuffer;
4394*fd1fabb7SAndroid Build Coastguard Worker 				AutoPtr<dng_memory_block> subTileBlockBuffer;
4395*fd1fabb7SAndroid Build Coastguard Worker 				AutoPtr<dng_memory_block> tempBuffer;
4396*fd1fabb7SAndroid Build Coastguard Worker 
4397*fd1fabb7SAndroid Build Coastguard Worker 				if (fCompressedSize)
4398*fd1fabb7SAndroid Build Coastguard Worker 					{
4399*fd1fabb7SAndroid Build Coastguard Worker 					compressedBuffer.Reset (fHost.Allocate (fCompressedSize));
4400*fd1fabb7SAndroid Build Coastguard Worker 					}
4401*fd1fabb7SAndroid Build Coastguard Worker 
4402*fd1fabb7SAndroid Build Coastguard Worker 				if (fUncompressedSize)
4403*fd1fabb7SAndroid Build Coastguard Worker 					{
4404*fd1fabb7SAndroid Build Coastguard Worker 					uncompressedBuffer.Reset (fHost.Allocate (fUncompressedSize));
4405*fd1fabb7SAndroid Build Coastguard Worker 					}
4406*fd1fabb7SAndroid Build Coastguard Worker 
4407*fd1fabb7SAndroid Build Coastguard Worker 				if (fIFD.fSubTileBlockRows > 1 && fUncompressedSize)
4408*fd1fabb7SAndroid Build Coastguard Worker 					{
4409*fd1fabb7SAndroid Build Coastguard Worker 					subTileBlockBuffer.Reset (fHost.Allocate (fUncompressedSize));
4410*fd1fabb7SAndroid Build Coastguard Worker 					}
4411*fd1fabb7SAndroid Build Coastguard Worker 
4412*fd1fabb7SAndroid Build Coastguard Worker 				while (true)
4413*fd1fabb7SAndroid Build Coastguard Worker 					{
4414*fd1fabb7SAndroid Build Coastguard Worker 
4415*fd1fabb7SAndroid Build Coastguard Worker 					// Find tile index to compress.
4416*fd1fabb7SAndroid Build Coastguard Worker 
4417*fd1fabb7SAndroid Build Coastguard Worker 					uint32 tileIndex;
4418*fd1fabb7SAndroid Build Coastguard Worker 
4419*fd1fabb7SAndroid Build Coastguard Worker 						{
4420*fd1fabb7SAndroid Build Coastguard Worker 
4421*fd1fabb7SAndroid Build Coastguard Worker 						dng_lock_mutex lock (&fMutex1);
4422*fd1fabb7SAndroid Build Coastguard Worker 
4423*fd1fabb7SAndroid Build Coastguard Worker 						if (fNextTileIndex == fTilesDown * fTilesAcross)
4424*fd1fabb7SAndroid Build Coastguard Worker 							{
4425*fd1fabb7SAndroid Build Coastguard Worker 							return;
4426*fd1fabb7SAndroid Build Coastguard Worker 							}
4427*fd1fabb7SAndroid Build Coastguard Worker 
4428*fd1fabb7SAndroid Build Coastguard Worker 						tileIndex = fNextTileIndex++;
4429*fd1fabb7SAndroid Build Coastguard Worker 
4430*fd1fabb7SAndroid Build Coastguard Worker 						}
4431*fd1fabb7SAndroid Build Coastguard Worker 
4432*fd1fabb7SAndroid Build Coastguard Worker 					dng_abort_sniffer::SniffForAbort (sniffer);
4433*fd1fabb7SAndroid Build Coastguard Worker 
4434*fd1fabb7SAndroid Build Coastguard Worker 					// Compress tile.
4435*fd1fabb7SAndroid Build Coastguard Worker 
4436*fd1fabb7SAndroid Build Coastguard Worker 					uint32 rowIndex = tileIndex / fTilesAcross;
4437*fd1fabb7SAndroid Build Coastguard Worker 
4438*fd1fabb7SAndroid Build Coastguard Worker 					uint32 colIndex = tileIndex - rowIndex * fTilesAcross;
4439*fd1fabb7SAndroid Build Coastguard Worker 
4440*fd1fabb7SAndroid Build Coastguard Worker 					dng_rect tileArea = fIFD.TileArea (rowIndex, colIndex);
4441*fd1fabb7SAndroid Build Coastguard Worker 
4442*fd1fabb7SAndroid Build Coastguard Worker 					dng_memory_stream tileStream (fHost.Allocator ());
4443*fd1fabb7SAndroid Build Coastguard Worker 
4444*fd1fabb7SAndroid Build Coastguard Worker 					tileStream.SetLittleEndian (fStream.LittleEndian ());
4445*fd1fabb7SAndroid Build Coastguard Worker 
4446*fd1fabb7SAndroid Build Coastguard Worker 					dng_host host (&fHost.Allocator (),
4447*fd1fabb7SAndroid Build Coastguard Worker 								   sniffer);
4448*fd1fabb7SAndroid Build Coastguard Worker 
4449*fd1fabb7SAndroid Build Coastguard Worker 					fImageWriter.WriteTile (host,
4450*fd1fabb7SAndroid Build Coastguard Worker 											fIFD,
4451*fd1fabb7SAndroid Build Coastguard Worker 											tileStream,
4452*fd1fabb7SAndroid Build Coastguard Worker 											fImage,
4453*fd1fabb7SAndroid Build Coastguard Worker 											tileArea,
4454*fd1fabb7SAndroid Build Coastguard Worker 											fFakeChannels,
4455*fd1fabb7SAndroid Build Coastguard Worker 											compressedBuffer,
4456*fd1fabb7SAndroid Build Coastguard Worker 											uncompressedBuffer,
4457*fd1fabb7SAndroid Build Coastguard Worker 											subTileBlockBuffer,
4458*fd1fabb7SAndroid Build Coastguard Worker 											tempBuffer);
4459*fd1fabb7SAndroid Build Coastguard Worker 
4460*fd1fabb7SAndroid Build Coastguard Worker 					tileStream.Flush ();
4461*fd1fabb7SAndroid Build Coastguard Worker 
4462*fd1fabb7SAndroid Build Coastguard Worker 					uint32 tileByteCount = (uint32) tileStream.Length ();
4463*fd1fabb7SAndroid Build Coastguard Worker 
4464*fd1fabb7SAndroid Build Coastguard Worker 					tileStream.SetReadPosition (0);
4465*fd1fabb7SAndroid Build Coastguard Worker 
4466*fd1fabb7SAndroid Build Coastguard Worker 					// Wait until it is our turn to write tile.
4467*fd1fabb7SAndroid Build Coastguard Worker 
4468*fd1fabb7SAndroid Build Coastguard Worker 						{
4469*fd1fabb7SAndroid Build Coastguard Worker 
4470*fd1fabb7SAndroid Build Coastguard Worker 						dng_lock_mutex lock (&fMutex2);
4471*fd1fabb7SAndroid Build Coastguard Worker 
4472*fd1fabb7SAndroid Build Coastguard Worker 						while (!fTaskFailed &&
4473*fd1fabb7SAndroid Build Coastguard Worker 							   fWriteTileIndex != tileIndex)
4474*fd1fabb7SAndroid Build Coastguard Worker 							{
4475*fd1fabb7SAndroid Build Coastguard Worker 
4476*fd1fabb7SAndroid Build Coastguard Worker 							fCondition.Wait (fMutex2);
4477*fd1fabb7SAndroid Build Coastguard Worker 
4478*fd1fabb7SAndroid Build Coastguard Worker 							}
4479*fd1fabb7SAndroid Build Coastguard Worker 
4480*fd1fabb7SAndroid Build Coastguard Worker 						// If the task failed in another thread, that thread already threw an exception.
4481*fd1fabb7SAndroid Build Coastguard Worker 
4482*fd1fabb7SAndroid Build Coastguard Worker 						if (fTaskFailed)
4483*fd1fabb7SAndroid Build Coastguard Worker 							return;
4484*fd1fabb7SAndroid Build Coastguard Worker 
4485*fd1fabb7SAndroid Build Coastguard Worker 						}
4486*fd1fabb7SAndroid Build Coastguard Worker 
4487*fd1fabb7SAndroid Build Coastguard Worker 					dng_abort_sniffer::SniffForAbort (sniffer);
4488*fd1fabb7SAndroid Build Coastguard Worker 
4489*fd1fabb7SAndroid Build Coastguard Worker 					// Remember this offset.
4490*fd1fabb7SAndroid Build Coastguard Worker 
4491*fd1fabb7SAndroid Build Coastguard Worker 					uint32 tileOffset = (uint32) fStream.Position ();
4492*fd1fabb7SAndroid Build Coastguard Worker 
4493*fd1fabb7SAndroid Build Coastguard Worker 					fBasic.SetTileOffset (tileIndex, tileOffset);
4494*fd1fabb7SAndroid Build Coastguard Worker 
4495*fd1fabb7SAndroid Build Coastguard Worker 					// Copy tile stream for tile into main stream.
4496*fd1fabb7SAndroid Build Coastguard Worker 
4497*fd1fabb7SAndroid Build Coastguard Worker 					tileStream.CopyToStream (fStream, tileByteCount);
4498*fd1fabb7SAndroid Build Coastguard Worker 
4499*fd1fabb7SAndroid Build Coastguard Worker 					// Update tile count.
4500*fd1fabb7SAndroid Build Coastguard Worker 
4501*fd1fabb7SAndroid Build Coastguard Worker 					fBasic.SetTileByteCount (tileIndex, tileByteCount);
4502*fd1fabb7SAndroid Build Coastguard Worker 
4503*fd1fabb7SAndroid Build Coastguard Worker 					// Keep the tiles on even byte offsets.
4504*fd1fabb7SAndroid Build Coastguard Worker 
4505*fd1fabb7SAndroid Build Coastguard Worker 					if (tileByteCount & 1)
4506*fd1fabb7SAndroid Build Coastguard Worker 						{
4507*fd1fabb7SAndroid Build Coastguard Worker 						fStream.Put_uint8 (0);
4508*fd1fabb7SAndroid Build Coastguard Worker 						}
4509*fd1fabb7SAndroid Build Coastguard Worker 
4510*fd1fabb7SAndroid Build Coastguard Worker 					// Let other threads know it is safe to write to stream.
4511*fd1fabb7SAndroid Build Coastguard Worker 
4512*fd1fabb7SAndroid Build Coastguard Worker 						{
4513*fd1fabb7SAndroid Build Coastguard Worker 
4514*fd1fabb7SAndroid Build Coastguard Worker 						dng_lock_mutex lock (&fMutex2);
4515*fd1fabb7SAndroid Build Coastguard Worker 
4516*fd1fabb7SAndroid Build Coastguard Worker 						// If the task failed in another thread, that thread already threw an exception.
4517*fd1fabb7SAndroid Build Coastguard Worker 
4518*fd1fabb7SAndroid Build Coastguard Worker 						if (fTaskFailed)
4519*fd1fabb7SAndroid Build Coastguard Worker 							return;
4520*fd1fabb7SAndroid Build Coastguard Worker 
4521*fd1fabb7SAndroid Build Coastguard Worker 						fWriteTileIndex++;
4522*fd1fabb7SAndroid Build Coastguard Worker 
4523*fd1fabb7SAndroid Build Coastguard Worker 						fCondition.Broadcast ();
4524*fd1fabb7SAndroid Build Coastguard Worker 
4525*fd1fabb7SAndroid Build Coastguard Worker 						}
4526*fd1fabb7SAndroid Build Coastguard Worker 
4527*fd1fabb7SAndroid Build Coastguard Worker 					}
4528*fd1fabb7SAndroid Build Coastguard Worker 
4529*fd1fabb7SAndroid Build Coastguard Worker 				}
4530*fd1fabb7SAndroid Build Coastguard Worker 
4531*fd1fabb7SAndroid Build Coastguard Worker 			catch (...)
4532*fd1fabb7SAndroid Build Coastguard Worker 				{
4533*fd1fabb7SAndroid Build Coastguard Worker 
4534*fd1fabb7SAndroid Build Coastguard Worker 				// If first to fail, wake up any threads waiting on condition.
4535*fd1fabb7SAndroid Build Coastguard Worker 
4536*fd1fabb7SAndroid Build Coastguard Worker 				bool needBroadcast = false;
4537*fd1fabb7SAndroid Build Coastguard Worker 
4538*fd1fabb7SAndroid Build Coastguard Worker 					{
4539*fd1fabb7SAndroid Build Coastguard Worker 
4540*fd1fabb7SAndroid Build Coastguard Worker 					dng_lock_mutex lock (&fMutex2);
4541*fd1fabb7SAndroid Build Coastguard Worker 
4542*fd1fabb7SAndroid Build Coastguard Worker 					needBroadcast = !fTaskFailed;
4543*fd1fabb7SAndroid Build Coastguard Worker 					fTaskFailed = true;
4544*fd1fabb7SAndroid Build Coastguard Worker 
4545*fd1fabb7SAndroid Build Coastguard Worker 					}
4546*fd1fabb7SAndroid Build Coastguard Worker 
4547*fd1fabb7SAndroid Build Coastguard Worker 				if (needBroadcast)
4548*fd1fabb7SAndroid Build Coastguard Worker 					fCondition.Broadcast ();
4549*fd1fabb7SAndroid Build Coastguard Worker 
4550*fd1fabb7SAndroid Build Coastguard Worker 				throw;
4551*fd1fabb7SAndroid Build Coastguard Worker 
4552*fd1fabb7SAndroid Build Coastguard Worker 				}
4553*fd1fabb7SAndroid Build Coastguard Worker 
4554*fd1fabb7SAndroid Build Coastguard Worker 			}
4555*fd1fabb7SAndroid Build Coastguard Worker 
4556*fd1fabb7SAndroid Build Coastguard Worker 	private:
4557*fd1fabb7SAndroid Build Coastguard Worker 
4558*fd1fabb7SAndroid Build Coastguard Worker 		// Hidden copy constructor and assignment operator.
4559*fd1fabb7SAndroid Build Coastguard Worker 
4560*fd1fabb7SAndroid Build Coastguard Worker 		dng_write_tiles_task (const dng_write_tiles_task &);
4561*fd1fabb7SAndroid Build Coastguard Worker 
4562*fd1fabb7SAndroid Build Coastguard Worker 		dng_write_tiles_task & operator= (const dng_write_tiles_task &);
4563*fd1fabb7SAndroid Build Coastguard Worker 
4564*fd1fabb7SAndroid Build Coastguard Worker 	};
4565*fd1fabb7SAndroid Build Coastguard Worker 
4566*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
4567*fd1fabb7SAndroid Build Coastguard Worker 
WriteImage(dng_host & host,const dng_ifd & ifd,dng_basic_tag_set & basic,dng_stream & stream,const dng_image & image,uint32 fakeChannels)4568*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::WriteImage (dng_host &host,
4569*fd1fabb7SAndroid Build Coastguard Worker 						           const dng_ifd &ifd,
4570*fd1fabb7SAndroid Build Coastguard Worker 						           dng_basic_tag_set &basic,
4571*fd1fabb7SAndroid Build Coastguard Worker 						           dng_stream &stream,
4572*fd1fabb7SAndroid Build Coastguard Worker 						           const dng_image &image,
4573*fd1fabb7SAndroid Build Coastguard Worker 						           uint32 fakeChannels)
4574*fd1fabb7SAndroid Build Coastguard Worker 	{
4575*fd1fabb7SAndroid Build Coastguard Worker 
4576*fd1fabb7SAndroid Build Coastguard Worker 	// Deal with row interleaved images.
4577*fd1fabb7SAndroid Build Coastguard Worker 
4578*fd1fabb7SAndroid Build Coastguard Worker 	if (ifd.fRowInterleaveFactor > 1 &&
4579*fd1fabb7SAndroid Build Coastguard Worker 		ifd.fRowInterleaveFactor < ifd.fImageLength)
4580*fd1fabb7SAndroid Build Coastguard Worker 		{
4581*fd1fabb7SAndroid Build Coastguard Worker 
4582*fd1fabb7SAndroid Build Coastguard Worker 		dng_ifd tempIFD (ifd);
4583*fd1fabb7SAndroid Build Coastguard Worker 
4584*fd1fabb7SAndroid Build Coastguard Worker 		tempIFD.fRowInterleaveFactor = 1;
4585*fd1fabb7SAndroid Build Coastguard Worker 
4586*fd1fabb7SAndroid Build Coastguard Worker 		dng_row_interleaved_image tempImage (*((dng_image *) &image),
4587*fd1fabb7SAndroid Build Coastguard Worker 											 ifd.fRowInterleaveFactor);
4588*fd1fabb7SAndroid Build Coastguard Worker 
4589*fd1fabb7SAndroid Build Coastguard Worker 		WriteImage (host,
4590*fd1fabb7SAndroid Build Coastguard Worker 					tempIFD,
4591*fd1fabb7SAndroid Build Coastguard Worker 					basic,
4592*fd1fabb7SAndroid Build Coastguard Worker 					stream,
4593*fd1fabb7SAndroid Build Coastguard Worker 					tempImage,
4594*fd1fabb7SAndroid Build Coastguard Worker 					fakeChannels);
4595*fd1fabb7SAndroid Build Coastguard Worker 
4596*fd1fabb7SAndroid Build Coastguard Worker 		return;
4597*fd1fabb7SAndroid Build Coastguard Worker 
4598*fd1fabb7SAndroid Build Coastguard Worker 		}
4599*fd1fabb7SAndroid Build Coastguard Worker 
4600*fd1fabb7SAndroid Build Coastguard Worker 	// Compute basic information.
4601*fd1fabb7SAndroid Build Coastguard Worker 
4602*fd1fabb7SAndroid Build Coastguard Worker 	uint32 bytesPerSample = TagTypeSize (image.PixelType ());
4603*fd1fabb7SAndroid Build Coastguard Worker 
4604*fd1fabb7SAndroid Build Coastguard Worker 	uint32 bytesPerPixel = SafeUint32Mult (ifd.fSamplesPerPixel,
4605*fd1fabb7SAndroid Build Coastguard Worker 										   bytesPerSample);
4606*fd1fabb7SAndroid Build Coastguard Worker 
4607*fd1fabb7SAndroid Build Coastguard Worker 	uint32 tileRowBytes = SafeUint32Mult (ifd.fTileWidth, bytesPerPixel);
4608*fd1fabb7SAndroid Build Coastguard Worker 
4609*fd1fabb7SAndroid Build Coastguard Worker 	// If we can compute the number of bytes needed to store the
4610*fd1fabb7SAndroid Build Coastguard Worker 	// data, we can split the write for each tile into sub-tiles.
4611*fd1fabb7SAndroid Build Coastguard Worker 
4612*fd1fabb7SAndroid Build Coastguard Worker 	uint32 subTileLength = ifd.fTileLength;
4613*fd1fabb7SAndroid Build Coastguard Worker 
4614*fd1fabb7SAndroid Build Coastguard Worker 	if (ifd.TileByteCount (ifd.TileArea (0, 0)) != 0)
4615*fd1fabb7SAndroid Build Coastguard Worker 		{
4616*fd1fabb7SAndroid Build Coastguard Worker 
4617*fd1fabb7SAndroid Build Coastguard Worker 		subTileLength = Pin_uint32 (ifd.fSubTileBlockRows,
4618*fd1fabb7SAndroid Build Coastguard Worker 									kImageBufferSize / tileRowBytes,
4619*fd1fabb7SAndroid Build Coastguard Worker 									ifd.fTileLength);
4620*fd1fabb7SAndroid Build Coastguard Worker 
4621*fd1fabb7SAndroid Build Coastguard Worker 		// Don't split sub-tiles across subTileBlocks.
4622*fd1fabb7SAndroid Build Coastguard Worker 
4623*fd1fabb7SAndroid Build Coastguard Worker 		subTileLength = subTileLength / ifd.fSubTileBlockRows
4624*fd1fabb7SAndroid Build Coastguard Worker 									  * ifd.fSubTileBlockRows;
4625*fd1fabb7SAndroid Build Coastguard Worker 
4626*fd1fabb7SAndroid Build Coastguard Worker 		}
4627*fd1fabb7SAndroid Build Coastguard Worker 
4628*fd1fabb7SAndroid Build Coastguard Worker 	// Find size of uncompressed buffer.
4629*fd1fabb7SAndroid Build Coastguard Worker 
4630*fd1fabb7SAndroid Build Coastguard Worker 	uint32 uncompressedSize = SafeUint32Mult(subTileLength, tileRowBytes);
4631*fd1fabb7SAndroid Build Coastguard Worker 
4632*fd1fabb7SAndroid Build Coastguard Worker 	// Find size of compressed buffer, if required.
4633*fd1fabb7SAndroid Build Coastguard Worker 
4634*fd1fabb7SAndroid Build Coastguard Worker 	uint32 compressedSize = CompressedBufferSize (ifd, uncompressedSize);
4635*fd1fabb7SAndroid Build Coastguard Worker 
4636*fd1fabb7SAndroid Build Coastguard Worker 	// See if we can do this write using multiple threads.
4637*fd1fabb7SAndroid Build Coastguard Worker 
4638*fd1fabb7SAndroid Build Coastguard Worker 	uint32 tilesAcross = ifd.TilesAcross ();
4639*fd1fabb7SAndroid Build Coastguard Worker 	uint32 tilesDown   = ifd.TilesDown   ();
4640*fd1fabb7SAndroid Build Coastguard Worker 
4641*fd1fabb7SAndroid Build Coastguard Worker 	bool useMultipleThreads = (tilesDown * tilesAcross >= 2) &&
4642*fd1fabb7SAndroid Build Coastguard Worker 							  (host.PerformAreaTaskThreads () > 1) &&
4643*fd1fabb7SAndroid Build Coastguard Worker 							  (subTileLength == ifd.fTileLength) &&
4644*fd1fabb7SAndroid Build Coastguard Worker 							  (ifd.fCompression != ccUncompressed);
4645*fd1fabb7SAndroid Build Coastguard Worker 
4646*fd1fabb7SAndroid Build Coastguard Worker 
4647*fd1fabb7SAndroid Build Coastguard Worker #if qImagecore
4648*fd1fabb7SAndroid Build Coastguard Worker 	useMultipleThreads = false;
4649*fd1fabb7SAndroid Build Coastguard Worker #endif
4650*fd1fabb7SAndroid Build Coastguard Worker 
4651*fd1fabb7SAndroid Build Coastguard Worker 	if (useMultipleThreads)
4652*fd1fabb7SAndroid Build Coastguard Worker 		{
4653*fd1fabb7SAndroid Build Coastguard Worker 
4654*fd1fabb7SAndroid Build Coastguard Worker 		uint32 threadCount = Min_uint32 (tilesDown * tilesAcross,
4655*fd1fabb7SAndroid Build Coastguard Worker 										 host.PerformAreaTaskThreads ());
4656*fd1fabb7SAndroid Build Coastguard Worker 
4657*fd1fabb7SAndroid Build Coastguard Worker 		dng_write_tiles_task task (*this,
4658*fd1fabb7SAndroid Build Coastguard Worker 								   host,
4659*fd1fabb7SAndroid Build Coastguard Worker 								   ifd,
4660*fd1fabb7SAndroid Build Coastguard Worker 								   basic,
4661*fd1fabb7SAndroid Build Coastguard Worker 								   stream,
4662*fd1fabb7SAndroid Build Coastguard Worker 								   image,
4663*fd1fabb7SAndroid Build Coastguard Worker 								   fakeChannels,
4664*fd1fabb7SAndroid Build Coastguard Worker 								   tilesDown,
4665*fd1fabb7SAndroid Build Coastguard Worker 								   tilesAcross,
4666*fd1fabb7SAndroid Build Coastguard Worker 								   compressedSize,
4667*fd1fabb7SAndroid Build Coastguard Worker 								   uncompressedSize);
4668*fd1fabb7SAndroid Build Coastguard Worker 
4669*fd1fabb7SAndroid Build Coastguard Worker 		host.PerformAreaTask (task,
4670*fd1fabb7SAndroid Build Coastguard Worker 							  dng_rect (0, 0, 16, 16 * threadCount));
4671*fd1fabb7SAndroid Build Coastguard Worker 
4672*fd1fabb7SAndroid Build Coastguard Worker 		}
4673*fd1fabb7SAndroid Build Coastguard Worker 
4674*fd1fabb7SAndroid Build Coastguard Worker 	else
4675*fd1fabb7SAndroid Build Coastguard Worker 		{
4676*fd1fabb7SAndroid Build Coastguard Worker 
4677*fd1fabb7SAndroid Build Coastguard Worker 		AutoPtr<dng_memory_block> compressedBuffer;
4678*fd1fabb7SAndroid Build Coastguard Worker 		AutoPtr<dng_memory_block> uncompressedBuffer;
4679*fd1fabb7SAndroid Build Coastguard Worker 		AutoPtr<dng_memory_block> subTileBlockBuffer;
4680*fd1fabb7SAndroid Build Coastguard Worker 		AutoPtr<dng_memory_block> tempBuffer;
4681*fd1fabb7SAndroid Build Coastguard Worker 
4682*fd1fabb7SAndroid Build Coastguard Worker 		if (compressedSize)
4683*fd1fabb7SAndroid Build Coastguard Worker 			{
4684*fd1fabb7SAndroid Build Coastguard Worker 			compressedBuffer.Reset (host.Allocate (compressedSize));
4685*fd1fabb7SAndroid Build Coastguard Worker 			}
4686*fd1fabb7SAndroid Build Coastguard Worker 
4687*fd1fabb7SAndroid Build Coastguard Worker 		if (uncompressedSize)
4688*fd1fabb7SAndroid Build Coastguard Worker 			{
4689*fd1fabb7SAndroid Build Coastguard Worker 			uncompressedBuffer.Reset (host.Allocate (uncompressedSize));
4690*fd1fabb7SAndroid Build Coastguard Worker 			}
4691*fd1fabb7SAndroid Build Coastguard Worker 
4692*fd1fabb7SAndroid Build Coastguard Worker 		if (ifd.fSubTileBlockRows > 1 && uncompressedSize)
4693*fd1fabb7SAndroid Build Coastguard Worker 			{
4694*fd1fabb7SAndroid Build Coastguard Worker 			subTileBlockBuffer.Reset (host.Allocate (uncompressedSize));
4695*fd1fabb7SAndroid Build Coastguard Worker 			}
4696*fd1fabb7SAndroid Build Coastguard Worker 
4697*fd1fabb7SAndroid Build Coastguard Worker 		// Write out each tile.
4698*fd1fabb7SAndroid Build Coastguard Worker 
4699*fd1fabb7SAndroid Build Coastguard Worker 		uint32 tileIndex = 0;
4700*fd1fabb7SAndroid Build Coastguard Worker 
4701*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 rowIndex = 0; rowIndex < tilesDown; rowIndex++)
4702*fd1fabb7SAndroid Build Coastguard Worker 			{
4703*fd1fabb7SAndroid Build Coastguard Worker 
4704*fd1fabb7SAndroid Build Coastguard Worker 			for (uint32 colIndex = 0; colIndex < tilesAcross; colIndex++)
4705*fd1fabb7SAndroid Build Coastguard Worker 				{
4706*fd1fabb7SAndroid Build Coastguard Worker 
4707*fd1fabb7SAndroid Build Coastguard Worker 				// Remember this offset.
4708*fd1fabb7SAndroid Build Coastguard Worker 
4709*fd1fabb7SAndroid Build Coastguard Worker 				uint32 tileOffset = (uint32) stream.Position ();
4710*fd1fabb7SAndroid Build Coastguard Worker 
4711*fd1fabb7SAndroid Build Coastguard Worker 				basic.SetTileOffset (tileIndex, tileOffset);
4712*fd1fabb7SAndroid Build Coastguard Worker 
4713*fd1fabb7SAndroid Build Coastguard Worker 				// Split tile into sub-tiles if possible.
4714*fd1fabb7SAndroid Build Coastguard Worker 
4715*fd1fabb7SAndroid Build Coastguard Worker 				dng_rect tileArea = ifd.TileArea (rowIndex, colIndex);
4716*fd1fabb7SAndroid Build Coastguard Worker 
4717*fd1fabb7SAndroid Build Coastguard Worker 				uint32 subTileCount = (tileArea.H () + subTileLength - 1) /
4718*fd1fabb7SAndroid Build Coastguard Worker 									  subTileLength;
4719*fd1fabb7SAndroid Build Coastguard Worker 
4720*fd1fabb7SAndroid Build Coastguard Worker 				for (uint32 subIndex = 0; subIndex < subTileCount; subIndex++)
4721*fd1fabb7SAndroid Build Coastguard Worker 					{
4722*fd1fabb7SAndroid Build Coastguard Worker 
4723*fd1fabb7SAndroid Build Coastguard Worker 					host.SniffForAbort ();
4724*fd1fabb7SAndroid Build Coastguard Worker 
4725*fd1fabb7SAndroid Build Coastguard Worker 					dng_rect subArea (tileArea);
4726*fd1fabb7SAndroid Build Coastguard Worker 
4727*fd1fabb7SAndroid Build Coastguard Worker 					subArea.t = tileArea.t + subIndex * subTileLength;
4728*fd1fabb7SAndroid Build Coastguard Worker 
4729*fd1fabb7SAndroid Build Coastguard Worker 					subArea.b = Min_int32 (subArea.t + subTileLength,
4730*fd1fabb7SAndroid Build Coastguard Worker 										   tileArea.b);
4731*fd1fabb7SAndroid Build Coastguard Worker 
4732*fd1fabb7SAndroid Build Coastguard Worker 					// Write the sub-tile.
4733*fd1fabb7SAndroid Build Coastguard Worker 
4734*fd1fabb7SAndroid Build Coastguard Worker 					WriteTile (host,
4735*fd1fabb7SAndroid Build Coastguard Worker 							   ifd,
4736*fd1fabb7SAndroid Build Coastguard Worker 							   stream,
4737*fd1fabb7SAndroid Build Coastguard Worker 							   image,
4738*fd1fabb7SAndroid Build Coastguard Worker 							   subArea,
4739*fd1fabb7SAndroid Build Coastguard Worker 							   fakeChannels,
4740*fd1fabb7SAndroid Build Coastguard Worker 							   compressedBuffer,
4741*fd1fabb7SAndroid Build Coastguard Worker 							   uncompressedBuffer,
4742*fd1fabb7SAndroid Build Coastguard Worker 							   subTileBlockBuffer,
4743*fd1fabb7SAndroid Build Coastguard Worker 							   tempBuffer);
4744*fd1fabb7SAndroid Build Coastguard Worker 
4745*fd1fabb7SAndroid Build Coastguard Worker 					}
4746*fd1fabb7SAndroid Build Coastguard Worker 
4747*fd1fabb7SAndroid Build Coastguard Worker 				// Update tile count.
4748*fd1fabb7SAndroid Build Coastguard Worker 
4749*fd1fabb7SAndroid Build Coastguard Worker 				uint32 tileByteCount = (uint32) stream.Position () - tileOffset;
4750*fd1fabb7SAndroid Build Coastguard Worker 
4751*fd1fabb7SAndroid Build Coastguard Worker 				basic.SetTileByteCount (tileIndex, tileByteCount);
4752*fd1fabb7SAndroid Build Coastguard Worker 
4753*fd1fabb7SAndroid Build Coastguard Worker 				tileIndex++;
4754*fd1fabb7SAndroid Build Coastguard Worker 
4755*fd1fabb7SAndroid Build Coastguard Worker 				// Keep the tiles on even byte offsets.
4756*fd1fabb7SAndroid Build Coastguard Worker 
4757*fd1fabb7SAndroid Build Coastguard Worker 				if (tileByteCount & 1)
4758*fd1fabb7SAndroid Build Coastguard Worker 					{
4759*fd1fabb7SAndroid Build Coastguard Worker 					stream.Put_uint8 (0);
4760*fd1fabb7SAndroid Build Coastguard Worker 					}
4761*fd1fabb7SAndroid Build Coastguard Worker 
4762*fd1fabb7SAndroid Build Coastguard Worker 				}
4763*fd1fabb7SAndroid Build Coastguard Worker 
4764*fd1fabb7SAndroid Build Coastguard Worker 			}
4765*fd1fabb7SAndroid Build Coastguard Worker 
4766*fd1fabb7SAndroid Build Coastguard Worker 		}
4767*fd1fabb7SAndroid Build Coastguard Worker 
4768*fd1fabb7SAndroid Build Coastguard Worker 	}
4769*fd1fabb7SAndroid Build Coastguard Worker 
4770*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
4771*fd1fabb7SAndroid Build Coastguard Worker 
4772*fd1fabb7SAndroid Build Coastguard Worker #if qDNGUseXMP
4773*fd1fabb7SAndroid Build Coastguard Worker 
CopyString(const dng_xmp & oldXMP,dng_xmp & newXMP,const char * ns,const char * path,dng_string * exif=NULL)4774*fd1fabb7SAndroid Build Coastguard Worker static void CopyString (const dng_xmp &oldXMP,
4775*fd1fabb7SAndroid Build Coastguard Worker 						dng_xmp &newXMP,
4776*fd1fabb7SAndroid Build Coastguard Worker 						const char *ns,
4777*fd1fabb7SAndroid Build Coastguard Worker 						const char *path,
4778*fd1fabb7SAndroid Build Coastguard Worker 						dng_string *exif = NULL)
4779*fd1fabb7SAndroid Build Coastguard Worker 	{
4780*fd1fabb7SAndroid Build Coastguard Worker 
4781*fd1fabb7SAndroid Build Coastguard Worker 	dng_string s;
4782*fd1fabb7SAndroid Build Coastguard Worker 
4783*fd1fabb7SAndroid Build Coastguard Worker 	if (oldXMP.GetString (ns, path, s))
4784*fd1fabb7SAndroid Build Coastguard Worker 		{
4785*fd1fabb7SAndroid Build Coastguard Worker 
4786*fd1fabb7SAndroid Build Coastguard Worker 		if (s.NotEmpty ())
4787*fd1fabb7SAndroid Build Coastguard Worker 			{
4788*fd1fabb7SAndroid Build Coastguard Worker 
4789*fd1fabb7SAndroid Build Coastguard Worker 			newXMP.SetString (ns, path, s);
4790*fd1fabb7SAndroid Build Coastguard Worker 
4791*fd1fabb7SAndroid Build Coastguard Worker 			if (exif)
4792*fd1fabb7SAndroid Build Coastguard Worker 				{
4793*fd1fabb7SAndroid Build Coastguard Worker 
4794*fd1fabb7SAndroid Build Coastguard Worker 				*exif = s;
4795*fd1fabb7SAndroid Build Coastguard Worker 
4796*fd1fabb7SAndroid Build Coastguard Worker 				}
4797*fd1fabb7SAndroid Build Coastguard Worker 
4798*fd1fabb7SAndroid Build Coastguard Worker 			}
4799*fd1fabb7SAndroid Build Coastguard Worker 
4800*fd1fabb7SAndroid Build Coastguard Worker 		}
4801*fd1fabb7SAndroid Build Coastguard Worker 
4802*fd1fabb7SAndroid Build Coastguard Worker 	}
4803*fd1fabb7SAndroid Build Coastguard Worker 
4804*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
4805*fd1fabb7SAndroid Build Coastguard Worker 
CopyStringList(const dng_xmp & oldXMP,dng_xmp & newXMP,const char * ns,const char * path,bool isBag)4806*fd1fabb7SAndroid Build Coastguard Worker static void CopyStringList (const dng_xmp &oldXMP,
4807*fd1fabb7SAndroid Build Coastguard Worker 							dng_xmp &newXMP,
4808*fd1fabb7SAndroid Build Coastguard Worker 							const char *ns,
4809*fd1fabb7SAndroid Build Coastguard Worker 							const char *path,
4810*fd1fabb7SAndroid Build Coastguard Worker 							bool isBag)
4811*fd1fabb7SAndroid Build Coastguard Worker 	{
4812*fd1fabb7SAndroid Build Coastguard Worker 
4813*fd1fabb7SAndroid Build Coastguard Worker 	dng_string_list list;
4814*fd1fabb7SAndroid Build Coastguard Worker 
4815*fd1fabb7SAndroid Build Coastguard Worker 	if (oldXMP.GetStringList (ns, path, list))
4816*fd1fabb7SAndroid Build Coastguard Worker 		{
4817*fd1fabb7SAndroid Build Coastguard Worker 
4818*fd1fabb7SAndroid Build Coastguard Worker 		if (list.Count ())
4819*fd1fabb7SAndroid Build Coastguard Worker 			{
4820*fd1fabb7SAndroid Build Coastguard Worker 
4821*fd1fabb7SAndroid Build Coastguard Worker 			newXMP.SetStringList (ns, path, list, isBag);
4822*fd1fabb7SAndroid Build Coastguard Worker 
4823*fd1fabb7SAndroid Build Coastguard Worker 			}
4824*fd1fabb7SAndroid Build Coastguard Worker 
4825*fd1fabb7SAndroid Build Coastguard Worker 		}
4826*fd1fabb7SAndroid Build Coastguard Worker 
4827*fd1fabb7SAndroid Build Coastguard Worker 	}
4828*fd1fabb7SAndroid Build Coastguard Worker 
4829*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
4830*fd1fabb7SAndroid Build Coastguard Worker 
CopyAltLangDefault(const dng_xmp & oldXMP,dng_xmp & newXMP,const char * ns,const char * path,dng_string * exif=NULL)4831*fd1fabb7SAndroid Build Coastguard Worker static void CopyAltLangDefault (const dng_xmp &oldXMP,
4832*fd1fabb7SAndroid Build Coastguard Worker 								dng_xmp &newXMP,
4833*fd1fabb7SAndroid Build Coastguard Worker 								const char *ns,
4834*fd1fabb7SAndroid Build Coastguard Worker 								const char *path,
4835*fd1fabb7SAndroid Build Coastguard Worker 								dng_string *exif = NULL)
4836*fd1fabb7SAndroid Build Coastguard Worker 	{
4837*fd1fabb7SAndroid Build Coastguard Worker 
4838*fd1fabb7SAndroid Build Coastguard Worker 	dng_string s;
4839*fd1fabb7SAndroid Build Coastguard Worker 
4840*fd1fabb7SAndroid Build Coastguard Worker 	if (oldXMP.GetAltLangDefault (ns, path, s))
4841*fd1fabb7SAndroid Build Coastguard Worker 		{
4842*fd1fabb7SAndroid Build Coastguard Worker 
4843*fd1fabb7SAndroid Build Coastguard Worker 		if (s.NotEmpty ())
4844*fd1fabb7SAndroid Build Coastguard Worker 			{
4845*fd1fabb7SAndroid Build Coastguard Worker 
4846*fd1fabb7SAndroid Build Coastguard Worker 			newXMP.SetAltLangDefault (ns, path, s);
4847*fd1fabb7SAndroid Build Coastguard Worker 
4848*fd1fabb7SAndroid Build Coastguard Worker 			if (exif)
4849*fd1fabb7SAndroid Build Coastguard Worker 				{
4850*fd1fabb7SAndroid Build Coastguard Worker 
4851*fd1fabb7SAndroid Build Coastguard Worker 				*exif = s;
4852*fd1fabb7SAndroid Build Coastguard Worker 
4853*fd1fabb7SAndroid Build Coastguard Worker 				}
4854*fd1fabb7SAndroid Build Coastguard Worker 
4855*fd1fabb7SAndroid Build Coastguard Worker 			}
4856*fd1fabb7SAndroid Build Coastguard Worker 
4857*fd1fabb7SAndroid Build Coastguard Worker 		}
4858*fd1fabb7SAndroid Build Coastguard Worker 
4859*fd1fabb7SAndroid Build Coastguard Worker 	}
4860*fd1fabb7SAndroid Build Coastguard Worker 
4861*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
4862*fd1fabb7SAndroid Build Coastguard Worker 
CopyStructField(const dng_xmp & oldXMP,dng_xmp & newXMP,const char * ns,const char * path,const char * field)4863*fd1fabb7SAndroid Build Coastguard Worker static void CopyStructField (const dng_xmp &oldXMP,
4864*fd1fabb7SAndroid Build Coastguard Worker 							 dng_xmp &newXMP,
4865*fd1fabb7SAndroid Build Coastguard Worker 							 const char *ns,
4866*fd1fabb7SAndroid Build Coastguard Worker 							 const char *path,
4867*fd1fabb7SAndroid Build Coastguard Worker 							 const char *field)
4868*fd1fabb7SAndroid Build Coastguard Worker 	{
4869*fd1fabb7SAndroid Build Coastguard Worker 
4870*fd1fabb7SAndroid Build Coastguard Worker 	dng_string s;
4871*fd1fabb7SAndroid Build Coastguard Worker 
4872*fd1fabb7SAndroid Build Coastguard Worker 	if (oldXMP.GetStructField (ns, path, ns, field, s))
4873*fd1fabb7SAndroid Build Coastguard Worker 		{
4874*fd1fabb7SAndroid Build Coastguard Worker 
4875*fd1fabb7SAndroid Build Coastguard Worker 		if (s.NotEmpty ())
4876*fd1fabb7SAndroid Build Coastguard Worker 			{
4877*fd1fabb7SAndroid Build Coastguard Worker 
4878*fd1fabb7SAndroid Build Coastguard Worker 			newXMP.SetStructField (ns, path, ns, field, s);
4879*fd1fabb7SAndroid Build Coastguard Worker 
4880*fd1fabb7SAndroid Build Coastguard Worker 			}
4881*fd1fabb7SAndroid Build Coastguard Worker 
4882*fd1fabb7SAndroid Build Coastguard Worker 		}
4883*fd1fabb7SAndroid Build Coastguard Worker 
4884*fd1fabb7SAndroid Build Coastguard Worker 	}
4885*fd1fabb7SAndroid Build Coastguard Worker 
4886*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
4887*fd1fabb7SAndroid Build Coastguard Worker 
CopyBoolean(const dng_xmp & oldXMP,dng_xmp & newXMP,const char * ns,const char * path)4888*fd1fabb7SAndroid Build Coastguard Worker static void CopyBoolean (const dng_xmp &oldXMP,
4889*fd1fabb7SAndroid Build Coastguard Worker 						 dng_xmp &newXMP,
4890*fd1fabb7SAndroid Build Coastguard Worker 						 const char *ns,
4891*fd1fabb7SAndroid Build Coastguard Worker 						 const char *path)
4892*fd1fabb7SAndroid Build Coastguard Worker 	{
4893*fd1fabb7SAndroid Build Coastguard Worker 
4894*fd1fabb7SAndroid Build Coastguard Worker 	bool b;
4895*fd1fabb7SAndroid Build Coastguard Worker 
4896*fd1fabb7SAndroid Build Coastguard Worker 	if (oldXMP.GetBoolean (ns, path, b))
4897*fd1fabb7SAndroid Build Coastguard Worker 		{
4898*fd1fabb7SAndroid Build Coastguard Worker 
4899*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.SetBoolean (ns, path, b);
4900*fd1fabb7SAndroid Build Coastguard Worker 
4901*fd1fabb7SAndroid Build Coastguard Worker 		}
4902*fd1fabb7SAndroid Build Coastguard Worker 
4903*fd1fabb7SAndroid Build Coastguard Worker 	}
4904*fd1fabb7SAndroid Build Coastguard Worker 
4905*fd1fabb7SAndroid Build Coastguard Worker #endif
4906*fd1fabb7SAndroid Build Coastguard Worker 
4907*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
4908*fd1fabb7SAndroid Build Coastguard Worker 
CleanUpMetadata(dng_host & host,dng_metadata & metadata,dng_metadata_subset metadataSubset,const char * dstMIMI,const char * software)4909*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::CleanUpMetadata (dng_host &host,
4910*fd1fabb7SAndroid Build Coastguard Worker 										dng_metadata &metadata,
4911*fd1fabb7SAndroid Build Coastguard Worker 										dng_metadata_subset metadataSubset,
4912*fd1fabb7SAndroid Build Coastguard Worker 										const char *dstMIMI,
4913*fd1fabb7SAndroid Build Coastguard Worker 										const char *software)
4914*fd1fabb7SAndroid Build Coastguard Worker 	{
4915*fd1fabb7SAndroid Build Coastguard Worker 
4916*fd1fabb7SAndroid Build Coastguard Worker 	#if qDNGUseXMP
4917*fd1fabb7SAndroid Build Coastguard Worker 
4918*fd1fabb7SAndroid Build Coastguard Worker 	if (metadata.GetXMP () && metadata.GetExif ())
4919*fd1fabb7SAndroid Build Coastguard Worker 		{
4920*fd1fabb7SAndroid Build Coastguard Worker 
4921*fd1fabb7SAndroid Build Coastguard Worker 		dng_xmp  &newXMP  (*metadata.GetXMP  ());
4922*fd1fabb7SAndroid Build Coastguard Worker 		dng_exif &newEXIF (*metadata.GetExif ());
4923*fd1fabb7SAndroid Build Coastguard Worker 
4924*fd1fabb7SAndroid Build Coastguard Worker 		// Update software tag.
4925*fd1fabb7SAndroid Build Coastguard Worker 
4926*fd1fabb7SAndroid Build Coastguard Worker 		if (software)
4927*fd1fabb7SAndroid Build Coastguard Worker 			{
4928*fd1fabb7SAndroid Build Coastguard Worker 
4929*fd1fabb7SAndroid Build Coastguard Worker 			newEXIF.fSoftware.Set (software);
4930*fd1fabb7SAndroid Build Coastguard Worker 
4931*fd1fabb7SAndroid Build Coastguard Worker 			newXMP.Set (XMP_NS_XAP,
4932*fd1fabb7SAndroid Build Coastguard Worker 						"CreatorTool",
4933*fd1fabb7SAndroid Build Coastguard Worker 						software);
4934*fd1fabb7SAndroid Build Coastguard Worker 
4935*fd1fabb7SAndroid Build Coastguard Worker 			}
4936*fd1fabb7SAndroid Build Coastguard Worker 
4937*fd1fabb7SAndroid Build Coastguard Worker 		#if qDNGXMPDocOps
4938*fd1fabb7SAndroid Build Coastguard Worker 
4939*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.DocOpsPrepareForSave (metadata.SourceMIMI ().Get (),
4940*fd1fabb7SAndroid Build Coastguard Worker 									 dstMIMI);
4941*fd1fabb7SAndroid Build Coastguard Worker 
4942*fd1fabb7SAndroid Build Coastguard Worker 		#else
4943*fd1fabb7SAndroid Build Coastguard Worker 
4944*fd1fabb7SAndroid Build Coastguard Worker 		metadata.UpdateDateTimeToNow ();
4945*fd1fabb7SAndroid Build Coastguard Worker 
4946*fd1fabb7SAndroid Build Coastguard Worker 		#endif
4947*fd1fabb7SAndroid Build Coastguard Worker 
4948*fd1fabb7SAndroid Build Coastguard Worker 		// Update EXIF version to at least 2.3 so all the exif tags
4949*fd1fabb7SAndroid Build Coastguard Worker 		// can be written.
4950*fd1fabb7SAndroid Build Coastguard Worker 
4951*fd1fabb7SAndroid Build Coastguard Worker 		if (newEXIF.fExifVersion < DNG_CHAR4 ('0','2','3','0'))
4952*fd1fabb7SAndroid Build Coastguard Worker 			{
4953*fd1fabb7SAndroid Build Coastguard Worker 
4954*fd1fabb7SAndroid Build Coastguard Worker 			newEXIF.fExifVersion = DNG_CHAR4 ('0','2','3','0');
4955*fd1fabb7SAndroid Build Coastguard Worker 
4956*fd1fabb7SAndroid Build Coastguard Worker 			newXMP.Set (XMP_NS_EXIF, "ExifVersion", "0230");
4957*fd1fabb7SAndroid Build Coastguard Worker 
4958*fd1fabb7SAndroid Build Coastguard Worker 			}
4959*fd1fabb7SAndroid Build Coastguard Worker 
4960*fd1fabb7SAndroid Build Coastguard Worker 		// Resync EXIF, remove EXIF tags from XMP.
4961*fd1fabb7SAndroid Build Coastguard Worker 
4962*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.SyncExif (newEXIF,
4963*fd1fabb7SAndroid Build Coastguard Worker 						 metadata.GetOriginalExif (),
4964*fd1fabb7SAndroid Build Coastguard Worker 						 false,
4965*fd1fabb7SAndroid Build Coastguard Worker 						 true);
4966*fd1fabb7SAndroid Build Coastguard Worker 
4967*fd1fabb7SAndroid Build Coastguard Worker 		// Deal with ImageIngesterPro bug.  This program is adding lots of
4968*fd1fabb7SAndroid Build Coastguard Worker 		// empty metadata strings into the XMP, which is screwing up Adobe CS4.
4969*fd1fabb7SAndroid Build Coastguard Worker 		// We are saving a new file, so this is a chance to clean up this mess.
4970*fd1fabb7SAndroid Build Coastguard Worker 
4971*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.RemoveEmptyStringsAndArrays (XMP_NS_DC);
4972*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.RemoveEmptyStringsAndArrays (XMP_NS_XAP);
4973*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.RemoveEmptyStringsAndArrays (XMP_NS_PHOTOSHOP);
4974*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.RemoveEmptyStringsAndArrays (XMP_NS_IPTC);
4975*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.RemoveEmptyStringsAndArrays (XMP_NS_XAP_RIGHTS);
4976*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.RemoveEmptyStringsAndArrays ("http://ns.iview-multimedia.com/mediapro/1.0/");
4977*fd1fabb7SAndroid Build Coastguard Worker 
4978*fd1fabb7SAndroid Build Coastguard Worker 		// Process metadata subset.
4979*fd1fabb7SAndroid Build Coastguard Worker 
4980*fd1fabb7SAndroid Build Coastguard Worker 		if (metadataSubset == kMetadataSubset_CopyrightOnly ||
4981*fd1fabb7SAndroid Build Coastguard Worker 			metadataSubset == kMetadataSubset_CopyrightAndContact)
4982*fd1fabb7SAndroid Build Coastguard Worker 			{
4983*fd1fabb7SAndroid Build Coastguard Worker 
4984*fd1fabb7SAndroid Build Coastguard Worker 			dng_xmp  oldXMP  (newXMP );
4985*fd1fabb7SAndroid Build Coastguard Worker 			dng_exif oldEXIF (newEXIF);
4986*fd1fabb7SAndroid Build Coastguard Worker 
4987*fd1fabb7SAndroid Build Coastguard Worker 			// For these options, we start from nothing, and only fill in the
4988*fd1fabb7SAndroid Build Coastguard Worker 			// fields that we absolutely need.
4989*fd1fabb7SAndroid Build Coastguard Worker 
4990*fd1fabb7SAndroid Build Coastguard Worker 			newXMP.RemoveProperties (NULL);
4991*fd1fabb7SAndroid Build Coastguard Worker 
4992*fd1fabb7SAndroid Build Coastguard Worker 			newEXIF.SetEmpty ();
4993*fd1fabb7SAndroid Build Coastguard Worker 
4994*fd1fabb7SAndroid Build Coastguard Worker 			metadata.ClearMakerNote ();
4995*fd1fabb7SAndroid Build Coastguard Worker 
4996*fd1fabb7SAndroid Build Coastguard Worker 			// Move copyright related fields over.
4997*fd1fabb7SAndroid Build Coastguard Worker 
4998*fd1fabb7SAndroid Build Coastguard Worker 			CopyAltLangDefault (oldXMP,
4999*fd1fabb7SAndroid Build Coastguard Worker 								newXMP,
5000*fd1fabb7SAndroid Build Coastguard Worker 								XMP_NS_DC,
5001*fd1fabb7SAndroid Build Coastguard Worker 								"rights",
5002*fd1fabb7SAndroid Build Coastguard Worker 								&newEXIF.fCopyright);
5003*fd1fabb7SAndroid Build Coastguard Worker 
5004*fd1fabb7SAndroid Build Coastguard Worker 			CopyAltLangDefault (oldXMP,
5005*fd1fabb7SAndroid Build Coastguard Worker 								newXMP,
5006*fd1fabb7SAndroid Build Coastguard Worker 								XMP_NS_XAP_RIGHTS,
5007*fd1fabb7SAndroid Build Coastguard Worker 								"UsageTerms");
5008*fd1fabb7SAndroid Build Coastguard Worker 
5009*fd1fabb7SAndroid Build Coastguard Worker 			CopyString (oldXMP,
5010*fd1fabb7SAndroid Build Coastguard Worker 						newXMP,
5011*fd1fabb7SAndroid Build Coastguard Worker 						XMP_NS_XAP_RIGHTS,
5012*fd1fabb7SAndroid Build Coastguard Worker 						"WebStatement");
5013*fd1fabb7SAndroid Build Coastguard Worker 
5014*fd1fabb7SAndroid Build Coastguard Worker 			CopyBoolean (oldXMP,
5015*fd1fabb7SAndroid Build Coastguard Worker 						 newXMP,
5016*fd1fabb7SAndroid Build Coastguard Worker 						 XMP_NS_XAP_RIGHTS,
5017*fd1fabb7SAndroid Build Coastguard Worker 						 "Marked");
5018*fd1fabb7SAndroid Build Coastguard Worker 
5019*fd1fabb7SAndroid Build Coastguard Worker 			#if qDNGXMPDocOps
5020*fd1fabb7SAndroid Build Coastguard Worker 
5021*fd1fabb7SAndroid Build Coastguard Worker 			// Include basic DocOps fields, but not the full history.
5022*fd1fabb7SAndroid Build Coastguard Worker 
5023*fd1fabb7SAndroid Build Coastguard Worker 			CopyString (oldXMP,
5024*fd1fabb7SAndroid Build Coastguard Worker 						newXMP,
5025*fd1fabb7SAndroid Build Coastguard Worker 						XMP_NS_MM,
5026*fd1fabb7SAndroid Build Coastguard Worker 						"OriginalDocumentID");
5027*fd1fabb7SAndroid Build Coastguard Worker 
5028*fd1fabb7SAndroid Build Coastguard Worker 			CopyString (oldXMP,
5029*fd1fabb7SAndroid Build Coastguard Worker 						newXMP,
5030*fd1fabb7SAndroid Build Coastguard Worker 						XMP_NS_MM,
5031*fd1fabb7SAndroid Build Coastguard Worker 						"DocumentID");
5032*fd1fabb7SAndroid Build Coastguard Worker 
5033*fd1fabb7SAndroid Build Coastguard Worker 			CopyString (oldXMP,
5034*fd1fabb7SAndroid Build Coastguard Worker 						newXMP,
5035*fd1fabb7SAndroid Build Coastguard Worker 						XMP_NS_MM,
5036*fd1fabb7SAndroid Build Coastguard Worker 						"InstanceID");
5037*fd1fabb7SAndroid Build Coastguard Worker 
5038*fd1fabb7SAndroid Build Coastguard Worker 			CopyString (oldXMP,
5039*fd1fabb7SAndroid Build Coastguard Worker 						newXMP,
5040*fd1fabb7SAndroid Build Coastguard Worker 						XMP_NS_XAP,
5041*fd1fabb7SAndroid Build Coastguard Worker 						"MetadataDate");
5042*fd1fabb7SAndroid Build Coastguard Worker 
5043*fd1fabb7SAndroid Build Coastguard Worker 			#endif
5044*fd1fabb7SAndroid Build Coastguard Worker 
5045*fd1fabb7SAndroid Build Coastguard Worker 			// Copyright and Contact adds the contact info fields.
5046*fd1fabb7SAndroid Build Coastguard Worker 
5047*fd1fabb7SAndroid Build Coastguard Worker 			if (metadataSubset == kMetadataSubset_CopyrightAndContact)
5048*fd1fabb7SAndroid Build Coastguard Worker 				{
5049*fd1fabb7SAndroid Build Coastguard Worker 
5050*fd1fabb7SAndroid Build Coastguard Worker 				// Note: Save for Web is not including the dc:creator list, but it
5051*fd1fabb7SAndroid Build Coastguard Worker 				// is part of the IPTC contract info metadata panel, so I
5052*fd1fabb7SAndroid Build Coastguard Worker 				// think it should be copied as part of the contact info.
5053*fd1fabb7SAndroid Build Coastguard Worker 
5054*fd1fabb7SAndroid Build Coastguard Worker 				CopyStringList (oldXMP,
5055*fd1fabb7SAndroid Build Coastguard Worker 								newXMP,
5056*fd1fabb7SAndroid Build Coastguard Worker 								XMP_NS_DC,
5057*fd1fabb7SAndroid Build Coastguard Worker 								"creator",
5058*fd1fabb7SAndroid Build Coastguard Worker 								false);
5059*fd1fabb7SAndroid Build Coastguard Worker 
5060*fd1fabb7SAndroid Build Coastguard Worker 				// The first string dc:creator list is mirrored to the
5061*fd1fabb7SAndroid Build Coastguard Worker 				// the exif artist tag, so copy that also.
5062*fd1fabb7SAndroid Build Coastguard Worker 
5063*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fArtist = oldEXIF.fArtist;
5064*fd1fabb7SAndroid Build Coastguard Worker 
5065*fd1fabb7SAndroid Build Coastguard Worker 				// Copy other contact fields.
5066*fd1fabb7SAndroid Build Coastguard Worker 
5067*fd1fabb7SAndroid Build Coastguard Worker 				CopyString (oldXMP,
5068*fd1fabb7SAndroid Build Coastguard Worker 							newXMP,
5069*fd1fabb7SAndroid Build Coastguard Worker 							XMP_NS_PHOTOSHOP,
5070*fd1fabb7SAndroid Build Coastguard Worker 							"AuthorsPosition");
5071*fd1fabb7SAndroid Build Coastguard Worker 
5072*fd1fabb7SAndroid Build Coastguard Worker 				CopyStructField (oldXMP,
5073*fd1fabb7SAndroid Build Coastguard Worker 								 newXMP,
5074*fd1fabb7SAndroid Build Coastguard Worker 								 XMP_NS_IPTC,
5075*fd1fabb7SAndroid Build Coastguard Worker 								 "CreatorContactInfo",
5076*fd1fabb7SAndroid Build Coastguard Worker 								 "CiEmailWork");
5077*fd1fabb7SAndroid Build Coastguard Worker 
5078*fd1fabb7SAndroid Build Coastguard Worker 				CopyStructField (oldXMP,
5079*fd1fabb7SAndroid Build Coastguard Worker 								 newXMP,
5080*fd1fabb7SAndroid Build Coastguard Worker 								 XMP_NS_IPTC,
5081*fd1fabb7SAndroid Build Coastguard Worker 								 "CreatorContactInfo",
5082*fd1fabb7SAndroid Build Coastguard Worker 								 "CiAdrExtadr");
5083*fd1fabb7SAndroid Build Coastguard Worker 
5084*fd1fabb7SAndroid Build Coastguard Worker 				CopyStructField (oldXMP,
5085*fd1fabb7SAndroid Build Coastguard Worker 								 newXMP,
5086*fd1fabb7SAndroid Build Coastguard Worker 								 XMP_NS_IPTC,
5087*fd1fabb7SAndroid Build Coastguard Worker 								 "CreatorContactInfo",
5088*fd1fabb7SAndroid Build Coastguard Worker 								 "CiAdrCity");
5089*fd1fabb7SAndroid Build Coastguard Worker 
5090*fd1fabb7SAndroid Build Coastguard Worker 				CopyStructField (oldXMP,
5091*fd1fabb7SAndroid Build Coastguard Worker 								 newXMP,
5092*fd1fabb7SAndroid Build Coastguard Worker 								 XMP_NS_IPTC,
5093*fd1fabb7SAndroid Build Coastguard Worker 								 "CreatorContactInfo",
5094*fd1fabb7SAndroid Build Coastguard Worker 								 "CiAdrRegion");
5095*fd1fabb7SAndroid Build Coastguard Worker 
5096*fd1fabb7SAndroid Build Coastguard Worker 				CopyStructField (oldXMP,
5097*fd1fabb7SAndroid Build Coastguard Worker 								 newXMP,
5098*fd1fabb7SAndroid Build Coastguard Worker 								 XMP_NS_IPTC,
5099*fd1fabb7SAndroid Build Coastguard Worker 								 "CreatorContactInfo",
5100*fd1fabb7SAndroid Build Coastguard Worker 								 "CiAdrPcode");
5101*fd1fabb7SAndroid Build Coastguard Worker 
5102*fd1fabb7SAndroid Build Coastguard Worker 				CopyStructField (oldXMP,
5103*fd1fabb7SAndroid Build Coastguard Worker 								 newXMP,
5104*fd1fabb7SAndroid Build Coastguard Worker 								 XMP_NS_IPTC,
5105*fd1fabb7SAndroid Build Coastguard Worker 								 "CreatorContactInfo",
5106*fd1fabb7SAndroid Build Coastguard Worker 								 "CiAdrCtry");
5107*fd1fabb7SAndroid Build Coastguard Worker 
5108*fd1fabb7SAndroid Build Coastguard Worker 				CopyStructField (oldXMP,
5109*fd1fabb7SAndroid Build Coastguard Worker 								 newXMP,
5110*fd1fabb7SAndroid Build Coastguard Worker 								 XMP_NS_IPTC,
5111*fd1fabb7SAndroid Build Coastguard Worker 								 "CreatorContactInfo",
5112*fd1fabb7SAndroid Build Coastguard Worker 								 "CiTelWork");
5113*fd1fabb7SAndroid Build Coastguard Worker 
5114*fd1fabb7SAndroid Build Coastguard Worker 				CopyStructField (oldXMP,
5115*fd1fabb7SAndroid Build Coastguard Worker 								 newXMP,
5116*fd1fabb7SAndroid Build Coastguard Worker 								 XMP_NS_IPTC,
5117*fd1fabb7SAndroid Build Coastguard Worker 								 "CreatorContactInfo",
5118*fd1fabb7SAndroid Build Coastguard Worker 								 "CiUrlWork");
5119*fd1fabb7SAndroid Build Coastguard Worker 
5120*fd1fabb7SAndroid Build Coastguard Worker 				CopyAltLangDefault (oldXMP,
5121*fd1fabb7SAndroid Build Coastguard Worker 									newXMP,
5122*fd1fabb7SAndroid Build Coastguard Worker 									XMP_NS_DC,
5123*fd1fabb7SAndroid Build Coastguard Worker 									"title");
5124*fd1fabb7SAndroid Build Coastguard Worker 
5125*fd1fabb7SAndroid Build Coastguard Worker 				}
5126*fd1fabb7SAndroid Build Coastguard Worker 
5127*fd1fabb7SAndroid Build Coastguard Worker  			}
5128*fd1fabb7SAndroid Build Coastguard Worker 
5129*fd1fabb7SAndroid Build Coastguard Worker 		else if (metadataSubset == kMetadataSubset_AllExceptCameraInfo        ||
5130*fd1fabb7SAndroid Build Coastguard Worker 				 metadataSubset == kMetadataSubset_AllExceptCameraAndLocation ||
5131*fd1fabb7SAndroid Build Coastguard Worker 				 metadataSubset == kMetadataSubset_AllExceptLocationInfo)
5132*fd1fabb7SAndroid Build Coastguard Worker 			{
5133*fd1fabb7SAndroid Build Coastguard Worker 
5134*fd1fabb7SAndroid Build Coastguard Worker 			dng_xmp  oldXMP  (newXMP );
5135*fd1fabb7SAndroid Build Coastguard Worker 			dng_exif oldEXIF (newEXIF);
5136*fd1fabb7SAndroid Build Coastguard Worker 
5137*fd1fabb7SAndroid Build Coastguard Worker 			if (metadataSubset == kMetadataSubset_AllExceptCameraInfo ||
5138*fd1fabb7SAndroid Build Coastguard Worker 				metadataSubset == kMetadataSubset_AllExceptCameraAndLocation)
5139*fd1fabb7SAndroid Build Coastguard Worker 				{
5140*fd1fabb7SAndroid Build Coastguard Worker 
5141*fd1fabb7SAndroid Build Coastguard Worker 				// This removes most of the EXIF info, so just copy the fields
5142*fd1fabb7SAndroid Build Coastguard Worker 				// we are not deleting.
5143*fd1fabb7SAndroid Build Coastguard Worker 
5144*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.SetEmpty ();
5145*fd1fabb7SAndroid Build Coastguard Worker 
5146*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fImageDescription  = oldEXIF.fImageDescription;		// Note: Differs from SFW
5147*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fSoftware          = oldEXIF.fSoftware;
5148*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fArtist            = oldEXIF.fArtist;
5149*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fCopyright         = oldEXIF.fCopyright;
5150*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fCopyright2        = oldEXIF.fCopyright2;
5151*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fDateTime          = oldEXIF.fDateTime;
5152*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fDateTimeOriginal  = oldEXIF.fDateTimeOriginal;
5153*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fDateTimeDigitized = oldEXIF.fDateTimeDigitized;
5154*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fExifVersion       = oldEXIF.fExifVersion;
5155*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.fImageUniqueID	   = oldEXIF.fImageUniqueID;
5156*fd1fabb7SAndroid Build Coastguard Worker 
5157*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.CopyGPSFrom (oldEXIF);
5158*fd1fabb7SAndroid Build Coastguard Worker 
5159*fd1fabb7SAndroid Build Coastguard Worker 				// Remove exif info from XMP.
5160*fd1fabb7SAndroid Build Coastguard Worker 
5161*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.RemoveProperties (XMP_NS_EXIF);
5162*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.RemoveProperties (XMP_NS_AUX);
5163*fd1fabb7SAndroid Build Coastguard Worker 
5164*fd1fabb7SAndroid Build Coastguard Worker 				// Remove Camera Raw info
5165*fd1fabb7SAndroid Build Coastguard Worker 
5166*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.RemoveProperties (XMP_NS_CRS);
5167*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.RemoveProperties (XMP_NS_CRSS);
5168*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.RemoveProperties (XMP_NS_CRX);
5169*fd1fabb7SAndroid Build Coastguard Worker 
5170*fd1fabb7SAndroid Build Coastguard Worker 				// Remove DocOps history, since it contains the original
5171*fd1fabb7SAndroid Build Coastguard Worker 				// camera format.
5172*fd1fabb7SAndroid Build Coastguard Worker 
5173*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.Remove (XMP_NS_MM, "History");
5174*fd1fabb7SAndroid Build Coastguard Worker 
5175*fd1fabb7SAndroid Build Coastguard Worker 				// MakerNote contains camera info.
5176*fd1fabb7SAndroid Build Coastguard Worker 
5177*fd1fabb7SAndroid Build Coastguard Worker 				metadata.ClearMakerNote ();
5178*fd1fabb7SAndroid Build Coastguard Worker 
5179*fd1fabb7SAndroid Build Coastguard Worker 				}
5180*fd1fabb7SAndroid Build Coastguard Worker 
5181*fd1fabb7SAndroid Build Coastguard Worker 			if (metadataSubset == kMetadataSubset_AllExceptLocationInfo ||
5182*fd1fabb7SAndroid Build Coastguard Worker 				metadataSubset == kMetadataSubset_AllExceptCameraAndLocation)
5183*fd1fabb7SAndroid Build Coastguard Worker 				{
5184*fd1fabb7SAndroid Build Coastguard Worker 
5185*fd1fabb7SAndroid Build Coastguard Worker 				// Remove GPS fields.
5186*fd1fabb7SAndroid Build Coastguard Worker 
5187*fd1fabb7SAndroid Build Coastguard Worker 				dng_exif blankExif;
5188*fd1fabb7SAndroid Build Coastguard Worker 
5189*fd1fabb7SAndroid Build Coastguard Worker 				newEXIF.CopyGPSFrom (blankExif);
5190*fd1fabb7SAndroid Build Coastguard Worker 
5191*fd1fabb7SAndroid Build Coastguard Worker 				// Remove MakerNote just in case, because we don't know
5192*fd1fabb7SAndroid Build Coastguard Worker 				// all of what is in it.
5193*fd1fabb7SAndroid Build Coastguard Worker 
5194*fd1fabb7SAndroid Build Coastguard Worker 				metadata.ClearMakerNote ();
5195*fd1fabb7SAndroid Build Coastguard Worker 
5196*fd1fabb7SAndroid Build Coastguard Worker 				// Remove XMP & IPTC location fields.
5197*fd1fabb7SAndroid Build Coastguard Worker 
5198*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.Remove (XMP_NS_PHOTOSHOP, "City");
5199*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.Remove (XMP_NS_PHOTOSHOP, "State");
5200*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.Remove (XMP_NS_PHOTOSHOP, "Country");
5201*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.Remove (XMP_NS_IPTC, "Location");
5202*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.Remove (XMP_NS_IPTC, "CountryCode");
5203*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.Remove (XMP_NS_IPTC_EXT, "LocationCreated");
5204*fd1fabb7SAndroid Build Coastguard Worker 				newXMP.Remove (XMP_NS_IPTC_EXT, "LocationShown");
5205*fd1fabb7SAndroid Build Coastguard Worker 
5206*fd1fabb7SAndroid Build Coastguard Worker 				}
5207*fd1fabb7SAndroid Build Coastguard Worker 
5208*fd1fabb7SAndroid Build Coastguard Worker 			}
5209*fd1fabb7SAndroid Build Coastguard Worker 
5210*fd1fabb7SAndroid Build Coastguard Worker 		// Rebuild the legacy IPTC block, if needed.
5211*fd1fabb7SAndroid Build Coastguard Worker 
5212*fd1fabb7SAndroid Build Coastguard Worker 		bool isTIFF = (strcmp (dstMIMI, "image/tiff") == 0);
5213*fd1fabb7SAndroid Build Coastguard Worker 		bool isDNG  = (strcmp (dstMIMI, "image/dng" ) == 0);
5214*fd1fabb7SAndroid Build Coastguard Worker 
5215*fd1fabb7SAndroid Build Coastguard Worker 		if (!isDNG)
5216*fd1fabb7SAndroid Build Coastguard Worker 			{
5217*fd1fabb7SAndroid Build Coastguard Worker 
5218*fd1fabb7SAndroid Build Coastguard Worker 			metadata.RebuildIPTC (host.Allocator (),
5219*fd1fabb7SAndroid Build Coastguard Worker 								  isTIFF);
5220*fd1fabb7SAndroid Build Coastguard Worker 
5221*fd1fabb7SAndroid Build Coastguard Worker 			}
5222*fd1fabb7SAndroid Build Coastguard Worker 
5223*fd1fabb7SAndroid Build Coastguard Worker 		else
5224*fd1fabb7SAndroid Build Coastguard Worker 			{
5225*fd1fabb7SAndroid Build Coastguard Worker 
5226*fd1fabb7SAndroid Build Coastguard Worker 			metadata.ClearIPTC ();
5227*fd1fabb7SAndroid Build Coastguard Worker 
5228*fd1fabb7SAndroid Build Coastguard Worker 			}
5229*fd1fabb7SAndroid Build Coastguard Worker 
5230*fd1fabb7SAndroid Build Coastguard Worker 		// Clear format related XMP.
5231*fd1fabb7SAndroid Build Coastguard Worker 
5232*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.ClearOrientation ();
5233*fd1fabb7SAndroid Build Coastguard Worker 
5234*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.ClearImageInfo ();
5235*fd1fabb7SAndroid Build Coastguard Worker 
5236*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.RemoveProperties (XMP_NS_DNG);
5237*fd1fabb7SAndroid Build Coastguard Worker 
5238*fd1fabb7SAndroid Build Coastguard Worker 		// All the formats we care about already keep the IPTC digest
5239*fd1fabb7SAndroid Build Coastguard Worker 		// elsewhere, do we don't need to write it to the XMP.
5240*fd1fabb7SAndroid Build Coastguard Worker 
5241*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.ClearIPTCDigest ();
5242*fd1fabb7SAndroid Build Coastguard Worker 
5243*fd1fabb7SAndroid Build Coastguard Worker 		// Make sure that sidecar specific tags never get written to files.
5244*fd1fabb7SAndroid Build Coastguard Worker 
5245*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.Remove (XMP_NS_PHOTOSHOP, "SidecarForExtension");
5246*fd1fabb7SAndroid Build Coastguard Worker 		newXMP.Remove (XMP_NS_PHOTOSHOP, "EmbeddedXMPDigest");
5247*fd1fabb7SAndroid Build Coastguard Worker 
5248*fd1fabb7SAndroid Build Coastguard Worker 		}
5249*fd1fabb7SAndroid Build Coastguard Worker 
5250*fd1fabb7SAndroid Build Coastguard Worker 	#endif
5251*fd1fabb7SAndroid Build Coastguard Worker 
5252*fd1fabb7SAndroid Build Coastguard Worker 	}
5253*fd1fabb7SAndroid Build Coastguard Worker 
5254*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
5255*fd1fabb7SAndroid Build Coastguard Worker 
WriteTIFF(dng_host & host,dng_stream & stream,const dng_image & image,uint32 photometricInterpretation,uint32 compression,dng_negative * negative,const dng_color_space * space,const dng_resolution * resolution,const dng_jpeg_preview * thumbnail,const dng_memory_block * imageResources,dng_metadata_subset metadataSubset)5256*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::WriteTIFF (dng_host &host,
5257*fd1fabb7SAndroid Build Coastguard Worker 								  dng_stream &stream,
5258*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_image &image,
5259*fd1fabb7SAndroid Build Coastguard Worker 								  uint32 photometricInterpretation,
5260*fd1fabb7SAndroid Build Coastguard Worker 								  uint32 compression,
5261*fd1fabb7SAndroid Build Coastguard Worker 								  dng_negative *negative,
5262*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_color_space *space,
5263*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_resolution *resolution,
5264*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_jpeg_preview *thumbnail,
5265*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_memory_block *imageResources,
5266*fd1fabb7SAndroid Build Coastguard Worker 								  dng_metadata_subset metadataSubset)
5267*fd1fabb7SAndroid Build Coastguard Worker 	{
5268*fd1fabb7SAndroid Build Coastguard Worker 
5269*fd1fabb7SAndroid Build Coastguard Worker 	WriteTIFF (host,
5270*fd1fabb7SAndroid Build Coastguard Worker 			   stream,
5271*fd1fabb7SAndroid Build Coastguard Worker 			   image,
5272*fd1fabb7SAndroid Build Coastguard Worker 			   photometricInterpretation,
5273*fd1fabb7SAndroid Build Coastguard Worker 			   compression,
5274*fd1fabb7SAndroid Build Coastguard Worker 			   negative ? &(negative->Metadata ()) : NULL,
5275*fd1fabb7SAndroid Build Coastguard Worker 			   space,
5276*fd1fabb7SAndroid Build Coastguard Worker 			   resolution,
5277*fd1fabb7SAndroid Build Coastguard Worker 			   thumbnail,
5278*fd1fabb7SAndroid Build Coastguard Worker 			   imageResources,
5279*fd1fabb7SAndroid Build Coastguard Worker 			   metadataSubset);
5280*fd1fabb7SAndroid Build Coastguard Worker 
5281*fd1fabb7SAndroid Build Coastguard Worker 	}
5282*fd1fabb7SAndroid Build Coastguard Worker 
5283*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
5284*fd1fabb7SAndroid Build Coastguard Worker 
WriteTIFF(dng_host & host,dng_stream & stream,const dng_image & image,uint32 photometricInterpretation,uint32 compression,const dng_metadata * metadata,const dng_color_space * space,const dng_resolution * resolution,const dng_jpeg_preview * thumbnail,const dng_memory_block * imageResources,dng_metadata_subset metadataSubset)5285*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::WriteTIFF (dng_host &host,
5286*fd1fabb7SAndroid Build Coastguard Worker 								  dng_stream &stream,
5287*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_image &image,
5288*fd1fabb7SAndroid Build Coastguard Worker 								  uint32 photometricInterpretation,
5289*fd1fabb7SAndroid Build Coastguard Worker 								  uint32 compression,
5290*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_metadata *metadata,
5291*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_color_space *space,
5292*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_resolution *resolution,
5293*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_jpeg_preview *thumbnail,
5294*fd1fabb7SAndroid Build Coastguard Worker 								  const dng_memory_block *imageResources,
5295*fd1fabb7SAndroid Build Coastguard Worker 								  dng_metadata_subset metadataSubset)
5296*fd1fabb7SAndroid Build Coastguard Worker 	{
5297*fd1fabb7SAndroid Build Coastguard Worker 
5298*fd1fabb7SAndroid Build Coastguard Worker 	const void *profileData = NULL;
5299*fd1fabb7SAndroid Build Coastguard Worker 	uint32 profileSize = 0;
5300*fd1fabb7SAndroid Build Coastguard Worker 
5301*fd1fabb7SAndroid Build Coastguard Worker 	const uint8 *data = NULL;
5302*fd1fabb7SAndroid Build Coastguard Worker 	uint32 size = 0;
5303*fd1fabb7SAndroid Build Coastguard Worker 
5304*fd1fabb7SAndroid Build Coastguard Worker 	if (space && space->ICCProfile (size, data))
5305*fd1fabb7SAndroid Build Coastguard Worker 		{
5306*fd1fabb7SAndroid Build Coastguard Worker 
5307*fd1fabb7SAndroid Build Coastguard Worker 		profileData = data;
5308*fd1fabb7SAndroid Build Coastguard Worker 		profileSize = size;
5309*fd1fabb7SAndroid Build Coastguard Worker 
5310*fd1fabb7SAndroid Build Coastguard Worker 		}
5311*fd1fabb7SAndroid Build Coastguard Worker 
5312*fd1fabb7SAndroid Build Coastguard Worker 	WriteTIFFWithProfile (host,
5313*fd1fabb7SAndroid Build Coastguard Worker 						  stream,
5314*fd1fabb7SAndroid Build Coastguard Worker 						  image,
5315*fd1fabb7SAndroid Build Coastguard Worker 						  photometricInterpretation,
5316*fd1fabb7SAndroid Build Coastguard Worker 						  compression,
5317*fd1fabb7SAndroid Build Coastguard Worker 						  metadata,
5318*fd1fabb7SAndroid Build Coastguard Worker 						  profileData,
5319*fd1fabb7SAndroid Build Coastguard Worker 						  profileSize,
5320*fd1fabb7SAndroid Build Coastguard Worker 						  resolution,
5321*fd1fabb7SAndroid Build Coastguard Worker 						  thumbnail,
5322*fd1fabb7SAndroid Build Coastguard Worker 						  imageResources,
5323*fd1fabb7SAndroid Build Coastguard Worker 						  metadataSubset);
5324*fd1fabb7SAndroid Build Coastguard Worker 
5325*fd1fabb7SAndroid Build Coastguard Worker 	}
5326*fd1fabb7SAndroid Build Coastguard Worker 
5327*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
5328*fd1fabb7SAndroid Build Coastguard Worker 
WriteTIFFWithProfile(dng_host & host,dng_stream & stream,const dng_image & image,uint32 photometricInterpretation,uint32 compression,dng_negative * negative,const void * profileData,uint32 profileSize,const dng_resolution * resolution,const dng_jpeg_preview * thumbnail,const dng_memory_block * imageResources,dng_metadata_subset metadataSubset)5329*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::WriteTIFFWithProfile (dng_host &host,
5330*fd1fabb7SAndroid Build Coastguard Worker 											 dng_stream &stream,
5331*fd1fabb7SAndroid Build Coastguard Worker 											 const dng_image &image,
5332*fd1fabb7SAndroid Build Coastguard Worker 											 uint32 photometricInterpretation,
5333*fd1fabb7SAndroid Build Coastguard Worker 											 uint32 compression,
5334*fd1fabb7SAndroid Build Coastguard Worker 											 dng_negative *negative,
5335*fd1fabb7SAndroid Build Coastguard Worker 											 const void *profileData,
5336*fd1fabb7SAndroid Build Coastguard Worker 											 uint32 profileSize,
5337*fd1fabb7SAndroid Build Coastguard Worker 											 const dng_resolution *resolution,
5338*fd1fabb7SAndroid Build Coastguard Worker 											 const dng_jpeg_preview *thumbnail,
5339*fd1fabb7SAndroid Build Coastguard Worker 											 const dng_memory_block *imageResources,
5340*fd1fabb7SAndroid Build Coastguard Worker 											 dng_metadata_subset metadataSubset)
5341*fd1fabb7SAndroid Build Coastguard Worker 	{
5342*fd1fabb7SAndroid Build Coastguard Worker 
5343*fd1fabb7SAndroid Build Coastguard Worker 	WriteTIFFWithProfile (host,
5344*fd1fabb7SAndroid Build Coastguard Worker 						  stream,
5345*fd1fabb7SAndroid Build Coastguard Worker 						  image,
5346*fd1fabb7SAndroid Build Coastguard Worker 						  photometricInterpretation,
5347*fd1fabb7SAndroid Build Coastguard Worker 						  compression,
5348*fd1fabb7SAndroid Build Coastguard Worker 						  negative ? &(negative->Metadata ()) : NULL,
5349*fd1fabb7SAndroid Build Coastguard Worker 						  profileData,
5350*fd1fabb7SAndroid Build Coastguard Worker 						  profileSize,
5351*fd1fabb7SAndroid Build Coastguard Worker 						  resolution,
5352*fd1fabb7SAndroid Build Coastguard Worker 						  thumbnail,
5353*fd1fabb7SAndroid Build Coastguard Worker 						  imageResources,
5354*fd1fabb7SAndroid Build Coastguard Worker 						  metadataSubset);
5355*fd1fabb7SAndroid Build Coastguard Worker 
5356*fd1fabb7SAndroid Build Coastguard Worker 	}
5357*fd1fabb7SAndroid Build Coastguard Worker 
5358*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
5359*fd1fabb7SAndroid Build Coastguard Worker 
WriteTIFFWithProfile(dng_host & host,dng_stream & stream,const dng_image & image,uint32 photometricInterpretation,uint32 compression,const dng_metadata * constMetadata,const void * profileData,uint32 profileSize,const dng_resolution * resolution,const dng_jpeg_preview * thumbnail,const dng_memory_block * imageResources,dng_metadata_subset metadataSubset)5360*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::WriteTIFFWithProfile (dng_host &host,
5361*fd1fabb7SAndroid Build Coastguard Worker 											 dng_stream &stream,
5362*fd1fabb7SAndroid Build Coastguard Worker 											 const dng_image &image,
5363*fd1fabb7SAndroid Build Coastguard Worker 											 uint32 photometricInterpretation,
5364*fd1fabb7SAndroid Build Coastguard Worker 											 uint32 compression,
5365*fd1fabb7SAndroid Build Coastguard Worker 											 const dng_metadata *constMetadata,
5366*fd1fabb7SAndroid Build Coastguard Worker 											 const void *profileData,
5367*fd1fabb7SAndroid Build Coastguard Worker 											 uint32 profileSize,
5368*fd1fabb7SAndroid Build Coastguard Worker 											 const dng_resolution *resolution,
5369*fd1fabb7SAndroid Build Coastguard Worker 											 const dng_jpeg_preview *thumbnail,
5370*fd1fabb7SAndroid Build Coastguard Worker 											 const dng_memory_block *imageResources,
5371*fd1fabb7SAndroid Build Coastguard Worker 											 dng_metadata_subset metadataSubset)
5372*fd1fabb7SAndroid Build Coastguard Worker 	{
5373*fd1fabb7SAndroid Build Coastguard Worker 
5374*fd1fabb7SAndroid Build Coastguard Worker 	uint32 j;
5375*fd1fabb7SAndroid Build Coastguard Worker 
5376*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_metadata> metadata;
5377*fd1fabb7SAndroid Build Coastguard Worker 
5378*fd1fabb7SAndroid Build Coastguard Worker 	if (constMetadata)
5379*fd1fabb7SAndroid Build Coastguard Worker 		{
5380*fd1fabb7SAndroid Build Coastguard Worker 
5381*fd1fabb7SAndroid Build Coastguard Worker 		metadata.Reset (constMetadata->Clone (host.Allocator ()));
5382*fd1fabb7SAndroid Build Coastguard Worker 
5383*fd1fabb7SAndroid Build Coastguard Worker 		CleanUpMetadata (host,
5384*fd1fabb7SAndroid Build Coastguard Worker 						 *metadata,
5385*fd1fabb7SAndroid Build Coastguard Worker 						 metadataSubset,
5386*fd1fabb7SAndroid Build Coastguard Worker 						 "image/tiff");
5387*fd1fabb7SAndroid Build Coastguard Worker 
5388*fd1fabb7SAndroid Build Coastguard Worker 		}
5389*fd1fabb7SAndroid Build Coastguard Worker 
5390*fd1fabb7SAndroid Build Coastguard Worker 	dng_ifd ifd;
5391*fd1fabb7SAndroid Build Coastguard Worker 
5392*fd1fabb7SAndroid Build Coastguard Worker 	ifd.fNewSubFileType = sfMainImage;
5393*fd1fabb7SAndroid Build Coastguard Worker 
5394*fd1fabb7SAndroid Build Coastguard Worker 	ifd.fImageWidth  = image.Bounds ().W ();
5395*fd1fabb7SAndroid Build Coastguard Worker 	ifd.fImageLength = image.Bounds ().H ();
5396*fd1fabb7SAndroid Build Coastguard Worker 
5397*fd1fabb7SAndroid Build Coastguard Worker 	ifd.fSamplesPerPixel = image.Planes ();
5398*fd1fabb7SAndroid Build Coastguard Worker 
5399*fd1fabb7SAndroid Build Coastguard Worker 	ifd.fBitsPerSample [0] = TagTypeSize (image.PixelType ()) * 8;
5400*fd1fabb7SAndroid Build Coastguard Worker 
5401*fd1fabb7SAndroid Build Coastguard Worker 	for (j = 1; j < ifd.fSamplesPerPixel; j++)
5402*fd1fabb7SAndroid Build Coastguard Worker 		{
5403*fd1fabb7SAndroid Build Coastguard Worker 		ifd.fBitsPerSample [j] = ifd.fBitsPerSample [0];
5404*fd1fabb7SAndroid Build Coastguard Worker 		}
5405*fd1fabb7SAndroid Build Coastguard Worker 
5406*fd1fabb7SAndroid Build Coastguard Worker 	ifd.fPhotometricInterpretation = photometricInterpretation;
5407*fd1fabb7SAndroid Build Coastguard Worker 
5408*fd1fabb7SAndroid Build Coastguard Worker 	ifd.fCompression = compression;
5409*fd1fabb7SAndroid Build Coastguard Worker 
5410*fd1fabb7SAndroid Build Coastguard Worker 	if (ifd.fCompression == ccUncompressed)
5411*fd1fabb7SAndroid Build Coastguard Worker 		{
5412*fd1fabb7SAndroid Build Coastguard Worker 
5413*fd1fabb7SAndroid Build Coastguard Worker 		ifd.SetSingleStrip ();
5414*fd1fabb7SAndroid Build Coastguard Worker 
5415*fd1fabb7SAndroid Build Coastguard Worker 		}
5416*fd1fabb7SAndroid Build Coastguard Worker 
5417*fd1fabb7SAndroid Build Coastguard Worker 	else
5418*fd1fabb7SAndroid Build Coastguard Worker 		{
5419*fd1fabb7SAndroid Build Coastguard Worker 
5420*fd1fabb7SAndroid Build Coastguard Worker 		ifd.FindStripSize (128 * 1024);
5421*fd1fabb7SAndroid Build Coastguard Worker 
5422*fd1fabb7SAndroid Build Coastguard Worker 		ifd.fPredictor = cpHorizontalDifference;
5423*fd1fabb7SAndroid Build Coastguard Worker 
5424*fd1fabb7SAndroid Build Coastguard Worker 		}
5425*fd1fabb7SAndroid Build Coastguard Worker 
5426*fd1fabb7SAndroid Build Coastguard Worker 	uint32 extraSamples = 0;
5427*fd1fabb7SAndroid Build Coastguard Worker 
5428*fd1fabb7SAndroid Build Coastguard Worker 	switch (photometricInterpretation)
5429*fd1fabb7SAndroid Build Coastguard Worker 		{
5430*fd1fabb7SAndroid Build Coastguard Worker 
5431*fd1fabb7SAndroid Build Coastguard Worker 		case piBlackIsZero:
5432*fd1fabb7SAndroid Build Coastguard Worker 			{
5433*fd1fabb7SAndroid Build Coastguard Worker 			extraSamples = image.Planes () - 1;
5434*fd1fabb7SAndroid Build Coastguard Worker 			break;
5435*fd1fabb7SAndroid Build Coastguard Worker 			}
5436*fd1fabb7SAndroid Build Coastguard Worker 
5437*fd1fabb7SAndroid Build Coastguard Worker 		case piRGB:
5438*fd1fabb7SAndroid Build Coastguard Worker 			{
5439*fd1fabb7SAndroid Build Coastguard Worker 			extraSamples = image.Planes () - 3;
5440*fd1fabb7SAndroid Build Coastguard Worker 			break;
5441*fd1fabb7SAndroid Build Coastguard Worker 			}
5442*fd1fabb7SAndroid Build Coastguard Worker 
5443*fd1fabb7SAndroid Build Coastguard Worker 		default:
5444*fd1fabb7SAndroid Build Coastguard Worker 			break;
5445*fd1fabb7SAndroid Build Coastguard Worker 
5446*fd1fabb7SAndroid Build Coastguard Worker 		}
5447*fd1fabb7SAndroid Build Coastguard Worker 
5448*fd1fabb7SAndroid Build Coastguard Worker 	ifd.fExtraSamplesCount = extraSamples;
5449*fd1fabb7SAndroid Build Coastguard Worker 
5450*fd1fabb7SAndroid Build Coastguard Worker 	if (image.PixelType () == ttFloat)
5451*fd1fabb7SAndroid Build Coastguard Worker 		{
5452*fd1fabb7SAndroid Build Coastguard Worker 
5453*fd1fabb7SAndroid Build Coastguard Worker 		for (j = 0; j < ifd.fSamplesPerPixel; j++)
5454*fd1fabb7SAndroid Build Coastguard Worker 			{
5455*fd1fabb7SAndroid Build Coastguard Worker 			ifd.fSampleFormat [j] = sfFloatingPoint;
5456*fd1fabb7SAndroid Build Coastguard Worker 			}
5457*fd1fabb7SAndroid Build Coastguard Worker 
5458*fd1fabb7SAndroid Build Coastguard Worker 		}
5459*fd1fabb7SAndroid Build Coastguard Worker 
5460*fd1fabb7SAndroid Build Coastguard Worker 	dng_tiff_directory mainIFD;
5461*fd1fabb7SAndroid Build Coastguard Worker 
5462*fd1fabb7SAndroid Build Coastguard Worker 	dng_basic_tag_set basic (mainIFD, ifd);
5463*fd1fabb7SAndroid Build Coastguard Worker 
5464*fd1fabb7SAndroid Build Coastguard Worker 	// Resolution.
5465*fd1fabb7SAndroid Build Coastguard Worker 
5466*fd1fabb7SAndroid Build Coastguard Worker 	dng_resolution res;
5467*fd1fabb7SAndroid Build Coastguard Worker 
5468*fd1fabb7SAndroid Build Coastguard Worker 	if (resolution)
5469*fd1fabb7SAndroid Build Coastguard Worker 		{
5470*fd1fabb7SAndroid Build Coastguard Worker 		res = *resolution;
5471*fd1fabb7SAndroid Build Coastguard Worker 		}
5472*fd1fabb7SAndroid Build Coastguard Worker 
5473*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational tagXResolution (tcXResolution, res.fXResolution);
5474*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational tagYResolution (tcYResolution, res.fYResolution);
5475*fd1fabb7SAndroid Build Coastguard Worker 
5476*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint16 tagResolutionUnit (tcResolutionUnit, res.fResolutionUnit);
5477*fd1fabb7SAndroid Build Coastguard Worker 
5478*fd1fabb7SAndroid Build Coastguard Worker 	if (resolution)
5479*fd1fabb7SAndroid Build Coastguard Worker 		{
5480*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagXResolution   );
5481*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagYResolution   );
5482*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagResolutionUnit);
5483*fd1fabb7SAndroid Build Coastguard Worker 		}
5484*fd1fabb7SAndroid Build Coastguard Worker 
5485*fd1fabb7SAndroid Build Coastguard Worker 	// ICC Profile.
5486*fd1fabb7SAndroid Build Coastguard Worker 
5487*fd1fabb7SAndroid Build Coastguard Worker 	tag_icc_profile iccProfileTag (profileData, profileSize);
5488*fd1fabb7SAndroid Build Coastguard Worker 
5489*fd1fabb7SAndroid Build Coastguard Worker 	if (iccProfileTag.Count ())
5490*fd1fabb7SAndroid Build Coastguard Worker 		{
5491*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&iccProfileTag);
5492*fd1fabb7SAndroid Build Coastguard Worker 		}
5493*fd1fabb7SAndroid Build Coastguard Worker 
5494*fd1fabb7SAndroid Build Coastguard Worker 	// XMP metadata.
5495*fd1fabb7SAndroid Build Coastguard Worker 
5496*fd1fabb7SAndroid Build Coastguard Worker 	#if qDNGUseXMP
5497*fd1fabb7SAndroid Build Coastguard Worker 
5498*fd1fabb7SAndroid Build Coastguard Worker 	tag_xmp tagXMP (metadata.Get () ? metadata->GetXMP () : NULL);
5499*fd1fabb7SAndroid Build Coastguard Worker 
5500*fd1fabb7SAndroid Build Coastguard Worker 	if (tagXMP.Count ())
5501*fd1fabb7SAndroid Build Coastguard Worker 		{
5502*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagXMP);
5503*fd1fabb7SAndroid Build Coastguard Worker 		}
5504*fd1fabb7SAndroid Build Coastguard Worker 
5505*fd1fabb7SAndroid Build Coastguard Worker 	#endif
5506*fd1fabb7SAndroid Build Coastguard Worker 
5507*fd1fabb7SAndroid Build Coastguard Worker 	// IPTC metadata.
5508*fd1fabb7SAndroid Build Coastguard Worker 
5509*fd1fabb7SAndroid Build Coastguard Worker 	tag_iptc tagIPTC (metadata.Get () ? metadata->IPTCData   () : NULL,
5510*fd1fabb7SAndroid Build Coastguard Worker 					  metadata.Get () ? metadata->IPTCLength () : 0);
5511*fd1fabb7SAndroid Build Coastguard Worker 
5512*fd1fabb7SAndroid Build Coastguard Worker 	if (tagIPTC.Count ())
5513*fd1fabb7SAndroid Build Coastguard Worker 		{
5514*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagIPTC);
5515*fd1fabb7SAndroid Build Coastguard Worker 		}
5516*fd1fabb7SAndroid Build Coastguard Worker 
5517*fd1fabb7SAndroid Build Coastguard Worker 	// Adobe data (thumbnail and IPTC digest)
5518*fd1fabb7SAndroid Build Coastguard Worker 
5519*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_memory_block> adobeData (BuildAdobeData (host,
5520*fd1fabb7SAndroid Build Coastguard Worker 														 metadata.Get (),
5521*fd1fabb7SAndroid Build Coastguard Worker 														 thumbnail,
5522*fd1fabb7SAndroid Build Coastguard Worker 														 imageResources));
5523*fd1fabb7SAndroid Build Coastguard Worker 
5524*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint8_ptr tagAdobe (tcAdobeData,
5525*fd1fabb7SAndroid Build Coastguard Worker 							adobeData->Buffer_uint8 (),
5526*fd1fabb7SAndroid Build Coastguard Worker 							adobeData->LogicalSize ());
5527*fd1fabb7SAndroid Build Coastguard Worker 
5528*fd1fabb7SAndroid Build Coastguard Worker 	if (tagAdobe.Count ())
5529*fd1fabb7SAndroid Build Coastguard Worker 		{
5530*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagAdobe);
5531*fd1fabb7SAndroid Build Coastguard Worker 		}
5532*fd1fabb7SAndroid Build Coastguard Worker 
5533*fd1fabb7SAndroid Build Coastguard Worker 	// Exif metadata.
5534*fd1fabb7SAndroid Build Coastguard Worker 
5535*fd1fabb7SAndroid Build Coastguard Worker 	exif_tag_set exifSet (mainIFD,
5536*fd1fabb7SAndroid Build Coastguard Worker 						  metadata.Get () && metadata->GetExif () ? *metadata->GetExif ()
5537*fd1fabb7SAndroid Build Coastguard Worker 																  : dng_exif (),
5538*fd1fabb7SAndroid Build Coastguard Worker 						  metadata.Get () ? metadata->IsMakerNoteSafe () : false,
5539*fd1fabb7SAndroid Build Coastguard Worker 						  metadata.Get () ? metadata->MakerNoteData   () : NULL,
5540*fd1fabb7SAndroid Build Coastguard Worker 						  metadata.Get () ? metadata->MakerNoteLength () : 0,
5541*fd1fabb7SAndroid Build Coastguard Worker 						  false);
5542*fd1fabb7SAndroid Build Coastguard Worker 
5543*fd1fabb7SAndroid Build Coastguard Worker 	// Find offset to main image data.
5544*fd1fabb7SAndroid Build Coastguard Worker 
5545*fd1fabb7SAndroid Build Coastguard Worker 	uint32 offsetMainIFD = 8;
5546*fd1fabb7SAndroid Build Coastguard Worker 
5547*fd1fabb7SAndroid Build Coastguard Worker 	uint32 offsetExifData = offsetMainIFD + mainIFD.Size ();
5548*fd1fabb7SAndroid Build Coastguard Worker 
5549*fd1fabb7SAndroid Build Coastguard Worker 	exifSet.Locate (offsetExifData);
5550*fd1fabb7SAndroid Build Coastguard Worker 
5551*fd1fabb7SAndroid Build Coastguard Worker 	uint32 offsetMainData = offsetExifData + exifSet.Size ();
5552*fd1fabb7SAndroid Build Coastguard Worker 
5553*fd1fabb7SAndroid Build Coastguard Worker 	stream.SetWritePosition (offsetMainData);
5554*fd1fabb7SAndroid Build Coastguard Worker 
5555*fd1fabb7SAndroid Build Coastguard Worker 	// Write the main image data.
5556*fd1fabb7SAndroid Build Coastguard Worker 
5557*fd1fabb7SAndroid Build Coastguard Worker 	WriteImage (host,
5558*fd1fabb7SAndroid Build Coastguard Worker 				ifd,
5559*fd1fabb7SAndroid Build Coastguard Worker 				basic,
5560*fd1fabb7SAndroid Build Coastguard Worker 				stream,
5561*fd1fabb7SAndroid Build Coastguard Worker 				image);
5562*fd1fabb7SAndroid Build Coastguard Worker 
5563*fd1fabb7SAndroid Build Coastguard Worker 	// Trim the file to this length.
5564*fd1fabb7SAndroid Build Coastguard Worker 
5565*fd1fabb7SAndroid Build Coastguard Worker 	stream.SetLength (stream.Position ());
5566*fd1fabb7SAndroid Build Coastguard Worker 
5567*fd1fabb7SAndroid Build Coastguard Worker 	// TIFF has a 4G size limit.
5568*fd1fabb7SAndroid Build Coastguard Worker 
5569*fd1fabb7SAndroid Build Coastguard Worker 	if (stream.Length () > 0x0FFFFFFFFL)
5570*fd1fabb7SAndroid Build Coastguard Worker 		{
5571*fd1fabb7SAndroid Build Coastguard Worker 		ThrowImageTooBigTIFF ();
5572*fd1fabb7SAndroid Build Coastguard Worker 		}
5573*fd1fabb7SAndroid Build Coastguard Worker 
5574*fd1fabb7SAndroid Build Coastguard Worker 	// Write TIFF Header.
5575*fd1fabb7SAndroid Build Coastguard Worker 
5576*fd1fabb7SAndroid Build Coastguard Worker 	stream.SetWritePosition (0);
5577*fd1fabb7SAndroid Build Coastguard Worker 
5578*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint16 (stream.BigEndian () ? byteOrderMM : byteOrderII);
5579*fd1fabb7SAndroid Build Coastguard Worker 
5580*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint16 (42);
5581*fd1fabb7SAndroid Build Coastguard Worker 
5582*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint32 (offsetMainIFD);
5583*fd1fabb7SAndroid Build Coastguard Worker 
5584*fd1fabb7SAndroid Build Coastguard Worker 	// Write the IFDs.
5585*fd1fabb7SAndroid Build Coastguard Worker 
5586*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Put (stream);
5587*fd1fabb7SAndroid Build Coastguard Worker 
5588*fd1fabb7SAndroid Build Coastguard Worker 	exifSet.Put (stream);
5589*fd1fabb7SAndroid Build Coastguard Worker 
5590*fd1fabb7SAndroid Build Coastguard Worker 	stream.Flush ();
5591*fd1fabb7SAndroid Build Coastguard Worker 
5592*fd1fabb7SAndroid Build Coastguard Worker 	}
5593*fd1fabb7SAndroid Build Coastguard Worker 
5594*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
5595*fd1fabb7SAndroid Build Coastguard Worker 
WriteDNG(dng_host & host,dng_stream & stream,dng_negative & negative,const dng_preview_list * previewList,uint32 maxBackwardVersion,bool uncompressed)5596*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::WriteDNG (dng_host &host,
5597*fd1fabb7SAndroid Build Coastguard Worker 							     dng_stream &stream,
5598*fd1fabb7SAndroid Build Coastguard Worker 							     dng_negative &negative,
5599*fd1fabb7SAndroid Build Coastguard Worker 							     const dng_preview_list *previewList,
5600*fd1fabb7SAndroid Build Coastguard Worker 								 uint32 maxBackwardVersion,
5601*fd1fabb7SAndroid Build Coastguard Worker 							     bool uncompressed)
5602*fd1fabb7SAndroid Build Coastguard Worker 	{
5603*fd1fabb7SAndroid Build Coastguard Worker 
5604*fd1fabb7SAndroid Build Coastguard Worker 	WriteDNG (host,
5605*fd1fabb7SAndroid Build Coastguard Worker 			  stream,
5606*fd1fabb7SAndroid Build Coastguard Worker 			  negative,
5607*fd1fabb7SAndroid Build Coastguard Worker 			  negative.Metadata (),
5608*fd1fabb7SAndroid Build Coastguard Worker 			  previewList,
5609*fd1fabb7SAndroid Build Coastguard Worker 			  maxBackwardVersion,
5610*fd1fabb7SAndroid Build Coastguard Worker 			  uncompressed);
5611*fd1fabb7SAndroid Build Coastguard Worker 
5612*fd1fabb7SAndroid Build Coastguard Worker 	}
5613*fd1fabb7SAndroid Build Coastguard Worker 
5614*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
5615*fd1fabb7SAndroid Build Coastguard Worker 
WriteDNG(dng_host & host,dng_stream & stream,const dng_negative & negative,const dng_metadata & constMetadata,const dng_preview_list * previewList,uint32 maxBackwardVersion,bool uncompressed)5616*fd1fabb7SAndroid Build Coastguard Worker void dng_image_writer::WriteDNG (dng_host &host,
5617*fd1fabb7SAndroid Build Coastguard Worker 							     dng_stream &stream,
5618*fd1fabb7SAndroid Build Coastguard Worker 							     const dng_negative &negative,
5619*fd1fabb7SAndroid Build Coastguard Worker 								 const dng_metadata &constMetadata,
5620*fd1fabb7SAndroid Build Coastguard Worker 								 const dng_preview_list *previewList,
5621*fd1fabb7SAndroid Build Coastguard Worker 								 uint32 maxBackwardVersion,
5622*fd1fabb7SAndroid Build Coastguard Worker 							     bool uncompressed)
5623*fd1fabb7SAndroid Build Coastguard Worker 	{
5624*fd1fabb7SAndroid Build Coastguard Worker 
5625*fd1fabb7SAndroid Build Coastguard Worker 	uint32 j;
5626*fd1fabb7SAndroid Build Coastguard Worker 
5627*fd1fabb7SAndroid Build Coastguard Worker 	// Clean up metadata per MWG recommendations.
5628*fd1fabb7SAndroid Build Coastguard Worker 
5629*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_metadata> metadata (constMetadata.Clone (host.Allocator ()));
5630*fd1fabb7SAndroid Build Coastguard Worker 
5631*fd1fabb7SAndroid Build Coastguard Worker 	CleanUpMetadata (host,
5632*fd1fabb7SAndroid Build Coastguard Worker 					 *metadata,
5633*fd1fabb7SAndroid Build Coastguard Worker 					 kMetadataSubset_All,
5634*fd1fabb7SAndroid Build Coastguard Worker 					 "image/dng");
5635*fd1fabb7SAndroid Build Coastguard Worker 
5636*fd1fabb7SAndroid Build Coastguard Worker 	// Figure out the compression to use.  Most of the time this is lossless
5637*fd1fabb7SAndroid Build Coastguard Worker 	// JPEG.
5638*fd1fabb7SAndroid Build Coastguard Worker 
5639*fd1fabb7SAndroid Build Coastguard Worker 	uint32 compression = uncompressed ? ccUncompressed : ccJPEG;
5640*fd1fabb7SAndroid Build Coastguard Worker 
5641*fd1fabb7SAndroid Build Coastguard Worker 	// Was the the original file lossy JPEG compressed?
5642*fd1fabb7SAndroid Build Coastguard Worker 
5643*fd1fabb7SAndroid Build Coastguard Worker 	const dng_jpeg_image *rawJPEGImage = negative.RawJPEGImage ();
5644*fd1fabb7SAndroid Build Coastguard Worker 
5645*fd1fabb7SAndroid Build Coastguard Worker 	// If so, can we save it using the requested compression and DNG version?
5646*fd1fabb7SAndroid Build Coastguard Worker 
5647*fd1fabb7SAndroid Build Coastguard Worker 	if (uncompressed || maxBackwardVersion < dngVersion_1_4_0_0)
5648*fd1fabb7SAndroid Build Coastguard Worker 		{
5649*fd1fabb7SAndroid Build Coastguard Worker 
5650*fd1fabb7SAndroid Build Coastguard Worker 		if (rawJPEGImage || negative.RawJPEGImageDigest ().IsValid ())
5651*fd1fabb7SAndroid Build Coastguard Worker 			{
5652*fd1fabb7SAndroid Build Coastguard Worker 
5653*fd1fabb7SAndroid Build Coastguard Worker 			rawJPEGImage = NULL;
5654*fd1fabb7SAndroid Build Coastguard Worker 
5655*fd1fabb7SAndroid Build Coastguard Worker 			negative.ClearRawJPEGImageDigest ();
5656*fd1fabb7SAndroid Build Coastguard Worker 
5657*fd1fabb7SAndroid Build Coastguard Worker 			negative.ClearRawImageDigest ();
5658*fd1fabb7SAndroid Build Coastguard Worker 
5659*fd1fabb7SAndroid Build Coastguard Worker 			}
5660*fd1fabb7SAndroid Build Coastguard Worker 
5661*fd1fabb7SAndroid Build Coastguard Worker 		}
5662*fd1fabb7SAndroid Build Coastguard Worker 
5663*fd1fabb7SAndroid Build Coastguard Worker 	else if (rawJPEGImage)
5664*fd1fabb7SAndroid Build Coastguard Worker 		{
5665*fd1fabb7SAndroid Build Coastguard Worker 
5666*fd1fabb7SAndroid Build Coastguard Worker 		compression = ccLossyJPEG;
5667*fd1fabb7SAndroid Build Coastguard Worker 
5668*fd1fabb7SAndroid Build Coastguard Worker 		}
5669*fd1fabb7SAndroid Build Coastguard Worker 
5670*fd1fabb7SAndroid Build Coastguard Worker 	// Are we saving the original size tags?
5671*fd1fabb7SAndroid Build Coastguard Worker 
5672*fd1fabb7SAndroid Build Coastguard Worker 	bool saveOriginalDefaultFinalSize     = false;
5673*fd1fabb7SAndroid Build Coastguard Worker 	bool saveOriginalBestQualityFinalSize = false;
5674*fd1fabb7SAndroid Build Coastguard Worker 	bool saveOriginalDefaultCropSize      = false;
5675*fd1fabb7SAndroid Build Coastguard Worker 
5676*fd1fabb7SAndroid Build Coastguard Worker 		{
5677*fd1fabb7SAndroid Build Coastguard Worker 
5678*fd1fabb7SAndroid Build Coastguard Worker 		// See if we are saving a proxy image.
5679*fd1fabb7SAndroid Build Coastguard Worker 
5680*fd1fabb7SAndroid Build Coastguard Worker 		dng_point defaultFinalSize (negative.DefaultFinalHeight (),
5681*fd1fabb7SAndroid Build Coastguard Worker 									negative.DefaultFinalWidth  ());
5682*fd1fabb7SAndroid Build Coastguard Worker 
5683*fd1fabb7SAndroid Build Coastguard Worker 		saveOriginalDefaultFinalSize = (negative.OriginalDefaultFinalSize () !=
5684*fd1fabb7SAndroid Build Coastguard Worker 										defaultFinalSize);
5685*fd1fabb7SAndroid Build Coastguard Worker 
5686*fd1fabb7SAndroid Build Coastguard Worker 		if (saveOriginalDefaultFinalSize)
5687*fd1fabb7SAndroid Build Coastguard Worker 			{
5688*fd1fabb7SAndroid Build Coastguard Worker 
5689*fd1fabb7SAndroid Build Coastguard Worker 			// If the save OriginalDefaultFinalSize tag, this changes the defaults
5690*fd1fabb7SAndroid Build Coastguard Worker 			// for the OriginalBestQualityFinalSize and OriginalDefaultCropSize tags.
5691*fd1fabb7SAndroid Build Coastguard Worker 
5692*fd1fabb7SAndroid Build Coastguard Worker 			saveOriginalBestQualityFinalSize = (negative.OriginalBestQualityFinalSize () !=
5693*fd1fabb7SAndroid Build Coastguard Worker 												defaultFinalSize);
5694*fd1fabb7SAndroid Build Coastguard Worker 
5695*fd1fabb7SAndroid Build Coastguard Worker 			saveOriginalDefaultCropSize = (negative.OriginalDefaultCropSizeV () !=
5696*fd1fabb7SAndroid Build Coastguard Worker 										   dng_urational (defaultFinalSize.v, 1)) ||
5697*fd1fabb7SAndroid Build Coastguard Worker 										  (negative.OriginalDefaultCropSizeH () !=
5698*fd1fabb7SAndroid Build Coastguard Worker 										   dng_urational (defaultFinalSize.h, 1));
5699*fd1fabb7SAndroid Build Coastguard Worker 
5700*fd1fabb7SAndroid Build Coastguard Worker 			}
5701*fd1fabb7SAndroid Build Coastguard Worker 
5702*fd1fabb7SAndroid Build Coastguard Worker 		else
5703*fd1fabb7SAndroid Build Coastguard Worker 			{
5704*fd1fabb7SAndroid Build Coastguard Worker 
5705*fd1fabb7SAndroid Build Coastguard Worker 			// Else these two tags default to the normal non-proxy size image values.
5706*fd1fabb7SAndroid Build Coastguard Worker 
5707*fd1fabb7SAndroid Build Coastguard Worker 			dng_point bestQualityFinalSize (negative.BestQualityFinalHeight (),
5708*fd1fabb7SAndroid Build Coastguard Worker 											negative.BestQualityFinalWidth  ());
5709*fd1fabb7SAndroid Build Coastguard Worker 
5710*fd1fabb7SAndroid Build Coastguard Worker 			saveOriginalBestQualityFinalSize = (negative.OriginalBestQualityFinalSize () !=
5711*fd1fabb7SAndroid Build Coastguard Worker 												bestQualityFinalSize);
5712*fd1fabb7SAndroid Build Coastguard Worker 
5713*fd1fabb7SAndroid Build Coastguard Worker 			saveOriginalDefaultCropSize = (negative.OriginalDefaultCropSizeV () !=
5714*fd1fabb7SAndroid Build Coastguard Worker 										   negative.DefaultCropSizeV ()) ||
5715*fd1fabb7SAndroid Build Coastguard Worker 										  (negative.OriginalDefaultCropSizeH () !=
5716*fd1fabb7SAndroid Build Coastguard Worker 										   negative.DefaultCropSizeH ());
5717*fd1fabb7SAndroid Build Coastguard Worker 
5718*fd1fabb7SAndroid Build Coastguard Worker 			}
5719*fd1fabb7SAndroid Build Coastguard Worker 
5720*fd1fabb7SAndroid Build Coastguard Worker 		}
5721*fd1fabb7SAndroid Build Coastguard Worker 
5722*fd1fabb7SAndroid Build Coastguard Worker 	// Is this a floating point image that we are saving?
5723*fd1fabb7SAndroid Build Coastguard Worker 
5724*fd1fabb7SAndroid Build Coastguard Worker 	bool isFloatingPoint = (negative.RawImage ().PixelType () == ttFloat);
5725*fd1fabb7SAndroid Build Coastguard Worker 
5726*fd1fabb7SAndroid Build Coastguard Worker 	// Does this image have a transparency mask?
5727*fd1fabb7SAndroid Build Coastguard Worker 
5728*fd1fabb7SAndroid Build Coastguard Worker 	bool hasTransparencyMask = (negative.RawTransparencyMask () != NULL);
5729*fd1fabb7SAndroid Build Coastguard Worker 
5730*fd1fabb7SAndroid Build Coastguard Worker 	// Should we save a compressed 32-bit integer file?
5731*fd1fabb7SAndroid Build Coastguard Worker 
5732*fd1fabb7SAndroid Build Coastguard Worker 	bool isCompressed32BitInteger = (negative.RawImage ().PixelType () == ttLong) &&
5733*fd1fabb7SAndroid Build Coastguard Worker 								    (maxBackwardVersion >= dngVersion_1_4_0_0) &&
5734*fd1fabb7SAndroid Build Coastguard Worker 									(!uncompressed);
5735*fd1fabb7SAndroid Build Coastguard Worker 
5736*fd1fabb7SAndroid Build Coastguard Worker 	// Figure out what main version to use.
5737*fd1fabb7SAndroid Build Coastguard Worker 
5738*fd1fabb7SAndroid Build Coastguard Worker 	uint32 dngVersion = dngVersion_Current;
5739*fd1fabb7SAndroid Build Coastguard Worker 
5740*fd1fabb7SAndroid Build Coastguard Worker 	// Don't write version 1.4 files unless we actually use some feature of the 1.4 spec.
5741*fd1fabb7SAndroid Build Coastguard Worker 
5742*fd1fabb7SAndroid Build Coastguard Worker 	if (dngVersion == dngVersion_1_4_0_0)
5743*fd1fabb7SAndroid Build Coastguard Worker 		{
5744*fd1fabb7SAndroid Build Coastguard Worker 
5745*fd1fabb7SAndroid Build Coastguard Worker 		if (!rawJPEGImage                     &&
5746*fd1fabb7SAndroid Build Coastguard Worker 			!isFloatingPoint				  &&
5747*fd1fabb7SAndroid Build Coastguard Worker 			!hasTransparencyMask			  &&
5748*fd1fabb7SAndroid Build Coastguard Worker 			!isCompressed32BitInteger		  &&
5749*fd1fabb7SAndroid Build Coastguard Worker 			!saveOriginalDefaultFinalSize     &&
5750*fd1fabb7SAndroid Build Coastguard Worker 			!saveOriginalBestQualityFinalSize &&
5751*fd1fabb7SAndroid Build Coastguard Worker 			!saveOriginalDefaultCropSize      )
5752*fd1fabb7SAndroid Build Coastguard Worker 			{
5753*fd1fabb7SAndroid Build Coastguard Worker 
5754*fd1fabb7SAndroid Build Coastguard Worker 			dngVersion = dngVersion_1_3_0_0;
5755*fd1fabb7SAndroid Build Coastguard Worker 
5756*fd1fabb7SAndroid Build Coastguard Worker 			}
5757*fd1fabb7SAndroid Build Coastguard Worker 
5758*fd1fabb7SAndroid Build Coastguard Worker 		}
5759*fd1fabb7SAndroid Build Coastguard Worker 
5760*fd1fabb7SAndroid Build Coastguard Worker 	// Figure out what backward version to use.
5761*fd1fabb7SAndroid Build Coastguard Worker 
5762*fd1fabb7SAndroid Build Coastguard Worker 	uint32 dngBackwardVersion = dngVersion_1_1_0_0;
5763*fd1fabb7SAndroid Build Coastguard Worker 
5764*fd1fabb7SAndroid Build Coastguard Worker 	#if defined(qTestRowInterleave) || defined(qTestSubTileBlockRows) || defined(qTestSubTileBlockCols)
5765*fd1fabb7SAndroid Build Coastguard Worker 	dngBackwardVersion = Max_uint32 (dngBackwardVersion, dngVersion_1_2_0_0);
5766*fd1fabb7SAndroid Build Coastguard Worker 	#endif
5767*fd1fabb7SAndroid Build Coastguard Worker 
5768*fd1fabb7SAndroid Build Coastguard Worker 	dngBackwardVersion = Max_uint32 (dngBackwardVersion,
5769*fd1fabb7SAndroid Build Coastguard Worker 									 negative.OpcodeList1 ().MinVersion (false));
5770*fd1fabb7SAndroid Build Coastguard Worker 
5771*fd1fabb7SAndroid Build Coastguard Worker 	dngBackwardVersion = Max_uint32 (dngBackwardVersion,
5772*fd1fabb7SAndroid Build Coastguard Worker 									 negative.OpcodeList2 ().MinVersion (false));
5773*fd1fabb7SAndroid Build Coastguard Worker 
5774*fd1fabb7SAndroid Build Coastguard Worker 	dngBackwardVersion = Max_uint32 (dngBackwardVersion,
5775*fd1fabb7SAndroid Build Coastguard Worker 									 negative.OpcodeList3 ().MinVersion (false));
5776*fd1fabb7SAndroid Build Coastguard Worker 
5777*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.GetMosaicInfo () &&
5778*fd1fabb7SAndroid Build Coastguard Worker 		negative.GetMosaicInfo ()->fCFALayout >= 6)
5779*fd1fabb7SAndroid Build Coastguard Worker 		{
5780*fd1fabb7SAndroid Build Coastguard Worker 		dngBackwardVersion = Max_uint32 (dngBackwardVersion, dngVersion_1_3_0_0);
5781*fd1fabb7SAndroid Build Coastguard Worker 		}
5782*fd1fabb7SAndroid Build Coastguard Worker 
5783*fd1fabb7SAndroid Build Coastguard Worker 	if (rawJPEGImage || isFloatingPoint || hasTransparencyMask || isCompressed32BitInteger)
5784*fd1fabb7SAndroid Build Coastguard Worker 		{
5785*fd1fabb7SAndroid Build Coastguard Worker 		dngBackwardVersion = Max_uint32 (dngBackwardVersion, dngVersion_1_4_0_0);
5786*fd1fabb7SAndroid Build Coastguard Worker 		}
5787*fd1fabb7SAndroid Build Coastguard Worker 
5788*fd1fabb7SAndroid Build Coastguard Worker 	if (dngBackwardVersion > dngVersion)
5789*fd1fabb7SAndroid Build Coastguard Worker 		{
5790*fd1fabb7SAndroid Build Coastguard Worker 		ThrowProgramError ();
5791*fd1fabb7SAndroid Build Coastguard Worker 		}
5792*fd1fabb7SAndroid Build Coastguard Worker 
5793*fd1fabb7SAndroid Build Coastguard Worker 	// Find best thumbnail from preview list, if any.
5794*fd1fabb7SAndroid Build Coastguard Worker 
5795*fd1fabb7SAndroid Build Coastguard Worker 	const dng_preview *thumbnail = NULL;
5796*fd1fabb7SAndroid Build Coastguard Worker 
5797*fd1fabb7SAndroid Build Coastguard Worker 	if (previewList)
5798*fd1fabb7SAndroid Build Coastguard Worker 		{
5799*fd1fabb7SAndroid Build Coastguard Worker 
5800*fd1fabb7SAndroid Build Coastguard Worker 		uint32 thumbArea = 0;
5801*fd1fabb7SAndroid Build Coastguard Worker 
5802*fd1fabb7SAndroid Build Coastguard Worker 		for (j = 0; j < previewList->Count (); j++)
5803*fd1fabb7SAndroid Build Coastguard Worker 			{
5804*fd1fabb7SAndroid Build Coastguard Worker 
5805*fd1fabb7SAndroid Build Coastguard Worker 			const dng_image_preview *imagePreview = dynamic_cast<const dng_image_preview *>(&previewList->Preview (j));
5806*fd1fabb7SAndroid Build Coastguard Worker 
5807*fd1fabb7SAndroid Build Coastguard Worker 			if (imagePreview)
5808*fd1fabb7SAndroid Build Coastguard Worker 				{
5809*fd1fabb7SAndroid Build Coastguard Worker 
5810*fd1fabb7SAndroid Build Coastguard Worker 				uint32 thisArea = imagePreview->fImage->Bounds ().W () *
5811*fd1fabb7SAndroid Build Coastguard Worker 								  imagePreview->fImage->Bounds ().H ();
5812*fd1fabb7SAndroid Build Coastguard Worker 
5813*fd1fabb7SAndroid Build Coastguard Worker 				if (!thumbnail || thisArea < thumbArea)
5814*fd1fabb7SAndroid Build Coastguard Worker 					{
5815*fd1fabb7SAndroid Build Coastguard Worker 
5816*fd1fabb7SAndroid Build Coastguard Worker 					thumbnail = &previewList->Preview (j);
5817*fd1fabb7SAndroid Build Coastguard Worker 
5818*fd1fabb7SAndroid Build Coastguard Worker 					thumbArea = thisArea;
5819*fd1fabb7SAndroid Build Coastguard Worker 
5820*fd1fabb7SAndroid Build Coastguard Worker 					}
5821*fd1fabb7SAndroid Build Coastguard Worker 
5822*fd1fabb7SAndroid Build Coastguard Worker 				}
5823*fd1fabb7SAndroid Build Coastguard Worker 
5824*fd1fabb7SAndroid Build Coastguard Worker 			const dng_jpeg_preview *jpegPreview = dynamic_cast<const dng_jpeg_preview *>(&previewList->Preview (j));
5825*fd1fabb7SAndroid Build Coastguard Worker 
5826*fd1fabb7SAndroid Build Coastguard Worker 			if (jpegPreview)
5827*fd1fabb7SAndroid Build Coastguard Worker 				{
5828*fd1fabb7SAndroid Build Coastguard Worker 
5829*fd1fabb7SAndroid Build Coastguard Worker 				uint32 thisArea = jpegPreview->fPreviewSize.h *
5830*fd1fabb7SAndroid Build Coastguard Worker 								  jpegPreview->fPreviewSize.v;
5831*fd1fabb7SAndroid Build Coastguard Worker 
5832*fd1fabb7SAndroid Build Coastguard Worker 				if (!thumbnail || thisArea < thumbArea)
5833*fd1fabb7SAndroid Build Coastguard Worker 					{
5834*fd1fabb7SAndroid Build Coastguard Worker 
5835*fd1fabb7SAndroid Build Coastguard Worker 					thumbnail = &previewList->Preview (j);
5836*fd1fabb7SAndroid Build Coastguard Worker 
5837*fd1fabb7SAndroid Build Coastguard Worker 					thumbArea = thisArea;
5838*fd1fabb7SAndroid Build Coastguard Worker 
5839*fd1fabb7SAndroid Build Coastguard Worker 					}
5840*fd1fabb7SAndroid Build Coastguard Worker 
5841*fd1fabb7SAndroid Build Coastguard Worker 				}
5842*fd1fabb7SAndroid Build Coastguard Worker 
5843*fd1fabb7SAndroid Build Coastguard Worker 			}
5844*fd1fabb7SAndroid Build Coastguard Worker 
5845*fd1fabb7SAndroid Build Coastguard Worker 		}
5846*fd1fabb7SAndroid Build Coastguard Worker 
5847*fd1fabb7SAndroid Build Coastguard Worker 	// Create the main IFD
5848*fd1fabb7SAndroid Build Coastguard Worker 
5849*fd1fabb7SAndroid Build Coastguard Worker 	dng_tiff_directory mainIFD;
5850*fd1fabb7SAndroid Build Coastguard Worker 
5851*fd1fabb7SAndroid Build Coastguard Worker 	// Create the IFD for the raw data. If there is no thumnail, this is
5852*fd1fabb7SAndroid Build Coastguard Worker 	// just a reference the main IFD.  Otherwise allocate a new one.
5853*fd1fabb7SAndroid Build Coastguard Worker 
5854*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_tiff_directory> rawIFD_IfNotMain;
5855*fd1fabb7SAndroid Build Coastguard Worker 
5856*fd1fabb7SAndroid Build Coastguard Worker 	if (thumbnail)
5857*fd1fabb7SAndroid Build Coastguard Worker 		{
5858*fd1fabb7SAndroid Build Coastguard Worker 		rawIFD_IfNotMain.Reset (new dng_tiff_directory);
5859*fd1fabb7SAndroid Build Coastguard Worker 		}
5860*fd1fabb7SAndroid Build Coastguard Worker 
5861*fd1fabb7SAndroid Build Coastguard Worker 	dng_tiff_directory &rawIFD (thumbnail ? *rawIFD_IfNotMain : mainIFD);
5862*fd1fabb7SAndroid Build Coastguard Worker 
5863*fd1fabb7SAndroid Build Coastguard Worker 	// Include DNG version tags.
5864*fd1fabb7SAndroid Build Coastguard Worker 
5865*fd1fabb7SAndroid Build Coastguard Worker 	uint8 dngVersionData [4];
5866*fd1fabb7SAndroid Build Coastguard Worker 
5867*fd1fabb7SAndroid Build Coastguard Worker 	dngVersionData [0] = (uint8) (dngVersion >> 24);
5868*fd1fabb7SAndroid Build Coastguard Worker 	dngVersionData [1] = (uint8) (dngVersion >> 16);
5869*fd1fabb7SAndroid Build Coastguard Worker 	dngVersionData [2] = (uint8) (dngVersion >>  8);
5870*fd1fabb7SAndroid Build Coastguard Worker 	dngVersionData [3] = (uint8) (dngVersion      );
5871*fd1fabb7SAndroid Build Coastguard Worker 
5872*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint8_ptr tagDNGVersion (tcDNGVersion, dngVersionData, 4);
5873*fd1fabb7SAndroid Build Coastguard Worker 
5874*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Add (&tagDNGVersion);
5875*fd1fabb7SAndroid Build Coastguard Worker 
5876*fd1fabb7SAndroid Build Coastguard Worker 	uint8 dngBackwardVersionData [4];
5877*fd1fabb7SAndroid Build Coastguard Worker 
5878*fd1fabb7SAndroid Build Coastguard Worker 	dngBackwardVersionData [0] = (uint8) (dngBackwardVersion >> 24);
5879*fd1fabb7SAndroid Build Coastguard Worker 	dngBackwardVersionData [1] = (uint8) (dngBackwardVersion >> 16);
5880*fd1fabb7SAndroid Build Coastguard Worker 	dngBackwardVersionData [2] = (uint8) (dngBackwardVersion >>  8);
5881*fd1fabb7SAndroid Build Coastguard Worker 	dngBackwardVersionData [3] = (uint8) (dngBackwardVersion      );
5882*fd1fabb7SAndroid Build Coastguard Worker 
5883*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint8_ptr tagDNGBackwardVersion (tcDNGBackwardVersion, dngBackwardVersionData, 4);
5884*fd1fabb7SAndroid Build Coastguard Worker 
5885*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Add (&tagDNGBackwardVersion);
5886*fd1fabb7SAndroid Build Coastguard Worker 
5887*fd1fabb7SAndroid Build Coastguard Worker 	// The main IFD contains the thumbnail, if there is a thumbnail.
5888*fd1fabb7SAndroid Build Coastguard Worker 
5889*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_basic_tag_set> thmBasic;
5890*fd1fabb7SAndroid Build Coastguard Worker 
5891*fd1fabb7SAndroid Build Coastguard Worker 	if (thumbnail)
5892*fd1fabb7SAndroid Build Coastguard Worker 		{
5893*fd1fabb7SAndroid Build Coastguard Worker 		thmBasic.Reset (thumbnail->AddTagSet (mainIFD));
5894*fd1fabb7SAndroid Build Coastguard Worker 		}
5895*fd1fabb7SAndroid Build Coastguard Worker 
5896*fd1fabb7SAndroid Build Coastguard Worker 	// Get the raw image we are writing.
5897*fd1fabb7SAndroid Build Coastguard Worker 
5898*fd1fabb7SAndroid Build Coastguard Worker 	const dng_image &rawImage (negative.RawImage ());
5899*fd1fabb7SAndroid Build Coastguard Worker 
5900*fd1fabb7SAndroid Build Coastguard Worker 	// For floating point, we only support ZIP compression.
5901*fd1fabb7SAndroid Build Coastguard Worker 
5902*fd1fabb7SAndroid Build Coastguard Worker 	if (isFloatingPoint && !uncompressed)
5903*fd1fabb7SAndroid Build Coastguard Worker 		{
5904*fd1fabb7SAndroid Build Coastguard Worker 
5905*fd1fabb7SAndroid Build Coastguard Worker 		compression = ccDeflate;
5906*fd1fabb7SAndroid Build Coastguard Worker 
5907*fd1fabb7SAndroid Build Coastguard Worker 		}
5908*fd1fabb7SAndroid Build Coastguard Worker 
5909*fd1fabb7SAndroid Build Coastguard Worker 	// For 32-bit integer images, we only support ZIP and uncompressed.
5910*fd1fabb7SAndroid Build Coastguard Worker 
5911*fd1fabb7SAndroid Build Coastguard Worker 	if (rawImage.PixelType () == ttLong)
5912*fd1fabb7SAndroid Build Coastguard Worker 		{
5913*fd1fabb7SAndroid Build Coastguard Worker 
5914*fd1fabb7SAndroid Build Coastguard Worker 		if (isCompressed32BitInteger)
5915*fd1fabb7SAndroid Build Coastguard Worker 			{
5916*fd1fabb7SAndroid Build Coastguard Worker 			compression = ccDeflate;
5917*fd1fabb7SAndroid Build Coastguard Worker 			}
5918*fd1fabb7SAndroid Build Coastguard Worker 
5919*fd1fabb7SAndroid Build Coastguard Worker 		else
5920*fd1fabb7SAndroid Build Coastguard Worker 			{
5921*fd1fabb7SAndroid Build Coastguard Worker 			compression = ccUncompressed;
5922*fd1fabb7SAndroid Build Coastguard Worker 			}
5923*fd1fabb7SAndroid Build Coastguard Worker 
5924*fd1fabb7SAndroid Build Coastguard Worker 		}
5925*fd1fabb7SAndroid Build Coastguard Worker 
5926*fd1fabb7SAndroid Build Coastguard Worker 	// Get a copy of the mosaic info.
5927*fd1fabb7SAndroid Build Coastguard Worker 
5928*fd1fabb7SAndroid Build Coastguard Worker 	dng_mosaic_info mosaicInfo;
5929*fd1fabb7SAndroid Build Coastguard Worker 
5930*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.GetMosaicInfo ())
5931*fd1fabb7SAndroid Build Coastguard Worker 		{
5932*fd1fabb7SAndroid Build Coastguard Worker 		mosaicInfo = *(negative.GetMosaicInfo ());
5933*fd1fabb7SAndroid Build Coastguard Worker 		}
5934*fd1fabb7SAndroid Build Coastguard Worker 
5935*fd1fabb7SAndroid Build Coastguard Worker 	// Create a dng_ifd record for the raw image.
5936*fd1fabb7SAndroid Build Coastguard Worker 
5937*fd1fabb7SAndroid Build Coastguard Worker 	dng_ifd info;
5938*fd1fabb7SAndroid Build Coastguard Worker 
5939*fd1fabb7SAndroid Build Coastguard Worker 	info.fImageWidth  = rawImage.Width  ();
5940*fd1fabb7SAndroid Build Coastguard Worker 	info.fImageLength = rawImage.Height ();
5941*fd1fabb7SAndroid Build Coastguard Worker 
5942*fd1fabb7SAndroid Build Coastguard Worker 	info.fSamplesPerPixel = rawImage.Planes ();
5943*fd1fabb7SAndroid Build Coastguard Worker 
5944*fd1fabb7SAndroid Build Coastguard Worker 	info.fPhotometricInterpretation = mosaicInfo.IsColorFilterArray () ? piCFA
5945*fd1fabb7SAndroid Build Coastguard Worker 																	   : piLinearRaw;
5946*fd1fabb7SAndroid Build Coastguard Worker 
5947*fd1fabb7SAndroid Build Coastguard Worker 	info.fCompression = compression;
5948*fd1fabb7SAndroid Build Coastguard Worker 
5949*fd1fabb7SAndroid Build Coastguard Worker 	if (isFloatingPoint && compression == ccDeflate)
5950*fd1fabb7SAndroid Build Coastguard Worker 		{
5951*fd1fabb7SAndroid Build Coastguard Worker 
5952*fd1fabb7SAndroid Build Coastguard Worker 		info.fPredictor = cpFloatingPoint;
5953*fd1fabb7SAndroid Build Coastguard Worker 
5954*fd1fabb7SAndroid Build Coastguard Worker 		if (mosaicInfo.IsColorFilterArray ())
5955*fd1fabb7SAndroid Build Coastguard Worker 			{
5956*fd1fabb7SAndroid Build Coastguard Worker 
5957*fd1fabb7SAndroid Build Coastguard Worker 			if (mosaicInfo.fCFAPatternSize.h == 2)
5958*fd1fabb7SAndroid Build Coastguard Worker 				{
5959*fd1fabb7SAndroid Build Coastguard Worker 				info.fPredictor = cpFloatingPointX2;
5960*fd1fabb7SAndroid Build Coastguard Worker 				}
5961*fd1fabb7SAndroid Build Coastguard Worker 
5962*fd1fabb7SAndroid Build Coastguard Worker 			else if (mosaicInfo.fCFAPatternSize.h == 4)
5963*fd1fabb7SAndroid Build Coastguard Worker 				{
5964*fd1fabb7SAndroid Build Coastguard Worker 				info.fPredictor = cpFloatingPointX4;
5965*fd1fabb7SAndroid Build Coastguard Worker 				}
5966*fd1fabb7SAndroid Build Coastguard Worker 
5967*fd1fabb7SAndroid Build Coastguard Worker 			}
5968*fd1fabb7SAndroid Build Coastguard Worker 
5969*fd1fabb7SAndroid Build Coastguard Worker 		}
5970*fd1fabb7SAndroid Build Coastguard Worker 
5971*fd1fabb7SAndroid Build Coastguard Worker 	if (isCompressed32BitInteger)
5972*fd1fabb7SAndroid Build Coastguard Worker 		{
5973*fd1fabb7SAndroid Build Coastguard Worker 
5974*fd1fabb7SAndroid Build Coastguard Worker 		info.fPredictor = cpHorizontalDifference;
5975*fd1fabb7SAndroid Build Coastguard Worker 
5976*fd1fabb7SAndroid Build Coastguard Worker 		if (mosaicInfo.IsColorFilterArray ())
5977*fd1fabb7SAndroid Build Coastguard Worker 			{
5978*fd1fabb7SAndroid Build Coastguard Worker 
5979*fd1fabb7SAndroid Build Coastguard Worker 			if (mosaicInfo.fCFAPatternSize.h == 2)
5980*fd1fabb7SAndroid Build Coastguard Worker 				{
5981*fd1fabb7SAndroid Build Coastguard Worker 				info.fPredictor = cpHorizontalDifferenceX2;
5982*fd1fabb7SAndroid Build Coastguard Worker 				}
5983*fd1fabb7SAndroid Build Coastguard Worker 
5984*fd1fabb7SAndroid Build Coastguard Worker 			else if (mosaicInfo.fCFAPatternSize.h == 4)
5985*fd1fabb7SAndroid Build Coastguard Worker 				{
5986*fd1fabb7SAndroid Build Coastguard Worker 				info.fPredictor = cpHorizontalDifferenceX4;
5987*fd1fabb7SAndroid Build Coastguard Worker 				}
5988*fd1fabb7SAndroid Build Coastguard Worker 
5989*fd1fabb7SAndroid Build Coastguard Worker 			}
5990*fd1fabb7SAndroid Build Coastguard Worker 
5991*fd1fabb7SAndroid Build Coastguard Worker 		}
5992*fd1fabb7SAndroid Build Coastguard Worker 
5993*fd1fabb7SAndroid Build Coastguard Worker 	uint32 rawPixelType = rawImage.PixelType ();
5994*fd1fabb7SAndroid Build Coastguard Worker 
5995*fd1fabb7SAndroid Build Coastguard Worker 	if (rawPixelType == ttShort)
5996*fd1fabb7SAndroid Build Coastguard Worker 		{
5997*fd1fabb7SAndroid Build Coastguard Worker 
5998*fd1fabb7SAndroid Build Coastguard Worker 		// See if we are using a linearization table with <= 256 entries, in which
5999*fd1fabb7SAndroid Build Coastguard Worker 		// case the useful data will all fit within 8-bits.
6000*fd1fabb7SAndroid Build Coastguard Worker 
6001*fd1fabb7SAndroid Build Coastguard Worker 		const dng_linearization_info *rangeInfo = negative.GetLinearizationInfo ();
6002*fd1fabb7SAndroid Build Coastguard Worker 
6003*fd1fabb7SAndroid Build Coastguard Worker 		if (rangeInfo)
6004*fd1fabb7SAndroid Build Coastguard Worker 			{
6005*fd1fabb7SAndroid Build Coastguard Worker 
6006*fd1fabb7SAndroid Build Coastguard Worker 			if (rangeInfo->fLinearizationTable.Get ())
6007*fd1fabb7SAndroid Build Coastguard Worker 				{
6008*fd1fabb7SAndroid Build Coastguard Worker 
6009*fd1fabb7SAndroid Build Coastguard Worker 				uint32 entries = rangeInfo->fLinearizationTable->LogicalSize () >> 1;
6010*fd1fabb7SAndroid Build Coastguard Worker 
6011*fd1fabb7SAndroid Build Coastguard Worker 				if (entries <= 256)
6012*fd1fabb7SAndroid Build Coastguard Worker 					{
6013*fd1fabb7SAndroid Build Coastguard Worker 
6014*fd1fabb7SAndroid Build Coastguard Worker 					rawPixelType = ttByte;
6015*fd1fabb7SAndroid Build Coastguard Worker 
6016*fd1fabb7SAndroid Build Coastguard Worker 					}
6017*fd1fabb7SAndroid Build Coastguard Worker 
6018*fd1fabb7SAndroid Build Coastguard Worker 				}
6019*fd1fabb7SAndroid Build Coastguard Worker 
6020*fd1fabb7SAndroid Build Coastguard Worker 			}
6021*fd1fabb7SAndroid Build Coastguard Worker 
6022*fd1fabb7SAndroid Build Coastguard Worker 		}
6023*fd1fabb7SAndroid Build Coastguard Worker 
6024*fd1fabb7SAndroid Build Coastguard Worker 	switch (rawPixelType)
6025*fd1fabb7SAndroid Build Coastguard Worker 		{
6026*fd1fabb7SAndroid Build Coastguard Worker 
6027*fd1fabb7SAndroid Build Coastguard Worker 		case ttByte:
6028*fd1fabb7SAndroid Build Coastguard Worker 			{
6029*fd1fabb7SAndroid Build Coastguard Worker 			info.fBitsPerSample [0] = 8;
6030*fd1fabb7SAndroid Build Coastguard Worker 			break;
6031*fd1fabb7SAndroid Build Coastguard Worker 			}
6032*fd1fabb7SAndroid Build Coastguard Worker 
6033*fd1fabb7SAndroid Build Coastguard Worker 		case ttShort:
6034*fd1fabb7SAndroid Build Coastguard Worker 			{
6035*fd1fabb7SAndroid Build Coastguard Worker 			info.fBitsPerSample [0] = 16;
6036*fd1fabb7SAndroid Build Coastguard Worker 			break;
6037*fd1fabb7SAndroid Build Coastguard Worker 			}
6038*fd1fabb7SAndroid Build Coastguard Worker 
6039*fd1fabb7SAndroid Build Coastguard Worker 		case ttLong:
6040*fd1fabb7SAndroid Build Coastguard Worker 			{
6041*fd1fabb7SAndroid Build Coastguard Worker 			info.fBitsPerSample [0] = 32;
6042*fd1fabb7SAndroid Build Coastguard Worker 			break;
6043*fd1fabb7SAndroid Build Coastguard Worker 			}
6044*fd1fabb7SAndroid Build Coastguard Worker 
6045*fd1fabb7SAndroid Build Coastguard Worker 		case ttFloat:
6046*fd1fabb7SAndroid Build Coastguard Worker 			{
6047*fd1fabb7SAndroid Build Coastguard Worker 
6048*fd1fabb7SAndroid Build Coastguard Worker 			if (negative.RawFloatBitDepth () == 16)
6049*fd1fabb7SAndroid Build Coastguard Worker 				{
6050*fd1fabb7SAndroid Build Coastguard Worker 				info.fBitsPerSample [0] = 16;
6051*fd1fabb7SAndroid Build Coastguard Worker 				}
6052*fd1fabb7SAndroid Build Coastguard Worker 
6053*fd1fabb7SAndroid Build Coastguard Worker 			else if (negative.RawFloatBitDepth () == 24)
6054*fd1fabb7SAndroid Build Coastguard Worker 				{
6055*fd1fabb7SAndroid Build Coastguard Worker 				info.fBitsPerSample [0] = 24;
6056*fd1fabb7SAndroid Build Coastguard Worker 				}
6057*fd1fabb7SAndroid Build Coastguard Worker 
6058*fd1fabb7SAndroid Build Coastguard Worker 			else
6059*fd1fabb7SAndroid Build Coastguard Worker 				{
6060*fd1fabb7SAndroid Build Coastguard Worker 				info.fBitsPerSample [0] = 32;
6061*fd1fabb7SAndroid Build Coastguard Worker 				}
6062*fd1fabb7SAndroid Build Coastguard Worker 
6063*fd1fabb7SAndroid Build Coastguard Worker 			for (j = 0; j < info.fSamplesPerPixel; j++)
6064*fd1fabb7SAndroid Build Coastguard Worker 				{
6065*fd1fabb7SAndroid Build Coastguard Worker 				info.fSampleFormat [j] = sfFloatingPoint;
6066*fd1fabb7SAndroid Build Coastguard Worker 				}
6067*fd1fabb7SAndroid Build Coastguard Worker 
6068*fd1fabb7SAndroid Build Coastguard Worker 			break;
6069*fd1fabb7SAndroid Build Coastguard Worker 
6070*fd1fabb7SAndroid Build Coastguard Worker 			}
6071*fd1fabb7SAndroid Build Coastguard Worker 
6072*fd1fabb7SAndroid Build Coastguard Worker 		default:
6073*fd1fabb7SAndroid Build Coastguard Worker 			{
6074*fd1fabb7SAndroid Build Coastguard Worker 			ThrowProgramError ();
6075*fd1fabb7SAndroid Build Coastguard Worker 			}
6076*fd1fabb7SAndroid Build Coastguard Worker 
6077*fd1fabb7SAndroid Build Coastguard Worker 		}
6078*fd1fabb7SAndroid Build Coastguard Worker 
6079*fd1fabb7SAndroid Build Coastguard Worker 	// For lossless JPEG compression, we often lie about the
6080*fd1fabb7SAndroid Build Coastguard Worker 	// actual channel count to get the predictors to work across
6081*fd1fabb7SAndroid Build Coastguard Worker 	// same color mosaic pixels.
6082*fd1fabb7SAndroid Build Coastguard Worker 
6083*fd1fabb7SAndroid Build Coastguard Worker 	uint32 fakeChannels = 1;
6084*fd1fabb7SAndroid Build Coastguard Worker 
6085*fd1fabb7SAndroid Build Coastguard Worker 	if (info.fCompression == ccJPEG)
6086*fd1fabb7SAndroid Build Coastguard Worker 		{
6087*fd1fabb7SAndroid Build Coastguard Worker 
6088*fd1fabb7SAndroid Build Coastguard Worker 		if (mosaicInfo.IsColorFilterArray ())
6089*fd1fabb7SAndroid Build Coastguard Worker 			{
6090*fd1fabb7SAndroid Build Coastguard Worker 
6091*fd1fabb7SAndroid Build Coastguard Worker 			if (mosaicInfo.fCFAPatternSize.h == 4)
6092*fd1fabb7SAndroid Build Coastguard Worker 				{
6093*fd1fabb7SAndroid Build Coastguard Worker 				fakeChannels = 4;
6094*fd1fabb7SAndroid Build Coastguard Worker 				}
6095*fd1fabb7SAndroid Build Coastguard Worker 
6096*fd1fabb7SAndroid Build Coastguard Worker 			else if (mosaicInfo.fCFAPatternSize.h == 2)
6097*fd1fabb7SAndroid Build Coastguard Worker 				{
6098*fd1fabb7SAndroid Build Coastguard Worker 				fakeChannels = 2;
6099*fd1fabb7SAndroid Build Coastguard Worker 				}
6100*fd1fabb7SAndroid Build Coastguard Worker 
6101*fd1fabb7SAndroid Build Coastguard Worker 			// However, lossless JEPG is limited to four channels,
6102*fd1fabb7SAndroid Build Coastguard Worker 			// so compromise might be required.
6103*fd1fabb7SAndroid Build Coastguard Worker 
6104*fd1fabb7SAndroid Build Coastguard Worker 			while (fakeChannels * info.fSamplesPerPixel > 4 &&
6105*fd1fabb7SAndroid Build Coastguard Worker 				   fakeChannels > 1)
6106*fd1fabb7SAndroid Build Coastguard Worker 				{
6107*fd1fabb7SAndroid Build Coastguard Worker 
6108*fd1fabb7SAndroid Build Coastguard Worker 				fakeChannels >>= 1;
6109*fd1fabb7SAndroid Build Coastguard Worker 
6110*fd1fabb7SAndroid Build Coastguard Worker 				}
6111*fd1fabb7SAndroid Build Coastguard Worker 
6112*fd1fabb7SAndroid Build Coastguard Worker 			}
6113*fd1fabb7SAndroid Build Coastguard Worker 
6114*fd1fabb7SAndroid Build Coastguard Worker 		}
6115*fd1fabb7SAndroid Build Coastguard Worker 
6116*fd1fabb7SAndroid Build Coastguard Worker 	// Figure out tile sizes.
6117*fd1fabb7SAndroid Build Coastguard Worker 
6118*fd1fabb7SAndroid Build Coastguard Worker 	if (rawJPEGImage)
6119*fd1fabb7SAndroid Build Coastguard Worker 		{
6120*fd1fabb7SAndroid Build Coastguard Worker 
6121*fd1fabb7SAndroid Build Coastguard Worker 		DNG_ASSERT (rawPixelType == ttByte,
6122*fd1fabb7SAndroid Build Coastguard Worker 					"Unexpected jpeg pixel type");
6123*fd1fabb7SAndroid Build Coastguard Worker 
6124*fd1fabb7SAndroid Build Coastguard Worker 		DNG_ASSERT (info.fImageWidth  == (uint32) rawJPEGImage->fImageSize.h &&
6125*fd1fabb7SAndroid Build Coastguard Worker 					info.fImageLength == (uint32) rawJPEGImage->fImageSize.v,
6126*fd1fabb7SAndroid Build Coastguard Worker 					"Unexpected jpeg image size");
6127*fd1fabb7SAndroid Build Coastguard Worker 
6128*fd1fabb7SAndroid Build Coastguard Worker 		info.fTileWidth  = rawJPEGImage->fTileSize.h;
6129*fd1fabb7SAndroid Build Coastguard Worker 		info.fTileLength = rawJPEGImage->fTileSize.v;
6130*fd1fabb7SAndroid Build Coastguard Worker 
6131*fd1fabb7SAndroid Build Coastguard Worker 		info.fUsesStrips = rawJPEGImage->fUsesStrips;
6132*fd1fabb7SAndroid Build Coastguard Worker 
6133*fd1fabb7SAndroid Build Coastguard Worker 		info.fUsesTiles = !info.fUsesStrips;
6134*fd1fabb7SAndroid Build Coastguard Worker 
6135*fd1fabb7SAndroid Build Coastguard Worker 		}
6136*fd1fabb7SAndroid Build Coastguard Worker 
6137*fd1fabb7SAndroid Build Coastguard Worker 	else if (info.fCompression == ccJPEG)
6138*fd1fabb7SAndroid Build Coastguard Worker 		{
6139*fd1fabb7SAndroid Build Coastguard Worker 
6140*fd1fabb7SAndroid Build Coastguard Worker 		info.FindTileSize (128 * 1024);
6141*fd1fabb7SAndroid Build Coastguard Worker 
6142*fd1fabb7SAndroid Build Coastguard Worker 		}
6143*fd1fabb7SAndroid Build Coastguard Worker 
6144*fd1fabb7SAndroid Build Coastguard Worker 	else if (info.fCompression == ccDeflate)
6145*fd1fabb7SAndroid Build Coastguard Worker 		{
6146*fd1fabb7SAndroid Build Coastguard Worker 
6147*fd1fabb7SAndroid Build Coastguard Worker 		info.FindTileSize (512 * 1024);
6148*fd1fabb7SAndroid Build Coastguard Worker 
6149*fd1fabb7SAndroid Build Coastguard Worker 		}
6150*fd1fabb7SAndroid Build Coastguard Worker 
6151*fd1fabb7SAndroid Build Coastguard Worker 	else if (info.fCompression == ccLossyJPEG)
6152*fd1fabb7SAndroid Build Coastguard Worker 		{
6153*fd1fabb7SAndroid Build Coastguard Worker 
6154*fd1fabb7SAndroid Build Coastguard Worker 		ThrowProgramError ("No JPEG compressed image");
6155*fd1fabb7SAndroid Build Coastguard Worker 
6156*fd1fabb7SAndroid Build Coastguard Worker 		}
6157*fd1fabb7SAndroid Build Coastguard Worker 
6158*fd1fabb7SAndroid Build Coastguard Worker 	// Don't use tiles for uncompressed images.
6159*fd1fabb7SAndroid Build Coastguard Worker 
6160*fd1fabb7SAndroid Build Coastguard Worker 	else
6161*fd1fabb7SAndroid Build Coastguard Worker 		{
6162*fd1fabb7SAndroid Build Coastguard Worker 
6163*fd1fabb7SAndroid Build Coastguard Worker 		info.SetSingleStrip ();
6164*fd1fabb7SAndroid Build Coastguard Worker 
6165*fd1fabb7SAndroid Build Coastguard Worker 		}
6166*fd1fabb7SAndroid Build Coastguard Worker 
6167*fd1fabb7SAndroid Build Coastguard Worker 	#ifdef qTestRowInterleave
6168*fd1fabb7SAndroid Build Coastguard Worker 
6169*fd1fabb7SAndroid Build Coastguard Worker 	info.fRowInterleaveFactor = qTestRowInterleave;
6170*fd1fabb7SAndroid Build Coastguard Worker 
6171*fd1fabb7SAndroid Build Coastguard Worker 	#endif
6172*fd1fabb7SAndroid Build Coastguard Worker 
6173*fd1fabb7SAndroid Build Coastguard Worker 	#if defined(qTestSubTileBlockRows) && defined(qTestSubTileBlockCols)
6174*fd1fabb7SAndroid Build Coastguard Worker 
6175*fd1fabb7SAndroid Build Coastguard Worker 	info.fSubTileBlockRows = qTestSubTileBlockRows;
6176*fd1fabb7SAndroid Build Coastguard Worker 	info.fSubTileBlockCols = qTestSubTileBlockCols;
6177*fd1fabb7SAndroid Build Coastguard Worker 
6178*fd1fabb7SAndroid Build Coastguard Worker 	if (fakeChannels == 2)
6179*fd1fabb7SAndroid Build Coastguard Worker 		fakeChannels = 4;
6180*fd1fabb7SAndroid Build Coastguard Worker 
6181*fd1fabb7SAndroid Build Coastguard Worker 	#endif
6182*fd1fabb7SAndroid Build Coastguard Worker 
6183*fd1fabb7SAndroid Build Coastguard Worker 	// Basic information.
6184*fd1fabb7SAndroid Build Coastguard Worker 
6185*fd1fabb7SAndroid Build Coastguard Worker 	dng_basic_tag_set rawBasic (rawIFD, info);
6186*fd1fabb7SAndroid Build Coastguard Worker 
6187*fd1fabb7SAndroid Build Coastguard Worker 	// JPEG tables, if any.
6188*fd1fabb7SAndroid Build Coastguard Worker 
6189*fd1fabb7SAndroid Build Coastguard Worker 	tag_data_ptr tagJPEGTables (tcJPEGTables,
6190*fd1fabb7SAndroid Build Coastguard Worker 								ttUndefined,
6191*fd1fabb7SAndroid Build Coastguard Worker 								0,
6192*fd1fabb7SAndroid Build Coastguard Worker 								NULL);
6193*fd1fabb7SAndroid Build Coastguard Worker 
6194*fd1fabb7SAndroid Build Coastguard Worker 	if (rawJPEGImage && rawJPEGImage->fJPEGTables.Get ())
6195*fd1fabb7SAndroid Build Coastguard Worker 		{
6196*fd1fabb7SAndroid Build Coastguard Worker 
6197*fd1fabb7SAndroid Build Coastguard Worker 		tagJPEGTables.SetData (rawJPEGImage->fJPEGTables->Buffer ());
6198*fd1fabb7SAndroid Build Coastguard Worker 
6199*fd1fabb7SAndroid Build Coastguard Worker 		tagJPEGTables.SetCount (rawJPEGImage->fJPEGTables->LogicalSize ());
6200*fd1fabb7SAndroid Build Coastguard Worker 
6201*fd1fabb7SAndroid Build Coastguard Worker 		rawIFD.Add (&tagJPEGTables);
6202*fd1fabb7SAndroid Build Coastguard Worker 
6203*fd1fabb7SAndroid Build Coastguard Worker 		}
6204*fd1fabb7SAndroid Build Coastguard Worker 
6205*fd1fabb7SAndroid Build Coastguard Worker 	// DefaultScale tag.
6206*fd1fabb7SAndroid Build Coastguard Worker 
6207*fd1fabb7SAndroid Build Coastguard Worker 	dng_urational defaultScaleData [2];
6208*fd1fabb7SAndroid Build Coastguard Worker 
6209*fd1fabb7SAndroid Build Coastguard Worker 	defaultScaleData [0] = negative.DefaultScaleH ();
6210*fd1fabb7SAndroid Build Coastguard Worker 	defaultScaleData [1] = negative.DefaultScaleV ();
6211*fd1fabb7SAndroid Build Coastguard Worker 
6212*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational_ptr tagDefaultScale (tcDefaultScale,
6213*fd1fabb7SAndroid Build Coastguard Worker 								       defaultScaleData,
6214*fd1fabb7SAndroid Build Coastguard Worker 								       2);
6215*fd1fabb7SAndroid Build Coastguard Worker 
6216*fd1fabb7SAndroid Build Coastguard Worker 	rawIFD.Add (&tagDefaultScale);
6217*fd1fabb7SAndroid Build Coastguard Worker 
6218*fd1fabb7SAndroid Build Coastguard Worker 	// Best quality scale tag.
6219*fd1fabb7SAndroid Build Coastguard Worker 
6220*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational tagBestQualityScale (tcBestQualityScale,
6221*fd1fabb7SAndroid Build Coastguard Worker 									   negative.BestQualityScale ());
6222*fd1fabb7SAndroid Build Coastguard Worker 
6223*fd1fabb7SAndroid Build Coastguard Worker 	rawIFD.Add (&tagBestQualityScale);
6224*fd1fabb7SAndroid Build Coastguard Worker 
6225*fd1fabb7SAndroid Build Coastguard Worker 	// DefaultCropOrigin tag.
6226*fd1fabb7SAndroid Build Coastguard Worker 
6227*fd1fabb7SAndroid Build Coastguard Worker 	dng_urational defaultCropOriginData [2];
6228*fd1fabb7SAndroid Build Coastguard Worker 
6229*fd1fabb7SAndroid Build Coastguard Worker 	defaultCropOriginData [0] = negative.DefaultCropOriginH ();
6230*fd1fabb7SAndroid Build Coastguard Worker 	defaultCropOriginData [1] = negative.DefaultCropOriginV ();
6231*fd1fabb7SAndroid Build Coastguard Worker 
6232*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational_ptr tagDefaultCropOrigin (tcDefaultCropOrigin,
6233*fd1fabb7SAndroid Build Coastguard Worker 								            defaultCropOriginData,
6234*fd1fabb7SAndroid Build Coastguard Worker 								            2);
6235*fd1fabb7SAndroid Build Coastguard Worker 
6236*fd1fabb7SAndroid Build Coastguard Worker 	rawIFD.Add (&tagDefaultCropOrigin);
6237*fd1fabb7SAndroid Build Coastguard Worker 
6238*fd1fabb7SAndroid Build Coastguard Worker 	// DefaultCropSize tag.
6239*fd1fabb7SAndroid Build Coastguard Worker 
6240*fd1fabb7SAndroid Build Coastguard Worker 	dng_urational defaultCropSizeData [2];
6241*fd1fabb7SAndroid Build Coastguard Worker 
6242*fd1fabb7SAndroid Build Coastguard Worker 	defaultCropSizeData [0] = negative.DefaultCropSizeH ();
6243*fd1fabb7SAndroid Build Coastguard Worker 	defaultCropSizeData [1] = negative.DefaultCropSizeV ();
6244*fd1fabb7SAndroid Build Coastguard Worker 
6245*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational_ptr tagDefaultCropSize (tcDefaultCropSize,
6246*fd1fabb7SAndroid Build Coastguard Worker 								          defaultCropSizeData,
6247*fd1fabb7SAndroid Build Coastguard Worker 								          2);
6248*fd1fabb7SAndroid Build Coastguard Worker 
6249*fd1fabb7SAndroid Build Coastguard Worker 	rawIFD.Add (&tagDefaultCropSize);
6250*fd1fabb7SAndroid Build Coastguard Worker 
6251*fd1fabb7SAndroid Build Coastguard Worker 	// DefaultUserCrop tag.
6252*fd1fabb7SAndroid Build Coastguard Worker 
6253*fd1fabb7SAndroid Build Coastguard Worker 	dng_urational defaultUserCropData [4];
6254*fd1fabb7SAndroid Build Coastguard Worker 
6255*fd1fabb7SAndroid Build Coastguard Worker 	defaultUserCropData [0] = negative.DefaultUserCropT ();
6256*fd1fabb7SAndroid Build Coastguard Worker 	defaultUserCropData [1] = negative.DefaultUserCropL ();
6257*fd1fabb7SAndroid Build Coastguard Worker 	defaultUserCropData [2] = negative.DefaultUserCropB ();
6258*fd1fabb7SAndroid Build Coastguard Worker 	defaultUserCropData [3] = negative.DefaultUserCropR ();
6259*fd1fabb7SAndroid Build Coastguard Worker 
6260*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational_ptr tagDefaultUserCrop (tcDefaultUserCrop,
6261*fd1fabb7SAndroid Build Coastguard Worker 										  defaultUserCropData,
6262*fd1fabb7SAndroid Build Coastguard Worker 										  4);
6263*fd1fabb7SAndroid Build Coastguard Worker 
6264*fd1fabb7SAndroid Build Coastguard Worker 	rawIFD.Add (&tagDefaultUserCrop);
6265*fd1fabb7SAndroid Build Coastguard Worker 
6266*fd1fabb7SAndroid Build Coastguard Worker 	// Range mapping tag set.
6267*fd1fabb7SAndroid Build Coastguard Worker 
6268*fd1fabb7SAndroid Build Coastguard Worker 	range_tag_set rangeSet (rawIFD, negative);
6269*fd1fabb7SAndroid Build Coastguard Worker 
6270*fd1fabb7SAndroid Build Coastguard Worker 	// Mosaic pattern information.
6271*fd1fabb7SAndroid Build Coastguard Worker 
6272*fd1fabb7SAndroid Build Coastguard Worker 	mosaic_tag_set mosaicSet (rawIFD, mosaicInfo);
6273*fd1fabb7SAndroid Build Coastguard Worker 
6274*fd1fabb7SAndroid Build Coastguard Worker 	// Chroma blur radius.
6275*fd1fabb7SAndroid Build Coastguard Worker 
6276*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational tagChromaBlurRadius (tcChromaBlurRadius,
6277*fd1fabb7SAndroid Build Coastguard Worker 									   negative.ChromaBlurRadius ());
6278*fd1fabb7SAndroid Build Coastguard Worker 
6279*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.ChromaBlurRadius ().IsValid ())
6280*fd1fabb7SAndroid Build Coastguard Worker 		{
6281*fd1fabb7SAndroid Build Coastguard Worker 
6282*fd1fabb7SAndroid Build Coastguard Worker 		rawIFD.Add (&tagChromaBlurRadius);
6283*fd1fabb7SAndroid Build Coastguard Worker 
6284*fd1fabb7SAndroid Build Coastguard Worker 		}
6285*fd1fabb7SAndroid Build Coastguard Worker 
6286*fd1fabb7SAndroid Build Coastguard Worker 	// Anti-alias filter strength.
6287*fd1fabb7SAndroid Build Coastguard Worker 
6288*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational tagAntiAliasStrength (tcAntiAliasStrength,
6289*fd1fabb7SAndroid Build Coastguard Worker 									    negative.AntiAliasStrength ());
6290*fd1fabb7SAndroid Build Coastguard Worker 
6291*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.AntiAliasStrength ().IsValid ())
6292*fd1fabb7SAndroid Build Coastguard Worker 		{
6293*fd1fabb7SAndroid Build Coastguard Worker 
6294*fd1fabb7SAndroid Build Coastguard Worker 		rawIFD.Add (&tagAntiAliasStrength);
6295*fd1fabb7SAndroid Build Coastguard Worker 
6296*fd1fabb7SAndroid Build Coastguard Worker 		}
6297*fd1fabb7SAndroid Build Coastguard Worker 
6298*fd1fabb7SAndroid Build Coastguard Worker 	// Profile and other color related tags.
6299*fd1fabb7SAndroid Build Coastguard Worker 
6300*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<profile_tag_set> profileSet;
6301*fd1fabb7SAndroid Build Coastguard Worker 
6302*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<color_tag_set> colorSet;
6303*fd1fabb7SAndroid Build Coastguard Worker 
6304*fd1fabb7SAndroid Build Coastguard Worker 	dng_std_vector<uint32> extraProfileIndex;
6305*fd1fabb7SAndroid Build Coastguard Worker 
6306*fd1fabb7SAndroid Build Coastguard Worker 	if (!negative.IsMonochrome ())
6307*fd1fabb7SAndroid Build Coastguard Worker 		{
6308*fd1fabb7SAndroid Build Coastguard Worker 
6309*fd1fabb7SAndroid Build Coastguard Worker 		const dng_camera_profile &mainProfile (*negative.ComputeCameraProfileToEmbed (constMetadata));
6310*fd1fabb7SAndroid Build Coastguard Worker 
6311*fd1fabb7SAndroid Build Coastguard Worker 		profileSet.Reset (new profile_tag_set (mainIFD,
6312*fd1fabb7SAndroid Build Coastguard Worker 											   mainProfile));
6313*fd1fabb7SAndroid Build Coastguard Worker 
6314*fd1fabb7SAndroid Build Coastguard Worker 		colorSet.Reset (new color_tag_set (mainIFD,
6315*fd1fabb7SAndroid Build Coastguard Worker 										   negative));
6316*fd1fabb7SAndroid Build Coastguard Worker 
6317*fd1fabb7SAndroid Build Coastguard Worker 		// Build list of profile indices to include in extra profiles tag.
6318*fd1fabb7SAndroid Build Coastguard Worker 
6319*fd1fabb7SAndroid Build Coastguard Worker 		uint32 profileCount = negative.ProfileCount ();
6320*fd1fabb7SAndroid Build Coastguard Worker 
6321*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 index = 0; index < profileCount; index++)
6322*fd1fabb7SAndroid Build Coastguard Worker 			{
6323*fd1fabb7SAndroid Build Coastguard Worker 
6324*fd1fabb7SAndroid Build Coastguard Worker 			const dng_camera_profile &profile (negative.ProfileByIndex (index));
6325*fd1fabb7SAndroid Build Coastguard Worker 
6326*fd1fabb7SAndroid Build Coastguard Worker 			if (&profile != &mainProfile)
6327*fd1fabb7SAndroid Build Coastguard Worker 				{
6328*fd1fabb7SAndroid Build Coastguard Worker 
6329*fd1fabb7SAndroid Build Coastguard Worker 				if (profile.WasReadFromDNG ())
6330*fd1fabb7SAndroid Build Coastguard Worker 					{
6331*fd1fabb7SAndroid Build Coastguard Worker 
6332*fd1fabb7SAndroid Build Coastguard Worker 					extraProfileIndex.push_back (index);
6333*fd1fabb7SAndroid Build Coastguard Worker 
6334*fd1fabb7SAndroid Build Coastguard Worker 					}
6335*fd1fabb7SAndroid Build Coastguard Worker 
6336*fd1fabb7SAndroid Build Coastguard Worker 				}
6337*fd1fabb7SAndroid Build Coastguard Worker 
6338*fd1fabb7SAndroid Build Coastguard Worker 			}
6339*fd1fabb7SAndroid Build Coastguard Worker 
6340*fd1fabb7SAndroid Build Coastguard Worker 		}
6341*fd1fabb7SAndroid Build Coastguard Worker 
6342*fd1fabb7SAndroid Build Coastguard Worker 	// Extra camera profiles tag.
6343*fd1fabb7SAndroid Build Coastguard Worker 
6344*fd1fabb7SAndroid Build Coastguard Worker 	uint32 extraProfileCount = (uint32) extraProfileIndex.size ();
6345*fd1fabb7SAndroid Build Coastguard Worker 
6346*fd1fabb7SAndroid Build Coastguard Worker 	dng_memory_data extraProfileOffsets (extraProfileCount, sizeof (uint32));
6347*fd1fabb7SAndroid Build Coastguard Worker 
6348*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint32_ptr extraProfileTag (tcExtraCameraProfiles,
6349*fd1fabb7SAndroid Build Coastguard Worker 									extraProfileOffsets.Buffer_uint32 (),
6350*fd1fabb7SAndroid Build Coastguard Worker 									extraProfileCount);
6351*fd1fabb7SAndroid Build Coastguard Worker 
6352*fd1fabb7SAndroid Build Coastguard Worker 	if (extraProfileCount)
6353*fd1fabb7SAndroid Build Coastguard Worker 		{
6354*fd1fabb7SAndroid Build Coastguard Worker 
6355*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&extraProfileTag);
6356*fd1fabb7SAndroid Build Coastguard Worker 
6357*fd1fabb7SAndroid Build Coastguard Worker 		}
6358*fd1fabb7SAndroid Build Coastguard Worker 
6359*fd1fabb7SAndroid Build Coastguard Worker 	// Other tags.
6360*fd1fabb7SAndroid Build Coastguard Worker 
6361*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint16 tagOrientation (tcOrientation,
6362*fd1fabb7SAndroid Build Coastguard Worker 						       (uint16) negative.ComputeOrientation (constMetadata).GetTIFF ());
6363*fd1fabb7SAndroid Build Coastguard Worker 
6364*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Add (&tagOrientation);
6365*fd1fabb7SAndroid Build Coastguard Worker 
6366*fd1fabb7SAndroid Build Coastguard Worker 	tag_srational tagBaselineExposure (tcBaselineExposure,
6367*fd1fabb7SAndroid Build Coastguard Worker 								       negative.BaselineExposureR ());
6368*fd1fabb7SAndroid Build Coastguard Worker 
6369*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Add (&tagBaselineExposure);
6370*fd1fabb7SAndroid Build Coastguard Worker 
6371*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational tagBaselineNoise (tcBaselineNoise,
6372*fd1fabb7SAndroid Build Coastguard Worker 							        negative.BaselineNoiseR ());
6373*fd1fabb7SAndroid Build Coastguard Worker 
6374*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Add (&tagBaselineNoise);
6375*fd1fabb7SAndroid Build Coastguard Worker 
6376*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational tagNoiseReductionApplied (tcNoiseReductionApplied,
6377*fd1fabb7SAndroid Build Coastguard Worker 											negative.NoiseReductionApplied ());
6378*fd1fabb7SAndroid Build Coastguard Worker 
6379*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.NoiseReductionApplied ().IsValid ())
6380*fd1fabb7SAndroid Build Coastguard Worker 		{
6381*fd1fabb7SAndroid Build Coastguard Worker 
6382*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagNoiseReductionApplied);
6383*fd1fabb7SAndroid Build Coastguard Worker 
6384*fd1fabb7SAndroid Build Coastguard Worker 		}
6385*fd1fabb7SAndroid Build Coastguard Worker 
6386*fd1fabb7SAndroid Build Coastguard Worker 	tag_dng_noise_profile tagNoiseProfile (negative.NoiseProfile ());
6387*fd1fabb7SAndroid Build Coastguard Worker 
6388*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.NoiseProfile ().IsValidForNegative (negative))
6389*fd1fabb7SAndroid Build Coastguard Worker 		{
6390*fd1fabb7SAndroid Build Coastguard Worker 
6391*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagNoiseProfile);
6392*fd1fabb7SAndroid Build Coastguard Worker 
6393*fd1fabb7SAndroid Build Coastguard Worker 		}
6394*fd1fabb7SAndroid Build Coastguard Worker 
6395*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational tagBaselineSharpness (tcBaselineSharpness,
6396*fd1fabb7SAndroid Build Coastguard Worker 								        negative.BaselineSharpnessR ());
6397*fd1fabb7SAndroid Build Coastguard Worker 
6398*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Add (&tagBaselineSharpness);
6399*fd1fabb7SAndroid Build Coastguard Worker 
6400*fd1fabb7SAndroid Build Coastguard Worker 	tag_string tagUniqueName (tcUniqueCameraModel,
6401*fd1fabb7SAndroid Build Coastguard Worker 						      negative.ModelName (),
6402*fd1fabb7SAndroid Build Coastguard Worker 						      true);
6403*fd1fabb7SAndroid Build Coastguard Worker 
6404*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Add (&tagUniqueName);
6405*fd1fabb7SAndroid Build Coastguard Worker 
6406*fd1fabb7SAndroid Build Coastguard Worker 	tag_string tagLocalName (tcLocalizedCameraModel,
6407*fd1fabb7SAndroid Build Coastguard Worker 						     negative.LocalName (),
6408*fd1fabb7SAndroid Build Coastguard Worker 						     false);
6409*fd1fabb7SAndroid Build Coastguard Worker 
6410*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.LocalName ().NotEmpty ())
6411*fd1fabb7SAndroid Build Coastguard Worker 		{
6412*fd1fabb7SAndroid Build Coastguard Worker 
6413*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagLocalName);
6414*fd1fabb7SAndroid Build Coastguard Worker 
6415*fd1fabb7SAndroid Build Coastguard Worker 		}
6416*fd1fabb7SAndroid Build Coastguard Worker 
6417*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational tagShadowScale (tcShadowScale,
6418*fd1fabb7SAndroid Build Coastguard Worker 							      negative.ShadowScaleR ());
6419*fd1fabb7SAndroid Build Coastguard Worker 
6420*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Add (&tagShadowScale);
6421*fd1fabb7SAndroid Build Coastguard Worker 
6422*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint16 tagColorimetricReference (tcColorimetricReference,
6423*fd1fabb7SAndroid Build Coastguard Worker 										 (uint16) negative.ColorimetricReference ());
6424*fd1fabb7SAndroid Build Coastguard Worker 
6425*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.ColorimetricReference () != crSceneReferred)
6426*fd1fabb7SAndroid Build Coastguard Worker 		{
6427*fd1fabb7SAndroid Build Coastguard Worker 
6428*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagColorimetricReference);
6429*fd1fabb7SAndroid Build Coastguard Worker 
6430*fd1fabb7SAndroid Build Coastguard Worker 		}
6431*fd1fabb7SAndroid Build Coastguard Worker 
6432*fd1fabb7SAndroid Build Coastguard Worker 	bool useNewDigest = (maxBackwardVersion >= dngVersion_1_4_0_0);
6433*fd1fabb7SAndroid Build Coastguard Worker 
6434*fd1fabb7SAndroid Build Coastguard Worker 	if (compression == ccLossyJPEG)
6435*fd1fabb7SAndroid Build Coastguard Worker 		{
6436*fd1fabb7SAndroid Build Coastguard Worker 
6437*fd1fabb7SAndroid Build Coastguard Worker 		negative.FindRawJPEGImageDigest (host);
6438*fd1fabb7SAndroid Build Coastguard Worker 
6439*fd1fabb7SAndroid Build Coastguard Worker 		}
6440*fd1fabb7SAndroid Build Coastguard Worker 
6441*fd1fabb7SAndroid Build Coastguard Worker 	else
6442*fd1fabb7SAndroid Build Coastguard Worker 		{
6443*fd1fabb7SAndroid Build Coastguard Worker 
6444*fd1fabb7SAndroid Build Coastguard Worker 		if (useNewDigest)
6445*fd1fabb7SAndroid Build Coastguard Worker 			{
6446*fd1fabb7SAndroid Build Coastguard Worker 			negative.FindNewRawImageDigest (host);
6447*fd1fabb7SAndroid Build Coastguard Worker 			}
6448*fd1fabb7SAndroid Build Coastguard Worker 		else
6449*fd1fabb7SAndroid Build Coastguard Worker 			{
6450*fd1fabb7SAndroid Build Coastguard Worker 			negative.FindRawImageDigest (host);
6451*fd1fabb7SAndroid Build Coastguard Worker 			}
6452*fd1fabb7SAndroid Build Coastguard Worker 
6453*fd1fabb7SAndroid Build Coastguard Worker 		}
6454*fd1fabb7SAndroid Build Coastguard Worker 
6455*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint8_ptr tagRawImageDigest (useNewDigest ? tcNewRawImageDigest : tcRawImageDigest,
6456*fd1fabb7SAndroid Build Coastguard Worker 									 compression == ccLossyJPEG ?
6457*fd1fabb7SAndroid Build Coastguard Worker 									 negative.RawJPEGImageDigest ().data :
6458*fd1fabb7SAndroid Build Coastguard Worker 									 (useNewDigest ? negative.NewRawImageDigest ().data
6459*fd1fabb7SAndroid Build Coastguard Worker 												   : negative.RawImageDigest    ().data),
6460*fd1fabb7SAndroid Build Coastguard Worker 							   		 16);
6461*fd1fabb7SAndroid Build Coastguard Worker 
6462*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Add (&tagRawImageDigest);
6463*fd1fabb7SAndroid Build Coastguard Worker 
6464*fd1fabb7SAndroid Build Coastguard Worker 	negative.FindRawDataUniqueID (host);
6465*fd1fabb7SAndroid Build Coastguard Worker 
6466*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint8_ptr tagRawDataUniqueID (tcRawDataUniqueID,
6467*fd1fabb7SAndroid Build Coastguard Worker 							   		  negative.RawDataUniqueID ().data,
6468*fd1fabb7SAndroid Build Coastguard Worker 							   		  16);
6469*fd1fabb7SAndroid Build Coastguard Worker 
6470*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.RawDataUniqueID ().IsValid ())
6471*fd1fabb7SAndroid Build Coastguard Worker 		{
6472*fd1fabb7SAndroid Build Coastguard Worker 
6473*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagRawDataUniqueID);
6474*fd1fabb7SAndroid Build Coastguard Worker 
6475*fd1fabb7SAndroid Build Coastguard Worker 		}
6476*fd1fabb7SAndroid Build Coastguard Worker 
6477*fd1fabb7SAndroid Build Coastguard Worker 	tag_string tagOriginalRawFileName (tcOriginalRawFileName,
6478*fd1fabb7SAndroid Build Coastguard Worker 						   			   negative.OriginalRawFileName (),
6479*fd1fabb7SAndroid Build Coastguard Worker 						   			   false);
6480*fd1fabb7SAndroid Build Coastguard Worker 
6481*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.HasOriginalRawFileName ())
6482*fd1fabb7SAndroid Build Coastguard Worker 		{
6483*fd1fabb7SAndroid Build Coastguard Worker 
6484*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagOriginalRawFileName);
6485*fd1fabb7SAndroid Build Coastguard Worker 
6486*fd1fabb7SAndroid Build Coastguard Worker 		}
6487*fd1fabb7SAndroid Build Coastguard Worker 
6488*fd1fabb7SAndroid Build Coastguard Worker 	negative.FindOriginalRawFileDigest ();
6489*fd1fabb7SAndroid Build Coastguard Worker 
6490*fd1fabb7SAndroid Build Coastguard Worker 	tag_data_ptr tagOriginalRawFileData (tcOriginalRawFileData,
6491*fd1fabb7SAndroid Build Coastguard Worker 										 ttUndefined,
6492*fd1fabb7SAndroid Build Coastguard Worker 										 negative.OriginalRawFileDataLength (),
6493*fd1fabb7SAndroid Build Coastguard Worker 										 negative.OriginalRawFileData       ());
6494*fd1fabb7SAndroid Build Coastguard Worker 
6495*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint8_ptr tagOriginalRawFileDigest (tcOriginalRawFileDigest,
6496*fd1fabb7SAndroid Build Coastguard Worker 											negative.OriginalRawFileDigest ().data,
6497*fd1fabb7SAndroid Build Coastguard Worker 											16);
6498*fd1fabb7SAndroid Build Coastguard Worker 
6499*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.OriginalRawFileData ())
6500*fd1fabb7SAndroid Build Coastguard Worker 		{
6501*fd1fabb7SAndroid Build Coastguard Worker 
6502*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagOriginalRawFileData);
6503*fd1fabb7SAndroid Build Coastguard Worker 
6504*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagOriginalRawFileDigest);
6505*fd1fabb7SAndroid Build Coastguard Worker 
6506*fd1fabb7SAndroid Build Coastguard Worker 		}
6507*fd1fabb7SAndroid Build Coastguard Worker 
6508*fd1fabb7SAndroid Build Coastguard Worker 	// XMP metadata.
6509*fd1fabb7SAndroid Build Coastguard Worker 
6510*fd1fabb7SAndroid Build Coastguard Worker 	#if qDNGUseXMP
6511*fd1fabb7SAndroid Build Coastguard Worker 
6512*fd1fabb7SAndroid Build Coastguard Worker 	tag_xmp tagXMP (metadata->GetXMP ());
6513*fd1fabb7SAndroid Build Coastguard Worker 
6514*fd1fabb7SAndroid Build Coastguard Worker 	if (tagXMP.Count ())
6515*fd1fabb7SAndroid Build Coastguard Worker 		{
6516*fd1fabb7SAndroid Build Coastguard Worker 
6517*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagXMP);
6518*fd1fabb7SAndroid Build Coastguard Worker 
6519*fd1fabb7SAndroid Build Coastguard Worker 		}
6520*fd1fabb7SAndroid Build Coastguard Worker 
6521*fd1fabb7SAndroid Build Coastguard Worker 	#endif
6522*fd1fabb7SAndroid Build Coastguard Worker 
6523*fd1fabb7SAndroid Build Coastguard Worker 	// Exif tags.
6524*fd1fabb7SAndroid Build Coastguard Worker 
6525*fd1fabb7SAndroid Build Coastguard Worker 	exif_tag_set exifSet (mainIFD,
6526*fd1fabb7SAndroid Build Coastguard Worker 						  *metadata->GetExif (),
6527*fd1fabb7SAndroid Build Coastguard Worker 						  metadata->IsMakerNoteSafe (),
6528*fd1fabb7SAndroid Build Coastguard Worker 						  metadata->MakerNoteData   (),
6529*fd1fabb7SAndroid Build Coastguard Worker 						  metadata->MakerNoteLength (),
6530*fd1fabb7SAndroid Build Coastguard Worker 						  true);
6531*fd1fabb7SAndroid Build Coastguard Worker 
6532*fd1fabb7SAndroid Build Coastguard Worker 	// Private data.
6533*fd1fabb7SAndroid Build Coastguard Worker 
6534*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint8_ptr tagPrivateData (tcDNGPrivateData,
6535*fd1fabb7SAndroid Build Coastguard Worker 						   		  negative.PrivateData (),
6536*fd1fabb7SAndroid Build Coastguard Worker 						   		  negative.PrivateLength ());
6537*fd1fabb7SAndroid Build Coastguard Worker 
6538*fd1fabb7SAndroid Build Coastguard Worker 	if (negative.PrivateLength ())
6539*fd1fabb7SAndroid Build Coastguard Worker 		{
6540*fd1fabb7SAndroid Build Coastguard Worker 
6541*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagPrivateData);
6542*fd1fabb7SAndroid Build Coastguard Worker 
6543*fd1fabb7SAndroid Build Coastguard Worker 		}
6544*fd1fabb7SAndroid Build Coastguard Worker 
6545*fd1fabb7SAndroid Build Coastguard Worker 	// Proxy size tags.
6546*fd1fabb7SAndroid Build Coastguard Worker 
6547*fd1fabb7SAndroid Build Coastguard Worker 	uint32 originalDefaultFinalSizeData [2];
6548*fd1fabb7SAndroid Build Coastguard Worker 
6549*fd1fabb7SAndroid Build Coastguard Worker 	originalDefaultFinalSizeData [0] = negative.OriginalDefaultFinalSize ().h;
6550*fd1fabb7SAndroid Build Coastguard Worker 	originalDefaultFinalSizeData [1] = negative.OriginalDefaultFinalSize ().v;
6551*fd1fabb7SAndroid Build Coastguard Worker 
6552*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint32_ptr tagOriginalDefaultFinalSize (tcOriginalDefaultFinalSize,
6553*fd1fabb7SAndroid Build Coastguard Worker 												originalDefaultFinalSizeData,
6554*fd1fabb7SAndroid Build Coastguard Worker 												2);
6555*fd1fabb7SAndroid Build Coastguard Worker 
6556*fd1fabb7SAndroid Build Coastguard Worker 	if (saveOriginalDefaultFinalSize)
6557*fd1fabb7SAndroid Build Coastguard Worker 		{
6558*fd1fabb7SAndroid Build Coastguard Worker 
6559*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagOriginalDefaultFinalSize);
6560*fd1fabb7SAndroid Build Coastguard Worker 
6561*fd1fabb7SAndroid Build Coastguard Worker 		}
6562*fd1fabb7SAndroid Build Coastguard Worker 
6563*fd1fabb7SAndroid Build Coastguard Worker 	uint32 originalBestQualityFinalSizeData [2];
6564*fd1fabb7SAndroid Build Coastguard Worker 
6565*fd1fabb7SAndroid Build Coastguard Worker 	originalBestQualityFinalSizeData [0] = negative.OriginalBestQualityFinalSize ().h;
6566*fd1fabb7SAndroid Build Coastguard Worker 	originalBestQualityFinalSizeData [1] = negative.OriginalBestQualityFinalSize ().v;
6567*fd1fabb7SAndroid Build Coastguard Worker 
6568*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint32_ptr tagOriginalBestQualityFinalSize (tcOriginalBestQualityFinalSize,
6569*fd1fabb7SAndroid Build Coastguard Worker 													originalBestQualityFinalSizeData,
6570*fd1fabb7SAndroid Build Coastguard Worker 													2);
6571*fd1fabb7SAndroid Build Coastguard Worker 
6572*fd1fabb7SAndroid Build Coastguard Worker 	if (saveOriginalBestQualityFinalSize)
6573*fd1fabb7SAndroid Build Coastguard Worker 		{
6574*fd1fabb7SAndroid Build Coastguard Worker 
6575*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagOriginalBestQualityFinalSize);
6576*fd1fabb7SAndroid Build Coastguard Worker 
6577*fd1fabb7SAndroid Build Coastguard Worker 		}
6578*fd1fabb7SAndroid Build Coastguard Worker 
6579*fd1fabb7SAndroid Build Coastguard Worker 	dng_urational originalDefaultCropSizeData [2];
6580*fd1fabb7SAndroid Build Coastguard Worker 
6581*fd1fabb7SAndroid Build Coastguard Worker 	originalDefaultCropSizeData [0] = negative.OriginalDefaultCropSizeH ();
6582*fd1fabb7SAndroid Build Coastguard Worker 	originalDefaultCropSizeData [1] = negative.OriginalDefaultCropSizeV ();
6583*fd1fabb7SAndroid Build Coastguard Worker 
6584*fd1fabb7SAndroid Build Coastguard Worker 	tag_urational_ptr tagOriginalDefaultCropSize (tcOriginalDefaultCropSize,
6585*fd1fabb7SAndroid Build Coastguard Worker 												  originalDefaultCropSizeData,
6586*fd1fabb7SAndroid Build Coastguard Worker 												  2);
6587*fd1fabb7SAndroid Build Coastguard Worker 
6588*fd1fabb7SAndroid Build Coastguard Worker 	if (saveOriginalDefaultCropSize)
6589*fd1fabb7SAndroid Build Coastguard Worker 		{
6590*fd1fabb7SAndroid Build Coastguard Worker 
6591*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagOriginalDefaultCropSize);
6592*fd1fabb7SAndroid Build Coastguard Worker 
6593*fd1fabb7SAndroid Build Coastguard Worker 		}
6594*fd1fabb7SAndroid Build Coastguard Worker 
6595*fd1fabb7SAndroid Build Coastguard Worker 	// Opcode list 1.
6596*fd1fabb7SAndroid Build Coastguard Worker 
6597*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_memory_block> opcodeList1Data (negative.OpcodeList1 ().Spool (host));
6598*fd1fabb7SAndroid Build Coastguard Worker 
6599*fd1fabb7SAndroid Build Coastguard Worker 	tag_data_ptr tagOpcodeList1 (tcOpcodeList1,
6600*fd1fabb7SAndroid Build Coastguard Worker 								 ttUndefined,
6601*fd1fabb7SAndroid Build Coastguard Worker 								 opcodeList1Data.Get () ? opcodeList1Data->LogicalSize () : 0,
6602*fd1fabb7SAndroid Build Coastguard Worker 								 opcodeList1Data.Get () ? opcodeList1Data->Buffer      () : NULL);
6603*fd1fabb7SAndroid Build Coastguard Worker 
6604*fd1fabb7SAndroid Build Coastguard Worker 	if (opcodeList1Data.Get ())
6605*fd1fabb7SAndroid Build Coastguard Worker 		{
6606*fd1fabb7SAndroid Build Coastguard Worker 
6607*fd1fabb7SAndroid Build Coastguard Worker 		rawIFD.Add (&tagOpcodeList1);
6608*fd1fabb7SAndroid Build Coastguard Worker 
6609*fd1fabb7SAndroid Build Coastguard Worker 		}
6610*fd1fabb7SAndroid Build Coastguard Worker 
6611*fd1fabb7SAndroid Build Coastguard Worker 	// Opcode list 2.
6612*fd1fabb7SAndroid Build Coastguard Worker 
6613*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_memory_block> opcodeList2Data (negative.OpcodeList2 ().Spool (host));
6614*fd1fabb7SAndroid Build Coastguard Worker 
6615*fd1fabb7SAndroid Build Coastguard Worker 	tag_data_ptr tagOpcodeList2 (tcOpcodeList2,
6616*fd1fabb7SAndroid Build Coastguard Worker 								 ttUndefined,
6617*fd1fabb7SAndroid Build Coastguard Worker 								 opcodeList2Data.Get () ? opcodeList2Data->LogicalSize () : 0,
6618*fd1fabb7SAndroid Build Coastguard Worker 								 opcodeList2Data.Get () ? opcodeList2Data->Buffer      () : NULL);
6619*fd1fabb7SAndroid Build Coastguard Worker 
6620*fd1fabb7SAndroid Build Coastguard Worker 	if (opcodeList2Data.Get ())
6621*fd1fabb7SAndroid Build Coastguard Worker 		{
6622*fd1fabb7SAndroid Build Coastguard Worker 
6623*fd1fabb7SAndroid Build Coastguard Worker 		rawIFD.Add (&tagOpcodeList2);
6624*fd1fabb7SAndroid Build Coastguard Worker 
6625*fd1fabb7SAndroid Build Coastguard Worker 		}
6626*fd1fabb7SAndroid Build Coastguard Worker 
6627*fd1fabb7SAndroid Build Coastguard Worker 	// Opcode list 3.
6628*fd1fabb7SAndroid Build Coastguard Worker 
6629*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_memory_block> opcodeList3Data (negative.OpcodeList3 ().Spool (host));
6630*fd1fabb7SAndroid Build Coastguard Worker 
6631*fd1fabb7SAndroid Build Coastguard Worker 	tag_data_ptr tagOpcodeList3 (tcOpcodeList3,
6632*fd1fabb7SAndroid Build Coastguard Worker 								 ttUndefined,
6633*fd1fabb7SAndroid Build Coastguard Worker 								 opcodeList3Data.Get () ? opcodeList3Data->LogicalSize () : 0,
6634*fd1fabb7SAndroid Build Coastguard Worker 								 opcodeList3Data.Get () ? opcodeList3Data->Buffer      () : NULL);
6635*fd1fabb7SAndroid Build Coastguard Worker 
6636*fd1fabb7SAndroid Build Coastguard Worker 	if (opcodeList3Data.Get ())
6637*fd1fabb7SAndroid Build Coastguard Worker 		{
6638*fd1fabb7SAndroid Build Coastguard Worker 
6639*fd1fabb7SAndroid Build Coastguard Worker 		rawIFD.Add (&tagOpcodeList3);
6640*fd1fabb7SAndroid Build Coastguard Worker 
6641*fd1fabb7SAndroid Build Coastguard Worker 		}
6642*fd1fabb7SAndroid Build Coastguard Worker 
6643*fd1fabb7SAndroid Build Coastguard Worker 	// Transparency mask, if any.
6644*fd1fabb7SAndroid Build Coastguard Worker 
6645*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_ifd> maskInfo;
6646*fd1fabb7SAndroid Build Coastguard Worker 
6647*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_tiff_directory> maskIFD;
6648*fd1fabb7SAndroid Build Coastguard Worker 
6649*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_basic_tag_set> maskBasic;
6650*fd1fabb7SAndroid Build Coastguard Worker 
6651*fd1fabb7SAndroid Build Coastguard Worker 	if (hasTransparencyMask)
6652*fd1fabb7SAndroid Build Coastguard Worker 		{
6653*fd1fabb7SAndroid Build Coastguard Worker 
6654*fd1fabb7SAndroid Build Coastguard Worker 		// Create mask IFD.
6655*fd1fabb7SAndroid Build Coastguard Worker 
6656*fd1fabb7SAndroid Build Coastguard Worker 		maskInfo.Reset (new dng_ifd);
6657*fd1fabb7SAndroid Build Coastguard Worker 
6658*fd1fabb7SAndroid Build Coastguard Worker 		maskInfo->fNewSubFileType = sfTransparencyMask;
6659*fd1fabb7SAndroid Build Coastguard Worker 
6660*fd1fabb7SAndroid Build Coastguard Worker 		maskInfo->fImageWidth  = negative.RawTransparencyMask ()->Bounds ().W ();
6661*fd1fabb7SAndroid Build Coastguard Worker 		maskInfo->fImageLength = negative.RawTransparencyMask ()->Bounds ().H ();
6662*fd1fabb7SAndroid Build Coastguard Worker 
6663*fd1fabb7SAndroid Build Coastguard Worker 		maskInfo->fSamplesPerPixel = 1;
6664*fd1fabb7SAndroid Build Coastguard Worker 
6665*fd1fabb7SAndroid Build Coastguard Worker 		maskInfo->fBitsPerSample [0] = negative.RawTransparencyMaskBitDepth ();
6666*fd1fabb7SAndroid Build Coastguard Worker 
6667*fd1fabb7SAndroid Build Coastguard Worker 		maskInfo->fPhotometricInterpretation = piTransparencyMask;
6668*fd1fabb7SAndroid Build Coastguard Worker 
6669*fd1fabb7SAndroid Build Coastguard Worker 		maskInfo->fCompression = uncompressed ? ccUncompressed  : ccDeflate;
6670*fd1fabb7SAndroid Build Coastguard Worker 		maskInfo->fPredictor   = uncompressed ? cpNullPredictor : cpHorizontalDifference;
6671*fd1fabb7SAndroid Build Coastguard Worker 
6672*fd1fabb7SAndroid Build Coastguard Worker 		if (negative.RawTransparencyMask ()->PixelType () == ttFloat)
6673*fd1fabb7SAndroid Build Coastguard Worker 			{
6674*fd1fabb7SAndroid Build Coastguard Worker 
6675*fd1fabb7SAndroid Build Coastguard Worker 			maskInfo->fSampleFormat [0] = sfFloatingPoint;
6676*fd1fabb7SAndroid Build Coastguard Worker 
6677*fd1fabb7SAndroid Build Coastguard Worker 			if (maskInfo->fCompression == ccDeflate)
6678*fd1fabb7SAndroid Build Coastguard Worker 				{
6679*fd1fabb7SAndroid Build Coastguard Worker 				maskInfo->fPredictor = cpFloatingPoint;
6680*fd1fabb7SAndroid Build Coastguard Worker 				}
6681*fd1fabb7SAndroid Build Coastguard Worker 
6682*fd1fabb7SAndroid Build Coastguard Worker 			}
6683*fd1fabb7SAndroid Build Coastguard Worker 
6684*fd1fabb7SAndroid Build Coastguard Worker 		if (maskInfo->fCompression == ccDeflate)
6685*fd1fabb7SAndroid Build Coastguard Worker 			{
6686*fd1fabb7SAndroid Build Coastguard Worker 			maskInfo->FindTileSize (512 * 1024);
6687*fd1fabb7SAndroid Build Coastguard Worker 			}
6688*fd1fabb7SAndroid Build Coastguard Worker 		else
6689*fd1fabb7SAndroid Build Coastguard Worker 			{
6690*fd1fabb7SAndroid Build Coastguard Worker 			maskInfo->SetSingleStrip ();
6691*fd1fabb7SAndroid Build Coastguard Worker 			}
6692*fd1fabb7SAndroid Build Coastguard Worker 
6693*fd1fabb7SAndroid Build Coastguard Worker 		// Create mask tiff directory.
6694*fd1fabb7SAndroid Build Coastguard Worker 
6695*fd1fabb7SAndroid Build Coastguard Worker 		maskIFD.Reset (new dng_tiff_directory);
6696*fd1fabb7SAndroid Build Coastguard Worker 
6697*fd1fabb7SAndroid Build Coastguard Worker 		// Add mask basic tag set.
6698*fd1fabb7SAndroid Build Coastguard Worker 
6699*fd1fabb7SAndroid Build Coastguard Worker 		maskBasic.Reset (new dng_basic_tag_set (*maskIFD, *maskInfo));
6700*fd1fabb7SAndroid Build Coastguard Worker 
6701*fd1fabb7SAndroid Build Coastguard Worker 		}
6702*fd1fabb7SAndroid Build Coastguard Worker 
6703*fd1fabb7SAndroid Build Coastguard Worker 	// Add other subfiles.
6704*fd1fabb7SAndroid Build Coastguard Worker 
6705*fd1fabb7SAndroid Build Coastguard Worker 	uint32 subFileCount = thumbnail ? 1 : 0;
6706*fd1fabb7SAndroid Build Coastguard Worker 
6707*fd1fabb7SAndroid Build Coastguard Worker 	if (hasTransparencyMask)
6708*fd1fabb7SAndroid Build Coastguard Worker 		{
6709*fd1fabb7SAndroid Build Coastguard Worker 		subFileCount++;
6710*fd1fabb7SAndroid Build Coastguard Worker 		}
6711*fd1fabb7SAndroid Build Coastguard Worker 
6712*fd1fabb7SAndroid Build Coastguard Worker 	// Add previews.
6713*fd1fabb7SAndroid Build Coastguard Worker 
6714*fd1fabb7SAndroid Build Coastguard Worker 	uint32 previewCount = previewList ? previewList->Count () : 0;
6715*fd1fabb7SAndroid Build Coastguard Worker 
6716*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_tiff_directory> previewIFD [kMaxDNGPreviews];
6717*fd1fabb7SAndroid Build Coastguard Worker 
6718*fd1fabb7SAndroid Build Coastguard Worker 	AutoPtr<dng_basic_tag_set> previewBasic [kMaxDNGPreviews];
6719*fd1fabb7SAndroid Build Coastguard Worker 
6720*fd1fabb7SAndroid Build Coastguard Worker 	for (j = 0; j < previewCount; j++)
6721*fd1fabb7SAndroid Build Coastguard Worker 		{
6722*fd1fabb7SAndroid Build Coastguard Worker 
6723*fd1fabb7SAndroid Build Coastguard Worker 		if (thumbnail != &previewList->Preview (j))
6724*fd1fabb7SAndroid Build Coastguard Worker 			{
6725*fd1fabb7SAndroid Build Coastguard Worker 
6726*fd1fabb7SAndroid Build Coastguard Worker 			previewIFD [j] . Reset (new dng_tiff_directory);
6727*fd1fabb7SAndroid Build Coastguard Worker 
6728*fd1fabb7SAndroid Build Coastguard Worker 			previewBasic [j] . Reset (previewList->Preview (j).AddTagSet (*previewIFD [j]));
6729*fd1fabb7SAndroid Build Coastguard Worker 
6730*fd1fabb7SAndroid Build Coastguard Worker 			subFileCount++;
6731*fd1fabb7SAndroid Build Coastguard Worker 
6732*fd1fabb7SAndroid Build Coastguard Worker 			}
6733*fd1fabb7SAndroid Build Coastguard Worker 
6734*fd1fabb7SAndroid Build Coastguard Worker 		}
6735*fd1fabb7SAndroid Build Coastguard Worker 
6736*fd1fabb7SAndroid Build Coastguard Worker 	// And a link to the raw and JPEG image IFDs.
6737*fd1fabb7SAndroid Build Coastguard Worker 
6738*fd1fabb7SAndroid Build Coastguard Worker 	uint32 subFileData [kMaxDNGPreviews + 2];
6739*fd1fabb7SAndroid Build Coastguard Worker 
6740*fd1fabb7SAndroid Build Coastguard Worker 	tag_uint32_ptr tagSubFile (tcSubIFDs,
6741*fd1fabb7SAndroid Build Coastguard Worker 							   subFileData,
6742*fd1fabb7SAndroid Build Coastguard Worker 							   subFileCount);
6743*fd1fabb7SAndroid Build Coastguard Worker 
6744*fd1fabb7SAndroid Build Coastguard Worker 	if (subFileCount)
6745*fd1fabb7SAndroid Build Coastguard Worker 		{
6746*fd1fabb7SAndroid Build Coastguard Worker 
6747*fd1fabb7SAndroid Build Coastguard Worker 		mainIFD.Add (&tagSubFile);
6748*fd1fabb7SAndroid Build Coastguard Worker 
6749*fd1fabb7SAndroid Build Coastguard Worker 		}
6750*fd1fabb7SAndroid Build Coastguard Worker 
6751*fd1fabb7SAndroid Build Coastguard Worker 	// Skip past the header and IFDs for now.
6752*fd1fabb7SAndroid Build Coastguard Worker 
6753*fd1fabb7SAndroid Build Coastguard Worker 	uint32 currentOffset = 8;
6754*fd1fabb7SAndroid Build Coastguard Worker 
6755*fd1fabb7SAndroid Build Coastguard Worker 	currentOffset += mainIFD.Size ();
6756*fd1fabb7SAndroid Build Coastguard Worker 
6757*fd1fabb7SAndroid Build Coastguard Worker 	uint32 subFileIndex = 0;
6758*fd1fabb7SAndroid Build Coastguard Worker 
6759*fd1fabb7SAndroid Build Coastguard Worker 	if (thumbnail)
6760*fd1fabb7SAndroid Build Coastguard Worker 		{
6761*fd1fabb7SAndroid Build Coastguard Worker 
6762*fd1fabb7SAndroid Build Coastguard Worker 		subFileData [subFileIndex++] = currentOffset;
6763*fd1fabb7SAndroid Build Coastguard Worker 
6764*fd1fabb7SAndroid Build Coastguard Worker 		currentOffset += rawIFD.Size ();
6765*fd1fabb7SAndroid Build Coastguard Worker 
6766*fd1fabb7SAndroid Build Coastguard Worker 		}
6767*fd1fabb7SAndroid Build Coastguard Worker 
6768*fd1fabb7SAndroid Build Coastguard Worker 	if (hasTransparencyMask)
6769*fd1fabb7SAndroid Build Coastguard Worker 		{
6770*fd1fabb7SAndroid Build Coastguard Worker 
6771*fd1fabb7SAndroid Build Coastguard Worker 		subFileData [subFileIndex++] = currentOffset;
6772*fd1fabb7SAndroid Build Coastguard Worker 
6773*fd1fabb7SAndroid Build Coastguard Worker 		currentOffset += maskIFD->Size ();
6774*fd1fabb7SAndroid Build Coastguard Worker 
6775*fd1fabb7SAndroid Build Coastguard Worker 		}
6776*fd1fabb7SAndroid Build Coastguard Worker 
6777*fd1fabb7SAndroid Build Coastguard Worker 	for (j = 0; j < previewCount; j++)
6778*fd1fabb7SAndroid Build Coastguard Worker 		{
6779*fd1fabb7SAndroid Build Coastguard Worker 
6780*fd1fabb7SAndroid Build Coastguard Worker 		if (thumbnail != &previewList->Preview (j))
6781*fd1fabb7SAndroid Build Coastguard Worker 			{
6782*fd1fabb7SAndroid Build Coastguard Worker 
6783*fd1fabb7SAndroid Build Coastguard Worker 			subFileData [subFileIndex++] = currentOffset;
6784*fd1fabb7SAndroid Build Coastguard Worker 
6785*fd1fabb7SAndroid Build Coastguard Worker 			currentOffset += previewIFD [j]->Size ();
6786*fd1fabb7SAndroid Build Coastguard Worker 
6787*fd1fabb7SAndroid Build Coastguard Worker 			}
6788*fd1fabb7SAndroid Build Coastguard Worker 
6789*fd1fabb7SAndroid Build Coastguard Worker 		}
6790*fd1fabb7SAndroid Build Coastguard Worker 
6791*fd1fabb7SAndroid Build Coastguard Worker 	exifSet.Locate (currentOffset);
6792*fd1fabb7SAndroid Build Coastguard Worker 
6793*fd1fabb7SAndroid Build Coastguard Worker 	currentOffset += exifSet.Size ();
6794*fd1fabb7SAndroid Build Coastguard Worker 
6795*fd1fabb7SAndroid Build Coastguard Worker 	stream.SetWritePosition (currentOffset);
6796*fd1fabb7SAndroid Build Coastguard Worker 
6797*fd1fabb7SAndroid Build Coastguard Worker 	// Write the extra profiles.
6798*fd1fabb7SAndroid Build Coastguard Worker 
6799*fd1fabb7SAndroid Build Coastguard Worker 	if (extraProfileCount)
6800*fd1fabb7SAndroid Build Coastguard Worker 		{
6801*fd1fabb7SAndroid Build Coastguard Worker 
6802*fd1fabb7SAndroid Build Coastguard Worker 		for (j = 0; j < extraProfileCount; j++)
6803*fd1fabb7SAndroid Build Coastguard Worker 			{
6804*fd1fabb7SAndroid Build Coastguard Worker 
6805*fd1fabb7SAndroid Build Coastguard Worker 			extraProfileOffsets.Buffer_uint32 () [j] = (uint32) stream.Position ();
6806*fd1fabb7SAndroid Build Coastguard Worker 
6807*fd1fabb7SAndroid Build Coastguard Worker 			uint32 index = extraProfileIndex [j];
6808*fd1fabb7SAndroid Build Coastguard Worker 
6809*fd1fabb7SAndroid Build Coastguard Worker 			const dng_camera_profile &profile (negative.ProfileByIndex (index));
6810*fd1fabb7SAndroid Build Coastguard Worker 
6811*fd1fabb7SAndroid Build Coastguard Worker 			tiff_dng_extended_color_profile extraWriter (profile);
6812*fd1fabb7SAndroid Build Coastguard Worker 
6813*fd1fabb7SAndroid Build Coastguard Worker 			extraWriter.Put (stream, false);
6814*fd1fabb7SAndroid Build Coastguard Worker 
6815*fd1fabb7SAndroid Build Coastguard Worker 			}
6816*fd1fabb7SAndroid Build Coastguard Worker 
6817*fd1fabb7SAndroid Build Coastguard Worker 		}
6818*fd1fabb7SAndroid Build Coastguard Worker 
6819*fd1fabb7SAndroid Build Coastguard Worker 	// Write the thumbnail data.
6820*fd1fabb7SAndroid Build Coastguard Worker 
6821*fd1fabb7SAndroid Build Coastguard Worker 	if (thumbnail)
6822*fd1fabb7SAndroid Build Coastguard Worker 		{
6823*fd1fabb7SAndroid Build Coastguard Worker 
6824*fd1fabb7SAndroid Build Coastguard Worker 		thumbnail->WriteData (host,
6825*fd1fabb7SAndroid Build Coastguard Worker 							  *this,
6826*fd1fabb7SAndroid Build Coastguard Worker 							  *thmBasic,
6827*fd1fabb7SAndroid Build Coastguard Worker 							  stream);
6828*fd1fabb7SAndroid Build Coastguard Worker 
6829*fd1fabb7SAndroid Build Coastguard Worker 		}
6830*fd1fabb7SAndroid Build Coastguard Worker 
6831*fd1fabb7SAndroid Build Coastguard Worker 	// Write the preview data.
6832*fd1fabb7SAndroid Build Coastguard Worker 
6833*fd1fabb7SAndroid Build Coastguard Worker 	for (j = 0; j < previewCount; j++)
6834*fd1fabb7SAndroid Build Coastguard Worker 		{
6835*fd1fabb7SAndroid Build Coastguard Worker 
6836*fd1fabb7SAndroid Build Coastguard Worker 		if (thumbnail != &previewList->Preview (j))
6837*fd1fabb7SAndroid Build Coastguard Worker 			{
6838*fd1fabb7SAndroid Build Coastguard Worker 
6839*fd1fabb7SAndroid Build Coastguard Worker 			previewList->Preview (j).WriteData (host,
6840*fd1fabb7SAndroid Build Coastguard Worker 												*this,
6841*fd1fabb7SAndroid Build Coastguard Worker 												*previewBasic [j],
6842*fd1fabb7SAndroid Build Coastguard Worker 												stream);
6843*fd1fabb7SAndroid Build Coastguard Worker 
6844*fd1fabb7SAndroid Build Coastguard Worker 			}
6845*fd1fabb7SAndroid Build Coastguard Worker 
6846*fd1fabb7SAndroid Build Coastguard Worker 		}
6847*fd1fabb7SAndroid Build Coastguard Worker 
6848*fd1fabb7SAndroid Build Coastguard Worker 	// Write the raw data.
6849*fd1fabb7SAndroid Build Coastguard Worker 
6850*fd1fabb7SAndroid Build Coastguard Worker 	if (rawJPEGImage)
6851*fd1fabb7SAndroid Build Coastguard Worker 		{
6852*fd1fabb7SAndroid Build Coastguard Worker 
6853*fd1fabb7SAndroid Build Coastguard Worker 		uint32 tileCount = info.TilesAcross () *
6854*fd1fabb7SAndroid Build Coastguard Worker 						   info.TilesDown   ();
6855*fd1fabb7SAndroid Build Coastguard Worker 
6856*fd1fabb7SAndroid Build Coastguard Worker 		for (uint32 tileIndex = 0; tileIndex < tileCount; tileIndex++)
6857*fd1fabb7SAndroid Build Coastguard Worker 			{
6858*fd1fabb7SAndroid Build Coastguard Worker 
6859*fd1fabb7SAndroid Build Coastguard Worker 			// Remember this offset.
6860*fd1fabb7SAndroid Build Coastguard Worker 
6861*fd1fabb7SAndroid Build Coastguard Worker 			uint32 tileOffset = (uint32) stream.Position ();
6862*fd1fabb7SAndroid Build Coastguard Worker 
6863*fd1fabb7SAndroid Build Coastguard Worker 			rawBasic.SetTileOffset (tileIndex, tileOffset);
6864*fd1fabb7SAndroid Build Coastguard Worker 
6865*fd1fabb7SAndroid Build Coastguard Worker 			// Write JPEG data.
6866*fd1fabb7SAndroid Build Coastguard Worker 
6867*fd1fabb7SAndroid Build Coastguard Worker 			stream.Put (rawJPEGImage->fJPEGData [tileIndex]->Buffer      (),
6868*fd1fabb7SAndroid Build Coastguard Worker 						rawJPEGImage->fJPEGData [tileIndex]->LogicalSize ());
6869*fd1fabb7SAndroid Build Coastguard Worker 
6870*fd1fabb7SAndroid Build Coastguard Worker 			// Update tile count.
6871*fd1fabb7SAndroid Build Coastguard Worker 
6872*fd1fabb7SAndroid Build Coastguard Worker 			uint32 tileByteCount = (uint32) stream.Position () - tileOffset;
6873*fd1fabb7SAndroid Build Coastguard Worker 
6874*fd1fabb7SAndroid Build Coastguard Worker 			rawBasic.SetTileByteCount (tileIndex, tileByteCount);
6875*fd1fabb7SAndroid Build Coastguard Worker 
6876*fd1fabb7SAndroid Build Coastguard Worker 			// Keep the tiles on even byte offsets.
6877*fd1fabb7SAndroid Build Coastguard Worker 
6878*fd1fabb7SAndroid Build Coastguard Worker 			if (tileByteCount & 1)
6879*fd1fabb7SAndroid Build Coastguard Worker 				{
6880*fd1fabb7SAndroid Build Coastguard Worker 				stream.Put_uint8 (0);
6881*fd1fabb7SAndroid Build Coastguard Worker 				}
6882*fd1fabb7SAndroid Build Coastguard Worker 
6883*fd1fabb7SAndroid Build Coastguard Worker 			}
6884*fd1fabb7SAndroid Build Coastguard Worker 
6885*fd1fabb7SAndroid Build Coastguard Worker 		}
6886*fd1fabb7SAndroid Build Coastguard Worker 
6887*fd1fabb7SAndroid Build Coastguard Worker 	else
6888*fd1fabb7SAndroid Build Coastguard Worker 		{
6889*fd1fabb7SAndroid Build Coastguard Worker 
6890*fd1fabb7SAndroid Build Coastguard Worker 		#if qDNGValidate
6891*fd1fabb7SAndroid Build Coastguard Worker 		dng_timer timer ("Write raw image time");
6892*fd1fabb7SAndroid Build Coastguard Worker 		#endif
6893*fd1fabb7SAndroid Build Coastguard Worker 
6894*fd1fabb7SAndroid Build Coastguard Worker 		WriteImage (host,
6895*fd1fabb7SAndroid Build Coastguard Worker 					info,
6896*fd1fabb7SAndroid Build Coastguard Worker 					rawBasic,
6897*fd1fabb7SAndroid Build Coastguard Worker 					stream,
6898*fd1fabb7SAndroid Build Coastguard Worker 					rawImage,
6899*fd1fabb7SAndroid Build Coastguard Worker 					fakeChannels);
6900*fd1fabb7SAndroid Build Coastguard Worker 
6901*fd1fabb7SAndroid Build Coastguard Worker 		}
6902*fd1fabb7SAndroid Build Coastguard Worker 
6903*fd1fabb7SAndroid Build Coastguard Worker 	// Write transparency mask image.
6904*fd1fabb7SAndroid Build Coastguard Worker 
6905*fd1fabb7SAndroid Build Coastguard Worker 	if (hasTransparencyMask)
6906*fd1fabb7SAndroid Build Coastguard Worker 		{
6907*fd1fabb7SAndroid Build Coastguard Worker 
6908*fd1fabb7SAndroid Build Coastguard Worker 		#if qDNGValidate
6909*fd1fabb7SAndroid Build Coastguard Worker 		dng_timer timer ("Write transparency mask time");
6910*fd1fabb7SAndroid Build Coastguard Worker 		#endif
6911*fd1fabb7SAndroid Build Coastguard Worker 
6912*fd1fabb7SAndroid Build Coastguard Worker 		WriteImage (host,
6913*fd1fabb7SAndroid Build Coastguard Worker 					*maskInfo,
6914*fd1fabb7SAndroid Build Coastguard Worker 					*maskBasic,
6915*fd1fabb7SAndroid Build Coastguard Worker 					stream,
6916*fd1fabb7SAndroid Build Coastguard Worker 					*negative.RawTransparencyMask ());
6917*fd1fabb7SAndroid Build Coastguard Worker 
6918*fd1fabb7SAndroid Build Coastguard Worker 		}
6919*fd1fabb7SAndroid Build Coastguard Worker 
6920*fd1fabb7SAndroid Build Coastguard Worker 	// Trim the file to this length.
6921*fd1fabb7SAndroid Build Coastguard Worker 
6922*fd1fabb7SAndroid Build Coastguard Worker 	stream.SetLength (stream.Position ());
6923*fd1fabb7SAndroid Build Coastguard Worker 
6924*fd1fabb7SAndroid Build Coastguard Worker 	// DNG has a 4G size limit.
6925*fd1fabb7SAndroid Build Coastguard Worker 
6926*fd1fabb7SAndroid Build Coastguard Worker 	if (stream.Length () > 0x0FFFFFFFFL)
6927*fd1fabb7SAndroid Build Coastguard Worker 		{
6928*fd1fabb7SAndroid Build Coastguard Worker 		ThrowImageTooBigDNG ();
6929*fd1fabb7SAndroid Build Coastguard Worker 		}
6930*fd1fabb7SAndroid Build Coastguard Worker 
6931*fd1fabb7SAndroid Build Coastguard Worker 	// Write TIFF Header.
6932*fd1fabb7SAndroid Build Coastguard Worker 
6933*fd1fabb7SAndroid Build Coastguard Worker 	stream.SetWritePosition (0);
6934*fd1fabb7SAndroid Build Coastguard Worker 
6935*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint16 (stream.BigEndian () ? byteOrderMM : byteOrderII);
6936*fd1fabb7SAndroid Build Coastguard Worker 
6937*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint16 (42);
6938*fd1fabb7SAndroid Build Coastguard Worker 
6939*fd1fabb7SAndroid Build Coastguard Worker 	stream.Put_uint32 (8);
6940*fd1fabb7SAndroid Build Coastguard Worker 
6941*fd1fabb7SAndroid Build Coastguard Worker 	// Write the IFDs.
6942*fd1fabb7SAndroid Build Coastguard Worker 
6943*fd1fabb7SAndroid Build Coastguard Worker 	mainIFD.Put (stream);
6944*fd1fabb7SAndroid Build Coastguard Worker 
6945*fd1fabb7SAndroid Build Coastguard Worker 	if (thumbnail)
6946*fd1fabb7SAndroid Build Coastguard Worker 		{
6947*fd1fabb7SAndroid Build Coastguard Worker 
6948*fd1fabb7SAndroid Build Coastguard Worker 		rawIFD.Put (stream);
6949*fd1fabb7SAndroid Build Coastguard Worker 
6950*fd1fabb7SAndroid Build Coastguard Worker 		}
6951*fd1fabb7SAndroid Build Coastguard Worker 
6952*fd1fabb7SAndroid Build Coastguard Worker 	if (hasTransparencyMask)
6953*fd1fabb7SAndroid Build Coastguard Worker 		{
6954*fd1fabb7SAndroid Build Coastguard Worker 
6955*fd1fabb7SAndroid Build Coastguard Worker 		maskIFD->Put (stream);
6956*fd1fabb7SAndroid Build Coastguard Worker 
6957*fd1fabb7SAndroid Build Coastguard Worker 		}
6958*fd1fabb7SAndroid Build Coastguard Worker 
6959*fd1fabb7SAndroid Build Coastguard Worker 	for (j = 0; j < previewCount; j++)
6960*fd1fabb7SAndroid Build Coastguard Worker 		{
6961*fd1fabb7SAndroid Build Coastguard Worker 
6962*fd1fabb7SAndroid Build Coastguard Worker 		if (thumbnail != &previewList->Preview (j))
6963*fd1fabb7SAndroid Build Coastguard Worker 			{
6964*fd1fabb7SAndroid Build Coastguard Worker 
6965*fd1fabb7SAndroid Build Coastguard Worker 			previewIFD [j]->Put (stream);
6966*fd1fabb7SAndroid Build Coastguard Worker 
6967*fd1fabb7SAndroid Build Coastguard Worker 			}
6968*fd1fabb7SAndroid Build Coastguard Worker 
6969*fd1fabb7SAndroid Build Coastguard Worker 		}
6970*fd1fabb7SAndroid Build Coastguard Worker 
6971*fd1fabb7SAndroid Build Coastguard Worker 	exifSet.Put (stream);
6972*fd1fabb7SAndroid Build Coastguard Worker 
6973*fd1fabb7SAndroid Build Coastguard Worker 	stream.Flush ();
6974*fd1fabb7SAndroid Build Coastguard Worker 
6975*fd1fabb7SAndroid Build Coastguard Worker 	}
6976*fd1fabb7SAndroid Build Coastguard Worker 
6977*fd1fabb7SAndroid Build Coastguard Worker /*****************************************************************************/
6978