Coverage Report

Created: 2026-07-16 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dng_sdk/source/dng_read_image.cpp
Line
Count
Source
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
246
  {
52
  
53
246
  const uint32 dRowStep = cols * channels;
54
  
55
27.7k
  for (uint32 row = 0; row < rows; row++)
56
27.4k
    {
57
    
58
27.4k
    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
27.4k
    dPtr += dRowStep;
71
    
72
27.4k
    }
73
74
246
  }
75
76
/******************************************************************************/
77
78
static void DecodeDelta16 (uint16 *dPtr,
79
               uint32 rows,
80
               uint32 cols,
81
               uint32 channels)
82
139
  {
83
  
84
139
  const uint32 dRowStep = cols * channels;
85
  
86
139
  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
139
  }
106
  
107
/******************************************************************************/
108
109
static void DecodeDelta32 (uint32 *dPtr,
110
               uint32 rows,
111
               uint32 cols,
112
               uint32 channels)
113
76
  {
114
  
115
76
  const uint32 dRowStep = cols * channels;
116
  
117
76
  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
76
  }
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
0
  , fTable       (NULL)
451
0
  , 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
205
  : dng_image (image.Bounds    (),
813
205
           image.Planes    (),
814
205
           image.PixelType ())
815
                            
816
205
  , fImage  (image )
817
205
  , fFactor (factor)
818
  
819
205
  {
820
  
821
205
  }
822
  
823
/*****************************************************************************/
824
825
int32 dng_row_interleaved_image::MapRow (int32 row) const
826
89.9k
  {
827
828
89.9k
  uint32 rows = Height ();
829
  
830
89.9k
  int32 top = Bounds ().t;
831
  
832
89.9k
  uint32 fieldRow = row - top;
833
  
834
14.6M
  for (uint32 field = 0; true; field++)
835
14.6M
    {
836
    
837
14.6M
    uint32 fieldRows = (rows - field + fFactor - 1) / fFactor;
838
    
839
14.6M
    if (fieldRow < fieldRows)
840
89.9k
      {
841
      
842
89.9k
      return fieldRow * fFactor + field + top;
843
      
844
89.9k
      }
845
      
846
14.5M
    fieldRow -= fieldRows;
847
    
848
14.5M
    }
849
    
850
0
  ThrowProgramError ();
851
    
852
0
  return 0;
853
  
854
89.9k
  }
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
485
  {
884
  
885
485
  dng_pixel_buffer tempBuffer (buffer);
886
  
887
90.4k
  for (int32 row = buffer.fArea.t; row < buffer.fArea.b; row++)
888
89.9k
    {
889
        
890
89.9k
    tempBuffer.fArea.t = MapRow (row);
891
    
892
89.9k
    tempBuffer.fArea.b = tempBuffer.fArea.t + 1;
893
    
894
89.9k
    tempBuffer.fData = (void *) buffer.ConstPixel (row,
895
89.9k
                             buffer.fArea.l,
896
89.9k
                             buffer.fPlane);
897
                     
898
89.9k
    fImage.Put (tempBuffer);
899
    
900
89.9k
    }
901
    
902
485
  }
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
551
  {
911
  
912
551
  uint32 tempBufferSize = ComputeBufferSize(buffer.fPixelType,
913
551
                        buffer.fArea.Size(),
914
551
                        buffer.fPlanes, padNone);
915
              
916
551
  if (!tempBuffer.Get () || tempBuffer->LogicalSize () < tempBufferSize)
917
185
    {
918
    
919
185
    tempBuffer.Reset (host.Allocate (tempBufferSize));
920
    
921
185
    }
922
  
923
551
  uint32 blockRows = ifd.fSubTileBlockRows;
924
551
  uint32 blockCols = ifd.fSubTileBlockCols;
925
  
926
551
  uint32 rowBlocks = buffer.fArea.H () / blockRows;
927
551
  uint32 colBlocks = buffer.fArea.W () / blockCols;
928
  
929
551
  int32 rowStep = buffer.fRowStep * buffer.fPixelSize;
930
551
  int32 colStep = buffer.fColStep * buffer.fPixelSize;
931
  
932
551
  int32 rowBlockStep = rowStep * blockRows;
933
551
  int32 colBlockStep = colStep * blockCols;
934
  
935
551
  uint32 blockColBytes = blockCols * buffer.fPlanes * buffer.fPixelSize;
936
  
937
551
  const uint8 *s0 = (const uint8 *) buffer.fData;
938
551
        uint8 *d0 = tempBuffer->Buffer_uint8 ();
939
  
940
21.8k
  for (uint32 rowBlock = 0; rowBlock < rowBlocks; rowBlock++)
941
21.2k
    {
942
    
943
21.2k
    uint8 *d1 = d0;
944
    
945
6.16M
    for (uint32 colBlock = 0; colBlock < colBlocks; colBlock++)
946
6.14M
      {
947
      
948
6.14M
      uint8 *d2 = d1;
949
      
950
19.3M
      for (uint32 blockRow = 0; blockRow < blockRows; blockRow++)
951
13.2M
        {
952
        
953
47.9M
        for (uint32 j = 0; j < blockColBytes; j++)
954
34.7M
          {
955
          
956
34.7M
          d2 [j] = s0 [j];
957
          
958
34.7M
          }
959
          
960
13.2M
        s0 += blockColBytes;
961
        
962
13.2M
        d2 += rowStep;
963
        
964
13.2M
        }
965
      
966
6.14M
      d1 += colBlockStep;
967
      
968
6.14M
      }
969
      
970
21.2k
    d0 += rowBlockStep;
971
    
972
21.2k
    }
973
    
974
  // Copy back reordered pixels.
975
    
976
551
  DoCopyBytes (tempBuffer->Buffer (),
977
551
         buffer.fData,
978
551
         tempBufferSize);
979
  
980
551
  }
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.37k
  : fHost (host)
1049
5.37k
  , fIFD (ifd)
1050
5.37k
  , fImage (image)
1051
5.37k
  , fTileArea (tileArea)
1052
5.37k
  , fPlane (plane)
1053
5.37k
  , fPlanes (planes)
1054
5.37k
  , fBlock (block)
1055
5.37k
  , fSubTileBuffer (subTileBuffer)
1056
  
1057
5.37k
  , fTileStrip ()
1058
5.37k
  , fBuffer (NULL)
1059
5.37k
  , fBufferCount (0)
1060
5.37k
  , fBufferSize (0)
1061
  
1062
5.37k
  {
1063
  
1064
5.37k
  uint32 bytesPerRow = fTileArea.W () * fPlanes * (uint32) sizeof (uint16);
1065
  
1066
5.37k
  uint32 stripLength = Pin_uint32 (ifd.fSubTileBlockRows,
1067
5.37k
                   fBlock.LogicalSize () / bytesPerRow,
1068
5.37k
                   fTileArea.H ());
1069
                  
1070
5.37k
  stripLength = stripLength / ifd.fSubTileBlockRows
1071
5.37k
                * ifd.fSubTileBlockRows;
1072
  
1073
5.37k
  fTileStrip   = fTileArea;
1074
5.37k
  fTileStrip.b = fTileArea.t + stripLength;
1075
  
1076
5.37k
  fBuffer = (uint8 *) fBlock.Buffer ();
1077
  
1078
5.37k
  fBufferCount = 0;
1079
5.37k
  fBufferSize  = bytesPerRow * stripLength;
1080
          
1081
5.37k
  }
1082
1083
/*****************************************************************************/
1084
1085
dng_image_spooler::~dng_image_spooler ()
1086
5.37k
  {
1087
  
1088
5.37k
  }
1089
1090
/*****************************************************************************/
1091
1092
void dng_image_spooler::Spool (const void *data,
1093
                 uint32 count)
