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