1 /*****************************************************************************/
2 // Copyright 2006-2007 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_2/dng_sdk/source/dng_read_image.cpp#1 $ */
10 /* $DateTime: 2008/03/09 14:29:54 $ */
11 /* $Change: 431850 $ */
12 /* $Author: tknoll $ */
13 
14 /*****************************************************************************/
15 
16 #include "dng_read_image.h"
17 
18 #include "dng_bottlenecks.h"
19 #include "dng_exceptions.h"
20 #include "dng_host.h"
21 #include "dng_image.h"
22 #include "dng_ifd.h"
23 #include "dng_lossless_jpeg.h"
24 #include "dng_memory.h"
25 #include "dng_pixel_buffer.h"
26 #include "dng_tag_types.h"
27 #include "dng_tag_values.h"
28 #include "dng_utils.h"
29 
30 /*****************************************************************************/
31 
dng_row_interleaved_image(dng_image & image,uint32 factor)32 dng_row_interleaved_image::dng_row_interleaved_image (dng_image &image,
33 													  uint32 factor)
34 
35 	:	dng_image (image.Bounds     (),
36 				   image.Planes     (),
37 				   image.PixelType  (),
38 				   image.PixelRange ())
39 
40 	,	fImage  (image )
41 	,	fFactor (factor)
42 
43 	{
44 
45 	}
46 
47 /*****************************************************************************/
48 
MapRow(int32 row) const49 int32 dng_row_interleaved_image::MapRow (int32 row) const
50 	{
51 
52 	uint32 rows = Height ();
53 
54 	int32 top = Bounds ().t;
55 
56 	uint32 fieldRow = row - top;
57 
58 	for (uint32 field = 0; true; field++)
59 		{
60 
61 		uint32 fieldRows = (rows - field + fFactor - 1) / fFactor;
62 
63 		if (fieldRow < fieldRows)
64 			{
65 
66 			return fieldRow * fFactor + field + top;
67 
68 			}
69 
70 		fieldRow -= fieldRows;
71 
72 		}
73 
74 	ThrowProgramError ();
75 
76 	return 0;
77 
78 	}
79 
80 /*****************************************************************************/
81 
DoGet(dng_pixel_buffer & buffer) const82 void dng_row_interleaved_image::DoGet (dng_pixel_buffer &buffer) const
83 	{
84 
85 	dng_pixel_buffer tempBuffer (buffer);
86 
87 	for (int32 row = buffer.fArea.t; row < buffer.fArea.b; row++)
88 		{
89 
90 		tempBuffer.fArea.t = MapRow (row);
91 
92 		tempBuffer.fArea.b = tempBuffer.fArea.t + 1;
93 
94 		tempBuffer.fData = (void *) buffer.DirtyPixel (row,
95 										 			   buffer.fArea.l,
96 										 			   buffer.fPlane);
97 
98 		fImage.Get (tempBuffer);
99 
100 		}
101 
102 	}
103 
104 /*****************************************************************************/
105 
DoPut(const dng_pixel_buffer & buffer)106 void dng_row_interleaved_image::DoPut (const dng_pixel_buffer &buffer)
107 	{
108 
109 	dng_pixel_buffer tempBuffer (buffer);
110 
111 	for (int32 row = buffer.fArea.t; row < buffer.fArea.b; row++)
112 		{
113 
114 		tempBuffer.fArea.t = MapRow (row);
115 
116 		tempBuffer.fArea.b = tempBuffer.fArea.t + 1;
117 
118 		tempBuffer.fData = (void *) buffer.ConstPixel (row,
119 										 			   buffer.fArea.l,
120 										 			   buffer.fPlane);
121 
122 		fImage.Put (tempBuffer);
123 
124 		}
125 
126 	}
127 
128 /*****************************************************************************/
129 
ReorderSubTileBlocks(dng_host & host,const dng_ifd & ifd,dng_pixel_buffer & buffer,AutoPtr<dng_memory_block> & tempBuffer)130 static void ReorderSubTileBlocks (dng_host &host,
131 								  const dng_ifd &ifd,
132 								  dng_pixel_buffer &buffer,
133 								  AutoPtr<dng_memory_block> &tempBuffer)
134 	{
135 
136 	uint32 tempBufferSize = buffer.fArea.W () *
137 							buffer.fArea.H () *
138 							buffer.fPlanes *
139 							buffer.fPixelSize;
140 
141 	if (!tempBuffer.Get () || tempBuffer->LogicalSize () < tempBufferSize)
142 		{
143 
144 		tempBuffer.Reset (host.Allocate (tempBufferSize));
145 
146 		}
147 
148 	uint32 blockRows = ifd.fSubTileBlockRows;
149 	uint32 blockCols = ifd.fSubTileBlockCols;
150 
151 	uint32 rowBlocks = buffer.fArea.H () / blockRows;
152 	uint32 colBlocks = buffer.fArea.W () / blockCols;
153 
154 	int32 rowStep = buffer.fRowStep * buffer.fPixelSize;
155 	int32 colStep = buffer.fColStep * buffer.fPixelSize;
156 
157 	int32 rowBlockStep = rowStep * blockRows;
158 	int32 colBlockStep = colStep * blockCols;
159 
160 	uint32 blockColBytes = blockCols * buffer.fPlanes * buffer.fPixelSize;
161 
162 	const uint8 *s0 = (const uint8 *) buffer.fData;
163 	      uint8 *d0 = tempBuffer->Buffer_uint8 ();
164 
165 	for (uint32 rowBlock = 0; rowBlock < rowBlocks; rowBlock++)
166 		{
167 
168 		uint8 *d1 = d0;
169 
170 		for (uint32 colBlock = 0; colBlock < colBlocks; colBlock++)
171 			{
172 
173 			uint8 *d2 = d1;
174 
175 			for (uint32 blockRow = 0; blockRow < blockRows; blockRow++)
176 				{
177 
178 				for (uint32 j = 0; j < blockColBytes; j++)
179 					{
180 
181 					d2 [j] = s0 [j];
182 
183 					}
184 
185 				s0 += blockColBytes;
186 
187 				d2 += rowStep;
188 
189 				}
190 
191 			d1 += colBlockStep;
192 
193 			}
194 
195 		d0 += rowBlockStep;
196 
197 		}
198 
199 	// Copy back reordered pixels.
200 
201 	DoCopyBytes (tempBuffer->Buffer (),
202 				 buffer.fData,
203 				 tempBufferSize);
204 
205 	}
206 
207 /*****************************************************************************/
208 
209 class dng_image_spooler: public dng_spooler
210 	{
211 
212 	private:
213 
214 		dng_host &fHost;
215 
216 		const dng_ifd &fIFD;
217 
218 		dng_image &fImage;
219 
220 		dng_rect fTileArea;
221 
222 		uint32 fPlane;
223 		uint32 fPlanes;
224 
225 		dng_memory_block &fBlock;
226 
227 		AutoPtr<dng_memory_block> &fSubTileBuffer;
228 
229 		dng_rect fTileStrip;
230 
231 		uint8 *fBuffer;
232 
233 		uint32 fBufferCount;
234 		uint32 fBufferSize;
235 
236 	public:
237 
238 		dng_image_spooler (dng_host &host,
239 						   const dng_ifd &ifd,
240 						   dng_image &image,
241 						   const dng_rect &tileArea,
242 						   uint32 plane,
243 						   uint32 planes,
244 						   dng_memory_block &block,
245 						   AutoPtr<dng_memory_block> &subTileBuffer);
246 
247 		virtual ~dng_image_spooler ();
248 
249 		virtual void Spool (const void *data,
250 							uint32 count);
251 
252 	private:
253 
254 		// Hidden copy constructor and assignment operator.
255 
256 		dng_image_spooler (const dng_image_spooler &spooler);
257 
258 		dng_image_spooler & operator= (const dng_image_spooler &spooler);
259 
260 	};
261 
262 /*****************************************************************************/
263 
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)264 dng_image_spooler::dng_image_spooler (dng_host &host,
265 									  const dng_ifd &ifd,
266 									  dng_image &image,
267 									  const dng_rect &tileArea,
268 									  uint32 plane,
269 									  uint32 planes,
270 									  dng_memory_block &block,
271 									  AutoPtr<dng_memory_block> &subTileBuffer)
272 
273 	:	fHost (host)
274 	,	fIFD (ifd)
275 	,	fImage (image)
276 	,	fTileArea (tileArea)
277 	,	fPlane (plane)
278 	,	fPlanes (planes)
279 	,	fBlock (block)
280 	,	fSubTileBuffer (subTileBuffer)
281 
282 	,	fTileStrip ()
283 	,	fBuffer (NULL)
284 	,	fBufferCount (0)
285 	,	fBufferSize (0)
286 
287 	{
288 
289 	uint32 bytesPerRow = fTileArea.W () * fPlanes * sizeof (uint16);
290 
291 	uint32 stripLength = Pin_uint32 (ifd.fSubTileBlockRows,
292 									 fBlock.LogicalSize () / bytesPerRow,
293 									 fTileArea.H ());
294 
295 	stripLength = stripLength / ifd.fSubTileBlockRows
296 							  * ifd.fSubTileBlockRows;
297 
298 	fTileStrip   = fTileArea;
299 	fTileStrip.b = fTileArea.t + stripLength;
300 
301 	fBuffer = (uint8 *) fBlock.Buffer ();
302 
303 	fBufferCount = 0;
304 	fBufferSize  = bytesPerRow * stripLength;
305 
306 	}
307 
308 /*****************************************************************************/
309 
~dng_image_spooler()310 dng_image_spooler::~dng_image_spooler ()
311 	{
312 
313 	}
314 
315 /*****************************************************************************/
316 
Spool(const void * data,uint32 count)317 void dng_image_spooler::Spool (const void *data,
318 							   uint32 count)
319 	{
320 
321 	while (count)
322 		{
323 
324 		uint32 block = Min_uint32 (count, fBufferSize - fBufferCount);
325 
326 		if (block == 0)
327 			{
328 			return;
329 			}
330 
331 		DoCopyBytes (data,
332 					 fBuffer + fBufferCount,
333 				     block);
334 
335 		data = ((const uint8 *) data) + block;
336 
337 		count -= block;
338 
339 		fBufferCount += block;
340 
341 		if (fBufferCount == fBufferSize)
342 			{
343 
344 			fHost.SniffForAbort ();
345 
346 			dng_pixel_buffer buffer;
347 
348 			buffer.fArea = fTileStrip;
349 
350 			buffer.fPlane  = fPlane;
351 			buffer.fPlanes = fPlanes;
352 
353 			buffer.fRowStep   = fPlanes * fTileStrip.W ();
354 			buffer.fColStep   = fPlanes;
355 			buffer.fPlaneStep = 1;
356 
357 			buffer.fData = fBuffer;
358 
359 			buffer.fPixelType = ttShort;
360 			buffer.fPixelSize = 2;
361 
362 			if (fIFD.fSubTileBlockRows > 1)
363 				{
364 
365 				ReorderSubTileBlocks (fHost,
366 									  fIFD,
367 									  buffer,
368 									  fSubTileBuffer);
369 
370 				}
371 
372 			fImage.Put (buffer);
373 
374 			uint32 stripLength = fTileStrip.H ();
375 
376 			fTileStrip.t = fTileStrip.b;
377 
378 			fTileStrip.b = Min_int32 (fTileStrip.t + stripLength,
379 									  fTileArea.b);
380 
381 			fBufferCount = 0;
382 
383 			fBufferSize = fTileStrip.W () *
384 						  fTileStrip.H () *
385 						  fPlanes * sizeof (uint16);
386 
387 			}
388 
389 		}
390 
391 	}
392 
393 /*****************************************************************************/
394 
dng_read_image()395 dng_read_image::dng_read_image ()
396 
397 	:	fCompressedBuffer   ()
398 	,	fUncompressedBuffer ()
399 	,	fSubTileBlockBuffer ()
400 
401 	{
402 
403 	}
404 
405 /*****************************************************************************/
406 
~dng_read_image()407 dng_read_image::~dng_read_image ()
408 	{
409 
410 	}
411 
412 /*****************************************************************************/
413 
ReadUncompressed(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image,const dng_rect & tileArea,uint32 plane,uint32 planes)414 bool dng_read_image::ReadUncompressed (dng_host &host,
415 									   const dng_ifd &ifd,
416 									   dng_stream &stream,
417 									   dng_image &image,
418 									   const dng_rect &tileArea,
419 									   uint32 plane,
420 									   uint32 planes)
421 	{
422 
423 	uint32 rows          = tileArea.H ();
424 	uint32 samplesPerRow = tileArea.W ();
425 
426 	if (ifd.fPlanarConfiguration == pcRowInterleaved)
427 		{
428 		rows *= planes;
429 		}
430 	else
431 		{
432 		samplesPerRow *= planes;
433 		}
434 
435 	uint32 samplesPerTile = samplesPerRow * rows;
436 
437 	dng_pixel_buffer buffer;
438 
439 	buffer.fArea = tileArea;
440 
441 	buffer.fPlane  = plane;
442 	buffer.fPlanes = planes;
443 
444 	buffer.fRowStep = planes * tileArea.W ();
445 
446 	if (ifd.fPlanarConfiguration == pcRowInterleaved)
447 		{
448 		buffer.fColStep   = 1;
449 		buffer.fPlaneStep = tileArea.W ();
450 		}
451 
452 	else
453 		{
454 		buffer.fColStep   = planes;
455 		buffer.fPlaneStep = 1;
456 		}
457 
458 	buffer.fData = fUncompressedBuffer->Buffer ();
459 
460 	uint32 bitDepth = ifd.fBitsPerSample [plane];
461 
462 	if (bitDepth == 8)
463 		{
464 
465 		buffer.fPixelType = ttByte;
466 		buffer.fPixelSize = 1;
467 
468 		stream.Get (buffer.fData, samplesPerTile);
469 
470 		}
471 
472 	else if (bitDepth == 16)
473 		{
474 
475 		buffer.fPixelType = ttShort;
476 		buffer.fPixelSize = 2;
477 
478 		stream.Get (buffer.fData, samplesPerTile * 2);
479 
480 		if (stream.SwapBytes ())
481 			{
482 
483 			DoSwapBytes16 ((uint16 *) buffer.fData,
484 						   samplesPerTile);
485 
486 			}
487 
488 		}
489 
490 	else if (bitDepth == 32)
491 		{
492 
493 		buffer.fPixelType = ttLong;
494 		buffer.fPixelSize = 4;
495 
496 		stream.Get (buffer.fData, samplesPerTile * 4);
497 
498 		if (stream.SwapBytes ())
499 			{
500 
501 			DoSwapBytes32 ((uint32 *) buffer.fData,
502 						   samplesPerTile);
503 
504 			}
505 
506 		}
507 
508 	else if (bitDepth == 12)
509 		{
510 
511 		buffer.fPixelType = ttShort;
512 		buffer.fPixelSize = 2;
513 
514 		uint16 *p = (uint16 *) buffer.fData;
515 
516 		uint32 evenSamples = samplesPerRow >> 1;
517 
518 		for (uint32 row = 0; row < rows; row++)
519 			{
520 
521 			for (uint32 j = 0; j < evenSamples; j++)
522 				{
523 
524 				uint32 b0 = stream.Get_uint8 ();
525 				uint32 b1 = stream.Get_uint8 ();
526 				uint32 b2 = stream.Get_uint8 ();
527 
528 				p [0] = (uint16) ((b0 << 4) | (b1 >> 4));
529 				p [1] = (uint16) (((b1 << 8) | b2) & 0x0FFF);
530 
531 				p += 2;
532 
533 				}
534 
535 			if (samplesPerRow & 1)
536 				{
537 
538 				uint32 b0 = stream.Get_uint8 ();
539 				uint32 b1 = stream.Get_uint8 ();
540 
541 				p [0] = (uint16) ((b0 << 4) | (b1 >> 4));
542 
543 				p += 1;
544 
545 				}
546 
547 			}
548 
549 		}
550 
551 	else if (bitDepth > 8 && bitDepth < 16)
552 		{
553 
554 		buffer.fPixelType = ttShort;
555 		buffer.fPixelSize = 2;
556 
557 		uint16 *p = (uint16 *) buffer.fData;
558 
559 		uint32 bitMask = (1 << bitDepth) - 1;
560 
561 		for (uint32 row = 0; row < rows; row++)
562 			{
563 
564 			uint32 bitBuffer  = 0;
565 			uint32 bufferBits = 0;
566 
567 			for (uint32 j = 0; j < samplesPerRow; j++)
568 				{
569 
570 				while (bufferBits < bitDepth)
571 					{
572 
573 					bitBuffer = (bitBuffer << 8) | stream.Get_uint8 ();
574 
575 					bufferBits += 8;
576 
577 					}
578 
579 				p [j] = (uint16) ((bitBuffer >> (bufferBits - bitDepth)) & bitMask);
580 
581 				bufferBits -= bitDepth;
582 
583 				}
584 
585 			p += samplesPerRow;
586 
587 			}
588 
589 		}
590 
591 	else if (bitDepth > 16 && bitDepth < 32)
592 		{
593 
594 		buffer.fPixelType = ttLong;
595 		buffer.fPixelSize = 4;
596 
597 		uint32 *p = (uint32 *) buffer.fData;
598 
599 		uint32 bitMask = (1 << bitDepth) - 1;
600 
601 		for (uint32 row = 0; row < rows; row++)
602 			{
603 
604 			uint64 bitBuffer  = 0;
605 			uint32 bufferBits = 0;
606 
607 			for (uint32 j = 0; j < samplesPerRow; j++)
608 				{
609 
610 				while (bufferBits < bitDepth)
611 					{
612 
613 					bitBuffer = (bitBuffer << 8) | stream.Get_uint8 ();
614 
615 					bufferBits += 8;
616 
617 					}
618 
619 				p [j] = ((uint32) (bitBuffer >> (bufferBits - bitDepth))) & bitMask;
620 
621 				bufferBits -= bitDepth;
622 
623 				}
624 
625 			p += samplesPerRow;
626 
627 			}
628 
629 		}
630 
631 	else
632 		{
633 
634 		return false;
635 
636 		}
637 
638 	if (ifd.fSampleBitShift)
639 		{
640 
641 		buffer.ShiftRight (ifd.fSampleBitShift);
642 
643 		}
644 
645 	if (ifd.fSubTileBlockRows > 1)
646 		{
647 
648 		ReorderSubTileBlocks (host,
649 							  ifd,
650 							  buffer,
651 							  fSubTileBlockBuffer);
652 
653 		}
654 
655 	image.Put (buffer);
656 
657 	return true;
658 
659 	}
660 
661 /*****************************************************************************/
662 
ReadBaselineJPEG(dng_host &,const dng_ifd &,dng_stream &,dng_image &,const dng_rect &,uint32,uint32,uint32)663 bool dng_read_image::ReadBaselineJPEG (dng_host & /* host */,
664 									   const dng_ifd & /* ifd */,
665 									   dng_stream & /* stream */,
666 									   dng_image & /* image */,
667 									   const dng_rect & /* tileArea */,
668 									   uint32 /* plane */,
669 									   uint32 /* planes */,
670 									   uint32 /* tileByteCount */)
671 	{
672 
673 	// The dng_sdk does not include a baseline JPEG decoder.  Override this
674 	// this method to add baseline JPEG support.
675 
676 	return false;
677 
678 	}
679 
680 /*****************************************************************************/
681 
ReadLosslessJPEG(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image,const dng_rect & tileArea,uint32 plane,uint32 planes,uint32 tileByteCount)682 bool dng_read_image::ReadLosslessJPEG (dng_host &host,
683 									   const dng_ifd &ifd,
684 									   dng_stream &stream,
685 									   dng_image &image,
686 									   const dng_rect &tileArea,
687 									   uint32 plane,
688 									   uint32 planes,
689 									   uint32 tileByteCount)
690 	{
691 
692 	if (fUncompressedBuffer.Get () == NULL)
693 		{
694 
695 		uint32 bytesPerRow = tileArea.W () * planes * sizeof (uint16);
696 
697 		uint32 rowsPerStrip = Pin_uint32 (ifd.fSubTileBlockRows,
698 										  kImageBufferSize / bytesPerRow,
699 										  tileArea.H ());
700 
701 		rowsPerStrip = rowsPerStrip / ifd.fSubTileBlockRows
702 									* ifd.fSubTileBlockRows;
703 
704 		uint32 bufferSize = bytesPerRow * rowsPerStrip;
705 
706 		fUncompressedBuffer.Reset (host.Allocate (bufferSize));
707 
708 		}
709 
710 	dng_image_spooler spooler (host,
711 							   ifd,
712 							   image,
713 							   tileArea,
714 							   plane,
715 							   planes,
716 							   *fUncompressedBuffer.Get (),
717 							   fSubTileBlockBuffer);
718 
719 	uint32 decodedSize = tileArea.W () *
720 						 tileArea.H () *
721 						 planes * sizeof (uint16);
722 
723 	bool bug16 = ifd.fLosslessJPEGBug16;
724 
725 	uint64 tileOffset = stream.Position ();
726 
727 	DecodeLosslessJPEG (stream,
728 					    spooler,
729 					    decodedSize,
730 					    decodedSize,
731 						bug16);
732 
733 	if (stream.Position () > tileOffset + tileByteCount)
734 		{
735 		ThrowBadFormat ();
736 		}
737 
738 	return true;
739 
740 	}
741 
742 /*****************************************************************************/
743 
CanReadTile(const dng_ifd & ifd)744 bool dng_read_image::CanReadTile (const dng_ifd &ifd)
745 	{
746 
747 	if (ifd.fSampleFormat [0] != sfUnsignedInteger)
748 		{
749 		return false;
750 		}
751 
752 	switch (ifd.fCompression)
753 		{
754 
755 		case ccUncompressed:
756 			{
757 
758 			return ifd.fBitsPerSample [0] >= 8 &&
759 				   ifd.fBitsPerSample [0] <= 32;
760 
761 			}
762 
763 		case ccJPEG:
764 			{
765 
766 			if (ifd.IsBaselineJPEG ())
767 				{
768 
769 				// Baseline JPEG.
770 
771 				return false;
772 
773 				}
774 
775 			else
776 				{
777 
778 				// Lossless JPEG.
779 
780 				return ifd.fBitsPerSample [0] >= 8 &&
781 					   ifd.fBitsPerSample [0] <= 16;
782 
783 				}
784 
785 			break;
786 
787 			}
788 
789 		default:
790 			{
791 			break;
792 			}
793 
794 		}
795 
796 	return false;
797 
798 	}
799 
800 /*****************************************************************************/
801 
NeedsCompressedBuffer(const dng_ifd &)802 bool dng_read_image::NeedsCompressedBuffer (const dng_ifd & /* ifd */)
803 	{
804 
805 	return false;
806 
807 	}
808 
809 /*****************************************************************************/
810 
ReadTile(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image,const dng_rect & tileArea,uint32 plane,uint32 planes,uint32 tileByteCount)811 void dng_read_image::ReadTile (dng_host &host,
812 						       const dng_ifd &ifd,
813 						       dng_stream &stream,
814 						       dng_image &image,
815 						       const dng_rect &tileArea,
816 						       uint32 plane,
817 						       uint32 planes,
818 						       uint32 tileByteCount)
819 	{
820 
821 	switch (ifd.fCompression)
822 		{
823 
824 		case ccUncompressed:
825 			{
826 
827 			if (ReadUncompressed (host,
828 								  ifd,
829 								  stream,
830 								  image,
831 								  tileArea,
832 								  plane,
833 								  planes))
834 				{
835 
836 				return;
837 
838 				}
839 
840 			break;
841 
842 			}
843 
844 		case ccJPEG:
845 			{
846 
847 			if (ifd.IsBaselineJPEG ())
848 				{
849 
850 				// Baseline JPEG.
851 
852 				if (ReadBaselineJPEG (host,
853 									  ifd,
854 									  stream,
855 									  image,
856 									  tileArea,
857 									  plane,
858 									  planes,
859 									  tileByteCount))
860 					{
861 
862 					return;
863 
864 					}
865 
866 				}
867 
868 			else
869 				{
870 
871 				// Otherwise is should be lossless JPEG.
872 
873 				if (ReadLosslessJPEG (host,
874 									  ifd,
875 									  stream,
876 									  image,
877 									  tileArea,
878 									  plane,
879 									  planes,
880 									  tileByteCount))
881 					{
882 
883 					return;
884 
885 					}
886 
887 				}
888 
889 			break;
890 
891 			}
892 
893 		default:
894 			break;
895 
896 		}
897 
898 	ThrowBadFormat ();
899 
900 	}
901 
902 /*****************************************************************************/
903 
CanRead(const dng_ifd & ifd)904 bool dng_read_image::CanRead (const dng_ifd &ifd)
905 	{
906 
907 	if (ifd.fImageWidth  < 1 ||
908 		ifd.fImageLength < 1)
909 		{
910 		return false;
911 		}
912 
913 	if (ifd.fSamplesPerPixel < 1)
914 		{
915 		return false;
916 		}
917 
918 	if (ifd.fBitsPerSample [0] < 1)
919 		{
920 		return false;
921 		}
922 
923 	for (uint32 j = 1; j < Min_uint32 (ifd.fSamplesPerPixel,
924 									   kMaxSamplesPerPixel); j++)
925 		{
926 
927 		if (ifd.fBitsPerSample [j] !=
928 			ifd.fBitsPerSample [0])
929 			{
930 			return false;
931 			}
932 
933 		if (ifd.fSampleFormat [j] !=
934 			ifd.fSampleFormat [0])
935 			{
936 			return false;
937 			}
938 
939 		}
940 
941 	if ((ifd.fPlanarConfiguration != pcInterleaved   ) &&
942 		(ifd.fPlanarConfiguration != pcPlanar        ) &&
943 		(ifd.fPlanarConfiguration != pcRowInterleaved))
944 		{
945 		return false;
946 		}
947 
948 	if (ifd.fUsesStrips == ifd.fUsesTiles)
949 		{
950 		return false;
951 		}
952 
953 	uint32 tileCount = ifd.TilesPerImage ();
954 
955 	if (tileCount < 1)
956 		{
957 		return false;
958 		}
959 
960 	bool needTileByteCounts = (ifd.TileByteCount (ifd.TileArea (0, 0)) == 0);
961 
962 	if (tileCount == 1)
963 		{
964 
965 		if (needTileByteCounts)
966 			{
967 
968 			if (ifd.fTileByteCount [0] < 1)
969 				{
970 				return false;
971 				}
972 
973 			}
974 
975 		}
976 
977 	else
978 		{
979 
980 		if (ifd.fTileOffsetsCount != tileCount)
981 			{
982 			return false;
983 			}
984 
985 		if (needTileByteCounts)
986 			{
987 
988 			if (ifd.fTileByteCountsCount != tileCount)
989 				{
990 				return false;
991 				}
992 
993 			}
994 
995 		}
996 
997 	if (!CanReadTile (ifd))
998 		{
999 		return false;
1000 		}
1001 
1002 	return true;
1003 
1004 	}
1005 
1006 /*****************************************************************************/
1007 
Read(dng_host & host,const dng_ifd & ifd,dng_stream & stream,dng_image & image)1008 void dng_read_image::Read (dng_host &host,
1009 						   const dng_ifd &ifd,
1010 						   dng_stream &stream,
1011 						   dng_image &image)
1012 	{
1013 
1014 	uint32 tileIndex;
1015 
1016 	// Deal with row interleaved images.
1017 
1018 	if (ifd.fRowInterleaveFactor > 1 &&
1019 		ifd.fRowInterleaveFactor < ifd.fImageLength)
1020 		{
1021 
1022 		dng_ifd tempIFD (ifd);
1023 
1024 		tempIFD.fRowInterleaveFactor = 1;
1025 
1026 		dng_row_interleaved_image tempImage (image,
1027 											 ifd.fRowInterleaveFactor);
1028 
1029 		Read (host,
1030 			  tempIFD,
1031 			  stream,
1032 			  tempImage);
1033 
1034 		return;
1035 
1036 		}
1037 
1038 	// Figure out inner and outer samples.
1039 
1040 	uint32 innerSamples = 1;
1041 	uint32 outerSamples = 1;
1042 
1043 	if (ifd.fPlanarConfiguration == pcPlanar)
1044 		{
1045 		outerSamples = ifd.fSamplesPerPixel;
1046 		}
1047 	else
1048 		{
1049 		innerSamples = ifd.fSamplesPerPixel;
1050 		}
1051 
1052 	// Calculate number of tiles to read.
1053 
1054 	uint32 tilesAcross = ifd.TilesAcross ();
1055 	uint32 tilesDown   = ifd.TilesDown   ();
1056 
1057 	uint32 tileCount = tilesAcross * tilesDown * outerSamples;
1058 
1059 	// Find the tile offsets.
1060 
1061 	dng_memory_data tileOffsetData (tileCount * sizeof (uint64));
1062 
1063 	uint64 *tileOffset = tileOffsetData.Buffer_uint64 ();
1064 
1065 	if (tileCount <= dng_ifd::kMaxTileInfo)
1066 		{
1067 
1068 		for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
1069 			{
1070 
1071 			tileOffset [tileIndex] = ifd.fTileOffset [tileIndex];
1072 
1073 			}
1074 
1075 		}
1076 
1077 	else
1078 		{
1079 
1080 		stream.SetReadPosition (ifd.fTileOffsetsOffset);
1081 
1082 		for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
1083 			{
1084 
1085 			tileOffset [tileIndex] = stream.TagValue_uint32 (ifd.fTileOffsetsType);
1086 
1087 			}
1088 
1089 		}
1090 
1091 	// Buffer to hold the tile byte counts, if needed.
1092 
1093 	dng_memory_data tileByteCountData;
1094 
1095 	uint32 *tileByteCount = NULL;
1096 
1097 	// If we can compute the number of bytes needed to store the
1098 	// data, we can split the read for each tile into sub-tiles.
1099 
1100 	uint32 subTileLength = ifd.fTileLength;
1101 
1102 	if (ifd.TileByteCount (ifd.TileArea (0, 0)) != 0)
1103 		{
1104 
1105 		uint32 bytesPerPixel = TagTypeSize (ifd.PixelType ());
1106 
1107 		uint32 bytesPerRow = ifd.fTileWidth * innerSamples * bytesPerPixel;
1108 
1109 		subTileLength = Pin_uint32 (ifd.fSubTileBlockRows,
1110 									kImageBufferSize / bytesPerRow,
1111 									ifd.fTileLength);
1112 
1113 		subTileLength = subTileLength / ifd.fSubTileBlockRows
1114 									  * ifd.fSubTileBlockRows;
1115 
1116 		fUncompressedBuffer.Reset (host.Allocate (subTileLength * bytesPerRow));
1117 
1118 		}
1119 
1120 	// Else we need to know the byte counts.
1121 
1122 	else
1123 		{
1124 
1125 		tileByteCountData.Allocate (tileCount * sizeof (uint32));
1126 
1127 		tileByteCount = tileByteCountData.Buffer_uint32 ();
1128 
1129 		if (tileCount <= dng_ifd::kMaxTileInfo)
1130 			{
1131 
1132 			for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
1133 				{
1134 
1135 				tileByteCount [tileIndex] = ifd.fTileByteCount [tileIndex];
1136 
1137 				}
1138 
1139 			}
1140 
1141 		else
1142 			{
1143 
1144 			stream.SetReadPosition (ifd.fTileByteCountsOffset);
1145 
1146 			for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
1147 				{
1148 
1149 				tileByteCount [tileIndex] = stream.TagValue_uint32 (ifd.fTileByteCountsType);
1150 
1151 				}
1152 
1153 			}
1154 
1155 		}
1156 
1157 	// See if we need to allocate the compressed tile data buffer.
1158 
1159 	if (tileByteCount && NeedsCompressedBuffer (ifd))
1160 		{
1161 
1162 		// Find maximum compressed tile size.
1163 
1164 		uint32 maxTileByteCount = 0;
1165 
1166 		for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
1167 			{
1168 
1169 			maxTileByteCount = Max_uint32 (maxTileByteCount,
1170 										   tileByteCount [tileIndex]);
1171 
1172 			}
1173 
1174 		// Allocate buffer that size.
1175 
1176 		if (maxTileByteCount)
1177 			{
1178 
1179 			fCompressedBuffer.Reset (host.Allocate (maxTileByteCount));
1180 
1181 			}
1182 
1183 		}
1184 
1185 	// Now read in each tile.
1186 
1187 	tileIndex = 0;
1188 
1189 	for (uint32 plane = 0; plane < outerSamples; plane++)
1190 		{
1191 
1192 		if (plane >= image.Planes ())
1193 			{
1194 			return;		// Don't waste time reading planes we are not saving.
1195 			}
1196 
1197 		for (uint32 rowIndex = 0; rowIndex < tilesDown; rowIndex++)
1198 			{
1199 
1200 			for (uint32 colIndex = 0; colIndex < tilesAcross; colIndex++)
1201 				{
1202 
1203 				stream.SetReadPosition (tileOffset [tileIndex]);
1204 
1205 				dng_rect tileArea = ifd.TileArea (rowIndex, colIndex);
1206 
1207 				uint32 subTileCount = (tileArea.H () + subTileLength - 1) /
1208 									  subTileLength;
1209 
1210 				for (uint32 subIndex = 0; subIndex < subTileCount; subIndex++)
1211 					{
1212 
1213 					host.SniffForAbort ();
1214 
1215 					dng_rect subArea (tileArea);
1216 
1217 					subArea.t = tileArea.t + subIndex * subTileLength;
1218 
1219 					subArea.b = Min_int32 (subArea.t + subTileLength,
1220 										   tileArea.b);
1221 
1222 					uint32 subByteCount;
1223 
1224 					if (tileByteCount)
1225 						{
1226 						subByteCount = tileByteCount [tileIndex];
1227 						}
1228 					else
1229 						{
1230 						subByteCount = ifd.TileByteCount (subArea);
1231 						}
1232 
1233 					ReadTile (host,
1234 							  ifd,
1235 							  stream,
1236 							  image,
1237 							  subArea,
1238 							  plane,
1239 							  innerSamples,
1240 							  subByteCount);
1241 
1242 					}
1243 
1244 				tileIndex++;
1245 
1246 				}
1247 
1248 			}
1249 
1250 		}
1251 
1252 	}
1253 
1254 /*****************************************************************************/
1255