1094
18.5M
  {
1095
  
1096
37.1M
  while (count)
1097
18.5M
    {
1098
    
1099
18.5M
    uint32 block = Min_uint32 (count, fBufferSize - fBufferCount);
1100
    
1101
18.5M
    if (block == 0)
1102
0
      {
1103
0
      return;
1104
0
      }
1105
    
1106
18.5M
    DoCopyBytes (data,
1107
18.5M
           fBuffer + fBufferCount,
1108
18.5M
             block);
1109
        
1110
18.5M
    data = ((const uint8 *) data) + block;
1111
    
1112
18.5M
    count -= block;
1113
    
1114
18.5M
    fBufferCount += block;
1115
    
1116
18.5M
    if (fBufferCount == fBufferSize)
1117
2.40k
      {
1118
      
1119
2.40k
      fHost.SniffForAbort ();
1120
      
1121
2.40k
      dng_pixel_buffer buffer (fTileStrip, fPlane, fPlanes, ttShort,
1122
2.40k
         pcInterleaved, fBuffer);
1123
      
1124
2.40k
      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
2.40k
      fImage.Put (buffer);
1135
      
1136
2.40k
      uint32 stripLength = fTileStrip.H ();
1137
      
1138
2.40k
      fTileStrip.t = fTileStrip.b;
1139
      
1140
2.40k
      fTileStrip.b = Min_int32 (fTileStrip.t + stripLength,
1141
2.40k
                    fTileArea.b);
1142
      
1143
2.40k
      fBufferCount = 0;
1144
      
1145
2.40k
      fBufferSize = fTileStrip.W () *
1146
2.40k
              fTileStrip.H () *
1147
2.40k
              fPlanes * (uint32) sizeof (uint16);
1148
  
1149
2.40k
      }
1150
1151
18.5M
    }
1152
  
1153
18.5M
  }
1154
1155
/*****************************************************************************/
1156
1157
dng_read_image::dng_read_image ()
1158
1159
69.9k
  : fJPEGTables ()
1160
  
1161
69.9k
  {
1162
  
1163
69.9k
  }
1164
1165
/*****************************************************************************/
1166
1167
dng_read_image::~dng_read_image ()
1168
69.9k
  {
1169
  
1170
69.9k
  }
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
29.2k
  {
1184
  
1185
29.2k
  uint32 rows          = tileArea.H ();
1186
29.2k
  uint32 samplesPerRow = tileArea.W ();
1187
  
1188
29.2k
  if (ifd.fPlanarConfiguration == pcRowInterleaved)
1189
0
    {
1190
0
    rows = SafeUint32Mult(rows, planes);
1191
0
    }
1192
29.2k
  else
1193
29.2k
    {
1194
29.2k
    samplesPerRow = SafeUint32Mult(samplesPerRow, planes);
1195
29.2k
    }
1196
  
1197
29.2k
  uint32 samplesPerTile = SafeUint32Mult(samplesPerRow, rows);
1198
    
1199
29.2k
  if (uncompressedBuffer.Get () == NULL)
1200
138
    {
1201
1202
    #if qDNGValidate
1203
    
1204
    ReportError ("Fuzz: Missing uncompressed buffer");
1205
    
1206
    #endif
1207
1208
138
    ThrowBadFormat ();
1209
    
1210
138
    }
1211
  
1212
29.2k
  uint32 bitDepth = ifd.fBitsPerSample [plane];
1213
  
1214
29.2k
  uint32 pixelType = ttUndefined;
1215
  
1216
29.2k
  if (bitDepth == 8)
1217
7.53k
    {
1218
    
1219
7.53k
    pixelType = ttByte;
1220
        
1221
7.53k
    stream.Get (uncompressedBuffer->Buffer (), samplesPerTile);
1222
    
1223
7.53k
    }
1224
    
1225
21.7k
  else if (bitDepth == 16 && ifd.fSampleFormat [0] == sfFloatingPoint)
1226
1.24k
    {
1227
    
1228
1.24k
    pixelType = ttFloat;
1229
    
1230
1.24k
    uint32 *p_uint32 = (uint32 *) uncompressedBuffer->Buffer ();
1231
      
1232
9.12M
    for (uint32 j = 0; j < samplesPerTile; j++)
1233
9.12M
      {
1234
      
1235
9.12M
      p_uint32 [j] = DNG_HalfToFloat (stream.Get_uint16 ());
1236
                      
1237
9.12M
      }
1238
    
1239
1.24k
    }
1240
  
1241
20.5k
  else if (bitDepth == 24 && ifd.fSampleFormat [0] == sfFloatingPoint)
1242
1.00k
    {
1243
    
1244
1.00k
    pixelType = ttFloat;
1245
    
1246
1.00k
    uint32 *p_uint32 = (uint32 *) uncompressedBuffer->Buffer ();
1247
      
1248
9.34M
    for (uint32 j = 0; j < samplesPerTile; j++)
1249
9.34M
      {
1250
      
1251
9.34M
      uint8 input [3];
1252
      
1253
9.34M
      if (stream.LittleEndian ())
1254
9.34M
        {
1255
9.34M
        input [2] = stream.Get_uint8 ();
1256
9.34M
        input [1] = stream.Get_uint8 ();
1257
9.34M
        input [0] = stream.Get_uint8 ();
1258
9.34M
        }
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
9.34M
      p_uint32 [j] = DNG_FP24ToFloat (input);
1268
                      
1269
9.34M
      }
1270
    
1271
1.00k
    }
1272
  
1273
19.5k
  else if (bitDepth == 16)
1274
2.01k
    {
1275
    
1276
2.01k
    pixelType = ttShort;
1277
    
1278
2.01k
    stream.Get (uncompressedBuffer->Buffer (), samplesPerTile * 2);
1279
    
1280
2.01k
    if (stream.SwapBytes ())
1281
0
      {
1282
      
1283
0
      DoSwapBytes16 ((uint16 *) uncompressedBuffer->Buffer (),
1284
0
               samplesPerTile);
1285
            
1286
0
      }
1287
        
1288
2.01k
    }
1289
    
1290
17.5k
  else if (bitDepth == 32)
1291
1.47k
    {
1292
    
1293
1.47k
    pixelType = image.PixelType ();
1294
    
1295
1.47k
    stream.Get (uncompressedBuffer->Buffer (), samplesPerTile * 4);
1296
    
1297
1.47k
    if (stream.SwapBytes ())
1298
0
      {
1299
      
1300
0
      DoSwapBytes32 ((uint32 *) uncompressedBuffer->Buffer (),
1301
0
               samplesPerTile);
1302
            
1303
0
      }
1304
        
1305
1.47k
    }
1306
    
1307
16.0k
  else if (bitDepth == 12)
1308
4.11k
    {
1309
    
1310
4.11k
    pixelType = ttShort;
1311
    
1312
4.11k
    uint16 *p = (uint16 *) uncompressedBuffer->Buffer ();
1313
      
1314
4.11k
    uint32 evenSamples = samplesPerRow >> 1;
1315
    
1316
1.82M
    for (uint32 row = 0; row < rows; row++)
1317
1.81M
      {
1318
      
1319
22.0M
      for (uint32 j = 0; j < evenSamples; j++)
1320
20.2M
        {
1321
        
1322
20.2M
        uint32 b0 = stream.Get_uint8 ();
1323
20.2M
        uint32 b1 = stream.Get_uint8 ();
1324
20.2M
        uint32 b2 = stream.Get_uint8 ();
1325
                
1326
20.2M
        p [0] = (uint16) ((b0 << 4) | (b1 >> 4));
1327
20.2M
        p [1] = (uint16) (((b1 << 8) | b2) & 0x0FFF);
1328
        
1329
20.2M
        p += 2;
1330
        
1331
20.2M
        }
1332
        
1333
1.81M
      if (samplesPerRow & 1)
1334
1.63M
        {
1335
        
1336
1.63M
        uint32 b0 = stream.Get_uint8 ();
1337
1.63M
        uint32 b1 = stream.Get_uint8 ();
1338
        
1339
1.63M
        p [0] = (uint16) ((b0 << 4) | (b1 >> 4));
1340
        
1341
1.63M
        p += 1;
1342
        
1343
1.63M
        }
1344
      
1345
1.81M
      }
1346
    
1347
4.11k
    }
1348
    
1349
11.9k
  else if (bitDepth > 8 && bitDepth < 16)
1350
4.78k
    {
1351
    
1352
4.78k
    pixelType = ttShort;
1353
    
1354
4.78k
    uint16 *p = (uint16 *) uncompressedBuffer->Buffer ();
1355
      
1356
4.78k
    uint32 bitMask = (1 << bitDepth) - 1;
1357
              
1358
2.55M
    for (uint32 row = 0; row < rows; row++)
1359
2.54M
      {
1360
      
1361
2.54M
      uint32 bitBuffer  = 0;
1362
2.54M
      uint32 bufferBits = 0;
1363
      
1364
22.6M
      for (uint32 j = 0; j < samplesPerRow; j++)
1365
20.1M
        {
1366
        
1367
47.2M
        while (bufferBits < bitDepth)
1368
27.1M
          {
1369
          
1370
27.1M
          bitBuffer = (bitBuffer << 8) | stream.Get_uint8 ();
1371
          
1372
27.1M
          bufferBits += 8;
1373
          
1374
27.1M
          }
1375
                  
1376
20.1M
        p [j] = (uint16) ((bitBuffer >> (bufferBits - bitDepth)) & bitMask);
1377
        
1378
20.1M
        bufferBits -= bitDepth;
1379
        
1380
20.1M
        }
1381
        
1382
2.54M
      p += samplesPerRow;
1383
      
1384
2.54M
      }
1385
      
1386
4.78k
    }
1387
    
1388
7.12k
  else if (bitDepth > 16 && bitDepth < 32)
1389
6.99k
    {
1390
    
1391
6.99k
    pixelType = ttLong;
1392
    
1393
6.99k
    uint32 *p = (uint32 *) uncompressedBuffer->Buffer ();
1394
      
1395
6.99k
    uint32 bitMask = ((uint32) 1 << bitDepth) - 1;
1396
              
1397
798k
    for (uint32 row = 0; row < rows; row++)
1398
791k
      {
1399
      
1400
791k
      uint64 bitBuffer  = 0;
1401
791k
      uint32 bufferBits = 0;
1402
      
1403
11.4M
      for (uint32 j = 0; j < samplesPerRow; j++)
1404
10.6M
        {
1405
        
1406
38.4M
        while (bufferBits < bitDepth)
1407
27.7M
          {
1408
          
1409
27.7M
          bitBuffer = (bitBuffer << 8) | stream.Get_uint8 ();
1410
          
1411
27.7M
          bufferBits += 8;
1412
          
1413
27.7M
          }
1414
                  
1415
10.6M
        p [j] = ((uint32) (bitBuffer >> (bufferBits - bitDepth))) & bitMask;
1416
        
1417
10.6M
        bufferBits -= bitDepth;
1418
        
1419
10.6M
        }
1420
        
1421
791k
      p += samplesPerRow;
1422
      
1423
791k
      }
1424
      
1425
6.99k
    }
1426
    
1427
138
  else
1428
138
    {
1429
    
1430
138
    return false;
1431
    
1432
138
    }
1433
    
1434
29.1k
  dng_pixel_buffer buffer (tileArea, plane, planes, pixelType,
1435
29.1k
     ifd.fPlanarConfiguration, uncompressedBuffer->Buffer ());
1436
  
1437
29.1k
  if (ifd.fSampleBitShift)
1438
0
    {
1439
    
1440
0
    buffer.ShiftRight (ifd.fSampleBitShift);
1441
    
1442
0
    }
1443
    
1444
29.1k
  if (ifd.fSubTileBlockRows > 1)
1445
551
    {
1446
    
1447
551
    ReorderSubTileBlocks (host,
1448
551
                ifd,
1449
551
                buffer,
1450
551
                subTileBlockBuffer);
1451
    
1452
551
    }
1453
    
1454
29.1k
  image.Put (buffer);
1455
  
1456
29.1k
  return true;
1457
    
1458
29.2k
  }
