Coverage Report

Created: 2025-07-23 06:38

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