1 /*****************************************************************************/
2 // Copyright 2006-2012 Adobe Systems Incorporated
3 // All Rights Reserved.
4 //
5 // NOTICE:  Adobe permits you to use, modify, and distribute this file in
6 // accordance with the terms of the Adobe license agreement accompanying it.
7 /*****************************************************************************/
8 
9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_read_image.cpp#7 $ */
10 /* $DateTime: 2012/07/31 22:04:34 $ */
11 /* $Change: 840853 $ */
12 /* $Author: tknoll $ */
13 
14 /*****************************************************************************/
15 
16 #include "dng_read_image.h"
17 
18 #include "dng_abort_sniffer.h"
19 #include "dng_area_task.h"
20 #include "dng_bottlenecks.h"
21 #include "dng_exceptions.h"
22 #include "dng_flags.h"
23 #include "dng_host.h"
24 #include "dng_image.h"
25 #include "dng_ifd.h"
26 #include "dng_jpeg_image.h"
27 #include "dng_lossless_jpeg.h"
28 #include "dng_mutex.h"
29 #include "dng_memory.h"
30 #include "dng_pixel_buffer.h"
31 #include "dng_safe_arithmetic.h"
32 #include "dng_tag_types.h"
33 #include "dng_tag_values.h"
34 #include "dng_utils.h"
35 
36 #include "zlib.h"
37 
38 #if qDNGUseLibJPEG
39 #include "dng_jpeg_memory_source.h"
40 #include "dng_jpeglib.h"
41 #endif
42 
43 #include <limits>
44 
45 /******************************************************************************/
46 
DecodeDelta8(uint8 * dPtr,uint32 rows,uint32 cols,uint32 channels)47 static void DecodeDelta8 (uint8 *dPtr,
48 						  uint32 rows,
49 						  uint32 cols,
50 						  uint32 channels)
51 	{
52 
53 	const uint32 dRowStep = cols * channels;
54 
55 	for (uint32 row = 0; row < rows; row++)
56 		{
57 
58 		for (uint32 col = 1; col < cols; col++)
59 			{
60 
61 			for (uint32 channel = 0; channel < channels; channel++)
62 				{
63 
64 				dPtr [col * channels + channel] += dPtr [(col - 1) * channels + channel];
65 
66 				}
67 
68 			}
69 
70 		dPtr += dRowStep;
71 
72 		}
73 
74 	}
75 
76 /******************************************************************************/
77 
DecodeDelta16(uint16 * dPtr,uint32 rows,uint32 cols,uint32 channels)78 static void DecodeDelta16 (uint16 *dPtr,
79 						   uint32 rows,
80 						   uint32 cols,
81 						   uint32 channels)
82 	{
83 
84 	const uint32 dRowStep = cols * channels;
85 
86 	for (uint32 row = 0; row < rows; row++)
87 		{
88 
89 		for (uint32 col = 1; col < cols; col++)
90 			{
91 
92 			for (uint32 channel = 0; channel < channels; channel++)
93 				{
94 
95 				dPtr [col * channels + channel] += dPtr [(col - 1) * channels + channel];
96 
97 				}
98 
99 			}
100 
101 		dPtr += dRowStep;
102 
103 		}
104 
105 	}
106 
107 /******************************************************************************/
108 
DecodeDelta32(uint32 * dPtr,uint32 rows,uint32 cols,uint32 channels)109 static void DecodeDelta32 (uint32 *dPtr,
110 						   uint32 rows,
111 						   uint32 cols,
112 						   uint32 channels)
113 	{
114 
115 	const uint32 dRowStep = cols * channels;
116 
117 	for (uint32 row = 0; row < rows; row++)
118 		{
119 
120 		for (uint32 col = 1; col < cols; col++)
121 			{
122 
123 			for (uint32 channel = 0; channel < channels; channel++)
124 				{
125 
126 				dPtr [col * channels + channel] += dPtr [(col - 1) * channels + channel];
127 
128 				}
129 
130 			}
131 
132 		dPtr += dRowStep;
133 
134 		}
135 
136 	}
137 
138 /*****************************************************************************/
139 
DecodeDeltaBytes(uint8 * bytePtr,int32 cols,int32 channels)140 inline void DecodeDeltaBytes (uint8 *bytePtr, int32 cols, int32 channels)
141 	{
142 
143 	if (channels == 1)
144 		{
145 
146 		uint8 b0 = bytePtr [0];
147 
148 		bytePtr += 1;
149 
150 		for (int32 col = 1; col < cols; ++col)
151 			{
152 
153 			b0 += bytePtr [0];
154 
155 			bytePtr [0] = b0;
156 
157 			bytePtr += 1;
158 
159 			}
160 
161 		}
162 
163 	else if (channels == 3)
164 		{
165 
166 		uint8 b0 = bytePtr [0];
167 		uint8 b1 = bytePtr [1];
168 		uint8 b2 = bytePtr [2];
169 
170 		bytePtr += 3;
171 
172 		for (int32 col = 1; col < cols; ++col)
173 			{
174 
175 			b0 += bytePtr [0];
176 			b1 += bytePtr [1];
177 			b2 += bytePtr [2];
178 
179 			bytePtr [0] = b0;
180 			bytePtr [1] = b1;
181 			bytePtr [2] = b2;
182 
183 			bytePtr += 3;
184 
185 			}
186 
187 		}
188 
189 	else if (channels == 4)
190 		{
191 
192 		uint8 b0 = bytePtr [0];
193 		uint8 b1 = bytePtr [1];
194 		uint8 b2 = bytePtr [2];
195 		uint8 b3 = bytePtr [3];
196 
197 		bytePtr += 4;
198 
199 		for (int32 col = 1; col < cols; ++col)
200 			{
201 
202 			b0 += bytePtr [0];
203 			b1 += bytePtr [1];
204 			b2 += bytePtr [2];
205 			b3 += bytePtr [3];
206 
207 			bytePtr [0] = b0;
208 			bytePtr [1] = b1;
209 			bytePtr [2] = b2;
210 			bytePtr [3] = b3;
211 
212 			bytePtr += 4;
213 
214 			}
215 
216 		}
217 
218 	else
219 		{
220 
221 		for (int32 col = 1; col < cols; ++col)
222 			{
223 
224 			for (int32 chan = 0; chan < channels; ++chan)
225 				{
226 
227 				bytePtr [chan + channels] += bytePtr [chan];
228 
229 				}
230 
231 			bytePtr += channels;
232 
233 			}
234 
235 		}
236 
237 	}
238 
239 /*****************************************************************************/
240 
DecodeFPDelta(uint8 * input,uint8 * output,int32 cols,int32 channels,int32 bytesPerSample)241 static void DecodeFPDelta (uint8 *input,
242 						   uint8 *output,
243 						   int32 cols,
244 						   int32 channels,
245 						   int32 bytesPerSample)
246 	{
247 
248 	DecodeDeltaBytes (input, cols * bytesPerSample, channels);
249 
250 	int32 rowIncrement = cols * channels;
251 
252 	if (bytesPerSample == 2)
253 		{
254 
255 		#if qDNGBigEndian
256 		const uint8 *input0 = input;
257 		const uint8 *input1 = input + rowIncrement;
258 		#else
259 		const uint8 *input1 = input;
260 		const uint8 *input0 = input + rowIncrement;
261 		#endif
262 
263 		for (int32 col = 0; col < rowIncrement; ++col)
264 			{
265 
266 			output [0] = input0 [col];
267 			output [1] = input1 [col];
268 
269 			output += 2;
270 
271 			}
272 
273 		}
274 
275 	else if (bytesPerSample == 3)
276 		{
277 
278 		const uint8 *input0 = input;
279 		const uint8 *input1 = input + rowIncrement;
280 		const uint8 *input2 = input + rowIncrement * 2;
281 
282 		for (int32 col = 0; col < rowIncrement; ++col)
283 			{
284 
285 			output [0] = input0 [col];
286 			output [1] = input1 [col];
287 			output [2] = input2 [col];
288 
289 			output += 3;
290 
291 			}
292 
293 		}
294 
295 	else
296 		{
297 
298 		#if qDNGBigEndian
299 		const uint8 *input0 = input;
300 		const uint8 *input1 = input + rowIncrement;
301 		const uint8 *input2 = input + rowIncrement * 2;
302 		const uint8 *input3 = input + rowIncrement * 3;
303 		#else
304 		const uint8 *input3 = input;
305 		const uint8 *input2 = input + rowIncrement;
306 		const uint8 *input1 = input + rowIncrement * 2;
307 		const uint8 *input0 = input + rowIncrement * 3;
308 		#endif
309 
310 		for (int32 col = 0; col < rowIncrement; ++col)
311 			{
312 
313 			output [0] = input0 [col];
314 			output [1] = input1 [col];
315 			output [2] = input2 [col];
316 			output [3] = input3 [col];
317 
318 			output += 4;
319 
320 			}
321 
322 		}
323 
324 	}
325 
326 /*****************************************************************************/
327 
DecodePackBits(dng_stream & stream,uint8 * dPtr,int32 dstCount)328 bool DecodePackBits (dng_stream &stream,
329 					 uint8 *dPtr,
330 					 int32 dstCount)
331 	{
332 
333 	while (dstCount > 0)
334 		{
335 
336 		int32 runCount = (int8) stream.Get_uint8 ();
337 
338 		if (runCount >= 0)
339 			{
340 
341 			++runCount;
342 
343 			dstCount -= runCount;
344 
345 			if (dstCount < 0)
346 				return false;
347 
348 			stream.Get (dPtr, runCount);
349 
350 			dPtr += runCount;
351 
352 			}
353 
354 		else
355 			{
356 
357 			runCount = -runCount + 1;
358 
359 			dstCount -= runCount;
360 
361 			if (dstCount < 0)
362 				return false;
363 
364 			uint8 x = stream.Get_uint8 ();
365 
366 			while (runCount--)
367 				{
368 
369 				*(dPtr++) = x;
370 
371 				}
372 
373 			}
374 
375 		}
376 
377 	return true;
378 
379 	}
380 
381 /******************************************************************************/
382 
383 class dng_lzw_expander
384 	{
385 
386 	private:
387 
388 		enum
389 			{
390 			kResetCode = 256,
391 			kEndCode   = 257,
392 			kTableSize = 4096
393 			};
394 
395 		struct LZWExpanderNode
396 			{
397 			int16 prefix;
398 			int16 final;
399 			int16 depth;
400 			int16 fake_for_padding;
401 			};
402 
403 		dng_memory_data fBuffer;
404 
405 		LZWExpanderNode *fTable;
406 
407 		const uint8 *fSrcPtr;
408 
409 		int32 fSrcCount;
410 
411 		int32 fByteOffset;
412 
413 		uint32 fBitBuffer;
414 		int32 fBitBufferCount;
415 
416 		int32 fNextCode;
417 
418 		int32 fCodeSize;
419 
420 	public:
421 
422 		dng_lzw_expander ();
423 
424 		bool Expand (const uint8 *sPtr,
425 					 uint8 *dPtr,
426 					 int32 sCount,
427 					 int32 dCount);
428 
429 	private:
430 
431 		void InitTable ();
432 
433 		void AddTable (int32 w, int32 k);
434 
435 		bool GetCodeWord (int32 &code);
436 
437 		// Hidden copy constructor and assignment operator.
438 
439 		dng_lzw_expander (const dng_lzw_expander &expander);
440 
441 		dng_lzw_expander & operator= (const dng_lzw_expander &expander);
442 
443 	};
444 
445 /******************************************************************************/
446 
dng_lzw_expander()447 dng_lzw_expander::dng_lzw_expander ()
448 
449 	:	fBuffer			 ()
450 	,	fTable			 (NULL)
451 	,	fSrcPtr			 (NULL)
452 	,	fSrcCount		 (0)
453 	,	fByteOffset		 (0)
454 	,	fBitBuffer		 (0)
455 	,	fBitBufferCount  (0)
456 	,	fNextCode		 (0)
457 	,	fCodeSize		 (0)
458 
459 	{
460 
461 	fBuffer.Allocate (kTableSize * sizeof (LZWExpanderNode));
462 
463 	fTable = (LZWExpanderNode *) fBuffer.Buffer ();
464 
465 	}
466 
467 /******************************************************************************/
468 
InitTable()469 void dng_lzw_expander::InitTable ()
470 	{
471 
472 	fCodeSize = 9;
473 
474 	fNextCode = 258;
475 
476 	LZWExpanderNode *node = &fTable [0];
477 
478 	for (int32 code = 0; code < 256; code++)
479 		{
480 
481 		node->prefix  = -1;
482 		node->final   = (int16) code;
483 		node->depth   = 1;
484 
485 		node++;
486 
487 		}
488 
489 	}
490 
491 /******************************************************************************/
492 
AddTable(int32 w,int32 k)493 void dng_lzw_expander::AddTable (int32 w, int32 k)
494 	{
495 
496 	DNG_ASSERT ((w >= 0) && (w <= kTableSize),
497 				"bad w value in dng_lzw_expander::AddTable");
498 
499 	LZWExpanderNode *parentNode = &fTable [w];
500 
501 	int32 nextCode = fNextCode;
502 
503 	fNextCode++;
504 
505 	DNG_ASSERT ((nextCode >= 0) && (nextCode <= kTableSize),
506 				"bad fNextCode value in dng_lzw_expander::AddTable");
507 
508 	LZWExpanderNode *node = &fTable [nextCode];
509 
510 	node->prefix  = (int16) w;
511 	node->final   = (int16) k;
512 	node->depth   = 1 + parentNode->depth;
513 
514 	if (nextCode + 1 == (1 << fCodeSize) - 1)
515 		{
516 		if (fCodeSize != 12)
517 			fCodeSize++;
518 		}
519 
520 	}
521 
522 /******************************************************************************/
523 
GetCodeWord(int32 & code)524 bool dng_lzw_expander::GetCodeWord (int32 &code)
525 	{
526 
527 	// The bit buffer has the current code in the most significant bits,
528 	// so shift off the low orders.
529 
530 	int32 codeSize = fCodeSize;
531 
532 	code = fBitBuffer >> (32 - codeSize);
533 
534 	if (fBitBufferCount >= codeSize)
535 		{
536 
537 		// Typical case; get the code from the bit buffer.
538 
539 		fBitBuffer     <<= codeSize;
540 		fBitBufferCount -= codeSize;
541 
542 		}
543 
544 	else
545 		{
546 
547 		// The buffer needs to be refreshed.
548 
549 		const int32 bitsSoFar = fBitBufferCount;
550 
551 		if (fByteOffset >= fSrcCount)
552 			return false;
553 
554 		// Buffer a long word
555 
556 		const uint8 *ptr = fSrcPtr + fByteOffset;
557 
558 		#if qDNGBigEndian
559 
560 		fBitBuffer = *((const uint32 *) ptr);
561 
562 		#else
563 
564 			{
565 
566 			uint32 b0 = ptr [0];
567 			uint32 b1 = ptr [1];
568 			uint32 b2 = ptr [2];
569 			uint32 b3 = ptr [3];
570 
571 			fBitBuffer = (((((b0 << 8) | b1) << 8) | b2) << 8) | b3;
572 
573 			}
574 
575 		#endif
576 
577 		fBitBufferCount = 32;
578 
579 		fByteOffset += 4;
580 
581 		// Number of additional bits we need
582 
583 		const int32 bitsUsed = codeSize - bitsSoFar;
584 
585 		// Number of low order bits in the current buffer we don't care about
586 
587 		const int32 bitsNotUsed = 32 - bitsUsed;
588 
589 		code |= fBitBuffer >> bitsNotUsed;
590 
591 		fBitBuffer     <<= bitsUsed;
592 		fBitBufferCount -= bitsUsed;
593 
594 		}
595 
596 	return true;
597 
598 	}
599 
600 /******************************************************************************/
601 
Expand(const uint8 * sPtr,uint8 * dPtr,int32 sCount,int32 dCount)602 bool dng_lzw_expander::Expand (const uint8 *sPtr,
603 						       uint8 *dPtr,
604 						       int32 sCount,
605 						       int32 dCount)
606 	{
607 
608 	void *dStartPtr = dPtr;
609 
610 	fSrcPtr = sPtr;
611 
612 	fSrcCount = sCount;
613 
614 	fByteOffset = 0;
615 
616 	/* the master decode loop */
617 
618 	while (true)
619 		{
620 
621 		InitTable ();
622 
623 		int32 code;
624 
625 		do
626 			{
627 
628 			if (!GetCodeWord (code))
629 				return false;
630 
631 			DNG_ASSERT (code <= fNextCode,
632 						"Unexpected LZW code in dng_lzw_expander::Expand");
633 
634 			}
635 		while (code == kResetCode);
636 
637 		if (code == kEndCode)
638 			return true;
639 
640 		if (code > kEndCode)
641 			return false;
642 
643 		int32 oldCode = code;
644 		int32 inChar  = code;
645 
646 		*(dPtr++) = (uint8) code;
647 
648 		if (--dCount == 0)
649 			return true;
650 
651 		while (true)
652 			{
653 
654 			if (!GetCodeWord (code))
655 				return false;
656 
657 			if (code == kResetCode)
658 				break;
659 
660 			if (code == kEndCode)
661 				return true;
662 
663 			const int32 inCode = code;
664 
665 			bool repeatLastPixel = false;
666 
667 			if (code >= fNextCode)
668 				{
669 
670 				// This is either a bad file or our code table is not big enough; we
671 				// are going to repeat the last code seen and attempt to muddle thru.
672 
673 				code = oldCode;
674 
675 				repeatLastPixel = true;
676 
677 				}
678 
679 			// this can only happen if we hit 2 bad codes in a row
680 
681 			if (code > fNextCode)
682 				return false;
683 
684 			const int32 depth = fTable [code].depth;
685 
686 			if (depth < dCount)
687 				{
688 
689 				dCount -= depth;
690 
691 				dPtr += depth;
692 
693 				uint8 *ptr = dPtr;
694 
695 				// give the compiler an extra hint to optimize these as registers
696 
697 				const LZWExpanderNode *localTable = fTable;
698 
699 				int32 localCode = code;
700 
701 				// this is usually the hottest loop in LZW expansion
702 
703 				while (localCode >= kResetCode)
704 					{
705 
706 					if (ptr <= dStartPtr)
707 						return false;		// about to trash memory
708 
709 					const LZWExpanderNode &node = localTable [localCode];
710 
711 					uint8 tempFinal = (uint8) node.final;
712 
713 					localCode = node.prefix;
714 
715 					// Check for bogus table entry
716 
717 					if (localCode < 0 || localCode > kTableSize)
718 						return false;
719 
720 					*(--ptr) = tempFinal;
721 
722 					}
723 
724 				code = localCode;
725 
726 				inChar = localCode;
727 
728 				if (ptr <= dStartPtr)
729 					return false;		// about to trash memory
730 
731 				*(--ptr) = (uint8) inChar;
732 
733 				}
734 
735 			else
736 				{
737 
738 				// There might not be enough room for the full code
739 				// so skip the end of it.
740 
741 				const int32 skip = depth - dCount;
742 
743 				for (int32 i = 0; i < skip ; i++)
744 					{
745 					const LZWExpanderNode &node = fTable [code];
746 					code = node.prefix;
747 					}
748 
749 				int32 depthUsed = depth - skip;
750 
751 				dCount -= depthUsed;
752 
753 				dPtr += depthUsed;
754 
755 				uint8 *ptr = dPtr;
756 
757 				while (code >= 0)
758 					{
759 
760 					if (ptr <= dStartPtr)
761 						return false;		// about to trash memory
762 
763 					const LZWExpanderNode &node = fTable [code];
764 
765 					*(--ptr) = (uint8) node.final;
766 
767 					code = node.prefix;
768 
769 					// Check for bogus table entry
770 
771 					if (code > kTableSize)
772 						return false;
773 
774 					}
775 
776 				return true;
777 
778 				}
779 
780 			if (repeatLastPixel)
781 				{
782 
783 				*(dPtr++) = (uint8) inChar;
784 
785 				if (--dCount == 0)
786 					return true;
787 
788 				}
789 
790 			if (fNextCode < kTableSize)
791 				{
792 
793 				AddTable (oldCode, code);
794 
795 				}
796 
797 			oldCode = inCode;
798 
799 			}
800 
801 		}
802 
803 	return false;
804 
805 	}
806 
807 /*****************************************************************************/
808 
dng_row_interleaved_image(dng_image & image,uint32 factor)809 dng_row_interleaved_image::dng_row_interleaved_image (dng_image &image,
810 													  uint32 factor)
811 
812 	:	dng_image (image.Bounds    (),
813 				   image.Planes    (),
814 				   image.PixelType ())
815 
816 	,	fImage  (image )
817 	,	fFactor (factor)
818 
819 	{
820 
821 	}
822 
823 /*****************************************************************************/
824 
MapRow(int32 row) const825 int32 dng_row_interleaved_image::MapRow (int32 row) const
826 	{
827 
828 	uint32 rows = Height ();
829 
830 	int32 top = Bounds ().t;
831 
832 	uint32 fieldRow = row - top;
833 
834 	for (uint32 field = 0; true; field++)
835 		{
836 
837 		uint32 fieldRows = (rows - field + fFactor - 1) / fFactor;
838 
839 		if (fieldRow < fieldRows)
840 			{
841 
842 			return fieldRow * fFactor + field + top;
843 
844 			}
845 
846 		fieldRow -= fieldRows;
847 
848 		}
849 
850 	ThrowProgramError ();
851 
852 	return 0;
853 
854 	}
855 
856 /*****************************************************************************/
857 
DoGet(dng_pixel_buffer & buffer) const858 void dng_row_interleaved_image::DoGet (dng_pixel_buffer &buffer) const
859 	{
860 
861 	dng_pixel_buffer tempBuffer (buffer);
862 
863 	for (int32 row = buffer.fArea.t; row < buffer.fArea.b; row++)
864 		{
865 
866 		tempBuffer.fArea.t = MapRow (row);
867 
868 		tempBuffer.fArea.b = tempBuffer.fArea.t + 1;
869 
870 		tempBuffer.fData = (void *) buffer.DirtyPixel (row,
871 										 			   buffer.fArea.l,
872 										 			   buffer.fPlane);
873 
874 		fImage.Get (tempBuffer);
875 
876 		}
877 
878 	}
879 
880 /*****************************************************************************/
881 
DoPut(const dng_pixel_buffer & buffer)882 void dng_row_interleaved_image::DoPut (const dng_pixel_buffer &buffer)
883 	{
884 
885 	dng_pixel_buffer tempBuffer (buffer);
886 
887 	for (int32 row = buffer.fArea.t; row < buffer.fArea.b; row++)
888 		{
889 
890 		tempBuffer.fArea.t = MapRow (row);
891 
892 		tempBuffer.fArea.b = tempBuffer.fArea.t + 1;
893 
894 		tempBuffer.fData = (void *) buffer.ConstPixel (row,
895 										 			   buffer.fArea.l,
896 										 			   buffer.fPlane);
897 
898 		fImage.Put (tempBuffer);
899 
900 		}
901 
902 	}
903 
904 /*****************************************************************************/
905 
ReorderSubTileBlocks(dng_host & host,const dng_ifd & ifd,dng_pixel_buffer & buffer,AutoPtr<dng_memory_block> & tempBuffer)906 static void ReorderSubTileBlocks (dng_host &host,
907 								  const dng_ifd &ifd,
908 								  dng_pixel_buffer &buffer,
909 								  AutoPtr<dng_memory_block> &tempBuffer)
910 	{
911 
912 	uint32 tempBufferSize = ComputeBufferSize(buffer.fPixelType,
913 											  buffer.fArea.Size(),
914 											  buffer.fPlanes, padNone);
915 
916 	if (!tempBuffer.Get () || tempBuffer->LogicalSize () < tempBufferSize)
917 		{
918 
919 		tempBuffer.Reset (host.Allocate (tempBufferSize));
920 
921 		}
922 
923 	uint32 blockRows = ifd.fSubTileBlockRows;
924 	uint32 blockCols = ifd.fSubTileBlockCols;
925 
926 	uint32 rowBlocks = buffer.fArea.H () / blockRows;
927 	uint32 colBlocks = buffer.fArea.W () / blockCols;
928 
929 	int32 rowStep = buffer.fRowStep * buffer.fPixelSize;
930 	int32 colStep = buffer.fColStep * buffer.fPixelSize;
931 
932 	int32 rowBlockStep = rowStep * blockRows;
933 	int32 colBlockStep = colStep * blockCols;
934 
935 	uint32 blockColBytes = blockCols * buffer.fPlanes * buffer.fPixelSize;
936 
937 	const uint8 *s0 = (const uint8 *) buffer.fData;
938 	      uint8 *d0 = tempBuffer->Buffer_uint8 ();
939 
940 	for (uint32 rowBlock = 0; rowBlock < rowBlocks; rowBlock++)
941 		{
942 
943 		uint8 *d1 = d0;
944 
945 		for (uint32 colBlock = 0; colBlock < colBlocks; colBlock++)
946 			{
947 
948 			uint8 *d2 = d1;
949 
950 			for (uint32 blockRow = 0; blockRow < blockRows; blockRow++)
951 				{
952 
953 				for (uint32 j = 0; j < blockColBytes; j++)
954 					{
955 
956 					d2 [j] = s0 [j];
957 
958 					}
959 
960 				s0 += blockColBytes;
961 
962 				d2 += rowStep;
963 
964 				}
965 
966 			d1 += colBlockStep;
967 
968 			}
969 
970 		d0 += rowBlockStep;
971 
972 		}
973 
974 	// Copy back reordered pixels.
975 
976 	DoCopyBytes (tempBuffer->Buffer (),
977 				 buffer.fData,
978 				 tempBufferSize);
979 
980 	}
981 
982 /*****************************************************************************/
983 
984 class dng_image_spooler: public dng_spooler
985 	{
986 
987 	private:
988 
989 		dng_host &fHost;
990 
991 		const dng_ifd &fIFD;
992 
993 		dng_image &fImage;
994 
995 		dng_rect fTileArea;
996 
997 		uint32 fPlane;
998 		uint32 fPlanes;
999 
1000 		dng_memory_block &fBlock;
1001 
1002 		AutoPtr<dng_memory_block> &fSubTileBuffer;
1003 
1004 		dng_rect fTileStrip;
1005 
1006 		uint8 *fBuffer;
1007 
1008 		uint32 fBufferCount;
1009 		uint32 fBufferSize;
1010 
1011 	public:
1012 
1013 		dng_image_spooler (dng_host &host,
1014 						   const dng_ifd &ifd,
1015 						   dng_image &image,
1016 						   const dng_rect &tileArea,
1017 						   uint32 plane,
1018 						   uint32 planes,
1019 						   dng_memory_block &block,
1020 						   AutoPtr<dng_memory_block> &subTileBuffer);
1021 
1022 		virtual ~dng_image_spooler ();
1023 
1024 		virtual void Spool (const void *data,
1025 							uint32 count);
1026 
1027 	private:
1028 
1029 		// Hidden copy constructor and assignment operator.
1030 
1031 		dng_image_spooler (const dng_image_spooler &spooler);
1032 
1033 		dng_image_spooler & operator= (const dng_image_spooler &spooler);
1034 
1035 	};
1036 
1037 /*****************************************************************************/
1038 
dng_image_spooler(dng_host & host,const dng_ifd & ifd,dng_image & image,const dng_rect & tileArea,uint32 plane,uint32 planes,dng_memory_block & block,AutoPtr<dng_memory_block> & subTileBuffer)1039 dng_image_spooler::dng_image_spooler (dng_host &host,
1040 									  const dng_ifd &ifd,
1041 									  dng_image &image,
1042 									  const dng_rect &tileArea,
1043 									  uint32 plane,
1044 									  uint32 planes,
1045 									  dng_memory_block &block,
1046 									  AutoPtr<dng_memory_block> &subTileBuffer)
1047 
1048 	:	fHost (host)
1049 	,	fIFD (ifd)
1050 	,	fImage (image)
1051 	,	fTileArea (tileArea)
1052 	,	fPlane (plane)
1053 	,	fPlanes (planes)
1054 	,	fBlock (block)
1055 	,	fSubTileBuffer (subTileBuffer)
1056 
1057 	,	fTileStrip ()
1058 	,	fBuffer (NULL)
1059 	,	fBufferCount (0)
1060 	,	fBufferSize (0)
1061 
1062 	{
1063 
1064 	uint32 bytesPerRow = fTileArea.W () * fPlanes * (uint32) sizeof (uint16);
1065 
1066 	uint32 stripLength = Pin_uint32 (ifd.fSubTileBlockRows,
1067 									 fBlock.LogicalSize () / bytesPerRow,
1068 									 fTileArea.H ());
1069 
1070 	stripLength = stripLength / ifd.fSubTileBlockRows
1071 							  * ifd.fSubTileBlockRows;
1072 
1073 	fTileStrip   = fTileArea;
1074 	fTileStrip.b = fTileArea.t + stripLength;
1075 
1076 	fBuffer = (uint8 *) fBlock.Buffer ();
1077 
1078 	fBufferCount = 0;
1079 	fBufferSize  = bytesPerRow * stripLength;
1080 
1081 	}
1082 
1083 /*****************************************************************************/
1084 
~dng_image_spooler()1085 dng_image_spooler::~dng_image_spooler ()
1086 	{
1087 
1088 	}
1089 
1090 /*****************************************************************************/
1091 
Spool(const void * data,uint32 count)1092 void dng_image_spooler::Spool (const void *data,
1093 							   uint32 count)
1094 	{
1095 
1096 	while (count)
1097 		{
1098 
1099 		uint32 block = Min_uint32 (count, fBufferSize - fBufferCount);
1100 
1101 		if (block == 0)
1102 			{
1103 			return;
1104 			}
1105 
1106 		DoCopyBytes (data,
1107 					 fBuffer + fBufferCount,
1108 				     block);
1109 
1110 		data = ((const uint8 *) data) + block;
1111 
1112 		count -= block;
1113 
1114 		fBufferCount += block;
1115 
1116 		if (fBufferCount == fBufferSize)
1117 			{
1118 
1119 			fHost.SniffForAbort ();
1120 
1121 			dng_pixel_buffer buffer (fTileStrip, fPlane, fPlanes, ttShort,
1122 				 pcInterleaved, fBuffer);
1123 
1124 			if (fIFD.fSubTileBlockRows > 1)
1125 				{
1126 
1127 				ReorderSubTileBlocks (fHost,
1128 									  fIFD,
1129 									  buffer,
1130 									  fSubTileBuffer);
1131 
1132 				}
1133 
1134 			fImage.Put (buffer);
1135 
1136 			uint32 stripLength = fTileStrip.H ();
1137 
1138 			fTileStrip.t = fTileStrip.b;
1139 
1140 			fTileStrip.b = Min_int32 (fTileStrip.t + stripLength,
1141 									  fTileArea.b);
1142 
1143 			fBufferCount = 0;
1144 
1145 			fBufferSize = fTileStrip.W () *
1146 						  fTileStrip.H () *
1147 						  fPlanes * (uint32) sizeof (uint16);
1148 
1149 			}
1150 
1151 		}
1152 
1153 	}
1154 
1155 /*****************************************************************************/
1156 
dng_read_image()1157 dng_read_image::dng_read_image ()
1158 
1159 	:	fJPEGTables ()
1160 
1161 	{
1162 
1163 	}
1164 
1165 /*****************************************************************************/
1166 
~dng_read_image()1167 dng_read_image::~dng_read_image ()
1168 	{
1169 
1170 	}
1171 
1172 /*****************************************************************************/
1173 
ReadUncompressed(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image,const dng_rect & tileArea,uint32 plane,uint32 planes,AutoPtr<dng_memory_block> & uncompressedBuffer,AutoPtr<dng_memory_block> & subTileBlockBuffer)1174 bool dng_read_image::ReadUncompressed (dng_host &host,
1175 									   const dng_ifd &ifd,
1176 									   dng_stream &stream,
1177 									   dng_image &image,
1178 									   const dng_rect &tileArea,
1179 									   uint32 plane,
1180 									   uint32 planes,
1181 									   AutoPtr<dng_memory_block> &uncompressedBuffer,
1182 									   AutoPtr<dng_memory_block> &subTileBlockBuffer)
1183 	{
1184 
1185 	uint32 rows          = tileArea.H ();
1186 	uint32 samplesPerRow = tileArea.W ();
1187 
1188 	if (ifd.fPlanarConfiguration == pcRowInterleaved)
1189 		{
1190 		rows = SafeUint32Mult(rows, planes);
1191 		}
1192 	else
1193 		{
1194 		samplesPerRow = SafeUint32Mult(samplesPerRow, planes);
1195 		}
1196 
1197 	uint32 samplesPerTile = SafeUint32Mult(samplesPerRow, rows);
1198 
1199 	if (uncompressedBuffer.Get () == NULL)
1200 		{
1201 
1202 		#if qDNGValidate
1203 
1204 		ReportError ("Fuzz: Missing uncompressed buffer");
1205 
1206 		#endif
1207 
1208 		ThrowBadFormat ();
1209 
1210 		}
1211 
1212 	uint32 bitDepth = ifd.fBitsPerSample [plane];
1213 
1214 	uint32 pixelType = ttUndefined;
1215 
1216 	if (bitDepth == 8)
1217 		{
1218 
1219 		pixelType = ttByte;
1220 
1221 		stream.Get (uncompressedBuffer->Buffer (), samplesPerTile);
1222 
1223 		}
1224 
1225 	else if (bitDepth == 16 && ifd.fSampleFormat [0] == sfFloatingPoint)
1226 		{
1227 
1228 		pixelType = ttFloat;
1229 
1230 		uint32 *p_uint32 = (uint32 *) uncompressedBuffer->Buffer ();
1231 
1232 		for (uint32 j = 0; j < samplesPerTile; j++)
1233 			{
1234 
1235 			p_uint32 [j] = DNG_HalfToFloat (stream.Get_uint16 ());
1236 
1237 			}
1238 
1239 		}
1240 
1241 	else if (bitDepth == 24 && ifd.fSampleFormat [0] == sfFloatingPoint)
1242 		{
1243 
1244 		pixelType = ttFloat;
1245 
1246 		uint32 *p_uint32 = (uint32 *) uncompressedBuffer->Buffer ();
1247 
1248 		for (uint32 j = 0; j < samplesPerTile; j++)
1249 			{
1250 
1251 			uint8 input [3];
1252 
1253 			if (stream.LittleEndian ())
1254 				{
1255 				input [2] = stream.Get_uint8 ();
1256 				input [1] = stream.Get_uint8 ();
1257 				input [0] = stream.Get_uint8 ();
1258 				}
1259 
1260 			else
1261 				{
1262 				input [0] = stream.Get_uint8 ();
1263 				input [1] = stream.Get_uint8 ();
1264 				input [2] = stream.Get_uint8 ();
1265 				}
1266 
1267 			p_uint32 [j] = DNG_FP24ToFloat (input);
1268 
1269 			}
1270 
1271 		}
1272 
1273 	else if (bitDepth == 16)
1274 		{
1275 
1276 		pixelType = ttShort;
1277 
1278 		stream.Get (uncompressedBuffer->Buffer (), samplesPerTile * 2);
1279 
1280 		if (stream.SwapBytes ())
1281 			{
1282 
1283 			DoSwapBytes16 ((uint16 *) uncompressedBuffer->Buffer (),
1284 						   samplesPerTile);
1285 
1286 			}
1287 
1288 		}
1289 
1290 	else if (bitDepth == 32)
1291 		{
1292 
1293 		pixelType = image.PixelType ();
1294 
1295 		stream.Get (uncompressedBuffer->Buffer (), samplesPerTile * 4);
1296 
1297 		if (stream.SwapBytes ())
1298 			{
1299 
1300 			DoSwapBytes32 ((uint32 *) uncompressedBuffer->Buffer (),
1301 						   samplesPerTile);
1302 
1303 			}
1304 
1305 		}
1306 
1307 	else if (bitDepth == 12)
1308 		{
1309 
1310 		pixelType = ttShort;
1311 
1312 		uint16 *p = (uint16 *) uncompressedBuffer->Buffer ();
1313 
1314 		uint32 evenSamples = samplesPerRow >> 1;
1315 
1316 		for (uint32 row = 0; row < rows; row++)
1317 			{
1318 
1319 			for (uint32 j = 0; j < evenSamples; j++)
1320 				{
1321 
1322 				uint32 b0 = stream.Get_uint8 ();
1323 				uint32 b1 = stream.Get_uint8 ();
1324 				uint32 b2 = stream.Get_uint8 ();
1325 
1326 				p [0] = (uint16) ((b0 << 4) | (b1 >> 4));
1327 				p [1] = (uint16) (((b1 << 8) | b2) & 0x0FFF);
1328 
1329 				p += 2;
1330 
1331 				}
1332 
1333 			if (samplesPerRow & 1)
1334 				{
1335 
1336 				uint32 b0 = stream.Get_uint8 ();
1337 				uint32 b1 = stream.Get_uint8 ();
1338 
1339 				p [0] = (uint16) ((b0 << 4) | (b1 >> 4));
1340 
1341 				p += 1;
1342 
1343 				}
1344 
1345 			}
1346 
1347 		}
1348 
1349 	else if (bitDepth > 8 && bitDepth < 16)
1350 		{
1351 
1352 		pixelType = ttShort;
1353 
1354 		uint16 *p = (uint16 *) uncompressedBuffer->Buffer ();
1355 
1356 		uint32 bitMask = (1 << bitDepth) - 1;
1357 
1358 		for (uint32 row = 0; row < rows; row++)
1359 			{
1360 
1361 			uint32 bitBuffer  = 0;
1362 			uint32 bufferBits = 0;
1363 
1364 			for (uint32 j = 0; j < samplesPerRow; j++)
1365 				{
1366 
1367 				while (bufferBits < bitDepth)
1368 					{
1369 
1370 					bitBuffer = (bitBuffer << 8) | stream.Get_uint8 ();
1371 
1372 					bufferBits += 8;
1373 
1374 					}
1375 
1376 				p [j] = (uint16) ((bitBuffer >> (bufferBits - bitDepth)) & bitMask);
1377 
1378 				bufferBits -= bitDepth;
1379 
1380 				}
1381 
1382 			p += samplesPerRow;
1383 
1384 			}
1385 
1386 		}
1387 
1388 	else if (bitDepth > 16 && bitDepth < 32)
1389 		{
1390 
1391 		pixelType = ttLong;
1392 
1393 		uint32 *p = (uint32 *) uncompressedBuffer->Buffer ();
1394 
1395 		uint32 bitMask = ((uint32) 1 << bitDepth) - 1;
1396 
1397 		for (uint32 row = 0; row < rows; row++)
1398 			{
1399 
1400 			uint64 bitBuffer  = 0;
1401 			uint32 bufferBits = 0;
1402 
1403 			for (uint32 j = 0; j < samplesPerRow; j++)
1404 				{
1405 
1406 				while (bufferBits < bitDepth)
1407 					{
1408 
1409 					bitBuffer = (bitBuffer << 8) | stream.Get_uint8 ();
1410 
1411 					bufferBits += 8;
1412 
1413 					}
1414 
1415 				p [j] = ((uint32) (bitBuffer >> (bufferBits - bitDepth))) & bitMask;
1416 
1417 				bufferBits -= bitDepth;
1418 
1419 				}
1420 
1421 			p += samplesPerRow;
1422 
1423 			}
1424 
1425 		}
1426 
1427 	else
1428 		{
1429 
1430 		return false;
1431 
1432 		}
1433 
1434 	dng_pixel_buffer buffer (tileArea, plane, planes, pixelType,
1435 		 ifd.fPlanarConfiguration, uncompressedBuffer->Buffer ());
1436 
1437 	if (ifd.fSampleBitShift)
1438 		{
1439 
1440 		buffer.ShiftRight (ifd.fSampleBitShift);
1441 
1442 		}
1443 
1444 	if (ifd.fSubTileBlockRows > 1)
1445 		{
1446 
1447 		ReorderSubTileBlocks (host,
1448 							  ifd,
1449 							  buffer,
1450 							  subTileBlockBuffer);
1451 
1452 		}
1453 
1454 	image.Put (buffer);
1455 
1456 	return true;
1457 
1458 	}
1459 
1460 /*****************************************************************************/
1461 
1462 #if qDNGUseLibJPEG
1463 
1464 /*****************************************************************************/
1465 
dng_error_exit(j_common_ptr cinfo)1466 static void dng_error_exit (j_common_ptr cinfo)
1467 	{
1468 
1469 	// Output message.
1470 
1471 	(*cinfo->err->output_message) (cinfo);
1472 
1473 	// Convert to a dng_exception.
1474 
1475 	switch (cinfo->err->msg_code)
1476 		{
1477 
1478 		case JERR_OUT_OF_MEMORY:
1479 			{
1480 			ThrowMemoryFull ();
1481 			break;
1482 			}
1483 
1484 		default:
1485 			{
1486 			ThrowBadFormat ();
1487 			}
1488 
1489 		}
1490 
1491 	}
1492 
1493 /*****************************************************************************/
1494 
dng_output_message(j_common_ptr cinfo)1495 static void dng_output_message (j_common_ptr cinfo)
1496 	{
1497 
1498 	// Format message to string.
1499 
1500 	char buffer [JMSG_LENGTH_MAX];
1501 
1502 	(*cinfo->err->format_message) (cinfo, buffer);
1503 
1504 	// Report the libjpeg message as a warning.
1505 
1506 	ReportWarning ("libjpeg", buffer);
1507 
1508 	}
1509 
1510 /*****************************************************************************/
1511 
1512 #endif
1513 
1514 /*****************************************************************************/
1515 
DecodeLossyJPEG(dng_host & host,dng_image & image,const dng_rect & tileArea,uint32 plane,uint32 planes,uint32,uint32 jpegDataSize,uint8 * jpegDataInMemory)1516 void dng_read_image::DecodeLossyJPEG (dng_host &host,
1517 									  dng_image &image,
1518 									  const dng_rect &tileArea,
1519 									  uint32 plane,
1520 									  uint32 planes,
1521 									  uint32 /* photometricInterpretation */,
1522 									  uint32 jpegDataSize,
1523 									  uint8 *jpegDataInMemory)
1524 	{
1525 
1526 	#if qDNGUseLibJPEG
1527 
1528 	struct jpeg_decompress_struct cinfo;
1529 
1530 	// Setup the error manager.
1531 
1532 	struct jpeg_error_mgr jerr;
1533 
1534 	cinfo.err = jpeg_std_error (&jerr);
1535 
1536 	jerr.error_exit     = dng_error_exit;
1537 	jerr.output_message = dng_output_message;
1538 
1539 	try
1540 		{
1541 
1542 		// Create the decompression context.
1543 
1544 		jpeg_create_decompress (&cinfo);
1545 
1546 		// Set up the memory data source manager.
1547 
1548 		size_t jpegDataSizeAsSizet = 0;
1549 		ConvertUnsigned(jpegDataSize, &jpegDataSizeAsSizet);
1550 		jpeg_source_mgr memorySource =
1551 			CreateJpegMemorySource(jpegDataInMemory,
1552 								   jpegDataSizeAsSizet);
1553 		cinfo.src = &memorySource;
1554 
1555 		// Read the JPEG header.
1556 
1557 		jpeg_read_header (&cinfo, TRUE);
1558 
1559 		// Check header.
1560 
1561 		{
1562 			// Number of components may not be negative.
1563 			if (cinfo.num_components < 0)
1564 				{
1565 				ThrowBadFormat();
1566 				}
1567 
1568 			// Convert relevant values from header to uint32.
1569 			uint32 imageWidthAsUint32 = 0;
1570 			uint32 imageHeightAsUint32 = 0;
1571 			uint32 numComponentsAsUint32 = 0;
1572 			ConvertUnsigned(cinfo.image_width, &imageWidthAsUint32);
1573 			ConvertUnsigned(cinfo.image_height, &imageHeightAsUint32);
1574 			// num_components is an int. Casting to unsigned is safe because the
1575 			// test above guarantees num_components is not negative.
1576 			ConvertUnsigned(static_cast<unsigned>(cinfo.num_components),
1577 							&numComponentsAsUint32);
1578 
1579 			// Check that dimensions of JPEG correspond to dimensions of tile.
1580 			if (imageWidthAsUint32    != tileArea.W () ||
1581 			    imageHeightAsUint32   != tileArea.H () ||
1582 			    numComponentsAsUint32 != planes        )
1583 				{
1584 				ThrowBadFormat ();
1585 				}
1586 		}
1587 
1588 		// Start the compression.
1589 
1590 		jpeg_start_decompress (&cinfo);
1591 
1592 		// Setup a one-scanline size buffer.
1593 
1594 		dng_pixel_buffer buffer(tileArea, plane, planes, ttByte, pcInterleaved,
1595 								NULL);
1596 		buffer.fArea.b = tileArea.t + 1;
1597 
1598 		buffer.fDirty = true;
1599 
1600 		AutoPtr<dng_memory_block> bufferData (host.Allocate (buffer.fRowStep));
1601 
1602 		buffer.fData = bufferData->Buffer ();
1603 
1604 		uint8 *sampArray [1];
1605 
1606 		sampArray [0] = bufferData->Buffer_uint8 ();
1607 
1608 		// Read each scanline and save to image.
1609 
1610 		while (buffer.fArea.t < tileArea.b)
1611 			{
1612 
1613 			jpeg_read_scanlines (&cinfo, sampArray, 1);
1614 
1615 			image.Put (buffer);
1616 
1617 			buffer.fArea.t = buffer.fArea.b;
1618 			buffer.fArea.b = buffer.fArea.t + 1;
1619 
1620 			}
1621 
1622 		// Cleanup.
1623 
1624 		jpeg_finish_decompress (&cinfo);
1625 
1626 		jpeg_destroy_decompress (&cinfo);
1627 
1628 		}
1629 
1630 	catch (...)
1631 		{
1632 
1633 		jpeg_destroy_decompress (&cinfo);
1634 
1635 		throw;
1636 
1637 		}
1638 
1639 	#else
1640 
1641 	// The dng_sdk does not include a lossy JPEG decoder.  Override this
1642 	// this method to add lossy JPEG support.
1643 
1644 	(void) host;
1645 	(void) image;
1646 	(void) tileArea;
1647 	(void) plane;
1648 	(void) planes;
1649 	(void) jpegDataSize;
1650 	(void) jpegDataInMemory;
1651 
1652 	ThrowProgramError ("Missing lossy JPEG decoder");
1653 
1654 	#endif
1655 
1656 	}
1657 
1658 /*****************************************************************************/
1659 
ReadJPEGDataToBlock(dng_host & host,dng_stream & stream,dng_memory_block * tablesBlock,uint64 tileOffset,uint32 tileByteCount,bool patchFirstByte)1660 static dng_memory_block * ReadJPEGDataToBlock (dng_host &host,
1661 											   dng_stream &stream,
1662 											   dng_memory_block *tablesBlock,
1663 											   uint64 tileOffset,
1664 											   uint32 tileByteCount,
1665 											   bool patchFirstByte)
1666 	{
1667 
1668 	// This ensures that the "tileByteCount -= 2" operation below will not wrap
1669 	// around.
1670 	if (tileByteCount <= 2)
1671 		{
1672 		ThrowEndOfFile ();
1673 		}
1674 
1675 	uint32 tablesByteCount = tablesBlock ? tablesBlock->LogicalSize () : 0;
1676 
1677 	// This ensures that the "tablesByteCount -= 2" operation below will not
1678 	// wrap around.
1679 	if (tablesByteCount && tablesByteCount < 4)
1680 		{
1681 		ThrowEndOfFile ();
1682 		}
1683 
1684 	// The JPEG tables start with a two byte SOI marker, and
1685 	// and end with a two byte EOI marker.  The JPEG tile
1686 	// data also starts with a two byte SOI marker.  We can
1687 	// convert this combination a normal JPEG stream removing
1688 	// the last two bytes of the JPEG tables and the first two
1689 	// bytes of the tile data, and then concatenating them.
1690 
1691 	if (tablesByteCount)
1692 		{
1693 
1694 		// Ensure the "tileOffset += 2" operation below will not wrap around.
1695 		if (tileOffset > std::numeric_limits<uint64>::max () - 2)
1696 			{
1697 			ThrowEndOfFile();
1698 			}
1699 
1700 		tablesByteCount -= 2;
1701 
1702 		tileOffset    += 2;
1703 		tileByteCount -= 2;
1704 
1705 		}
1706 
1707 	// Allocate buffer.
1708 
1709 	AutoPtr<dng_memory_block> buffer (host.Allocate (
1710 		SafeUint32Add(tablesByteCount, tileByteCount)));
1711 
1712 	// Read in table.
1713 
1714 	if (tablesByteCount)
1715 		{
1716 
1717 		DoCopyBytes (tablesBlock->Buffer (),
1718 					 buffer->Buffer (),
1719 					 tablesByteCount);
1720 
1721 		}
1722 
1723 	// Read in tile data.
1724 
1725 	stream.SetReadPosition (tileOffset);
1726 
1727 	stream.Get (buffer->Buffer_uint8 () + tablesByteCount, tileByteCount);
1728 
1729 	// Patch first byte, if required.
1730 
1731 	if (patchFirstByte)
1732 		{
1733 
1734 		buffer->Buffer_uint8 () [0] = 0xFF;
1735 
1736 		}
1737 
1738 	// Return buffer.
1739 
1740 	return buffer.Release ();
1741 
1742 	}
1743 
1744 /*****************************************************************************/
1745 
ReadBaselineJPEG(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image,const dng_rect & tileArea,uint32 plane,uint32 planes,uint32 tileByteCount,uint8 * jpegDataInMemory)1746 bool dng_read_image::ReadBaselineJPEG (dng_host &host,
1747 									   const dng_ifd &ifd,
1748 									   dng_stream &stream,
1749 									   dng_image &image,
1750 									   const dng_rect &tileArea,
1751 									   uint32 plane,
1752 									   uint32 planes,
1753 									   uint32 tileByteCount,
1754 									   uint8 *jpegDataInMemory)
1755 	{
1756 
1757 	// Setup the data source.
1758 
1759 	if (fJPEGTables.Get () || !jpegDataInMemory)
1760 		{
1761 
1762 		AutoPtr<dng_memory_block> jpegDataBlock;
1763 
1764 		jpegDataBlock.Reset (ReadJPEGDataToBlock (host,
1765 												  stream,
1766 												  fJPEGTables.Get (),
1767 												  stream.Position (),
1768 												  tileByteCount,
1769 												  ifd.fPatchFirstJPEGByte));
1770 
1771 		DecodeLossyJPEG (host,
1772 						 image,
1773 						 tileArea,
1774 						 plane,
1775 						 planes,
1776 						 ifd.fPhotometricInterpretation,
1777 						 jpegDataBlock->LogicalSize (),
1778 						 jpegDataBlock->Buffer_uint8 ());
1779 
1780 		}
1781 
1782 	else
1783 		{
1784 
1785 		if (ifd.fPatchFirstJPEGByte && tileByteCount)
1786 			{
1787 			jpegDataInMemory [0] = 0xFF;
1788 			}
1789 
1790 		DecodeLossyJPEG (host,
1791 						 image,
1792 						 tileArea,
1793 						 plane,
1794 						 planes,
1795 						 ifd.fPhotometricInterpretation,
1796 						 tileByteCount,
1797 						 jpegDataInMemory);
1798 
1799 		}
1800 
1801 	return true;
1802 
1803 	}
1804 
1805 /*****************************************************************************/
1806 
ReadLosslessJPEG(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image,const dng_rect & tileArea,uint32 plane,uint32 planes,uint32 tileByteCount,AutoPtr<dng_memory_block> & uncompressedBuffer,AutoPtr<dng_memory_block> & subTileBlockBuffer)1807 bool dng_read_image::ReadLosslessJPEG (dng_host &host,
1808 									   const dng_ifd &ifd,
1809 									   dng_stream &stream,
1810 									   dng_image &image,
1811 									   const dng_rect &tileArea,
1812 									   uint32 plane,
1813 									   uint32 planes,
1814 									   uint32 tileByteCount,
1815 									   AutoPtr<dng_memory_block> &uncompressedBuffer,
1816 									   AutoPtr<dng_memory_block> &subTileBlockBuffer)
1817 	{
1818 
1819 	// If the tile area is empty, there's nothing to read.
1820 	if (tileArea.IsEmpty ())
1821 		{
1822 		return true;
1823 		}
1824 
1825 	uint32 bytesPerRow = SafeUint32Mult (tileArea.W(), planes,
1826 		static_cast<uint32> (sizeof (uint16)));
1827 
1828 	uint32 rowsPerStrip = Pin_uint32 (ifd.fSubTileBlockRows,
1829 									  kImageBufferSize / bytesPerRow,
1830 									  tileArea.H ());
1831 
1832 	rowsPerStrip = rowsPerStrip / ifd.fSubTileBlockRows
1833 								* ifd.fSubTileBlockRows;
1834 
1835 	uint32 bufferSize = SafeUint32Mult (bytesPerRow, rowsPerStrip);
1836 
1837 	if (uncompressedBuffer.Get () &&
1838 		uncompressedBuffer->LogicalSize () < bufferSize)
1839 		{
1840 
1841 		uncompressedBuffer.Reset ();
1842 
1843 		}
1844 
1845 	if (uncompressedBuffer.Get () == NULL)
1846 		{
1847 
1848 		uncompressedBuffer.Reset (host.Allocate (bufferSize));
1849 
1850 		}
1851 
1852 	dng_image_spooler spooler (host,
1853 							   ifd,
1854 							   image,
1855 							   tileArea,
1856 							   plane,
1857 							   planes,
1858 							   *uncompressedBuffer.Get (),
1859 							   subTileBlockBuffer);
1860 
1861 	uint32 decodedSize = SafeUint32Mult(tileArea.W (),
1862 						 tileArea.H (),
1863 						 planes, (uint32) sizeof (uint16));
1864 
1865 	bool bug16 = ifd.fLosslessJPEGBug16;
1866 
1867 	uint64 tileOffset = stream.Position ();
1868 
1869 	DecodeLosslessJPEG (stream,
1870 					    spooler,
1871 					    decodedSize,
1872 					    decodedSize,
1873 						bug16);
1874 
1875 	if (stream.Position () > tileOffset + tileByteCount)
1876 		{
1877 		ThrowBadFormat ();
1878 		}
1879 
1880 	return true;
1881 
1882 	}
1883 
1884 /*****************************************************************************/
1885 
CanReadTile(const dng_ifd & ifd)1886 bool dng_read_image::CanReadTile (const dng_ifd &ifd)
1887 	{
1888 
1889 	if (ifd.fSampleFormat [0] != sfUnsignedInteger &&
1890 		ifd.fSampleFormat [0] != sfFloatingPoint)
1891 		{
1892 		return false;
1893 		}
1894 
1895 	switch (ifd.fCompression)
1896 		{
1897 
1898 		case ccUncompressed:
1899 			{
1900 
1901 			if (ifd.fSampleFormat [0] == sfFloatingPoint)
1902 				{
1903 
1904 				return (ifd.fBitsPerSample [0] == 16 ||
1905 						ifd.fBitsPerSample [0] == 24 ||
1906 						ifd.fBitsPerSample [0] == 32);
1907 
1908 				}
1909 
1910 			return ifd.fBitsPerSample [0] >= 8 &&
1911 				   ifd.fBitsPerSample [0] <= 32;
1912 
1913 			}
1914 
1915 		case ccJPEG:
1916 			{
1917 
1918 			if (ifd.fSampleFormat [0] != sfUnsignedInteger)
1919 				{
1920 				return false;
1921 				}
1922 
1923 			if (ifd.IsBaselineJPEG ())
1924 				{
1925 
1926 				// Baseline JPEG.
1927 
1928 				return true;
1929 
1930 				}
1931 
1932 			else
1933 				{
1934 
1935 				// Lossless JPEG.
1936 
1937 				return ifd.fBitsPerSample [0] >= 8 &&
1938 					   ifd.fBitsPerSample [0] <= 16;
1939 
1940 				}
1941 
1942 			break;
1943 
1944 			}
1945 
1946 		case ccLZW:
1947 		case ccDeflate:
1948 		case ccOldDeflate:
1949 		case ccPackBits:
1950 			{
1951 
1952 			if (ifd.fSampleFormat [0] == sfFloatingPoint)
1953 				{
1954 
1955 				if (ifd.fCompression == ccPackBits)
1956 					{
1957 					return false;
1958 					}
1959 
1960 				if (ifd.fPredictor != cpNullPredictor   &&
1961 					ifd.fPredictor != cpFloatingPoint   &&
1962 					ifd.fPredictor != cpFloatingPointX2 &&
1963 					ifd.fPredictor != cpFloatingPointX4)
1964 					{
1965 					return false;
1966 					}
1967 
1968 				if (ifd.fBitsPerSample [0] != 16 &&
1969 					ifd.fBitsPerSample [0] != 24 &&
1970 					ifd.fBitsPerSample [0] != 32)
1971 					{
1972 					return false;
1973 					}
1974 
1975 				}
1976 
1977 			else
1978 				{
1979 
1980 				if (ifd.fPredictor != cpNullPredictor		   &&
1981 					ifd.fPredictor != cpHorizontalDifference   &&
1982 					ifd.fPredictor != cpHorizontalDifferenceX2 &&
1983 					ifd.fPredictor != cpHorizontalDifferenceX4)
1984 					{
1985 					return false;
1986 					}
1987 
1988 				if (ifd.fBitsPerSample [0] != 8  &&
1989 					ifd.fBitsPerSample [0] != 16 &&
1990 					ifd.fBitsPerSample [0] != 32)
1991 					{
1992 					return false;
1993 					}
1994 
1995 				}
1996 
1997 			return true;
1998 
1999 			}
2000 
2001 		default:
2002 			{
2003 			break;
2004 			}
2005 
2006 		}
2007 
2008 	return false;
2009 
2010 	}
2011 
2012 /*****************************************************************************/
2013 
NeedsCompressedBuffer(const dng_ifd & ifd)2014 bool dng_read_image::NeedsCompressedBuffer (const dng_ifd &ifd)
2015 	{
2016 
2017 	if (ifd.fCompression == ccLZW        ||
2018 		ifd.fCompression == ccDeflate    ||
2019 		ifd.fCompression == ccOldDeflate ||
2020 		ifd.fCompression == ccPackBits)
2021 		{
2022 		return true;
2023 		}
2024 
2025 	return false;
2026 
2027 	}
2028 
2029 /*****************************************************************************/
2030 
ByteSwapBuffer(dng_host &,dng_pixel_buffer & buffer)2031 void dng_read_image::ByteSwapBuffer (dng_host & /* host */,
2032 									 dng_pixel_buffer &buffer)
2033 	{
2034 
2035 	uint32 pixels = buffer.fRowStep * buffer.fArea.H ();
2036 
2037 	switch (buffer.fPixelSize)
2038 		{
2039 
2040 		case 2:
2041 			{
2042 
2043 			DoSwapBytes16 ((uint16 *) buffer.fData,
2044 						   pixels);
2045 
2046 			break;
2047 
2048 			}
2049 
2050 		case 4:
2051 			{
2052 
2053 			DoSwapBytes32 ((uint32 *) buffer.fData,
2054 						   pixels);
2055 
2056 			break;
2057 
2058 			}
2059 
2060 		default:
2061 			break;
2062 
2063 		}
2064 
2065 	}
2066 
2067 /*****************************************************************************/
2068 
DecodePredictor(dng_host &,const dng_ifd & ifd,dng_pixel_buffer & buffer)2069 void dng_read_image::DecodePredictor (dng_host & /* host */,
2070 									  const dng_ifd &ifd,
2071 						        	  dng_pixel_buffer &buffer)
2072 	{
2073 
2074 	switch (ifd.fPredictor)
2075 		{
2076 
2077 		case cpNullPredictor:
2078 			{
2079 
2080 			return;
2081 
2082 			}
2083 
2084 		case cpHorizontalDifference:
2085 		case cpHorizontalDifferenceX2:
2086 		case cpHorizontalDifferenceX4:
2087 			{
2088 
2089 			int32 xFactor = 1;
2090 
2091 			if (ifd.fPredictor == cpHorizontalDifferenceX2)
2092 				{
2093 				xFactor = 2;
2094 				}
2095 
2096 			else if (ifd.fPredictor == cpHorizontalDifferenceX4)
2097 				{
2098 				xFactor = 4;
2099 				}
2100 
2101 			switch (buffer.fPixelType)
2102 				{
2103 
2104 				case ttByte:
2105 					{
2106 
2107 					DecodeDelta8 ((uint8 *) buffer.fData,
2108 								  buffer.fArea.H (),
2109 								  buffer.fArea.W () / xFactor,
2110 								  buffer.fPlanes    * xFactor);
2111 
2112 					return;
2113 
2114 					}
2115 
2116 				case ttShort:
2117 					{
2118 
2119 					DecodeDelta16 ((uint16 *) buffer.fData,
2120 								   buffer.fArea.H (),
2121 								   buffer.fArea.W () / xFactor,
2122 								   buffer.fPlanes    * xFactor);
2123 
2124 					return;
2125 
2126 					}
2127 
2128 				case ttLong:
2129 					{
2130 
2131 					DecodeDelta32 ((uint32 *) buffer.fData,
2132 								   buffer.fArea.H (),
2133 								   buffer.fArea.W () / xFactor,
2134 								   buffer.fPlanes    * xFactor);
2135 
2136 					return;
2137 
2138 					}
2139 
2140 				default:
2141 					break;
2142 
2143 				}
2144 
2145 			break;
2146 
2147 			}
2148 
2149 		default:
2150 			break;
2151 
2152 		}
2153 
2154 	ThrowBadFormat ();
2155 
2156 	}
2157 
2158 /*****************************************************************************/
2159 
ReadTile(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image,const dng_rect & tileArea,uint32 plane,uint32 planes,uint32 tileByteCount,AutoPtr<dng_memory_block> & compressedBuffer,AutoPtr<dng_memory_block> & uncompressedBuffer,AutoPtr<dng_memory_block> & subTileBlockBuffer)2160 void dng_read_image::ReadTile (dng_host &host,
2161 						       const dng_ifd &ifd,
2162 						       dng_stream &stream,
2163 						       dng_image &image,
2164 						       const dng_rect &tileArea,
2165 						       uint32 plane,
2166 						       uint32 planes,
2167 						       uint32 tileByteCount,
2168 							   AutoPtr<dng_memory_block> &compressedBuffer,
2169 							   AutoPtr<dng_memory_block> &uncompressedBuffer,
2170 							   AutoPtr<dng_memory_block> &subTileBlockBuffer)
2171 	{
2172 
2173 	switch (ifd.fCompression)
2174 		{
2175 
2176 		case ccLZW:
2177 		case ccDeflate:
2178 		case ccOldDeflate:
2179 		case ccPackBits:
2180 			{
2181 
2182 			// Figure out uncompressed size.
2183 
2184 			uint32 bytesPerSample = (ifd.fBitsPerSample [0] >> 3);
2185 
2186 			uint32 rowStep = 0;
2187 
2188 			uint32 sampleCount = 0;
2189 
2190 			if (!SafeUint32Mult (planes, tileArea.W (), &rowStep) ||
2191 				 !SafeUint32Mult (rowStep, tileArea.H (), &sampleCount))
2192 				{
2193 
2194 				ThrowMemoryFull ("Arithmetic overflow computing sample count.");
2195 
2196 				}
2197 
2198 			// Setup pixel buffer to hold uncompressed data.
2199 
2200 			uint32 pixelType = ttUndefined;
2201 
2202 			if (ifd.fSampleFormat [0] == sfFloatingPoint)
2203 				{
2204 				pixelType = ttFloat;
2205 				}
2206 
2207 			else if (ifd.fBitsPerSample [0] == 8)
2208 				{
2209 				pixelType = ttByte;
2210 				}
2211 
2212 			else if (ifd.fBitsPerSample [0] == 16)
2213 				{
2214 				pixelType = ttShort;
2215 				}
2216 
2217 			else if (ifd.fBitsPerSample [0] == 32)
2218 				{
2219 				pixelType = ttLong;
2220 				}
2221 
2222 			else
2223 				{
2224 				ThrowBadFormat ();
2225 				}
2226 
2227 			uint32 uncompressedSize = ComputeBufferSize (pixelType, tileArea.Size(),
2228 				 planes, padNone);
2229 
2230 			dng_pixel_buffer buffer (tileArea, plane, planes, pixelType, pcInterleaved,
2231 				 NULL);
2232 
2233 			uint32 bufferSize = uncompressedSize;
2234 
2235 			// If we are using the floating point predictor, we need an extra
2236 			// buffer row.
2237 
2238 			if (ifd.fPredictor == cpFloatingPoint   ||
2239 				ifd.fPredictor == cpFloatingPointX2 ||
2240 				ifd.fPredictor == cpFloatingPointX4)
2241 				{
2242 				uint32 rowSize = 0;
2243 				if (!SafeUint32Mult (rowStep, buffer.fPixelSize, &rowSize) ||
2244 					 !SafeUint32Add (bufferSize, rowSize, &bufferSize))
2245 					{
2246 
2247 					ThrowMemoryFull ("Arithmetic overflow computing buffer size.");
2248 
2249 					}
2250 				}
2251 
2252 			// If are processing less than full size floating point data,
2253 			// we need space to expand the data to full floating point size.
2254 
2255 			if (buffer.fPixelType == ttFloat)
2256 				{
2257 				bufferSize = Max_uint32 (bufferSize,
2258 										 SafeUint32Mult(sampleCount, 4));
2259 				}
2260 
2261 			// Sometimes with multi-threading and planar image using strips,
2262 			// we can process a small tile before a large tile on a thread.
2263 			// Simple fix is to just reallocate the buffer if it is too small.
2264 
2265 			if (uncompressedBuffer.Get () &&
2266 				uncompressedBuffer->LogicalSize () < bufferSize)
2267 				{
2268 
2269 				uncompressedBuffer.Reset ();
2270 
2271 				}
2272 
2273 			if (uncompressedBuffer.Get () == NULL)
2274 				{
2275 
2276 				uncompressedBuffer.Reset (host.Allocate (bufferSize));
2277 
2278 				}
2279 
2280 			buffer.fData = uncompressedBuffer->Buffer ();
2281 
2282 			// If using floating point predictor, move buffer pointer to second row.
2283 
2284 			if (ifd.fPredictor == cpFloatingPoint   ||
2285 				ifd.fPredictor == cpFloatingPointX2 ||
2286 				ifd.fPredictor == cpFloatingPointX4)
2287 				{
2288 
2289 				buffer.fData = (uint8 *) buffer.fData +
2290 							   buffer.fRowStep * buffer.fPixelSize;
2291 
2292 				}
2293 
2294 			// Decompress the data.
2295 
2296 			if (ifd.fCompression == ccLZW)
2297 				{
2298 
2299 				dng_lzw_expander expander;
2300 
2301 				if (!expander.Expand (compressedBuffer->Buffer_uint8 (),
2302 									  (uint8 *) buffer.fData,
2303 									  tileByteCount,
2304 									  uncompressedSize))
2305 					{
2306 					ThrowBadFormat ();
2307 					}
2308 
2309 				}
2310 
2311 			else if (ifd.fCompression == ccPackBits)
2312 				{
2313 
2314 				dng_stream subStream (compressedBuffer->Buffer_uint8 (),
2315 									  tileByteCount);
2316 
2317 				if (!DecodePackBits (subStream,
2318 									 (uint8 *) buffer.fData,
2319 									 uncompressedSize))
2320 					{
2321 					ThrowBadFormat ();
2322 					}
2323 
2324 				}
2325 
2326 			else
2327 				{
2328 
2329 				uLongf dstLen = uncompressedSize;
2330 
2331 				int err = uncompress ((Bytef *) buffer.fData,
2332 									  &dstLen,
2333 									  (const Bytef *) compressedBuffer->Buffer (),
2334 									  tileByteCount);
2335 
2336 				if (err != Z_OK)
2337 					{
2338 
2339 					if (err == Z_MEM_ERROR)
2340 						{
2341 						ThrowMemoryFull ();
2342 						}
2343 
2344 					else if (err == Z_DATA_ERROR)
2345 						{
2346 						// Most other TIFF readers do not fail for this error
2347 						// so we should not either, even if it means showing
2348 						// a corrupted image to the user.  Watson #2530216
2349 						// - tknoll 12/20/11
2350 						}
2351 
2352 					else
2353 						{
2354 						ThrowBadFormat ();
2355 						}
2356 
2357 					}
2358 
2359 				if (dstLen != uncompressedSize)
2360 					{
2361 					ThrowBadFormat ();
2362 					}
2363 
2364 				}
2365 
2366 			// The floating point predictor is byte order independent.
2367 
2368 			if (ifd.fPredictor == cpFloatingPoint   ||
2369 				ifd.fPredictor == cpFloatingPointX2 ||
2370 				ifd.fPredictor == cpFloatingPointX4)
2371 				{
2372 
2373 				int32 xFactor = 1;
2374 
2375 				if (ifd.fPredictor == cpFloatingPointX2)
2376 					{
2377 					xFactor = 2;
2378 					}
2379 
2380 				else if (ifd.fPredictor == cpFloatingPointX4)
2381 					{
2382 					xFactor = 4;
2383 					}
2384 
2385 				for (int32 row = tileArea.t; row < tileArea.b; row++)
2386 					{
2387 
2388 					uint8 *srcPtr = (uint8 *) buffer.DirtyPixel (row    , tileArea.l, plane);
2389 					// Destination is previous row.
2390 					// Subtracting buffer.fRowStep * buffer.fPixelSize will
2391 					// always result in a pointer that lies inside the buffer
2392 					// because above, we added exactly the same offset to
2393 					// buffer.fData (see the piece of code commented "move
2394 					// buffer pointer to second row").
2395 					uint8 *dstPtr = srcPtr -
2396 						buffer.fRowStep * buffer.fPixelSize;
2397 
2398 					DecodeFPDelta (srcPtr,
2399 								   dstPtr,
2400 								   tileArea.W () / xFactor,
2401 								   planes        * xFactor,
2402 								   bytesPerSample);
2403 
2404 					}
2405 
2406 				buffer.fData = (uint8 *) buffer.fData -
2407 							   buffer.fRowStep * buffer.fPixelSize;
2408 
2409 				}
2410 
2411 			else
2412 				{
2413 
2414 				// Both these compression algorithms are byte based.
2415 
2416 				if (stream.SwapBytes ())
2417 					{
2418 
2419 					ByteSwapBuffer (host,
2420 									buffer);
2421 
2422 					}
2423 
2424 				// Undo the predictor.
2425 
2426 				DecodePredictor (host,
2427 								 ifd,
2428 								 buffer);
2429 
2430 				}
2431 
2432 			// Expand floating point data, if needed.
2433 
2434 			if (buffer.fPixelType == ttFloat && buffer.fPixelSize == 2)
2435 				{
2436 
2437 				uint16 *srcPtr = (uint16 *) buffer.fData;
2438 				uint32 *dstPtr = (uint32 *) buffer.fData;
2439 
2440 				for (int32 index = sampleCount - 1; index >= 0; index--)
2441 					{
2442 
2443 					dstPtr [index] = DNG_HalfToFloat (srcPtr [index]);
2444 
2445 					}
2446 
2447 				buffer.fPixelSize = 4;
2448 
2449 				}
2450 
2451 			else if (buffer.fPixelType == ttFloat && buffer.fPixelSize == 3)
2452 				{
2453 
2454 				uint8  *srcPtr = ((uint8  *) buffer.fData) + (sampleCount - 1) * 3;
2455 				uint32 *dstPtr = ((uint32 *) buffer.fData) + (sampleCount - 1);
2456 
2457 				if (stream.BigEndian () || ifd.fPredictor == cpFloatingPoint   ||
2458 										   ifd.fPredictor == cpFloatingPointX2 ||
2459 										   ifd.fPredictor == cpFloatingPointX4)
2460 					{
2461 
2462 					for (uint32 index = 0; index < sampleCount; index++)
2463 						{
2464 
2465 						*(dstPtr--) = DNG_FP24ToFloat (srcPtr);
2466 
2467 						srcPtr -= 3;
2468 
2469 						}
2470 
2471 					}
2472 
2473 				else
2474 					{
2475 
2476 					for (uint32 index = 0; index < sampleCount; index++)
2477 						{
2478 
2479 						uint8 input [3];
2480 
2481 						input [2] = srcPtr [0];
2482 						input [1] = srcPtr [1];
2483 						input [0] = srcPtr [2];
2484 
2485 						*(dstPtr--) = DNG_FP24ToFloat (input);
2486 
2487 						srcPtr -= 3;
2488 
2489 						}
2490 
2491 					}
2492 
2493 				buffer.fPixelSize = 4;
2494 
2495 				}
2496 
2497 			// Save the data.
2498 
2499 			image.Put (buffer);
2500 
2501 			return;
2502 
2503 			}
2504 
2505 		case ccUncompressed:
2506 			{
2507 
2508 			if (ReadUncompressed (host,
2509 								  ifd,
2510 								  stream,
2511 								  image,
2512 								  tileArea,
2513 								  plane,
2514 								  planes,
2515 								  uncompressedBuffer,
2516 								  subTileBlockBuffer))
2517 				{
2518 
2519 				return;
2520 
2521 				}
2522 
2523 			break;
2524 
2525 			}
2526 
2527 		case ccJPEG:
2528 			{
2529 
2530 			if (ifd.IsBaselineJPEG ())
2531 				{
2532 
2533 				// Baseline JPEG.
2534 
2535 				if (ReadBaselineJPEG (host,
2536 									  ifd,
2537 									  stream,
2538 									  image,
2539 									  tileArea,
2540 									  plane,
2541 									  planes,
2542 									  tileByteCount,
2543 									  compressedBuffer.Get () ? compressedBuffer->Buffer_uint8 () : NULL))
2544 					{
2545 
2546 					return;
2547 
2548 					}
2549 
2550 				}
2551 
2552 			else
2553 				{
2554 
2555 				// Otherwise is should be lossless JPEG.
2556 
2557 				if (ReadLosslessJPEG (host,
2558 									  ifd,
2559 									  stream,
2560 									  image,
2561 									  tileArea,
2562 									  plane,
2563 									  planes,
2564 									  tileByteCount,
2565 									  uncompressedBuffer,
2566 									  subTileBlockBuffer))
2567 					{
2568 
2569 					return;
2570 
2571 					}
2572 
2573 				}
2574 
2575 			break;
2576 
2577 			}
2578 
2579 		case ccLossyJPEG:
2580 			{
2581 
2582 			if (ReadBaselineJPEG (host,
2583 								  ifd,
2584 								  stream,
2585 								  image,
2586 								  tileArea,
2587 								  plane,
2588 								  planes,
2589 								  tileByteCount,
2590 								  compressedBuffer.Get () ? compressedBuffer->Buffer_uint8 () : NULL))
2591 				{
2592 
2593 				return;
2594 
2595 				}
2596 
2597 			break;
2598 
2599 			}
2600 
2601 		default:
2602 			break;
2603 
2604 		}
2605 
2606 	ThrowBadFormat ();
2607 
2608 	}
2609 
2610 /*****************************************************************************/
2611 
CanRead(const dng_ifd & ifd)2612 bool dng_read_image::CanRead (const dng_ifd &ifd)
2613 	{
2614 
2615 	if (ifd.fImageWidth  < 1 ||
2616 		ifd.fImageLength < 1)
2617 		{
2618 		return false;
2619 		}
2620 
2621 	if (ifd.fSamplesPerPixel < 1)
2622 		{
2623 		return false;
2624 		}
2625 
2626 	if (ifd.fBitsPerSample [0] < 1)
2627 		{
2628 		return false;
2629 		}
2630 
2631 	for (uint32 j = 1; j < Min_uint32 (ifd.fSamplesPerPixel,
2632 									   kMaxSamplesPerPixel); j++)
2633 		{
2634 
2635 		if (ifd.fBitsPerSample [j] !=
2636 			ifd.fBitsPerSample [0])
2637 			{
2638 			return false;
2639 			}
2640 
2641 		if (ifd.fSampleFormat [j] !=
2642 			ifd.fSampleFormat [0])
2643 			{
2644 			return false;
2645 			}
2646 
2647 		}
2648 
2649 	if ((ifd.fPlanarConfiguration != pcInterleaved   ) &&
2650 		(ifd.fPlanarConfiguration != pcPlanar        ) &&
2651 		(ifd.fPlanarConfiguration != pcRowInterleaved))
2652 		{
2653 		return false;
2654 		}
2655 
2656 	if (ifd.fUsesStrips == ifd.fUsesTiles)
2657 		{
2658 		return false;
2659 		}
2660 
2661 	uint32 tileCount = ifd.TilesPerImage ();
2662 
2663 	if (tileCount < 1)
2664 		{
2665 		return false;
2666 		}
2667 
2668 	bool needTileByteCounts = (ifd.TileByteCount (ifd.TileArea (0, 0)) == 0);
2669 
2670 	if (tileCount == 1)
2671 		{
2672 
2673 		if (needTileByteCounts)
2674 			{
2675 
2676 			if (ifd.fTileByteCount [0] < 1)
2677 				{
2678 				return false;
2679 				}
2680 
2681 			}
2682 
2683 		}
2684 
2685 	else
2686 		{
2687 
2688 		if (ifd.fTileOffsetsCount != tileCount)
2689 			{
2690 			return false;
2691 			}
2692 
2693 		if (needTileByteCounts)
2694 			{
2695 
2696 			if (ifd.fTileByteCountsCount != tileCount)
2697 				{
2698 				return false;
2699 				}
2700 
2701 			}
2702 
2703 		}
2704 
2705 	if (!CanReadTile (ifd))
2706 		{
2707 		return false;
2708 		}
2709 
2710 	return true;
2711 
2712 	}
2713 
2714 /*****************************************************************************/
2715 
2716 class dng_read_tiles_task : public dng_area_task
2717 	{
2718 
2719 	private:
2720 
2721 		dng_read_image &fReadImage;
2722 
2723 		dng_host &fHost;
2724 
2725 		const dng_ifd &fIFD;
2726 
2727 		dng_stream &fStream;
2728 
2729 		dng_image &fImage;
2730 
2731 		dng_jpeg_image *fJPEGImage;
2732 
2733 		dng_fingerprint *fJPEGTileDigest;
2734 
2735 		uint32 fOuterSamples;
2736 
2737 		uint32 fInnerSamples;
2738 
2739 		uint32 fTilesDown;
2740 
2741 		uint32 fTilesAcross;
2742 
2743 		uint64 *fTileOffset;
2744 
2745 		uint32 *fTileByteCount;
2746 
2747 		uint32 fCompressedSize;
2748 
2749 		uint32 fUncompressedSize;
2750 
2751 		dng_mutex fMutex;
2752 
2753 		uint32 fNextTileIndex;
2754 
2755 	public:
2756 
dng_read_tiles_task(dng_read_image & readImage,dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image,dng_jpeg_image * jpegImage,dng_fingerprint * jpegTileDigest,uint32 outerSamples,uint32 innerSamples,uint32 tilesDown,uint32 tilesAcross,uint64 * tileOffset,uint32 * tileByteCount,uint32 compressedSize,uint32 uncompressedSize)2757 		dng_read_tiles_task (dng_read_image &readImage,
2758 							 dng_host &host,
2759 							 const dng_ifd &ifd,
2760 							 dng_stream &stream,
2761 							 dng_image &image,
2762 							 dng_jpeg_image *jpegImage,
2763 							 dng_fingerprint *jpegTileDigest,
2764 							 uint32 outerSamples,
2765 							 uint32 innerSamples,
2766 							 uint32 tilesDown,
2767 							 uint32 tilesAcross,
2768 							 uint64 *tileOffset,
2769 							 uint32 *tileByteCount,
2770 							 uint32 compressedSize,
2771 							 uint32 uncompressedSize)
2772 
2773 			:	fReadImage        (readImage)
2774 			,	fHost		      (host)
2775 			,	fIFD		      (ifd)
2776 			,	fStream		      (stream)
2777 			,	fImage		      (image)
2778 			,	fJPEGImage		  (jpegImage)
2779 			,	fJPEGTileDigest   (jpegTileDigest)
2780 			,	fOuterSamples     (outerSamples)
2781 			,	fInnerSamples     (innerSamples)
2782 			,	fTilesDown        (tilesDown)
2783 			,	fTilesAcross	  (tilesAcross)
2784 			,	fTileOffset		  (tileOffset)
2785 			,	fTileByteCount	  (tileByteCount)
2786 			,	fCompressedSize   (compressedSize)
2787 			,	fUncompressedSize (uncompressedSize)
2788 			,	fMutex			  ("dng_read_tiles_task")
2789 			,	fNextTileIndex	  (0)
2790 
2791 			{
2792 
2793 			fMinTaskArea = 16 * 16;
2794 			fUnitCell    = dng_point (16, 16);
2795 			fMaxTileSize = dng_point (16, 16);
2796 
2797 			}
2798 
Process(uint32,const dng_rect &,dng_abort_sniffer * sniffer)2799 		void Process (uint32 /* threadIndex */,
2800 					  const dng_rect & /* tile */,
2801 					  dng_abort_sniffer *sniffer)
2802 			{
2803 
2804 			AutoPtr<dng_memory_block> compressedBuffer;
2805 			AutoPtr<dng_memory_block> uncompressedBuffer;
2806 			AutoPtr<dng_memory_block> subTileBlockBuffer;
2807 
2808 			if (!fJPEGImage)
2809 				{
2810 				compressedBuffer.Reset (fHost.Allocate (fCompressedSize));
2811 				}
2812 
2813 			if (fUncompressedSize)
2814 				{
2815 				uncompressedBuffer.Reset (fHost.Allocate (fUncompressedSize));
2816 				}
2817 
2818 			while (true)
2819 				{
2820 
2821 				uint32 tileIndex;
2822 				uint32 byteCount;
2823 
2824 					{
2825 
2826 					dng_lock_mutex lock (&fMutex);
2827 
2828 					if (fNextTileIndex == fOuterSamples * fTilesDown * fTilesAcross)
2829 						{
2830 						return;
2831 						}
2832 
2833 					tileIndex = fNextTileIndex++;
2834 
2835 					TempStreamSniffer noSniffer (fStream, NULL);
2836 
2837 					fStream.SetReadPosition (fTileOffset [tileIndex]);
2838 
2839 					byteCount = fTileByteCount [tileIndex];
2840 
2841 					if (fJPEGImage)
2842 						{
2843 
2844 						fJPEGImage->fJPEGData [tileIndex] . Reset (fHost.Allocate (byteCount));
2845 
2846 						}
2847 
2848 					fStream.Get (fJPEGImage ? fJPEGImage->fJPEGData [tileIndex]->Buffer ()
2849 											: compressedBuffer->Buffer (),
2850 								 byteCount);
2851 
2852 					}
2853 
2854 				dng_abort_sniffer::SniffForAbort (sniffer);
2855 
2856 				if (fJPEGTileDigest)
2857 					{
2858 
2859 					dng_md5_printer printer;
2860 
2861 					printer.Process (compressedBuffer->Buffer (),
2862 									 byteCount);
2863 
2864 					fJPEGTileDigest [tileIndex] = printer.Result ();
2865 
2866 					}
2867 
2868 				dng_stream tileStream (fJPEGImage ? fJPEGImage->fJPEGData [tileIndex]->Buffer ()
2869 												  : compressedBuffer->Buffer (),
2870 									   byteCount);
2871 
2872 				tileStream.SetLittleEndian (fStream.LittleEndian ());
2873 
2874 				uint32 plane = tileIndex / (fTilesDown * fTilesAcross);
2875 
2876 				uint32 rowIndex = (tileIndex - plane * fTilesDown * fTilesAcross) / fTilesAcross;
2877 
2878 				uint32 colIndex = tileIndex - (plane * fTilesDown + rowIndex) * fTilesAcross;
2879 
2880 				dng_rect tileArea = fIFD.TileArea (rowIndex, colIndex);
2881 
2882 				dng_host host (&fHost.Allocator (),
2883 							   sniffer);				// Cannot use sniffer attached to main host
2884 
2885 				fReadImage.ReadTile (host,
2886 									 fIFD,
2887 									 tileStream,
2888 									 fImage,
2889 									 tileArea,
2890 									 plane,
2891 									 fInnerSamples,
2892 									 byteCount,
2893 									 fJPEGImage ? fJPEGImage->fJPEGData [tileIndex]
2894 												: compressedBuffer,
2895 									 uncompressedBuffer,
2896 									 subTileBlockBuffer);
2897 
2898 				}
2899 
2900 			}
2901 
2902 	private:
2903 
2904 		// Hidden copy constructor and assignment operator.
2905 
2906 		dng_read_tiles_task (const dng_read_tiles_task &);
2907 
2908 		dng_read_tiles_task & operator= (const dng_read_tiles_task &);
2909 
2910 	};
2911 
2912 /*****************************************************************************/
2913 
Read(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image,dng_jpeg_image * jpegImage,dng_fingerprint * jpegDigest)2914 void dng_read_image::Read (dng_host &host,
2915 						   const dng_ifd &ifd,
2916 						   dng_stream &stream,
2917 						   dng_image &image,
2918 						   dng_jpeg_image *jpegImage,
2919 						   dng_fingerprint *jpegDigest)
2920 	{
2921 
2922 	uint32 tileIndex;
2923 
2924 	// Deal with row interleaved images.
2925 
2926 	if (ifd.fRowInterleaveFactor > 1 &&
2927 		ifd.fRowInterleaveFactor < ifd.fImageLength)
2928 		{
2929 
2930 		dng_ifd tempIFD (ifd);
2931 
2932 		tempIFD.fRowInterleaveFactor = 1;
2933 
2934 		dng_row_interleaved_image tempImage (image,
2935 											 ifd.fRowInterleaveFactor);
2936 
2937 		Read (host,
2938 			  tempIFD,
2939 			  stream,
2940 			  tempImage,
2941 			  jpegImage,
2942 			  jpegDigest);
2943 
2944 		return;
2945 
2946 		}
2947 
2948 	// Figure out inner and outer samples.
2949 
2950 	uint32 innerSamples = 1;
2951 	uint32 outerSamples = 1;
2952 
2953 	if (ifd.fPlanarConfiguration == pcPlanar)
2954 		{
2955 		outerSamples = ifd.fSamplesPerPixel;
2956 		}
2957 	else
2958 		{
2959 		innerSamples = ifd.fSamplesPerPixel;
2960 		}
2961 
2962 	// Calculate number of tiles to read.
2963 
2964 	uint32 tilesAcross = ifd.TilesAcross ();
2965 	uint32 tilesDown   = ifd.TilesDown   ();
2966 
2967 	uint32 tileCount = SafeUint32Mult (tilesAcross, tilesDown, outerSamples);
2968 
2969 	// Find the tile offsets.
2970 
2971 	dng_memory_data tileOffsetData (tileCount, sizeof (uint64));
2972 
2973 	uint64 *tileOffset = tileOffsetData.Buffer_uint64 ();
2974 
2975 	if (tileCount <= dng_ifd::kMaxTileInfo)
2976 		{
2977 
2978 		for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
2979 			{
2980 
2981 			tileOffset [tileIndex] = ifd.fTileOffset [tileIndex];
2982 
2983 			}
2984 
2985 		}
2986 
2987 	else
2988 		{
2989 
2990 		stream.SetReadPosition (ifd.fTileOffsetsOffset);
2991 
2992 		for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
2993 			{
2994 
2995 			tileOffset [tileIndex] = stream.TagValue_uint32 (ifd.fTileOffsetsType);
2996 
2997 			}
2998 
2999 		}
3000 
3001 	// Quick validity check on tile offsets.
3002 
3003 	for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3004 		{
3005 
3006 		#if qDNGValidate
3007 
3008 		if (tileOffset [tileIndex] < 8)
3009 			{
3010 
3011 			ReportWarning ("Tile/Strip offset less than 8");
3012 
3013 			}
3014 
3015 		#endif
3016 
3017 		if (tileOffset [tileIndex] >= stream.Length ())
3018 			{
3019 
3020 			ThrowBadFormat ();
3021 
3022 			}
3023 
3024 		}
3025 
3026 	// Buffer to hold the tile byte counts, if needed.
3027 
3028 	dng_memory_data tileByteCountData;
3029 
3030 	uint32 *tileByteCount = NULL;
3031 
3032 	// If we can compute the number of bytes needed to store the
3033 	// data, we can split the read for each tile into sub-tiles.
3034 
3035 	uint32 uncompressedSize = 0;
3036 
3037 	uint32 subTileLength = ifd.fTileLength;
3038 
3039 	if (ifd.TileByteCount (ifd.TileArea (0, 0)) != 0)
3040 		{
3041 
3042 		uint32 bytesPerPixel = TagTypeSize (ifd.PixelType ());
3043 
3044 		uint32 bytesPerRow = SafeUint32Mult (ifd.fTileWidth, innerSamples,
3045 											 bytesPerPixel);
3046 
3047 		subTileLength = Pin_uint32 (ifd.fSubTileBlockRows,
3048 									kImageBufferSize / bytesPerRow,
3049 									ifd.fTileLength);
3050 
3051 		subTileLength = subTileLength / ifd.fSubTileBlockRows
3052 									  * ifd.fSubTileBlockRows;
3053 
3054 		uncompressedSize = SafeUint32Mult (subTileLength, bytesPerRow);
3055 
3056 		}
3057 
3058 	// Else we need to know the byte counts.
3059 
3060 	else
3061 		{
3062 
3063 		tileByteCountData.Allocate (tileCount, sizeof (uint32));
3064 
3065 		tileByteCount = tileByteCountData.Buffer_uint32 ();
3066 
3067 		if (tileCount <= dng_ifd::kMaxTileInfo)
3068 			{
3069 
3070 			for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3071 				{
3072 
3073 				tileByteCount [tileIndex] = ifd.fTileByteCount [tileIndex];
3074 
3075 				}
3076 
3077 			}
3078 
3079 		else
3080 			{
3081 
3082 			stream.SetReadPosition (ifd.fTileByteCountsOffset);
3083 
3084 			for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3085 				{
3086 
3087 				tileByteCount [tileIndex] = stream.TagValue_uint32 (ifd.fTileByteCountsType);
3088 
3089 				}
3090 
3091 			}
3092 
3093 		// Quick validity check on tile byte counts.
3094 
3095 		for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3096 			{
3097 
3098 			if (tileByteCount [tileIndex] < 1 ||
3099 				tileByteCount [tileIndex] > stream.Length ())
3100 				{
3101 
3102 				ThrowBadFormat ();
3103 
3104 				}
3105 
3106 			}
3107 
3108 		}
3109 
3110 	// Find maximum tile size, if possible.
3111 
3112 	uint32 maxTileByteCount = 0;
3113 
3114 	if (tileByteCount)
3115 		{
3116 
3117 		for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3118 			{
3119 
3120 			maxTileByteCount = Max_uint32 (maxTileByteCount,
3121 										   tileByteCount [tileIndex]);
3122 
3123 			}
3124 
3125 		}
3126 
3127 	// Do we need a compressed data buffer?
3128 
3129 	uint32 compressedSize = 0;
3130 
3131 	bool needsCompressedBuffer = NeedsCompressedBuffer (ifd);
3132 
3133 	if (needsCompressedBuffer)
3134 		{
3135 
3136 		if (!tileByteCount)
3137 			{
3138 			ThrowBadFormat ();
3139 			}
3140 
3141 		compressedSize = maxTileByteCount;
3142 
3143 		}
3144 
3145 	// Are we keeping the compressed JPEG image data?
3146 
3147 	if (jpegImage)
3148 		{
3149 
3150 		if (ifd.IsBaselineJPEG ())
3151 			{
3152 
3153 			jpegImage->fImageSize.h = ifd.fImageWidth;
3154 			jpegImage->fImageSize.v = ifd.fImageLength;
3155 
3156 			jpegImage->fTileSize.h = ifd.fTileWidth;
3157 			jpegImage->fTileSize.v = ifd.fTileLength;
3158 
3159 			jpegImage->fUsesStrips = ifd.fUsesStrips;
3160 
3161 			jpegImage->fJPEGData.Reset (tileCount);
3162 
3163 			}
3164 
3165 		else
3166 			{
3167 
3168 			jpegImage = NULL;
3169 
3170 			}
3171 
3172 		}
3173 
3174 	// Do we need to read the JPEG tables?
3175 
3176 	if (ifd.fJPEGTablesOffset && ifd.fJPEGTablesCount)
3177 		{
3178 
3179 		if (ifd.IsBaselineJPEG ())
3180 			{
3181 
3182 			fJPEGTables.Reset (host.Allocate (ifd.fJPEGTablesCount));
3183 
3184 			stream.SetReadPosition (ifd.fJPEGTablesOffset);
3185 
3186 			stream.Get (fJPEGTables->Buffer      (),
3187 						fJPEGTables->LogicalSize ());
3188 
3189 			}
3190 
3191 		}
3192 
3193 	AutoArray<dng_fingerprint> jpegTileDigest;
3194 
3195 	if (jpegDigest)
3196 		{
3197 
3198 		jpegTileDigest.Reset (
3199 			SafeUint32Add(tileCount, (fJPEGTables.Get () ? 1 : 0)));
3200 
3201 		}
3202 
3203 	// Don't read planes we are not actually saving.
3204 
3205 	outerSamples = Min_uint32 (image.Planes (), outerSamples);
3206 
3207 	// See if we can do this read using multiple threads.
3208 
3209 	bool useMultipleThreads = (outerSamples * tilesDown * tilesAcross >= 2) &&
3210 							  (host.PerformAreaTaskThreads () > 1) &&
3211 							  (maxTileByteCount > 0 && maxTileByteCount <= 1024 * 1024) &&
3212 							  (subTileLength == ifd.fTileLength) &&
3213 							  (ifd.fCompression != ccUncompressed);
3214 
3215 #if qImagecore
3216 	useMultipleThreads = false;
3217 #endif
3218 
3219 	if (useMultipleThreads)
3220 		{
3221 
3222 		uint32 threadCount = Min_uint32 (outerSamples * tilesDown * tilesAcross,
3223 										 host.PerformAreaTaskThreads ());
3224 
3225 		dng_read_tiles_task task (*this,
3226 								  host,
3227 								  ifd,
3228 								  stream,
3229 								  image,
3230 								  jpegImage,
3231 								  jpegTileDigest.Get (),
3232 								  outerSamples,
3233 								  innerSamples,
3234 								  tilesDown,
3235 								  tilesAcross,
3236 								  tileOffset,
3237 								  tileByteCount,
3238 								  maxTileByteCount,
3239 								  uncompressedSize);
3240 
3241 		host.PerformAreaTask (task,
3242 							  dng_rect (0, 0, 16, 16 * threadCount));
3243 
3244 		}
3245 
3246 	// Else use a single thread to read all the tiles.
3247 
3248 	else
3249 		{
3250 
3251 		AutoPtr<dng_memory_block> compressedBuffer;
3252 		AutoPtr<dng_memory_block> uncompressedBuffer;
3253 		AutoPtr<dng_memory_block> subTileBlockBuffer;
3254 
3255 		if (uncompressedSize)
3256 			{
3257 			uncompressedBuffer.Reset (host.Allocate (uncompressedSize));
3258 			}
3259 
3260 		if (compressedSize && !jpegImage)
3261 			{
3262 			compressedBuffer.Reset (host.Allocate (compressedSize));
3263 			}
3264 
3265 		else if (jpegDigest)
3266 			{
3267 			compressedBuffer.Reset (host.Allocate (maxTileByteCount));
3268 			}
3269 
3270 		tileIndex = 0;
3271 
3272 		for (uint32 plane = 0; plane < outerSamples; plane++)
3273 			{
3274 
3275 			for (uint32 rowIndex = 0; rowIndex < tilesDown; rowIndex++)
3276 				{
3277 
3278 				for (uint32 colIndex = 0; colIndex < tilesAcross; colIndex++)
3279 					{
3280 
3281 					stream.SetReadPosition (tileOffset [tileIndex]);
3282 
3283 					dng_rect tileArea = ifd.TileArea (rowIndex, colIndex);
3284 
3285 					uint32 subTileCount = (tileArea.H () + subTileLength - 1) /
3286 										  subTileLength;
3287 
3288 					for (uint32 subIndex = 0; subIndex < subTileCount; subIndex++)
3289 						{
3290 
3291 						host.SniffForAbort ();
3292 
3293 						dng_rect subArea (tileArea);
3294 
3295 						subArea.t = tileArea.t + subIndex * subTileLength;
3296 
3297 						subArea.b = Min_int32 (subArea.t + subTileLength,
3298 											   tileArea.b);
3299 
3300 						uint32 subByteCount;
3301 
3302 						if (tileByteCount)
3303 							{
3304 							subByteCount = tileByteCount [tileIndex];
3305 							}
3306 						else
3307 							{
3308 							subByteCount = ifd.TileByteCount (subArea);
3309 							}
3310 
3311 						if (jpegImage)
3312 							{
3313 
3314 							jpegImage->fJPEGData [tileIndex].Reset (host.Allocate (subByteCount));
3315 
3316 							stream.Get (jpegImage->fJPEGData [tileIndex]->Buffer (), subByteCount);
3317 
3318 							stream.SetReadPosition (tileOffset [tileIndex]);
3319 
3320 							}
3321 
3322 						else if ((needsCompressedBuffer || jpegDigest) && subByteCount)
3323 							{
3324 
3325 							stream.Get (compressedBuffer->Buffer (), subByteCount);
3326 
3327 							if (jpegDigest)
3328 								{
3329 
3330 								dng_md5_printer printer;
3331 
3332 								printer.Process (compressedBuffer->Buffer (),
3333 												 subByteCount);
3334 
3335 								jpegTileDigest [tileIndex] = printer.Result ();
3336 
3337 								}
3338 
3339 							}
3340 
3341 						ReadTile (host,
3342 								  ifd,
3343 								  stream,
3344 								  image,
3345 								  subArea,
3346 								  plane,
3347 								  innerSamples,
3348 								  subByteCount,
3349 								  jpegImage ? jpegImage->fJPEGData [tileIndex] : compressedBuffer,
3350 								  uncompressedBuffer,
3351 								  subTileBlockBuffer);
3352 
3353 						}
3354 
3355 					tileIndex++;
3356 
3357 					}
3358 
3359 				}
3360 
3361 			}
3362 
3363 		}
3364 
3365 	// Finish up JPEG digest computation, if needed.
3366 
3367 	if (jpegDigest)
3368 		{
3369 
3370 		if (fJPEGTables.Get ())
3371 			{
3372 
3373 			dng_md5_printer printer;
3374 
3375 			printer.Process (fJPEGTables->Buffer      (),
3376 							 fJPEGTables->LogicalSize ());
3377 
3378 			jpegTileDigest [tileCount] = printer.Result ();
3379 
3380 			}
3381 
3382 		dng_md5_printer printer2;
3383 
3384 		for (uint32 j = 0; j < tileCount + (fJPEGTables.Get () ? 1 : 0); j++)
3385 			{
3386 
3387 			printer2.Process (jpegTileDigest [j].data,
3388 							  dng_fingerprint::kDNGFingerprintSize);
3389 
3390 			}
3391 
3392 		*jpegDigest = printer2.Result ();
3393 
3394 		}
3395 
3396 	// Keep the JPEG table in the jpeg image, if any.
3397 
3398 	if (jpegImage)
3399 		{
3400 
3401 		jpegImage->fJPEGTables.Reset (fJPEGTables.Release ());
3402 
3403 		}
3404 
3405 	}
3406 
3407 /*****************************************************************************/
3408