1459
1460
/*****************************************************************************/
1461
1462
#if qDNGUseLibJPEG
1463
1464
/*****************************************************************************/
1465
1466
static void dng_error_exit (j_common_ptr cinfo)
1467
136
  {
1468
  
1469
  // Output message.
1470
  
1471
136
  (*cinfo->err->output_message) (cinfo);
1472
  
1473
  // Convert to a dng_exception.
1474
1475
136
  switch (cinfo->err->msg_code)
1476
136
    {
1477
    
1478
0
    case JERR_OUT_OF_MEMORY:
1479
0
      {
1480
0
      ThrowMemoryFull ();
1481
0
      break;
1482
0
      }
1483
      
1484
136
    default:
1485
136
      {
1486
136
      ThrowBadFormat ();
1487
136
      }
1488
      
1489
136
    }
1490
      
1491
136
  }
1492
1493
/*****************************************************************************/
1494
1495
static void dng_output_message (j_common_ptr cinfo)
1496
176
  {
1497
  
1498
  // Format message to string.
1499
  
1500
176
  char buffer [JMSG_LENGTH_MAX];
1501
1502
176
  (*cinfo->err->format_message) (cinfo, buffer);
1503
  
1504
  // Report the libjpeg message as a warning.
1505
  
1506
176
  ReportWarning ("libjpeg", buffer);
1507
1508
176
  }
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
136
  {
1525
  
1526
136
  #if qDNGUseLibJPEG
1527
  
1528
136
  struct jpeg_decompress_struct cinfo;
1529
  
1530
  // Setup the error manager.
1531
  
1532
136
  struct jpeg_error_mgr jerr;
1533
1534
136
  cinfo.err = jpeg_std_error (&jerr);
1535
  
1536
136
  jerr.error_exit     = dng_error_exit;
1537
136
  jerr.output_message = dng_output_message;
1538
  
1539
136
  try
1540
136
    {
1541
    
1542
    // Create the decompression context.
1543
1544
136
    jpeg_create_decompress (&cinfo);
1545
    
1546
    // Set up the memory data source manager.
1547
    
1548
136
    size_t jpegDataSizeAsSizet = 0;
1549
136
    ConvertUnsigned(jpegDataSize, &jpegDataSizeAsSizet);
1550
136
    jpeg_source_mgr memorySource =
1551
136
      CreateJpegMemorySource(jpegDataInMemory,
1552
136
                   jpegDataSizeAsSizet);
1553
136
    cinfo.src = &memorySource;
1554
      
1555
    // Read the JPEG header.
1556
      
1557
136
    jpeg_read_header (&cinfo, TRUE);
1558
    
1559
    // Check header.
1560
    
1561
136
    {
1562
      // Number of components may not be negative.
1563
136
      if (cinfo.num_components < 0)
1564
0
        {
1565
0
        ThrowBadFormat();
1566
0
        }
1567
      
1568
      // Convert relevant values from header to uint32.
1569
136
      uint32 imageWidthAsUint32 = 0;
1570
136
      uint32 imageHeightAsUint32 = 0;
1571
136
      uint32 numComponentsAsUint32 = 0;
1572
136
      ConvertUnsigned(cinfo.image_width, &imageWidthAsUint32);
1573
136
      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
136
      ConvertUnsigned(static_cast<unsigned>(cinfo.num_components),
1577
136
              &numComponentsAsUint32);
1578
      
1579
      // Check that dimensions of JPEG correspond to dimensions of tile.
1580
136
      if (imageWidthAsUint32    != tileArea.W () ||
1581
0
          imageHeightAsUint32   != tileArea.H () ||
1582
0
          numComponentsAsUint32 != planes        )
1583
0
        {
1584
0
        ThrowBadFormat ();
1585
0
        }
1586
136
    }
1587
      
1588
    // Start the compression.
1589
    
1590
136
    jpeg_start_decompress (&cinfo);
1591
    
1592
    // Setup a one-scanline size buffer.
1593
    
1594
136
    dng_pixel_buffer buffer(tileArea, plane, planes, ttByte, pcInterleaved,
1595
136
                NULL);
1596
136
    buffer.fArea.b = tileArea.t + 1;
1597
    
1598
136
    buffer.fDirty = true;
1599
    
1600
136
    AutoPtr<dng_memory_block> bufferData (host.Allocate (buffer.fRowStep));
1601
    
1602
136
    buffer.fData = bufferData->Buffer ();
1603
    
1604
136
    uint8 *sampArray [1];
1605
    
1606
136
    sampArray [0] = bufferData->Buffer_uint8 ();
1607
    
1608
    // Read each scanline and save to image.
1609
      
1610
136
    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
136
    jpeg_finish_decompress (&cinfo);
1625
1626
136
    jpeg_destroy_decompress (&cinfo);
1627
      
1628
136
    }
1629
    
1630
136
  catch (...)
1631
136
    {
1632
    
1633
136
    jpeg_destroy_decompress (&cinfo);
1634
    
1635
136
    throw;
1636
    
1637
136
    }
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
136
  }
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
131
  {
1667
  
1668
  // This ensures that the "tileByteCount -= 2" operation below will not wrap
1669
  // around.
1670
131
  if (tileByteCount <= 2)
1671
11
    {
1672
11
    ThrowEndOfFile ();
1673
11
    }
1674
    
1675
131
  uint32 tablesByteCount = tablesBlock ? tablesBlock->LogicalSize () : 0;
1676
  
1677
  // This ensures that the "tablesByteCount -= 2" operation below will not
1678
  // wrap around.
1679
131
  if (tablesByteCount && tablesByteCount < 4)
1680
15
    {
1681
15
    ThrowEndOfFile ();
1682
15
    }
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
131
  if (tablesByteCount)
1692
40
    {
1693
    
1694
    // Ensure the "tileOffset += 2" operation below will not wrap around.
1695
40
    if (tileOffset > std::numeric_limits<uint64>::max () - 2)
1696
0
      {
1697
0
      ThrowEndOfFile();
1698
0
      }
1699
    
1700
40
    tablesByteCount -= 2;
1701
    
1702
40
    tileOffset    += 2;
1703
40
    tileByteCount -= 2;
1704
    
1705
40
    }
1706
    
1707
  // Allocate buffer.
1708
  
1709
131
  AutoPtr<dng_memory_block> buffer (host.Allocate (
1710
131
    SafeUint32Add(tablesByteCount, tileByteCount)));
1711
                            
1712
  // Read in table.
1713
  
1714
131
  if (tablesByteCount)
1715
40
    {
1716
    
1717
40
    DoCopyBytes (tablesBlock->Buffer (),
1718
40
           buffer->Buffer (),
1719
40
           tablesByteCount);
1720
    
1721
40
    }
1722
    
1723
  // Read in tile data.
1724
  
1725
131
  stream.SetReadPosition (tileOffset);
1726
  
1727
131
  stream.Get (buffer->Buffer_uint8 () + tablesByteCount, tileByteCount);
1728
    
1729
  // Patch first byte, if required.
1730
    
1731
131
  if (patchFirstByte)
1732
0
    {
1733
    
1734
0
    buffer->Buffer_uint8 () [0] = 0xFF;
1735
    
1736
0
    }
1737
    
1738
  // Return buffer.
1739
  
1740
131
  return buffer.Release ();
1741
  
1742
131
  }
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
189
  {
1756
  
1757
  // Setup the data source.
1758
  
1759
189
  if (fJPEGTables.Get () || !jpegDataInMemory)
1760
131
    {
1761
    
1762
131
    AutoPtr<dng_memory_block> jpegDataBlock;
1763
  
1764
131
    jpegDataBlock.Reset (ReadJPEGDataToBlock (host,
1765
131
                          stream,
1766
131
                          fJPEGTables.Get (),
1767
131
                          stream.Position (),
1768
131
                          tileByteCount,
1769
131
                          ifd.fPatchFirstJPEGByte));
1770
                          
1771
131
    DecodeLossyJPEG (host,
1772
131
             image,
1773
131
             tileArea,
1774
131
             plane,
1775
131
             planes,
1776
131
             ifd.fPhotometricInterpretation,
1777
131
             jpegDataBlock->LogicalSize (),
1778
131
             jpegDataBlock->Buffer_uint8 ());
1779
    
1780
131
    }
1781
    
1782
58
  else
1783
58
    {
1784
  
1785
58
    if (ifd.fPatchFirstJPEGByte && tileByteCount)
1786
0
      {
1787
0
      jpegDataInMemory [0] = 0xFF;
1788
0
      }
1789
1790
58
    DecodeLossyJPEG (host,
1791
58
             image,
1792
58
             tileArea,
1793
58
             plane,
1794
58
             planes,
1795
58
             ifd.fPhotometricInterpretation,
1796
58
             tileByteCount,
1797
58
             jpegDataInMemory);
1798
    
1799
58
    }
1800
        
1801
189
  return true;
1802
  
1803
189
  }
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
10.0k
  {
1818
  
1819
  // If the tile area is empty, there's nothing to read.
1820
10.0k
  if (tileArea.IsEmpty ())
1821
4.66k
    {
1822
4.66k
    return true;
1823
4.66k
    }
1824
  
1825
5.38k
  uint32 bytesPerRow = SafeUint32Mult (tileArea.W(), planes, 
1826
5.38k
    static_cast<uint32> (sizeof (uint16)));
1827
  
1828
5.38k
  uint32 rowsPerStrip = Pin_uint32 (ifd.fSubTileBlockRows,
1829
5.38k
                    kImageBufferSize / bytesPerRow,
1830
5.38k
                    tileArea.H ());
1831
                    
1832
5.38k
  rowsPerStrip = rowsPerStrip / ifd.fSubTileBlockRows
1833
5.38k
                * ifd.fSubTileBlockRows;
1834
                    
1835
5.38k
  uint32 bufferSize = SafeUint32Mult (bytesPerRow, rowsPerStrip);
1836
  
1837
5.38k
  if (uncompressedBuffer.Get () &&
1838
192
    uncompressedBuffer->LogicalSize () < bufferSize)
1839
0
    {
1840
    
1841
0
    uncompressedBuffer.Reset ();
1842
    
1843
0
    }
1844
    
1845
5.38k
  if (uncompressedBuffer.Get () == NULL)
1846
5.18k
    {
1847
    
1848
5.18k
    uncompressedBuffer.Reset (host.Allocate (bufferSize));
1849
                  
1850
5.18k
    }
1851
  
1852
5.38k
  dng_image_spooler spooler (host,
1853
5.38k
                 ifd,
1854
5.38k
                 image,
1855
5.38k
                 tileArea,
1856
5.38k
                 plane,
1857
5.38k
                 planes,
1858
5.38k
                 *uncompressedBuffer.Get (),
1859
5.38k
                 subTileBlockBuffer);
1860
                 
1861
5.38k
  uint32 decodedSize = SafeUint32Mult(tileArea.W (),
1862
5.38k
             tileArea.H (),
1863
5.38k
             planes, (uint32) sizeof (uint16));
1864
              
1865
5.38k
  bool bug16 = ifd.fLosslessJPEGBug16;
1866
  
1867
5.38k
  uint64 tileOffset = stream.Position ();
1868
  
1869
5.38k
  DecodeLosslessJPEG (stream,
1870
5.38k
              spooler,
1871
5.38k
              decodedSize,
1872
5.38k
              decodedSize,
1873
5.38k
            bug16);
1874
            
1875
5.38k
  if (stream.Position () > tileOffset + tileByteCount)
1876
511
    {
1877
511
    ThrowBadFormat ();
1878
511
    }
1879
1880
5.38k
  return true;
1881
  
1882
10.0k
  }
