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
47static 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
78static 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
109static 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
140inline 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
241static 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
328bool 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
383class 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
447dng_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
469void 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
493void 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
524bool 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
602bool 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
809dng_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
825int32 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
858void 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
882void 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
906static 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
984class 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
1039dng_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
1085dng_image_spooler::~dng_image_spooler ()
1086 {
1087
1088 }
1089
1090/*****************************************************************************/
1091
1092void 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
1157dng_read_image::dng_read_image ()
1158
1159 : fJPEGTables ()
1160
1161 {
1162
1163 }
1164
1165/*****************************************************************************/
1166
1167dng_read_image::~dng_read_image ()
1168 {
1169
1170 }
1171
1172/*****************************************************************************/
1173
1174bool 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
1466static 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
1495static 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
1516void 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
1660static 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
1746bool 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
1807bool 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
1886bool 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
2014bool 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
2031void 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
2069void 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
2160void 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
2612bool 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
2716class 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
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
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
2914void 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