1883
  
1884
/*****************************************************************************/
1885
1886
bool dng_read_image::CanReadTile (const dng_ifd &ifd)
1887
11.7k
  {
1888
  
1889
11.7k
  if (ifd.fSampleFormat [0] != sfUnsignedInteger &&
1890
952
    ifd.fSampleFormat [0] != sfFloatingPoint)
1891
156
    {
1892
156
    return false;
1893
156
    }
1894
1895
11.5k
  switch (ifd.fCompression)
1896
11.5k
    {
1897
    
1898
9.94k
    case ccUncompressed:
1899
9.94k
      {
1900
      
1901
9.94k
      if (ifd.fSampleFormat [0] == sfFloatingPoint)
1902
588
        {
1903
        
1904
588
        return (ifd.fBitsPerSample [0] == 16 ||
1905
360
            ifd.fBitsPerSample [0] == 24 ||
1906
24
            ifd.fBitsPerSample [0] == 32);
1907
            
1908
588
        }
1909
        
1910
9.35k
      return ifd.fBitsPerSample [0] >= 8 &&
1911
9.29k
           ifd.fBitsPerSample [0] <= 32;
1912
      
1913
9.94k
      }
1914
      
1915
76
    case ccJPEG:
1916
76
      {
1917
      
1918
76
      if (ifd.fSampleFormat [0] != sfUnsignedInteger)
1919
4
        {
1920
4
        return false;
1921
4
        }
1922
        
1923
72
      if (ifd.IsBaselineJPEG ())
1924
12
        {
1925
        
1926
        // Baseline JPEG.
1927
        
1928
12
        return true;
1929
        
1930
12
        }
1931
        
1932
60
      else
1933
60
        {
1934
        
1935
        // Lossless JPEG.
1936
        
1937
60
        return ifd.fBitsPerSample [0] >= 8 &&
1938
56
             ifd.fBitsPerSample [0] <= 16;
1939
        
1940
60
        }
1941
        
1942
0
      break;
1943
      
1944
72
      }
1945
1946
12
    case ccLZW:
1947
1.22k
    case ccDeflate:
1948
1.23k
    case ccOldDeflate:
1949
1.25k
    case ccPackBits:
1950
1.25k
      {
1951
      
1952
1.25k
      if (ifd.fSampleFormat [0] == sfFloatingPoint)
1953
200
        {
1954
        
1955
200
        if (ifd.fCompression == ccPackBits)
1956
4
          {
1957
4
          return false;
1958
4
          }
1959
        
1960
196
        if (ifd.fPredictor != cpNullPredictor   &&
1961
152
          ifd.fPredictor != cpFloatingPoint   &&
1962
136
          ifd.fPredictor != cpFloatingPointX2 &&
1963
132
          ifd.fPredictor != cpFloatingPointX4)
1964
128
          {
1965
128
          return false;
1966
128
          }
1967
          
1968
68
        if (ifd.fBitsPerSample [0] != 16 &&
1969
28
          ifd.fBitsPerSample [0] != 24 &&
1970
24
          ifd.fBitsPerSample [0] != 32)
1971
12
          {
1972
12
          return false;
1973
12
          }
1974
        
1975
68
        }
1976
        
1977
1.05k
      else
1978
1.05k
        {
1979
1980
1.05k
        if (ifd.fPredictor != cpNullPredictor       &&
1981
412
          ifd.fPredictor != cpHorizontalDifference   &&
1982
200
          ifd.fPredictor != cpHorizontalDifferenceX2 &&
1983
192
          ifd.fPredictor != cpHorizontalDifferenceX4)
1984
160
          {
1985
160
          return false;
1986
160
          }
1987
          
1988
892
        if (ifd.fBitsPerSample [0] != 8  &&
1989
760
          ifd.fBitsPerSample [0] != 16 &&
1990
148
          ifd.fBitsPerSample [0] != 32)
1991
32
          {
1992
32
          return false;
1993
32
          }
1994
          
1995
892
        }
1996
          
1997
916
      return true;
1998
      
1999
1.25k
      }
2000
      
2001
312
    default:
2002
312
      {
2003
312
      break;
2004
1.25k
      }
2005
      
2006
11.5k
    }
2007
    
2008
312
  return false;
2009
2010
11.5k
  }
2011
  
2012
/*****************************************************************************/
2013
2014
bool dng_read_image::NeedsCompressedBuffer (const dng_ifd &ifd)
2015
37.1k
  {
2016
  
2017
37.1k
  if (ifd.fCompression == ccLZW        ||
2018
37.1k
    ifd.fCompression == ccDeflate    ||
2019
34.7k
    ifd.fCompression == ccOldDeflate ||
2020
34.7k
    ifd.fCompression == ccPackBits)
2021
2.43k
    {
2022
2.43k
    return true;
2023
2.43k
    }
2024
    
2025
34.7k
  return false;
2026
  
2027
37.1k
  }
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.57k
  {
2073
  
2074
2.57k
  switch (ifd.fPredictor)
2075
2.57k
    {
2076
    
2077
2.10k
    case cpNullPredictor:
2078
2.10k
      {
2079
      
2080
2.10k
      return;
2081
      
2082
0
      }
2083
    
2084
272
    case cpHorizontalDifference:
2085
381
    case cpHorizontalDifferenceX2:
2086
461
    case cpHorizontalDifferenceX4:
2087
461
      {
2088
      
2089
461
      int32 xFactor = 1;
2090
      
2091
461
      if (ifd.fPredictor == cpHorizontalDifferenceX2)
2092
109
        {
2093
109
        xFactor = 2;
2094
109
        }
2095
        
2096
352
      else if (ifd.fPredictor == cpHorizontalDifferenceX4)
2097
80
        {
2098
80
        xFactor = 4;
2099
80
        }
2100
      
2101
461
      switch (buffer.fPixelType)
2102
461
        {
2103
        
2104
246
        case ttByte:
2105
246
          {
2106
          
2107
246
          DecodeDelta8 ((uint8 *) buffer.fData,
2108
246
                  buffer.fArea.H (),
2109
246
                  buffer.fArea.W () / xFactor,
2110
246
                  buffer.fPlanes    * xFactor);
2111
          
2112
246
          return;
2113
          
2114
0
          }
2115
          
2116
139
        case ttShort:
2117
139
          {
2118
          
2119
139
          DecodeDelta16 ((uint16 *) buffer.fData,
2120
139
                   buffer.fArea.H (),
2121
139
                   buffer.fArea.W () / xFactor,
2122
139
                   buffer.fPlanes    * xFactor);
2123
          
2124
139
          return;
2125
          
2126
0
          }
2127
          
2128
76
        case ttLong:
2129
76
          {
2130
          
2131
76
          DecodeDelta32 ((uint32 *) buffer.fData,
2132
76
                   buffer.fArea.H (),
2133
76
                   buffer.fArea.W () / xFactor,
2134
76
                   buffer.fPlanes    * xFactor);
2135
          
2136
76
          return;
2137
          
2138
0
          }
2139
          
2140
0
        default:
2141
0
          break;
2142
          
2143
461
        }
2144
      
2145
0
      break;
2146
      
2147
461
      }
2148
      
2149
0
    default:
2150
0
      break;
2151
    
2152
2.57k
    }
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.4k
  {
2172
  
2173
42.4k
  switch (ifd.fCompression)
2174
42.4k
    {
2175
    
2176
0
    case ccLZW:
2177
2.91k
    case ccDeflate:
2178
2.91k
    case ccOldDeflate:
2179
2.91k
    case ccPackBits:
2180
2.91k
      {
2181
      
2182
      // Figure out uncompressed size.
2183
      
2184
2.91k
      uint32 bytesPerSample = (ifd.fBitsPerSample [0] >> 3);
2185
      
2186
2.91k
      uint32 rowStep = 0;
2187
      
2188
2.91k
      uint32 sampleCount = 0;
2189
        
2190
2.91k
      if (!SafeUint32Mult (planes, tileArea.W (), &rowStep) ||
2191
2.90k
         !SafeUint32Mult (rowStep, tileArea.H (), &sampleCount))
2192
40
        {
2193
        
2194
40
        ThrowMemoryFull ("Arithmetic overflow computing sample count.");
2195
        
2196
40
        }
2197
        
2198
      // Setup pixel buffer to hold uncompressed data.
2199
      
2200
2.91k
      uint32 pixelType = ttUndefined;
2201
      
2202
2.91k
      if (ifd.fSampleFormat [0] == sfFloatingPoint)
2203
318
        {
2204
318
        pixelType = ttFloat;
2205
318
        }
2206
      
2207
2.60k
      else if (ifd.fBitsPerSample [0] == 8)
2208
1.11k
        {
2209
1.11k
        pixelType = ttByte;
2210
1.11k
        }
2211
        
2212
1.48k
      else if (ifd.fBitsPerSample [0] == 16)
2213
1.06k
        {
2214
1.06k
        pixelType = ttShort;
2215
1.06k
        }
2216
        
2217
417
      else if (ifd.fBitsPerSample [0] == 32)
2218
311
        {
2219
311
        pixelType = ttLong;
2220
311
        }
2221
        
2222
106
      else
2223
106
        {
2224
106
        ThrowBadFormat ();
2225
106
        }
2226
        
2227
2.91k
      uint32 uncompressedSize = ComputeBufferSize (pixelType, tileArea.Size(),
2228
2.91k
         planes, padNone);
2229
      
2230
2.91k
      dng_pixel_buffer buffer (tileArea, plane, planes, pixelType, pcInterleaved,
2231
2.91k
         NULL);
2232
      
2233
2.91k
      uint32 bufferSize = uncompressedSize;
2234
      
2235
      // If we are using the floating point predictor, we need an extra
2236
      // buffer row.
2237
      
2238
2.91k
      if (ifd.fPredictor == cpFloatingPoint   ||
2239
2.71k
        ifd.fPredictor == cpFloatingPointX2 ||
2240
2.71k
        ifd.fPredictor == cpFloatingPointX4)
2241
73
        {
2242
73
        uint32 rowSize = 0;
2243
73
        if (!SafeUint32Mult (rowStep, buffer.fPixelSize, &rowSize) ||
2244
73
           !SafeUint32Add (bufferSize, rowSize, &bufferSize))
2245
0
          {
2246
          
2247
0
          ThrowMemoryFull ("Arithmetic overflow computing buffer size.");
2248
          
2249
0
          }
2250
73
        }
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.91k
      if (buffer.fPixelType == ttFloat)
2256
318
        {
2257
318
        bufferSize = Max_uint32 (bufferSize,
2258
318
                     SafeUint32Mult(sampleCount, 4));
2259
318
        }
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.91k
      if (uncompressedBuffer.Get () &&
2266
502
        uncompressedBuffer->LogicalSize () < bufferSize)
2267
0
        {
2268
        
2269
0
        uncompressedBuffer.Reset ();
2270
        
2271
0
        }
2272
        
2273
2.91k
      if (uncompressedBuffer.Get () == NULL)
2274
2.28k
        {
2275
2276
2.28k
        uncompressedBuffer.Reset (host.Allocate (bufferSize));
2277
                      
2278
2.28k
        }
2279
        
2280
2.91k
      buffer.fData = uncompressedBuffer->Buffer ();
2281
      
2282
      // If using floating point predictor, move buffer pointer to second row.
2283
      
2284
2.91k
      if (ifd.fPredictor == cpFloatingPoint   ||
2285
2.71k
        ifd.fPredictor == cpFloatingPointX2 ||
2286
2.71k
        ifd.fPredictor == cpFloatingPointX4)
2287
73
        {
2288
        
2289
73
        buffer.fData = (uint8 *) buffer.fData +
2290
73
                 buffer.fRowStep * buffer.fPixelSize;
2291
                 
2292
73
        }
2293
      
2294
      // Decompress the data.
2295
      
2296
2.91k
      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.91k
      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.91k
      else
2327
2.91k
        {
2328
        
2329
2.91k
        uLongf dstLen = uncompressedSize;
2330
              
2331
2.91k
        int err = uncompress ((Bytef *) buffer.fData,
2332
2.91k
                    &dstLen,
2333
2.91k
                    (const Bytef *) compressedBuffer->Buffer (),
2334
2.91k
                    tileByteCount);
2335
                    
2336
2.91k
        if (err != Z_OK)
2337
2.78k
          {
2338
          
2339
2.78k
          if (err == Z_MEM_ERROR)
2340
0
            {
2341
0
            ThrowMemoryFull ();
2342
0
            }
2343
            
2344
2.78k
          else if (err == Z_DATA_ERROR)
2345
2.78k
            {
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.78k
            }
2351
            
2352
0
          else
2353
0
            {
2354
0
            ThrowBadFormat ();
2355
0
            }
2356
            
2357
2.78k
          }
2358
          
2359
2.91k
        if (dstLen != uncompressedSize)
2360
169
          {
2361
169
          ThrowBadFormat ();
2362
169
          }
2363
        
2364
2.91k
        }
2365
        
2366
      // The floating point predictor is byte order independent.
2367
      
2368
2.91k
      if (ifd.fPredictor == cpFloatingPoint   ||
2369
2.57k
        ifd.fPredictor == cpFloatingPointX2 ||
2370
2.57k
        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
0
          {
2382
0
          xFactor = 4;
2383
0
          }
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.87k
      else
2412
2.87k
        {
2413
        
2414
        // Both these compression algorithms are byte based.
2415
        
2416
2.87k
        if (stream.SwapBytes ())
2417
0
          {
2418
          
2419
0
          ByteSwapBuffer (host,
2420
0
                  buffer);
2421
                  
2422
0
          }
2423
          
2424
        // Undo the predictor.
2425
        
2426
2.87k
        DecodePredictor (host,
2427
2.87k
                 ifd,
2428
2.87k
                 buffer);
2429
                 
2430
2.87k
        }
2431
        
2432
      // Expand floating point data, if needed.
2433
      
2434
2.91k
      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.91k
      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.91k
      image.Put (buffer);
2500
      
2501
2.91k
      return;
2502
      
2503
2.91k
      }
2504
  
2505
29.2k
    case ccUncompressed:
2506
29.2k
      {
2507
      
2508
29.2k
      if (ReadUncompressed (host,
2509
29.2k
                  ifd,
2510
29.2k
                  stream,
2511
29.2k
                  image,
2512
29.2k
                  tileArea,
2513
29.2k
                  plane,
2514
29.2k
                  planes,
2515
29.2k
                  uncompressedBuffer,
2516
29.2k
                  subTileBlockBuffer))
2517
26.1k
        {
2518
        
2519
26.1k
        return;
2520
        
2521
26.1k
        }
2522
        
2523
3.11k
      break;
2524
      
2525
29.2k
      }
2526
      
2527
10.0k
    case ccJPEG:
2528
10.0k
      {
2529
      
2530
10.0k
      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
10.0k
      else
2553
10.0k
        {
2554
        
2555
        // Otherwise is should be lossless JPEG.
2556
        
2557
10.0k
        if (ReadLosslessJPEG (host,
2558
10.0k
                    ifd,
2559
10.0k
                    stream,
2560
10.0k
                    image,
2561
10.0k
                    tileArea,
2562
10.0k
                    plane,
2563
10.0k
                    planes,
2564
10.0k
                    tileByteCount,
2565
10.0k
                    uncompressedBuffer,
2566
10.0k
                    subTileBlockBuffer))
2567
4.89k
          {
2568
          
2569
4.89k
          return;
2570
          
2571
4.89k
          }
2572
        
2573
10.0k
        }
2574
      
2575
5.16k
      break;
2576
      
2577
10.0k
      }
2578
      
2579
5.16k
    case ccLossyJPEG:
2580
189
      {
2581
      
2582
189
      if (ReadBaselineJPEG (host,
2583
189
                  ifd,
2584
189
                  stream,
2585
189
                  image,
2586
189
                  tileArea,
2587
189
                  plane,
2588
189
                  planes,
2589
189
                  tileByteCount,
2590
189
                  compressedBuffer.Get () ? compressedBuffer->Buffer_uint8 () : NULL))
2591
0
        {
2592
        
2593
0
        return;
2594
        
2595
0
        }
2596
              
2597
189
      break;
2598
      
2599
189
      }
2600
      
2601
189
    default:
2602
0
      break;
2603
      
2604
42.4k
    }
2605
    
2606
0
  ThrowBadFormat ();
2607
    
2608
0
  }
2609
2610
/*****************************************************************************/
2611
2612
bool dng_read_image::CanRead (const dng_ifd &ifd)
2613
30.8k
  {
2614
  
2615
30.8k
  if (ifd.fImageWidth  < 1 ||
2616
21.0k
    ifd.fImageLength < 1)
2617
13.1k
    {
2618
13.1k
    return false;
2619
13.1k
    }
2620
    
2621
17.6k
  if (ifd.fSamplesPerPixel < 1)
2622
12
    {
2623
12
    return false;
2624
12
    }
2625
    
2626
17.6k
  if (ifd.fBitsPerSample [0] < 1)
2627
1.68k
    {
2628
1.68k
    return false;
2629
1.68k
    }
2630
  
2631
17.1k
  for (uint32 j = 1; j < Min_uint32 (ifd.fSamplesPerPixel,
2632
17.1k
                     kMaxSamplesPerPixel); j++)
2633
1.32k
    {
2634
    
2635
1.32k
    if (ifd.fBitsPerSample [j] !=
2636
1.32k
      ifd.fBitsPerSample [0])
2637
88
      {
2638
88
      return false;
2639
88
      }
2640
      
2641
1.23k
    if (ifd.fSampleFormat [j] !=
2642
1.23k
      ifd.fSampleFormat [0])
2643
44
      {
2644
44
      return false;
2645
44
      }
2646
2647
1.23k
    }
2648
    
2649
15.8k
  if ((ifd.fPlanarConfiguration != pcInterleaved   ) &&
2650
100
    (ifd.fPlanarConfiguration != pcPlanar        ) &&
2651
92
    (ifd.fPlanarConfiguration != pcRowInterleaved))
2652
84
    {
2653
84
    return false;
2654
84
    }
2655
    
2656
15.7k
  if (ifd.fUsesStrips == ifd.fUsesTiles)
2657
348
    {
2658
348
    return false;
2659
348
    }
2660
    
2661
15.4k
  uint32 tileCount = ifd.TilesPerImage ();
2662
  
2663
15.4k
  if (tileCount < 1)
2664
4
    {
2665
4
    return false;
2666
4
    }
2667
    
2668
15.4k
  bool needTileByteCounts = (ifd.TileByteCount (ifd.TileArea (0, 0)) == 0);
2669
    
2670
15.4k
  if (tileCount == 1)
2671
11.8k
    {
2672
    
2673
11.8k
    if (needTileByteCounts)
2674
1.80k
      {
2675
      
2676
1.80k
      if (ifd.fTileByteCount [0] < 1)
2677
176
        {
2678
176
        return false;
2679
176
        }
2680
      
2681
1.80k
      }
2682
    
2683
11.8k
    }
2684
    
2685
3.60k
  else
2686
3.60k
    {
2687
    
2688
3.60k
    if (ifd.fTileOffsetsCount != tileCount)
2689
164
      {
2690
164
      return false;
2691
164
      }
2692
      
2693
3.43k
    if (needTileByteCounts)
2694
40
      {
2695
      
2696
40
      if (ifd.fTileByteCountsCount != tileCount)
2697
4
        {
2698
4
        return false;
2699
4
        }
2700
      
2701
40
      }
2702
    
2703
3.43k
    }
2704
    
2705
15.0k
  if (!CanReadTile (ifd))
2706
892
    {
2707
892
    return false;
2708
892
    }
2709
    
2710
14.1k
  return true;
2711
  
2712
15.0k
  }
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.2k
  {
2921
  
2922
39.2k
  uint32 tileIndex;
2923
  
2924
  // Deal with row interleaved images.
2925
  
2926
39.2k
  if (ifd.fRowInterleaveFactor > 1 &&
2927
221
    ifd.fRowInterleaveFactor < ifd.fImageLength)
2928
205
    {
2929
    
2930
205
    dng_ifd tempIFD (ifd);
2931
    
2932
205
    tempIFD.fRowInterleaveFactor = 1;
2933
    
2934
205
    dng_row_interleaved_image tempImage (image,
2935
205
                       ifd.fRowInterleaveFactor);
2936
    
2937
205
    Read (host,
2938
205
        tempIFD,
2939
205
        stream,
2940
205
        tempImage,
2941
205
        jpegImage,
2942
205
        jpegDigest);
2943
        
2944
205
    return;
2945
    
2946
205
    }
2947
  
2948
  // Figure out inner and outer samples.
2949
  
2950
39.0k
  uint32 innerSamples = 1;
2951
39.0k
  uint32 outerSamples = 1;
2952
  
2953
39.0k
  if (ifd.fPlanarConfiguration == pcPlanar)
2954
0
    {
2955
0
    outerSamples = ifd.fSamplesPerPixel;
2956
0
    }
2957
39.0k
  else
2958
39.0k
    {
2959
39.0k
    innerSamples = ifd.fSamplesPerPixel;
2960
39.0k
    }
2961
  
2962
  // Calculate number of tiles to read.
2963
  
2964
39.0k
  uint32 tilesAcross = ifd.TilesAcross ();
2965
39.0k
  uint32 tilesDown   = ifd.TilesDown   ();
2966
  
2967
39.0k
  uint32 tileCount = SafeUint32Mult (tilesAcross, tilesDown, outerSamples);
2968
  
2969
  // Find the tile offsets.
2970
    
2971
39.0k
  dng_memory_data tileOffsetData (tileCount, sizeof (uint64));
2972
  
2973
39.0k
  uint64 *tileOffset = tileOffsetData.Buffer_uint64 ();
2974
  
2975
39.0k
  if (tileCount <= dng_ifd::kMaxTileInfo)
2976
39.0k
    {
2977
    
2978
90.2k
    for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
2979
51.2k
      {
2980
      
2981
51.2k
      tileOffset [tileIndex] = ifd.fTileOffset [tileIndex];
2982
      
2983
51.2k
      }
2984
    
2985
39.0k
    }
2986
    
2987
32
  else
2988
32
    {
2989
    
2990
32
    stream.SetReadPosition (ifd.fTileOffsetsOffset);
2991
    
2992
32
    for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
2993
0
      {
2994
      
2995
0
      tileOffset [tileIndex] = stream.TagValue_uint32 (ifd.fTileOffsetsType);
2996
      
2997
0
      }
2998
    
2999
32
    }
3000
    
3001
  // Quick validity check on tile offsets.
3002
  
3003
89.3k
  for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3004
50.2k
    {
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
50.2k
    if (tileOffset [tileIndex] >= stream.Length ())
3018
1.15k
      {
3019
      
3020
1.15k
      ThrowBadFormat ();
3021
      
3022
1.15k
      }
3023
    
3024
50.2k
    }
3025
    
3026
  // Buffer to hold the tile byte counts, if needed.
3027
  
3028
39.0k
  dng_memory_data tileByteCountData;
3029
  
3030
39.0k
  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.0k
  uint32 uncompressedSize = 0;
3036
3037
39.0k
  uint32 subTileLength = ifd.fTileLength;
3038
  
3039
39.0k
  if (ifd.TileByteCount (ifd.TileArea (0, 0)) != 0)
3040
26.1k
    {
3041
    
3042
26.1k
    uint32 bytesPerPixel = TagTypeSize (ifd.PixelType ());
3043
    
3044
26.1k
    uint32 bytesPerRow = SafeUint32Mult (ifd.fTileWidth, innerSamples,
3045
26.1k
                       bytesPerPixel);
3046
        
3047
26.1k
    subTileLength = Pin_uint32 (ifd.fSubTileBlockRows,
3048
26.1k
                  kImageBufferSize / bytesPerRow, 
3049
26.1k
                  ifd.fTileLength);
3050
                  
3051
26.1k
    subTileLength = subTileLength / ifd.fSubTileBlockRows
3052
26.1k
                    * ifd.fSubTileBlockRows;
3053
                    
3054
26.1k
    uncompressedSize = SafeUint32Mult (subTileLength, bytesPerRow);
3055
                  
3056
26.1k
    }
3057
    
3058
  // Else we need to know the byte counts.
3059
  
3060
12.8k
  else
3061
12.8k
    {
3062
    
3063
12.8k
    tileByteCountData.Allocate (tileCount, sizeof (uint32));
3064
    
3065
12.8k
    tileByteCount = tileByteCountData.Buffer_uint32 ();
3066
    
3067
12.8k
    if (tileCount <= dng_ifd::kMaxTileInfo)
3068
11.6k
      {
3069
      
3070
33.8k
      for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3071
22.1k
        {
3072
        
3073
22.1k
        tileByteCount [tileIndex] = ifd.fTileByteCount [tileIndex];
3074
        
3075
22.1k
        }
3076
      
3077
11.6k
      }
3078
      
3079
1.24k
    else
3080
1.24k
      {
3081
      
3082
1.24k
      stream.SetReadPosition (ifd.fTileByteCountsOffset);
3083
      
3084
1.24k
      for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3085
0
        {
3086
        
3087
0
        tileByteCount [tileIndex] = stream.TagValue_uint32 (ifd.fTileByteCountsType);
3088
        
3089
0
        }
3090
      
3091
1.24k
      }
3092
      
3093
    // Quick validity check on tile byte counts.
3094
    
3095
33.6k
    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
675
        {
3101
        
3102
675
        ThrowBadFormat ();
3103
        
3104
675
        }
3105
      
3106
20.7k
      }
3107
    
3108
12.8k
    }
3109
    
3110
  // Find maximum tile size, if possible.
3111
    
3112
39.0k
  uint32 maxTileByteCount = 0;
3113
  
3114
39.0k
  if (tileByteCount)
3115
10.9k
    {
3116
    
3117
31.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
10.9k
    }
3126
    
3127
  // Do we need a compressed data buffer?
3128
3129
39.0k
  uint32 compressedSize = 0;
3130
  
3131
39.0k
  bool needsCompressedBuffer = NeedsCompressedBuffer (ifd);
3132
  
3133
39.0k
  if (needsCompressedBuffer)
3134
2.43k
    {
3135
    
3136
2.43k
    if (!tileByteCount)
3137
0
      {
3138
0
      ThrowBadFormat ();
3139
0
      }
3140
    
3141
2.43k
    compressedSize = maxTileByteCount;
3142
    
3143
2.43k
    }
3144
    
3145
  // Are we keeping the compressed JPEG image data?
3146
  
3147
39.0k
  if (jpegImage)
3148
393
    {
3149
    
3150
393
    if (ifd.IsBaselineJPEG ())
3151
393
      {
3152
      
3153
393
      jpegImage->fImageSize.h = ifd.fImageWidth;
3154
393
      jpegImage->fImageSize.v = ifd.fImageLength;
3155
      
3156
393
      jpegImage->fTileSize.h = ifd.fTileWidth;
3157
393
      jpegImage->fTileSize.v = ifd.fTileLength;
3158
      
3159
393
      jpegImage->fUsesStrips = ifd.fUsesStrips;
3160
      
3161
393
      jpegImage->fJPEGData.Reset (tileCount);
3162
            
3163
393
      }
3164
      
3165
0
    else
3166
0
      {
3167
      
3168
0
      jpegImage = NULL;
3169
      
3170
0
      }
3171
    
3172
393
    }
3173
    
3174
  // Do we need to read the JPEG tables?
3175
  
3176
39.0k
  if (ifd.fJPEGTablesOffset && ifd.fJPEGTablesCount)
3177
1.07k
    {
3178
  
3179
1.07k
    if (ifd.IsBaselineJPEG ())
3180
154
      {
3181
      
3182
154
      fJPEGTables.Reset (host.Allocate (ifd.fJPEGTablesCount));
3183
      
3184
154
      stream.SetReadPosition (ifd.fJPEGTablesOffset);
3185
      
3186
154
      stream.Get (fJPEGTables->Buffer      (),
3187
154
            fJPEGTables->LogicalSize ());
3188
      
3189
154
      }
3190
      
3191
1.07k
    }
3192
    
3193
39.0k
  AutoArray<dng_fingerprint> jpegTileDigest;
3194
  
3195
39.0k
  if (jpegDigest)
3196
418
    {
3197
    
3198
418
    jpegTileDigest.Reset (
3199
418
      SafeUint32Add(tileCount, (fJPEGTables.Get () ? 1 : 0)));
3200
    
3201
418
    }
3202
      
3203
  // Don't read planes we are not actually saving.
3204
  
3205
39.0k
  outerSamples = Min_uint32 (image.Planes (), outerSamples);
3206
    
3207
  // See if we can do this read using multiple threads.
3208
  
3209
39.0k
  bool useMultipleThreads = (outerSamples * tilesDown * tilesAcross >= 2) &&
3210
3.24k
                (host.PerformAreaTaskThreads () > 1) &&
3211
0
                (maxTileByteCount > 0 && maxTileByteCount <= 1024 * 1024) &&
3212
0
                (subTileLength == ifd.fTileLength) &&
3213
0
                (ifd.fCompression != ccUncompressed);
3214
  
3215
#if qImagecore
3216
  useMultipleThreads = false; 
3217
#endif
3218
    
3219
39.0k
  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.0k
  else
3249
39.0k
    {
3250
    
3251
39.0k
    AutoPtr<dng_memory_block> compressedBuffer;
3252
39.0k
    AutoPtr<dng_memory_block> uncompressedBuffer;
3253
39.0k
    AutoPtr<dng_memory_block> subTileBlockBuffer;
3254
    
3255
39.0k
    if (uncompressedSize)
3256
26.1k
      {
3257
26.1k
      uncompressedBuffer.Reset (host.Allocate (uncompressedSize));
3258
26.1k
      }
3259
      
3260
39.0k
    if (compressedSize && !jpegImage)
3261
2.43k
      {
3262
2.43k
      compressedBuffer.Reset (host.Allocate (compressedSize));
3263
2.43k
      }
3264
      
3265
36.6k
    else if (jpegDigest)
3266
418
      {
3267
418
      compressedBuffer.Reset (host.Allocate (maxTileByteCount));
3268
418
      }
3269
      
3270
39.0k
    tileIndex = 0;
3271
    
3272
76.1k
    for (uint32 plane = 0; plane < outerSamples; plane++)
3273
37.1k
      {
3274
      
3275
78.4k
      for (uint32 rowIndex = 0; rowIndex < tilesDown; rowIndex++)
3276
41.3k
        {
3277
        
3278
83.1k
        for (uint32 colIndex = 0; colIndex < tilesAcross; colIndex++)
3279
41.8k
          {
3280
          
3281
41.8k
          stream.SetReadPosition (tileOffset [tileIndex]);
3282
          
3283
41.8k
          dng_rect tileArea = ifd.TileArea (rowIndex, colIndex);
3284
          
3285
41.8k
          uint32 subTileCount = (tileArea.H () + subTileLength - 1) /
3286
41.8k
                      subTileLength;
3287
                      
3288
84.3k
          for (uint32 subIndex = 0; subIndex < subTileCount; subIndex++)
3289
42.4k
            {
3290
            
3291
42.4k
            host.SniffForAbort ();
3292
          
3293
42.4k
            dng_rect subArea (tileArea);
3294
            
3295
42.4k
            subArea.t = tileArea.t + subIndex * subTileLength;
3296
            
3297
42.4k
            subArea.b = Min_int32 (subArea.t + subTileLength,
3298
42.4k
                         tileArea.b);
3299
            
3300
42.4k
            uint32 subByteCount;
3301
            
3302
42.4k
            if (tileByteCount)
3303
13.3k
              {
3304
13.3k
              subByteCount = tileByteCount [tileIndex];
3305
13.3k
              }
3306
29.1k
            else
3307
29.1k
              {
3308
29.1k
              subByteCount = ifd.TileByteCount (subArea);
3309
29.1k
              }
3310
              
3311
42.4k
            if (jpegImage)
3312
47
              {
3313
              
3314
47
              jpegImage->fJPEGData [tileIndex].Reset (host.Allocate (subByteCount));
3315
              
3316
47
              stream.Get (jpegImage->fJPEGData [tileIndex]->Buffer (), subByteCount);
3317
              
3318
47
              stream.SetReadPosition (tileOffset [tileIndex]);
3319
              
3320
47
              }
3321
              
3322
42.4k
            else if ((needsCompressedBuffer || jpegDigest) && subByteCount)
3323
3.00k
              {
3324
              
3325
3.00k
              stream.Get (compressedBuffer->Buffer (), subByteCount);
3326
              
3327
3.00k
              if (jpegDigest)
3328
57
                {
3329
                
3330
57
                dng_md5_printer printer;
3331
                
3332
57
                printer.Process (compressedBuffer->Buffer (),
3333
57
                         subByteCount);
3334
                         
3335
57
                jpegTileDigest [tileIndex] = printer.Result ();
3336
                
3337
57
                }
3338
              
3339
3.00k
              }
3340
              
3341
42.4k
            ReadTile (host,
3342
42.4k
                  ifd,
3343
42.4k
                  stream,
3344
42.4k
                  image,
3345
42.4k
                  subArea,
3346
42.4k
                  plane,
3347
42.4k
                  innerSamples,
3348
42.4k
                  subByteCount,
3349
42.4k
                  jpegImage ? jpegImage->fJPEGData [tileIndex] : compressedBuffer,
3350
42.4k
                  uncompressedBuffer,
3351
42.4k
                  subTileBlockBuffer);
3352
                  
3353
42.4k
            }
3354
          
3355
41.8k
          tileIndex++;
3356
          
3357
41.8k
          }
3358
          
3359
41.3k
        }
3360
3361
37.1k
      }
3362
      
3363
39.0k
    }
3364
    
3365
  // Finish up JPEG digest computation, if needed.
3366
  
3367
39.0k
  if (jpegDigest)
3368
354
    {
3369
    
3370
354
    if (fJPEGTables.Get ())
3371
19
      {
3372
      
3373
19
      dng_md5_printer printer;
3374
      
3375
19
      printer.Process (fJPEGTables->Buffer      (),
3376
19
               fJPEGTables->LogicalSize ());
3377
               
3378
19
      jpegTileDigest [tileCount] = printer.Result ();
3379
      
3380
19
      }
3381
      
3382
354
    dng_md5_printer printer2;
3383
    
3384
727
    for (uint32 j = 0; j < tileCount + (fJPEGTables.Get () ? 1 : 0); j++)
3385
373
      {
3386
      
3387
373
      printer2.Process (jpegTileDigest [j].data,
3388
373
                dng_fingerprint::kDNGFingerprintSize);
3389
                
3390
373
      }
3391
      
3392
354
    *jpegDigest = printer2.Result ();
3393
    
3394
354
    }
3395
    
3396
  // Keep the JPEG table in the jpeg image, if any.
3397
  
3398
39.0k
  if (jpegImage)
3399
339
    {
3400
    
3401
339
    jpegImage->fJPEGTables.Reset (fJPEGTables.Release ());
3402
    
3403
339
    }
3404
3405
39.0k
  }
3406
3407
/*****************************************************************************/