Coverage Report

Created: 2025-01-23 06:27

/src/dng_sdk/source/dng_read_image.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************/
2
// Copyright 2006-2012 Adobe Systems Incorporated
3
// All Rights Reserved.
4
//
5
// NOTICE:  Adobe permits you to use, modify, and distribute this file in
6
// accordance with the terms of the Adobe license agreement accompanying it.
7
/*****************************************************************************/
8
9
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_read_image.cpp#7 $ */ 
10
/* $DateTime: 2012/07/31 22:04:34 $ */
11
/* $Change: 840853 $ */
12
/* $Author: tknoll $ */
13
14
/*****************************************************************************/
15
16
#include "dng_read_image.h"
17
18
#include "dng_abort_sniffer.h"
19
#include "dng_area_task.h"
20
#include "dng_bottlenecks.h"
21
#include "dng_exceptions.h"
22
#include "dng_flags.h"
23
#include "dng_host.h"
24
#include "dng_image.h"
25
#include "dng_ifd.h"
26
#include "dng_jpeg_image.h"
27
#include "dng_lossless_jpeg.h"
28
#include "dng_mutex.h"
29
#include "dng_memory.h"
30
#include "dng_pixel_buffer.h"
31
#include "dng_safe_arithmetic.h"
32
#include "dng_tag_types.h"
33
#include "dng_tag_values.h"
34
#include "dng_utils.h"
35
36
#include "zlib.h"
37
38
#if qDNGUseLibJPEG
39
#include "dng_jpeg_memory_source.h"
40
#include "dng_jpeglib.h"
41
#endif
42
43
#include <limits>
44
45
/******************************************************************************/
46
47
static void DecodeDelta8 (uint8 *dPtr,
48
              uint32 rows,
49
              uint32 cols,
50
              uint32 channels)
51
18
  {
52
  
53
18
  const uint32 dRowStep = cols * channels;
54
  
55
68.5k
  for (uint32 row = 0; row < rows; row++)
56
68.5k
    {
57
    
58
68.5k
    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
68.5k
    dPtr += dRowStep;
71
    
72
68.5k
    }
73
74
18
  }
75
76
/******************************************************************************/
77
78
static void DecodeDelta16 (uint16 *dPtr,
79
               uint32 rows,
80
               uint32 cols,
81
               uint32 channels)
82
2
  {
83
  
84
2
  const uint32 dRowStep = cols * channels;
85
  
86
2
  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
2
  }
106
  
107
/******************************************************************************/
108
109
static void DecodeDelta32 (uint32 *dPtr,
110
               uint32 rows,
111
               uint32 cols,
112
               uint32 channels)
113
0
  {
114
  
115
0
  const uint32 dRowStep = cols * channels;
116
  
117
0
  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
0
  }
137
  
138
/*****************************************************************************/
139
140
inline void DecodeDeltaBytes (uint8 *bytePtr, int32 cols, int32 channels)
141
0
  {
142
  
143
0
  if (channels == 1)
144
0
    {
145
    
146
0
    uint8 b0 = bytePtr [0];
147
    
148
0
    bytePtr += 1;
149
    
150
0
    for (int32 col = 1; col < cols; ++col)
151
0
      {
152
      
153
0
      b0 += bytePtr [0];
154
      
155
0
      bytePtr [0] = b0;
156
      
157
0
      bytePtr += 1;
158
159
0
      }
160
      
161
0
    }
162
  
163
0
  else if (channels == 3)
164
0
    {
165
    
166
0
    uint8 b0 = bytePtr [0];
167
0
    uint8 b1 = bytePtr [1];
168
0
    uint8 b2 = bytePtr [2];
169
    
170
0
    bytePtr += 3;
171
    
172
0
    for (int32 col = 1; col < cols; ++col)
173
0
      {
174
      
175
0
      b0 += bytePtr [0];
176
0
      b1 += bytePtr [1];
177
0
      b2 += bytePtr [2];
178
      
179
0
      bytePtr [0] = b0;
180
0
      bytePtr [1] = b1;
181
0
      bytePtr [2] = b2;
182
      
183
0
      bytePtr += 3;
184
185
0
      }
186
      
187
0
    }
188
    
189
0
  else if (channels == 4)
190
0
    {
191
    
192
0
    uint8 b0 = bytePtr [0];
193
0
    uint8 b1 = bytePtr [1];
194
0
    uint8 b2 = bytePtr [2];
195
0
    uint8 b3 = bytePtr [3];
196
    
197
0
    bytePtr += 4;
198
    
199
0
    for (int32 col = 1; col < cols; ++col)
200
0
      {
201
      
202
0
      b0 += bytePtr [0];
203
0
      b1 += bytePtr [1];
204
0
      b2 += bytePtr [2];
205
0
      b3 += bytePtr [3];
206
      
207
0
      bytePtr [0] = b0;
208
0
      bytePtr [1] = b1;
209
0
      bytePtr [2] = b2;
210
0
      bytePtr [3] = b3;
211
      
212
0
      bytePtr += 4;
213
214
0
      }
215
      
216
0
    }
217
    
218
0
  else
219
0
    {
220
    
221
0
    for (int32 col = 1; col < cols; ++col)
222
0
      {
223
      
224
0
      for (int32 chan = 0; chan < channels; ++chan)
225
0
        {
226
        
227
0
        bytePtr [chan + channels] += bytePtr [chan];
228
        
229
0
        }
230
        
231
0
      bytePtr += channels;
232
233
0
      }
234
      
235
0
    }
236
237
0
  }
238
                
239
/*****************************************************************************/
240
241
static void DecodeFPDelta (uint8 *input,
242
               uint8 *output,
243
               int32 cols,
244
               int32 channels,
245
               int32 bytesPerSample)
246
0
  {
247
  
248
0
  DecodeDeltaBytes (input, cols * bytesPerSample, channels);
249
  
250
0
  int32 rowIncrement = cols * channels;
251
  
252
0
  if (bytesPerSample == 2)
253
0
    {
254
    
255
    #if qDNGBigEndian
256
    const uint8 *input0 = input;
257
    const uint8 *input1 = input + rowIncrement;
258
    #else
259
0
    const uint8 *input1 = input;
260
0
    const uint8 *input0 = input + rowIncrement;
261
0
    #endif
262
    
263
0
    for (int32 col = 0; col < rowIncrement; ++col)
264
0
      {
265
      
266
0
      output [0] = input0 [col];
267
0
      output [1] = input1 [col];
268
      
269
0
      output += 2;
270
        
271
0
      }
272
      
273
0
    }
274
    
275
0
  else if (bytesPerSample == 3)
276
0
    {
277
    
278
0
    const uint8 *input0 = input;
279
0
    const uint8 *input1 = input + rowIncrement;
280
0
    const uint8 *input2 = input + rowIncrement * 2;
281
    
282
0
    for (int32 col = 0; col < rowIncrement; ++col)
283
0
      {
284
      
285
0
      output [0] = input0 [col];
286
0
      output [1] = input1 [col];
287
0
      output [2] = input2 [col];
288
      
289
0
      output += 3;
290
        
291
0
      }
292
      
293
0
    }
294
    
295
0
  else
296
0
    {
297
    
298
    #if qDNGBigEndian
299
    const uint8 *input0 = input;
300
    const uint8 *input1 = input + rowIncrement;
301
    const uint8 *input2 = input + rowIncrement * 2;
302
    const uint8 *input3 = input + rowIncrement * 3;
303
    #else
304
0
    const uint8 *input3 = input;
305
0
    const uint8 *input2 = input + rowIncrement;
306
0
    const uint8 *input1 = input + rowIncrement * 2;
307
0
    const uint8 *input0 = input + rowIncrement * 3;
308
0
    #endif
309
    
310
0
    for (int32 col = 0; col < rowIncrement; ++col)
311
0
      {
312
      
313
0
      output [0] = input0 [col];
314
0
      output [1] = input1 [col];
315
0
      output [2] = input2 [col];
316
0
      output [3] = input3 [col];
317
      
318
0
      output += 4;
319
        
320
0
      }
321
      
322
0
    }
323
    
324
0
  }  
325
              
326
/*****************************************************************************/
327
328
bool DecodePackBits (dng_stream &stream,
329
           uint8 *dPtr,
330
           int32 dstCount)
331
0
  {
332
333
0
  while (dstCount > 0)
334
0
    {
335
    
336
0
    int32 runCount = (int8) stream.Get_uint8 ();
337
338
0
    if (runCount >= 0)
339
0
      {
340
      
341
0
      ++runCount;
342
      
343
0
      dstCount -= runCount;
344
345
0
      if (dstCount < 0)
346
0
        return false;
347
        
348
0
      stream.Get (dPtr, runCount);
349
      
350
0
      dPtr += runCount;
351
      
352
0
      }
353
      
354
0
    else
355
0
      {
356
      
357
0
      runCount = -runCount + 1;
358
359
0
      dstCount -= runCount;
360
361
0
      if (dstCount < 0)
362
0
        return false;
363
        
364
0
      uint8 x = stream.Get_uint8 ();
365
      
366
0
      while (runCount--)
367
0
        {
368
        
369
0
        *(dPtr++) = x;
370
        
371
0
        }
372
373
0
      }
374
      
375
0
    }
376
377
0
  return true;
378
379
0
  }
380
381
/******************************************************************************/
382
383
class dng_lzw_expander
384
  {
385
  
386
  private:
387
  
388
    enum
389
      {
390
      kResetCode = 256,
391
      kEndCode   = 257,
392
      kTableSize = 4096
393
      };
394
    
395
    struct LZWExpanderNode
396
      {
397
      int16 prefix;
398
      int16 final;
399
      int16 depth;
400
      int16 fake_for_padding;
401
      };
402
403
    dng_memory_data fBuffer;
404
405
    LZWExpanderNode *fTable;
406
    
407
    const uint8 *fSrcPtr;
408
    
409
    int32 fSrcCount;
410
    
411
    int32 fByteOffset;
412
413
    uint32 fBitBuffer;
414
    int32 fBitBufferCount;
415
    
416
    int32 fNextCode;
417
    
418
    int32 fCodeSize;
419
    
420
  public:
421
  
422
    dng_lzw_expander ();
423
424
    bool Expand (const uint8 *sPtr,
425
           uint8 *dPtr,
426
           int32 sCount,
427
           int32 dCount);
428
  
429
  private:
430
  
431
    void InitTable ();
432
  
433
    void AddTable (int32 w, int32 k);
434
    
435
    bool GetCodeWord (int32 &code);
436
437
    // Hidden copy constructor and assignment operator.
438
  
439
    dng_lzw_expander (const dng_lzw_expander &expander);
440
    
441
    dng_lzw_expander & operator= (const dng_lzw_expander &expander);
442
443
  };
444
445
/******************************************************************************/
446
447
dng_lzw_expander::dng_lzw_expander ()
448
449
0
  : fBuffer      ()
450
  , fTable       (NULL)
451
  , fSrcPtr      (NULL)
452
0
  , fSrcCount    (0)
453
0
  , fByteOffset    (0)
454
0
  , fBitBuffer     (0)
455
0
  , fBitBufferCount  (0)
456
0
  , fNextCode    (0)
457
0
  , fCodeSize    (0)
458
  
459
0
  {
460
  
461
0
  fBuffer.Allocate (kTableSize * sizeof (LZWExpanderNode));
462
  
463
0
  fTable = (LZWExpanderNode *) fBuffer.Buffer ();
464
465
0
  }
466
467
/******************************************************************************/
468
469
void dng_lzw_expander::InitTable ()
470
0
  {
471
472
0
  fCodeSize = 9;
473
474
0
  fNextCode = 258;
475
    
476
0
  LZWExpanderNode *node = &fTable [0];
477
  
478
0
  for (int32 code = 0; code < 256; code++)
479
0
    {
480
    
481
0
    node->prefix  = -1;
482
0
    node->final   = (int16) code;
483
0
    node->depth   = 1;
484
    
485
0
    node++;
486
    
487
0
    }
488
    
489
0
  }
490
491
/******************************************************************************/
492
493
void dng_lzw_expander::AddTable (int32 w, int32 k)
494
0
  {
495
  
496
0
  DNG_ASSERT ((w >= 0) && (w <= kTableSize),
497
0
        "bad w value in dng_lzw_expander::AddTable");
498
499
0
  LZWExpanderNode *parentNode = &fTable [w];
500
  
501
0
  int32 nextCode = fNextCode;
502
  
503
0
  fNextCode++;
504
  
505
0
  DNG_ASSERT ((nextCode >= 0) && (nextCode <= kTableSize),
506
0
        "bad fNextCode value in dng_lzw_expander::AddTable");
507
  
508
0
  LZWExpanderNode *node = &fTable [nextCode];
509
  
510
0
  node->prefix  = (int16) w;
511
0
  node->final   = (int16) k;
512
0
  node->depth   = 1 + parentNode->depth;
513
  
514
0
  if (nextCode + 1 == (1 << fCodeSize) - 1)
515
0
    {
516
0
    if (fCodeSize != 12)
517
0
      fCodeSize++;
518
0
    }
519
    
520
0
  }
521
522
/******************************************************************************/
523
524
bool dng_lzw_expander::GetCodeWord (int32 &code)
525
0
  {
526
527
  // The bit buffer has the current code in the most significant bits,
528
  // so shift off the low orders.
529
  
530
0
  int32 codeSize = fCodeSize;
531
532
0
  code = fBitBuffer >> (32 - codeSize);
533
534
0
  if (fBitBufferCount >= codeSize)
535
0
    {
536
    
537
    // Typical case; get the code from the bit buffer.
538
539
0
    fBitBuffer     <<= codeSize;
540
0
    fBitBufferCount -= codeSize;
541
    
542
0
    }
543
544
0
  else
545
0
    {
546
    
547
    // The buffer needs to be refreshed.
548
549
0
    const int32 bitsSoFar = fBitBufferCount;
550
551
0
    if (fByteOffset >= fSrcCount)
552
0
      return false;
553
554
    // Buffer a long word
555
    
556
0
    const uint8 *ptr = fSrcPtr + fByteOffset;
557
558
    #if qDNGBigEndian
559
560
    fBitBuffer = *((const uint32 *) ptr);
561
562
    #else
563
    
564
0
      {
565
      
566
0
      uint32 b0 = ptr [0];
567
0
      uint32 b1 = ptr [1];
568
0
      uint32 b2 = ptr [2];
569
0
      uint32 b3 = ptr [3];
570
      
571
0
      fBitBuffer = (((((b0 << 8) | b1) << 8) | b2) << 8) | b3;
572
      
573
0
      }
574
575
0
    #endif
576
577
0
    fBitBufferCount = 32;
578
    
579
0
    fByteOffset += 4;
580
581
    // Number of additional bits we need
582
    
583
0
    const int32 bitsUsed = codeSize - bitsSoFar;
584
585
    // Number of low order bits in the current buffer we don't care about
586
    
587
0
    const int32 bitsNotUsed = 32 - bitsUsed;
588
589
0
    code |= fBitBuffer >> bitsNotUsed;
590
591
0
    fBitBuffer     <<= bitsUsed;
592
0
    fBitBufferCount -= bitsUsed;
593
594
0
    }
595
596
0
  return true;
597
598
0
  }
599
600
/******************************************************************************/
601
602
bool dng_lzw_expander::Expand (const uint8 *sPtr,
603
                   uint8 *dPtr,
604
                   int32 sCount,
605
                   int32 dCount)
606
0
  {
607
  
608
0
  void *dStartPtr = dPtr;
609
  
610
0
  fSrcPtr = sPtr;
611
  
612
0
  fSrcCount = sCount;
613
  
614
0
  fByteOffset = 0;
615
  
616
  /* the master decode loop */
617
  
618
0
  while (true)
619
0
    {
620
    
621
0
    InitTable ();
622
      
623
0
    int32 code;
624
      
625
0
    do
626
0
      {
627
      
628
0
      if (!GetCodeWord (code)) 
629
0
        return false;
630
        
631
0
      DNG_ASSERT (code <= fNextCode,
632
0
            "Unexpected LZW code in dng_lzw_expander::Expand");
633
      
634
0
      }
635
0
    while (code == kResetCode);
636
    
637
0
    if (code == kEndCode) 
638
0
      return true;
639
    
640
0
    if (code > kEndCode) 
641
0
      return false;
642
    
643
0
    int32 oldCode = code;
644
0
    int32 inChar  = code;
645
    
646
0
    *(dPtr++) = (uint8) code;
647
    
648
0
    if (--dCount == 0) 
649
0
      return true;
650
    
651
0
    while (true)
652
0
      {
653
      
654
0
      if (!GetCodeWord (code)) 
655
0
        return false;
656
657
0
      if (code == kResetCode) 
658
0
        break;
659
      
660
0
      if (code == kEndCode) 
661
0
        return true;
662
      
663
0
      const int32 inCode = code;
664
665
0
      bool repeatLastPixel = false;
666
      
667
0
      if (code >= fNextCode)
668
0
        {
669
          
670
        // This is either a bad file or our code table is not big enough; we
671
        // are going to repeat the last code seen and attempt to muddle thru.
672
        
673
0
        code = oldCode; 
674
675
0
        repeatLastPixel = true;
676
677
0
        }
678
      
679
      // this can only happen if we hit 2 bad codes in a row
680
      
681
0
      if (code > fNextCode)
682
0
        return false;
683
684
0
      const int32 depth = fTable [code].depth;
685
686
0
      if (depth < dCount)
687
0
        {
688
689
0
        dCount -= depth;
690
        
691
0
        dPtr += depth;
692
693
0
        uint8 *ptr = dPtr;
694
        
695
        // give the compiler an extra hint to optimize these as registers
696
        
697
0
        const LZWExpanderNode *localTable = fTable;
698
        
699
0
        int32 localCode = code;
700
        
701
        // this is usually the hottest loop in LZW expansion
702
        
703
0
        while (localCode >= kResetCode)
704
0
          {
705
          
706
0
          if (ptr <= dStartPtr)
707
0
            return false;   // about to trash memory
708
709
0
          const LZWExpanderNode &node = localTable [localCode];
710
          
711
0
          uint8 tempFinal = (uint8) node.final;
712
          
713
0
          localCode = node.prefix;
714
715
          // Check for bogus table entry
716
717
0
          if (localCode < 0 || localCode > kTableSize)
718
0
            return false;
719
720
0
          *(--ptr) = tempFinal;
721
722
0
          }
723
        
724
0
        code = localCode;
725
726
0
        inChar = localCode;
727
728
0
        if (ptr <= dStartPtr)
729
0
          return false;   // about to trash memory
730
731
0
        *(--ptr) = (uint8) inChar;
732
733
0
        }
734
    
735
0
      else
736
0
        {
737
        
738
        // There might not be enough room for the full code
739
        // so skip the end of it.
740
        
741
0
        const int32 skip = depth - dCount;
742
743
0
        for (int32 i = 0; i < skip ; i++)
744
0
          {
745
0
          const LZWExpanderNode &node = fTable [code];
746
0
          code = node.prefix;
747
0
          }
748
749
0
        int32 depthUsed = depth - skip;
750
751
0
        dCount -= depthUsed;
752
        
753
0
        dPtr += depthUsed;
754
755
0
        uint8 *ptr = dPtr;
756
757
0
        while (code >= 0)
758
0
          {
759
          
760
0
          if (ptr <= dStartPtr)
761
0
            return false;   // about to trash memory
762
763
0
          const LZWExpanderNode &node = fTable [code];
764
765
0
          *(--ptr) = (uint8) node.final;
766
767
0
          code = node.prefix;
768
          
769
          // Check for bogus table entry
770
771
0
          if (code > kTableSize)
772
0
            return false;
773
774
0
          }
775
776
0
        return true;
777
778
0
        }
779
780
0
      if (repeatLastPixel)
781
0
        {
782
        
783
0
        *(dPtr++) = (uint8) inChar;
784
        
785
0
        if (--dCount == 0)
786
0
          return true;
787
  
788
0
        }
789
        
790
0
      if (fNextCode < kTableSize)
791
0
        {
792
        
793
0
        AddTable (oldCode, code);
794
        
795
0
        }
796
      
797
0
      oldCode = inCode;
798
      
799
0
      }
800
      
801
0
    } 
802
803
0
  return false;
804
  
805
0
  }
806
807
/*****************************************************************************/
808
809
dng_row_interleaved_image::dng_row_interleaved_image (dng_image &image,
810
                            uint32 factor)
811
                            
812
46
  : dng_image (image.Bounds    (),
813
46
           image.Planes    (),
814
46
           image.PixelType ())
815
                            
816
46
  , fImage  (image )
817
46
  , fFactor (factor)
818
  
819
46
  {
820
  
821
46
  }
822
  
823
/*****************************************************************************/
824
825
int32 dng_row_interleaved_image::MapRow (int32 row) const
826
223k
  {
827
828
223k
  uint32 rows = Height ();
829
  
830
223k
  int32 top = Bounds ().t;
831
  
832
223k
  uint32 fieldRow = row - top;
833
  
834
2.04M
  for (uint32 field = 0; true; field++)
835
2.04M
    {
836
    
837
2.04M
    uint32 fieldRows = (rows - field + fFactor - 1) / fFactor;
838
    
839
2.04M
    if (fieldRow < fieldRows)
840
223k
      {
841
      
842
223k
      return fieldRow * fFactor + field + top;
843
      
844
223k
      }
845
      
846
1.81M
    fieldRow -= fieldRows;
847
    
848
1.81M
    }
849
    
850
0
  ThrowProgramError ();
851
    
852
0
  return 0;
853
  
854
223k
  }
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
60
  {
884
  
885
60
  dng_pixel_buffer tempBuffer (buffer);
886
  
887
223k
  for (int32 row = buffer.fArea.t; row < buffer.fArea.b; row++)
888
223k
    {
889
        
890
223k
    tempBuffer.fArea.t = MapRow (row);
891
    
892
223k
    tempBuffer.fArea.b = tempBuffer.fArea.t + 1;
893
    
894
223k
    tempBuffer.fData = (void *) buffer.ConstPixel (row,
895
223k
                             buffer.fArea.l,
896
223k
                             buffer.fPlane);
897
                     
898
223k
    fImage.Put (tempBuffer);
899
    
900
223k
    }
901
    
902
60
  }
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
337
  {
911
  
912
337
  uint32 tempBufferSize = ComputeBufferSize(buffer.fPixelType,
913
337
                        buffer.fArea.Size(),
914
337
                        buffer.fPlanes, padNone);
915
              
916
337
  if (!tempBuffer.Get () || tempBuffer->LogicalSize () < tempBufferSize)
917
58
    {
918
    
919
58
    tempBuffer.Reset (host.Allocate (tempBufferSize));
920
    
921
58
    }
922
  
923
337
  uint32 blockRows = ifd.fSubTileBlockRows;
924
337
  uint32 blockCols = ifd.fSubTileBlockCols;
925
  
926
337
  uint32 rowBlocks = buffer.fArea.H () / blockRows;
927
337
  uint32 colBlocks = buffer.fArea.W () / blockCols;
928
  
929
337
  int32 rowStep = buffer.fRowStep * buffer.fPixelSize;
930
337
  int32 colStep = buffer.fColStep * buffer.fPixelSize;
931
  
932
337
  int32 rowBlockStep = rowStep * blockRows;
933
337
  int32 colBlockStep = colStep * blockCols;
934
  
935
337
  uint32 blockColBytes = blockCols * buffer.fPlanes * buffer.fPixelSize;
936
  
937
337
  const uint8 *s0 = (const uint8 *) buffer.fData;
938
337
        uint8 *d0 = tempBuffer->Buffer_uint8 ();
939
  
940
31.6k
  for (uint32 rowBlock = 0; rowBlock < rowBlocks; rowBlock++)
941
31.3k
    {
942
    
943
31.3k
    uint8 *d1 = d0;
944
    
945
2.07M
    for (uint32 colBlock = 0; colBlock < colBlocks; colBlock++)
946
2.04M
      {
947
      
948
2.04M
      uint8 *d2 = d1;
949
      
950
7.06M
      for (uint32 blockRow = 0; blockRow < blockRows; blockRow++)
951
5.02M
        {
952
        
953
27.9M
        for (uint32 j = 0; j < blockColBytes; j++)
954
22.9M
          {
955
          
956
22.9M
          d2 [j] = s0 [j];
957
          
958
22.9M
          }
959
          
960
5.02M
        s0 += blockColBytes;
961
        
962
5.02M
        d2 += rowStep;
963
        
964
5.02M
        }
965
      
966
2.04M
      d1 += colBlockStep;
967
      
968
2.04M
      }
969
      
970
31.3k
    d0 += rowBlockStep;
971
    
972
31.3k
    }
973
    
974
  // Copy back reordered pixels.
975
    
976
337
  DoCopyBytes (tempBuffer->Buffer (),
977
337
         buffer.fData,
978
337
         tempBufferSize);
979
  
980
337
  }
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
1.54k
  : fHost (host)
1049
1.54k
  , fIFD (ifd)
1050
1.54k
  , fImage (image)
1051
1.54k
  , fTileArea (tileArea)
1052
1.54k
  , fPlane (plane)
1053
1.54k
  , fPlanes (planes)
1054
1.54k
  , fBlock (block)
1055
1.54k
  , fSubTileBuffer (subTileBuffer)
1056
  
1057
1.54k
  , fTileStrip ()
1058
  , fBuffer (NULL)
1059
1.54k
  , fBufferCount (0)
1060
1.54k
  , fBufferSize (0)
1061
  
1062
1.54k
  {
1063
  
1064
1.54k
  uint32 bytesPerRow = fTileArea.W () * fPlanes * (uint32) sizeof (uint16);
1065
  
1066
1.54k
  uint32 stripLength = Pin_uint32 (ifd.fSubTileBlockRows,
1067
1.54k
                   fBlock.LogicalSize () / bytesPerRow,
1068
1.54k
                   fTileArea.H ());
1069
                  
1070
1.54k
  stripLength = stripLength / ifd.fSubTileBlockRows
1071
1.54k
                * ifd.fSubTileBlockRows;
1072
  
1073
1.54k
  fTileStrip   = fTileArea;
1074
1.54k
  fTileStrip.b = fTileArea.t + stripLength;
1075
  
1076
1.54k
  fBuffer = (uint8 *) fBlock.Buffer ();
1077
  
1078
1.54k
  fBufferCount = 0;
1079
1.54k
  fBufferSize  = bytesPerRow * stripLength;
1080
          
1081
1.54k
  }
1082
1083
/*****************************************************************************/
1084
1085
dng_image_spooler::~dng_image_spooler ()
1086
1.54k
  {
1087
  
1088
1.54k
  }
1089
1090
/*****************************************************************************/
1091
1092
void dng_image_spooler::Spool (const void *data,
1093
                 uint32 count)
1094
4.30M
  {
1095
  
1096
8.61M
  while (count)
1097
4.30M
    {
1098
    
1099
4.30M
    uint32 block = Min_uint32 (count, fBufferSize - fBufferCount);
1100
    
1101
4.30M
    if (block == 0)
1102
0
      {
1103
0
      return;
1104
0
      }
1105
    
1106
4.30M
    DoCopyBytes (data,
1107
4.30M
           fBuffer + fBufferCount,
1108
4.30M
             block);
1109
        
1110
4.30M
    data = ((const uint8 *) data) + block;
1111
    
1112
4.30M
    count -= block;
1113
    
1114
4.30M
    fBufferCount += block;
1115
    
1116
4.30M
    if (fBufferCount == fBufferSize)
1117
566
      {
1118
      
1119
566
      fHost.SniffForAbort ();
1120
      
1121
566
      dng_pixel_buffer buffer (fTileStrip, fPlane, fPlanes, ttShort,
1122
566
         pcInterleaved, fBuffer);
1123
      
1124
566
      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
566
      fImage.Put (buffer);
1135
      
1136
566
      uint32 stripLength = fTileStrip.H ();
1137
      
1138
566
      fTileStrip.t = fTileStrip.b;
1139
      
1140
566
      fTileStrip.b = Min_int32 (fTileStrip.t + stripLength,
1141
566
                    fTileArea.b);
1142
      
1143
566
      fBufferCount = 0;
1144
      
1145
566
      fBufferSize = fTileStrip.W () *
1146
566
              fTileStrip.H () *
1147
566
              fPlanes * (uint32) sizeof (uint16);
1148
  
1149
566
      }
1150
1151
4.30M
    }
1152
  
1153
4.30M
  }
1154
1155
/*****************************************************************************/
1156
1157
dng_read_image::dng_read_image ()
1158
1159
3.26k
  : fJPEGTables ()
1160
  
1161
3.26k
  {
1162
  
1163
3.26k
  }
1164
1165
/*****************************************************************************/
1166
1167
dng_read_image::~dng_read_image ()
1168
3.26k
  {
1169
  
1170
3.26k
  }
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
1.50k
  {
1184
  
1185
1.50k
  uint32 rows          = tileArea.H ();
1186
1.50k
  uint32 samplesPerRow = tileArea.W ();
1187
  
1188
1.50k
  if (ifd.fPlanarConfiguration == pcRowInterleaved)
1189
0
    {
1190
0
    rows = SafeUint32Mult(rows, planes);
1191
0
    }
1192
1.50k
  else
1193
1.50k
    {
1194
1.50k
    samplesPerRow = SafeUint32Mult(samplesPerRow, planes);
1195
1.50k
    }
1196
  
1197
1.50k
  uint32 samplesPerTile = SafeUint32Mult(samplesPerRow, rows);
1198
    
1199
1.50k
  if (uncompressedBuffer.Get () == NULL)
1200
69
    {
1201
1202
    #if qDNGValidate
1203
    
1204
    ReportError ("Fuzz: Missing uncompressed buffer");
1205
    
1206
    #endif
1207
1208
69
    ThrowBadFormat ();
1209
    
1210
69
    }
1211
  
1212
1.50k
  uint32 bitDepth = ifd.fBitsPerSample [plane];
1213
  
1214
1.50k
  uint32 pixelType = ttUndefined;
1215
  
1216
1.50k
  if (bitDepth == 8)
1217
490
    {
1218
    
1219
490
    pixelType = ttByte;
1220
        
1221
490
    stream.Get (uncompressedBuffer->Buffer (), samplesPerTile);
1222
    
1223
490
    }
1224
    
1225
1.01k
  else if (bitDepth == 16 && ifd.fSampleFormat [0] == sfFloatingPoint)
1226
164
    {
1227
    
1228
164
    pixelType = ttFloat;
1229
    
1230
164
    uint32 *p_uint32 = (uint32 *) uncompressedBuffer->Buffer ();
1231
      
1232
2.47M
    for (uint32 j = 0; j < samplesPerTile; j++)
1233
2.47M
      {
1234
      
1235
2.47M
      p_uint32 [j] = DNG_HalfToFloat (stream.Get_uint16 ());
1236
                      
1237
2.47M
      }
1238
    
1239
164
    }
1240
  
1241
853
  else if (bitDepth == 24 && ifd.fSampleFormat [0] == sfFloatingPoint)
1242
136
    {
1243
    
1244
136
    pixelType = ttFloat;
1245
    
1246
136
    uint32 *p_uint32 = (uint32 *) uncompressedBuffer->Buffer ();
1247
      
1248
1.79M
    for (uint32 j = 0; j < samplesPerTile; j++)
1249
1.79M
      {
1250
      
1251
1.79M
      uint8 input [3];
1252
      
1253
1.79M
      if (stream.LittleEndian ())
1254
1.79M
        {
1255
1.79M
        input [2] = stream.Get_uint8 ();
1256
1.79M
        input [1] = stream.Get_uint8 ();
1257
1.79M
        input [0] = stream.Get_uint8 ();
1258
1.79M
        }
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
1.79M
      p_uint32 [j] = DNG_FP24ToFloat (input);
1268
                      
1269
1.79M
      }
1270
    
1271
136
    }
1272
  
1273
717
  else if (bitDepth == 16)
1274
51
    {
1275
    
1276
51
    pixelType = ttShort;
1277
    
1278
51
    stream.Get (uncompressedBuffer->Buffer (), samplesPerTile * 2);
1279
    
1280
51
    if (stream.SwapBytes ())
1281
0
      {
1282
      
1283
0
      DoSwapBytes16 ((uint16 *) uncompressedBuffer->Buffer (),
1284
0
               samplesPerTile);
1285
            
1286
0
      }
1287
        
1288
51
    }
1289
    
1290
666
  else if (bitDepth == 32)
1291
11
    {
1292
    
1293
11
    pixelType = image.PixelType ();
1294
    
1295
11
    stream.Get (uncompressedBuffer->Buffer (), samplesPerTile * 4);
1296
    
1297
11
    if (stream.SwapBytes ())
1298
0
      {
1299
      
1300
0
      DoSwapBytes32 ((uint32 *) uncompressedBuffer->Buffer (),
1301
0
               samplesPerTile);
1302
            
1303
0
      }
1304
        
1305
11
    }
1306
    
1307
655
  else if (bitDepth == 12)
1308
236
    {
1309
    
1310
236
    pixelType = ttShort;
1311
    
1312
236
    uint16 *p = (uint16 *) uncompressedBuffer->Buffer ();
1313
      
1314
236
    uint32 evenSamples = samplesPerRow >> 1;
1315
    
1316
406k
    for (uint32 row = 0; row < rows; row++)
1317
405k
      {
1318
      
1319
2.13M
      for (uint32 j = 0; j < evenSamples; j++)
1320
1.72M
        {
1321
        
1322
1.72M
        uint32 b0 = stream.Get_uint8 ();
1323
1.72M
        uint32 b1 = stream.Get_uint8 ();
1324
1.72M
        uint32 b2 = stream.Get_uint8 ();
1325
                
1326
1.72M
        p [0] = (uint16) ((b0 << 4) | (b1 >> 4));
1327
1.72M
        p [1] = (uint16) (((b1 << 8) | b2) & 0x0FFF);
1328
        
1329
1.72M
        p += 2;
1330
        
1331
1.72M
        }
1332
        
1333
405k
      if (samplesPerRow & 1)
1334
404k
        {
1335
        
1336
404k
        uint32 b0 = stream.Get_uint8 ();
1337
404k
        uint32 b1 = stream.Get_uint8 ();
1338
        
1339
404k
        p [0] = (uint16) ((b0 << 4) | (b1 >> 4));
1340
        
1341
404k
        p += 1;
1342
        
1343
404k
        }
1344
      
1345
405k
      }
1346
    
1347
236
    }
1348
    
1349
419
  else if (bitDepth > 8 && bitDepth < 16)
1350
118
    {
1351
    
1352
118
    pixelType = ttShort;
1353
    
1354
118
    uint16 *p = (uint16 *) uncompressedBuffer->Buffer ();
1355
      
1356
118
    uint32 bitMask = (1 << bitDepth) - 1;
1357
              
1358
17.9k
    for (uint32 row = 0; row < rows; row++)
1359
17.8k
      {
1360
      
1361
17.8k
      uint32 bitBuffer  = 0;
1362
17.8k
      uint32 bufferBits = 0;
1363
      
1364
2.22M
      for (uint32 j = 0; j < samplesPerRow; j++)
1365
2.20M
        {
1366
        
1367
4.81M
        while (bufferBits < bitDepth)
1368
2.61M
          {
1369
          
1370
2.61M
          bitBuffer = (bitBuffer << 8) | stream.Get_uint8 ();
1371
          
1372
2.61M
          bufferBits += 8;
1373
          
1374
2.61M
          }
1375
                  
1376
2.20M
        p [j] = (uint16) ((bitBuffer >> (bufferBits - bitDepth)) & bitMask);
1377
        
1378
2.20M
        bufferBits -= bitDepth;
1379
        
1380
2.20M
        }
1381
        
1382
17.8k
      p += samplesPerRow;
1383
      
1384
17.8k
      }
1385
      
1386
118
    }
1387
    
1388
301
  else if (bitDepth > 16 && bitDepth < 32)
1389
232
    {
1390
    
1391
232
    pixelType = ttLong;
1392
    
1393
232
    uint32 *p = (uint32 *) uncompressedBuffer->Buffer ();
1394
      
1395
232
    uint32 bitMask = ((uint32) 1 << bitDepth) - 1;
1396
              
1397
12.2k
    for (uint32 row = 0; row < rows; row++)
1398
12.0k
      {
1399
      
1400
12.0k
      uint64 bitBuffer  = 0;
1401
12.0k
      uint32 bufferBits = 0;
1402
      
1403
1.85M
      for (uint32 j = 0; j < samplesPerRow; j++)
1404
1.84M
        {
1405
        
1406
7.14M
        while (bufferBits < bitDepth)
1407
5.30M
          {
1408
          
1409
5.30M
          bitBuffer = (bitBuffer << 8) | stream.Get_uint8 ();
1410
          
1411
5.30M
          bufferBits += 8;
1412
          
1413
5.30M
          }
1414
                  
1415
1.84M
        p [j] = ((uint32) (bitBuffer >> (bufferBits - bitDepth))) & bitMask;
1416
        
1417
1.84M
        bufferBits -= bitDepth;
1418
        
1419
1.84M
        }
1420
        
1421
12.0k
      p += samplesPerRow;
1422
      
1423
12.0k
      }
1424
      
1425
232
    }
1426
    
1427
69
  else
1428
69
    {
1429
    
1430
69
    return false;
1431
    
1432
69
    }
1433
    
1434
1.43k
  dng_pixel_buffer buffer (tileArea, plane, planes, pixelType,
1435
1.43k
     ifd.fPlanarConfiguration, uncompressedBuffer->Buffer ());
1436
  
1437
1.43k
  if (ifd.fSampleBitShift)
1438
0
    {
1439
    
1440
0
    buffer.ShiftRight (ifd.fSampleBitShift);
1441
    
1442
0
    }
1443
    
1444
1.43k
  if (ifd.fSubTileBlockRows > 1)
1445
337
    {
1446
    
1447
337
    ReorderSubTileBlocks (host,
1448
337
                ifd,
1449
337
                buffer,
1450
337
                subTileBlockBuffer);
1451
    
1452
337
    }
1453
    
1454
1.43k
  image.Put (buffer);
1455
  
1456
1.43k
  return true;
1457
    
1458
1.50k
  }
1459
1460
/*****************************************************************************/
1461
1462
#if qDNGUseLibJPEG
1463
1464
/*****************************************************************************/
1465
1466
static void dng_error_exit (j_common_ptr cinfo)
1467
36
  {
1468
  
1469
  // Output message.
1470
  
1471
36
  (*cinfo->err->output_message) (cinfo);
1472
  
1473
  // Convert to a dng_exception.
1474
1475
36
  switch (cinfo->err->msg_code)
1476
36
    {
1477
    
1478
0
    case JERR_OUT_OF_MEMORY:
1479
0
      {
1480
0
      ThrowMemoryFull ();
1481
0
      break;
1482
0
      }
1483
      
1484
36
    default:
1485
36
      {
1486
36
      ThrowBadFormat ();
1487
36
      }
1488
      
1489
36
    }
1490
      
1491
36
  }
1492
1493
/*****************************************************************************/
1494
1495
static void dng_output_message (j_common_ptr cinfo)
1496
42
  {
1497
  
1498
  // Format message to string.
1499
  
1500
42
  char buffer [JMSG_LENGTH_MAX];
1501
1502
42
  (*cinfo->err->format_message) (cinfo, buffer);
1503
  
1504
  // Report the libjpeg message as a warning.
1505
  
1506
42
  ReportWarning ("libjpeg", buffer);
1507
1508
42
  }
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
36
  {
1525
  
1526
36
  #if qDNGUseLibJPEG
1527
  
1528
36
  struct jpeg_decompress_struct cinfo;
1529
  
1530
  // Setup the error manager.
1531
  
1532
36
  struct jpeg_error_mgr jerr;
1533
1534
36
  cinfo.err = jpeg_std_error (&jerr);
1535
  
1536
36
  jerr.error_exit     = dng_error_exit;
1537
36
  jerr.output_message = dng_output_message;
1538
  
1539
36
  try
1540
36
    {
1541
    
1542
    // Create the decompression context.
1543
1544
36
    jpeg_create_decompress (&cinfo);
1545
    
1546
    // Set up the memory data source manager.
1547
    
1548
36
    size_t jpegDataSizeAsSizet = 0;
1549
36
    ConvertUnsigned(jpegDataSize, &jpegDataSizeAsSizet);
1550
36
    jpeg_source_mgr memorySource =
1551
36
      CreateJpegMemorySource(jpegDataInMemory,
1552
36
                   jpegDataSizeAsSizet);
1553
36
    cinfo.src = &memorySource;
1554
      
1555
    // Read the JPEG header.
1556
      
1557
36
    jpeg_read_header (&cinfo, TRUE);
1558
    
1559
    // Check header.
1560
    
1561
36
    {
1562
      // Number of components may not be negative.
1563
36
      if (cinfo.num_components < 0)
1564
0
        {
1565
0
        ThrowBadFormat();
1566
0
        }
1567
      
1568
      // Convert relevant values from header to uint32.
1569
36
      uint32 imageWidthAsUint32 = 0;
1570
36
      uint32 imageHeightAsUint32 = 0;
1571
36
      uint32 numComponentsAsUint32 = 0;
1572
36
      ConvertUnsigned(cinfo.image_width, &imageWidthAsUint32);
1573
36
      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
36
      ConvertUnsigned(static_cast<unsigned>(cinfo.num_components),
1577
36
              &numComponentsAsUint32);
1578
      
1579
      // Check that dimensions of JPEG correspond to dimensions of tile.
1580
36
      if (imageWidthAsUint32    != tileArea.W () ||
1581
36
          imageHeightAsUint32   != tileArea.H () ||
1582
36
          numComponentsAsUint32 != planes        )
1583
0
        {
1584
0
        ThrowBadFormat ();
1585
0
        }
1586
36
    }
1587
      
1588
    // Start the compression.
1589
    
1590
36
    jpeg_start_decompress (&cinfo);
1591
    
1592
    // Setup a one-scanline size buffer.
1593
    
1594
36
    dng_pixel_buffer buffer(tileArea, plane, planes, ttByte, pcInterleaved,
1595
36
                NULL);
1596
36
    buffer.fArea.b = tileArea.t + 1;
1597
    
1598
36
    buffer.fDirty = true;
1599
    
1600
36
    AutoPtr<dng_memory_block> bufferData (host.Allocate (buffer.fRowStep));
1601
    
1602
36
    buffer.fData = bufferData->Buffer ();
1603
    
1604
36
    uint8 *sampArray [1];
1605
    
1606
36
    sampArray [0] = bufferData->Buffer_uint8 ();
1607
    
1608
    // Read each scanline and save to image.
1609
      
1610
36
    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
36
    jpeg_finish_decompress (&cinfo);
1625
1626
36
    jpeg_destroy_decompress (&cinfo);
1627
      
1628
36
    }
1629
    
1630
36
  catch (...)
1631
36
    {
1632
    
1633
36
    jpeg_destroy_decompress (&cinfo);
1634
    
1635
36
    throw;
1636
    
1637
36
    }
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
36
  }
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
28
  {
1667
  
1668
  // This ensures that the "tileByteCount -= 2" operation below will not wrap
1669
  // around.
1670
28
  if (tileByteCount <= 2)
1671
5
    {
1672
5
    ThrowEndOfFile ();
1673
5
    }
1674
    
1675
28
  uint32 tablesByteCount = tablesBlock ? tablesBlock->LogicalSize () : 0;
1676
  
1677
  // This ensures that the "tablesByteCount -= 2" operation below will not
1678
  // wrap around.
1679
28
  if (tablesByteCount && tablesByteCount < 4)
1680
11
    {
1681
11
    ThrowEndOfFile ();
1682
11
    }
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
28
  if (tablesByteCount)
1692
7
    {
1693
    
1694
    // Ensure the "tileOffset += 2" operation below will not wrap around.
1695
7
    if (tileOffset > std::numeric_limits<uint64>::max () - 2)
1696
0
      {
1697
0
      ThrowEndOfFile();
1698
0
      }
1699
    
1700
7
    tablesByteCount -= 2;
1701
    
1702
7
    tileOffset    += 2;
1703
7
    tileByteCount -= 2;
1704
    
1705
7
    }
1706
    
1707
  // Allocate buffer.
1708
  
1709
28
  AutoPtr<dng_memory_block> buffer (host.Allocate (
1710
28
    SafeUint32Add(tablesByteCount, tileByteCount)));
1711
                            
1712
  // Read in table.
1713
  
1714
28
  if (tablesByteCount)
1715
7
    {
1716
    
1717
7
    DoCopyBytes (tablesBlock->Buffer (),
1718
7
           buffer->Buffer (),
1719
7
           tablesByteCount);
1720
    
1721
7
    }
1722
    
1723
  // Read in tile data.
1724
  
1725
28
  stream.SetReadPosition (tileOffset);
1726
  
1727
28
  stream.Get (buffer->Buffer_uint8 () + tablesByteCount, tileByteCount);
1728
    
1729
  // Patch first byte, if required.
1730
    
1731
28
  if (patchFirstByte)
1732
0
    {
1733
    
1734
0
    buffer->Buffer_uint8 () [0] = 0xFF;
1735
    
1736
0
    }
1737
    
1738
  // Return buffer.
1739
  
1740
28
  return buffer.Release ();
1741
  
1742
28
  }
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
55
  {
1756
  
1757
  // Setup the data source.
1758
  
1759
55
  if (fJPEGTables.Get () || !jpegDataInMemory)
1760
28
    {
1761
    
1762
28
    AutoPtr<dng_memory_block> jpegDataBlock;
1763
  
1764
28
    jpegDataBlock.Reset (ReadJPEGDataToBlock (host,
1765
28
                          stream,
1766
28
                          fJPEGTables.Get (),
1767
28
                          stream.Position (),
1768
28
                          tileByteCount,
1769
28
                          ifd.fPatchFirstJPEGByte));
1770
                          
1771
28
    DecodeLossyJPEG (host,
1772
28
             image,
1773
28
             tileArea,
1774
28
             plane,
1775
28
             planes,
1776
28
             ifd.fPhotometricInterpretation,
1777
28
             jpegDataBlock->LogicalSize (),
1778
28
             jpegDataBlock->Buffer_uint8 ());
1779
    
1780
28
    }
1781
    
1782
27
  else
1783
27
    {
1784
  
1785
27
    if (ifd.fPatchFirstJPEGByte && tileByteCount)
1786
0
      {
1787
0
      jpegDataInMemory [0] = 0xFF;
1788
0
      }
1789
1790
27
    DecodeLossyJPEG (host,
1791
27
             image,
1792
27
             tileArea,
1793
27
             plane,
1794
27
             planes,
1795
27
             ifd.fPhotometricInterpretation,
1796
27
             tileByteCount,
1797
27
             jpegDataInMemory);
1798
    
1799
27
    }
1800
        
1801
55
  return true;
1802
  
1803
55
  }
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
1.56k
  {
1818
  
1819
  // If the tile area is empty, there's nothing to read.
1820
1.56k
  if (tileArea.IsEmpty ())
1821
19
    {
1822
19
    return true;
1823
19
    }
1824
  
1825
1.54k
  uint32 bytesPerRow = SafeUint32Mult (tileArea.W(), planes, 
1826
1.54k
    static_cast<uint32> (sizeof (uint16)));
1827
  
1828
1.54k
  uint32 rowsPerStrip = Pin_uint32 (ifd.fSubTileBlockRows,
1829
1.54k
                    kImageBufferSize / bytesPerRow,
1830
1.54k
                    tileArea.H ());
1831
                    
1832
1.54k
  rowsPerStrip = rowsPerStrip / ifd.fSubTileBlockRows
1833
1.54k
                * ifd.fSubTileBlockRows;
1834
                    
1835
1.54k
  uint32 bufferSize = SafeUint32Mult (bytesPerRow, rowsPerStrip);
1836
  
1837
1.54k
  if (uncompressedBuffer.Get () &&
1838
1.54k
    uncompressedBuffer->LogicalSize () < bufferSize)
1839
0
    {
1840
    
1841
0
    uncompressedBuffer.Reset ();
1842
    
1843
0
    }
1844
    
1845
1.54k
  if (uncompressedBuffer.Get () == NULL)
1846
1.52k
    {
1847
    
1848
1.52k
    uncompressedBuffer.Reset (host.Allocate (bufferSize));
1849
                  
1850
1.52k
    }
1851
  
1852
1.54k
  dng_image_spooler spooler (host,
1853
1.54k
                 ifd,
1854
1.54k
                 image,
1855
1.54k
                 tileArea,
1856
1.54k
                 plane,
1857
1.54k
                 planes,
1858
1.54k
                 *uncompressedBuffer.Get (),
1859
1.54k
                 subTileBlockBuffer);
1860
                 
1861
1.54k
  uint32 decodedSize = SafeUint32Mult(tileArea.W (),
1862
1.54k
             tileArea.H (),
1863
1.54k
             planes, (uint32) sizeof (uint16));
1864
              
1865
1.54k
  bool bug16 = ifd.fLosslessJPEGBug16;
1866
  
1867
1.54k
  uint64 tileOffset = stream.Position ();
1868
  
1869
1.54k
  DecodeLosslessJPEG (stream,
1870
1.54k
              spooler,
1871
1.54k
              decodedSize,
1872
1.54k
              decodedSize,
1873
1.54k
            bug16);
1874
            
1875
1.54k
  if (stream.Position () > tileOffset + tileByteCount)
1876
108
    {
1877
108
    ThrowBadFormat ();
1878
108
    }
1879
1880
1.54k
  return true;
1881
  
1882
1.56k
  }
1883
  
1884
/*****************************************************************************/
1885
1886
bool dng_read_image::CanReadTile (const dng_ifd &ifd)
1887
0
  {
1888
  
1889
0
  if (ifd.fSampleFormat [0] != sfUnsignedInteger &&
1890
0
    ifd.fSampleFormat [0] != sfFloatingPoint)
1891
0
    {
1892
0
    return false;
1893
0
    }
1894
1895
0
  switch (ifd.fCompression)
1896
0
    {
1897
    
1898
0
    case ccUncompressed:
1899
0
      {
1900
      
1901
0
      if (ifd.fSampleFormat [0] == sfFloatingPoint)
1902
0
        {
1903
        
1904
0
        return (ifd.fBitsPerSample [0] == 16 ||
1905
0
            ifd.fBitsPerSample [0] == 24 ||
1906
0
            ifd.fBitsPerSample [0] == 32);
1907
            
1908
0
        }
1909
        
1910
0
      return ifd.fBitsPerSample [0] >= 8 &&
1911
0
           ifd.fBitsPerSample [0] <= 32;
1912
      
1913
0
      }
1914
      
1915
0
    case ccJPEG:
1916
0
      {
1917
      
1918
0
      if (ifd.fSampleFormat [0] != sfUnsignedInteger)
1919
0
        {
1920
0
        return false;
1921
0
        }
1922
        
1923
0
      if (ifd.IsBaselineJPEG ())
1924
0
        {
1925
        
1926
        // Baseline JPEG.
1927
        
1928
0
        return true;
1929
        
1930
0
        }
1931
        
1932
0
      else
1933
0
        {
1934
        
1935
        // Lossless JPEG.
1936
        
1937
0
        return ifd.fBitsPerSample [0] >= 8 &&
1938
0
             ifd.fBitsPerSample [0] <= 16;
1939
        
1940
0
        }
1941
        
1942
0
      break;
1943
      
1944
0
      }
1945
1946
0
    case ccLZW:
1947
0
    case ccDeflate:
1948
0
    case ccOldDeflate:
1949
0
    case ccPackBits:
1950
0
      {
1951
      
1952
0
      if (ifd.fSampleFormat [0] == sfFloatingPoint)
1953
0
        {
1954
        
1955
0
        if (ifd.fCompression == ccPackBits)
1956
0
          {
1957
0
          return false;
1958
0
          }
1959
        
1960
0
        if (ifd.fPredictor != cpNullPredictor   &&
1961
0
          ifd.fPredictor != cpFloatingPoint   &&
1962
0
          ifd.fPredictor != cpFloatingPointX2 &&
1963
0
          ifd.fPredictor != cpFloatingPointX4)
1964
0
          {
1965
0
          return false;
1966
0
          }
1967
          
1968
0
        if (ifd.fBitsPerSample [0] != 16 &&
1969
0
          ifd.fBitsPerSample [0] != 24 &&
1970
0
          ifd.fBitsPerSample [0] != 32)
1971
0
          {
1972
0
          return false;
1973
0
          }
1974
        
1975
0
        }
1976
        
1977
0
      else
1978
0
        {
1979
1980
0
        if (ifd.fPredictor != cpNullPredictor       &&
1981
0
          ifd.fPredictor != cpHorizontalDifference   &&
1982
0
          ifd.fPredictor != cpHorizontalDifferenceX2 &&
1983
0
          ifd.fPredictor != cpHorizontalDifferenceX4)
1984
0
          {
1985
0
          return false;
1986
0
          }
1987
          
1988
0
        if (ifd.fBitsPerSample [0] != 8  &&
1989
0
          ifd.fBitsPerSample [0] != 16 &&
1990
0
          ifd.fBitsPerSample [0] != 32)
1991
0
          {
1992
0
          return false;
1993
0
          }
1994
          
1995
0
        }
1996
          
1997
0
      return true;
1998
      
1999
0
      }
2000
      
2001
0
    default:
2002
0
      {
2003
0
      break;
2004
0
      }
2005
      
2006
0
    }
2007
    
2008
0
  return false;
2009
2010
0
  }
2011
  
2012
/*****************************************************************************/
2013
2014
bool dng_read_image::NeedsCompressedBuffer (const dng_ifd &ifd)
2015
2.78k
  {
2016
  
2017
2.78k
  if (ifd.fCompression == ccLZW        ||
2018
2.78k
    ifd.fCompression == ccDeflate    ||
2019
2.78k
    ifd.fCompression == ccOldDeflate ||
2020
2.78k
    ifd.fCompression == ccPackBits)
2021
152
    {
2022
152
    return true;
2023
152
    }
2024
    
2025
2.62k
  return false;
2026
  
2027
2.78k
  }
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
80
  {
2073
  
2074
80
  switch (ifd.fPredictor)
2075
80
    {
2076
    
2077
60
    case cpNullPredictor:
2078
60
      {
2079
      
2080
60
      return;
2081
      
2082
0
      }
2083
    
2084
3
    case cpHorizontalDifference:
2085
6
    case cpHorizontalDifferenceX2:
2086
20
    case cpHorizontalDifferenceX4:
2087
20
      {
2088
      
2089
20
      int32 xFactor = 1;
2090
      
2091
20
      if (ifd.fPredictor == cpHorizontalDifferenceX2)
2092
3
        {
2093
3
        xFactor = 2;
2094
3
        }
2095
        
2096
17
      else if (ifd.fPredictor == cpHorizontalDifferenceX4)
2097
14
        {
2098
14
        xFactor = 4;
2099
14
        }
2100
      
2101
20
      switch (buffer.fPixelType)
2102
20
        {
2103
        
2104
18
        case ttByte:
2105
18
          {
2106
          
2107
18
          DecodeDelta8 ((uint8 *) buffer.fData,
2108
18
                  buffer.fArea.H (),
2109
18
                  buffer.fArea.W () / xFactor,
2110
18
                  buffer.fPlanes    * xFactor);
2111
          
2112
18
          return;
2113
          
2114
0
          }
2115
          
2116
2
        case ttShort:
2117
2
          {
2118
          
2119
2
          DecodeDelta16 ((uint16 *) buffer.fData,
2120
2
                   buffer.fArea.H (),
2121
2
                   buffer.fArea.W () / xFactor,
2122
2
                   buffer.fPlanes    * xFactor);
2123
          
2124
2
          return;
2125
          
2126
0
          }
2127
          
2128
0
        case ttLong:
2129
0
          {
2130
          
2131
0
          DecodeDelta32 ((uint32 *) buffer.fData,
2132
0
                   buffer.fArea.H (),
2133
0
                   buffer.fArea.W () / xFactor,
2134
0
                   buffer.fPlanes    * xFactor);
2135
          
2136
0
          return;
2137
          
2138
0
          }
2139
          
2140
0
        default:
2141
0
          break;
2142
          
2143
20
        }
2144
      
2145
0
      break;
2146
      
2147
20
      }
2148
      
2149
0
    default:
2150
0
      break;
2151
    
2152
80
    }
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
3.27k
  {
2172
  
2173
3.27k
  switch (ifd.fCompression)
2174
3.27k
    {
2175
    
2176
0
    case ccLZW:
2177
148
    case ccDeflate:
2178
148
    case ccOldDeflate:
2179
148
    case ccPackBits:
2180
148
      {
2181
      
2182
      // Figure out uncompressed size.
2183
      
2184
148
      uint32 bytesPerSample = (ifd.fBitsPerSample [0] >> 3);
2185
      
2186
148
      uint32 rowStep = 0;
2187
      
2188
148
      uint32 sampleCount = 0;
2189
        
2190
148
      if (!SafeUint32Mult (planes, tileArea.W (), &rowStep) ||
2191
148
         !SafeUint32Mult (rowStep, tileArea.H (), &sampleCount))
2192
8
        {
2193
        
2194
8
        ThrowMemoryFull ("Arithmetic overflow computing sample count.");
2195
        
2196
8
        }
2197
        
2198
      // Setup pixel buffer to hold uncompressed data.
2199
      
2200
148
      uint32 pixelType = ttUndefined;
2201
      
2202
148
      if (ifd.fSampleFormat [0] == sfFloatingPoint)
2203
17
        {
2204
17
        pixelType = ttFloat;
2205
17
        }
2206
      
2207
131
      else if (ifd.fBitsPerSample [0] == 8)
2208
117
        {
2209
117
        pixelType = ttByte;
2210
117
        }
2211
        
2212
14
      else if (ifd.fBitsPerSample [0] == 16)
2213
6
        {
2214
6
        pixelType = ttShort;
2215
6
        }
2216
        
2217
8
      else if (ifd.fBitsPerSample [0] == 32)
2218
0
        {
2219
0
        pixelType = ttLong;
2220
0
        }
2221
        
2222
8
      else
2223
8
        {
2224
8
        ThrowBadFormat ();
2225
8
        }
2226
        
2227
148
      uint32 uncompressedSize = ComputeBufferSize (pixelType, tileArea.Size(),
2228
148
         planes, padNone);
2229
      
2230
148
      dng_pixel_buffer buffer (tileArea, plane, planes, pixelType, pcInterleaved,
2231
148
         NULL);
2232
      
2233
148
      uint32 bufferSize = uncompressedSize;
2234
      
2235
      // If we are using the floating point predictor, we need an extra
2236
      // buffer row.
2237
      
2238
148
      if (ifd.fPredictor == cpFloatingPoint   ||
2239
148
        ifd.fPredictor == cpFloatingPointX2 ||
2240
148
        ifd.fPredictor == cpFloatingPointX4)
2241
15
        {
2242
15
        uint32 rowSize = 0;
2243
15
        if (!SafeUint32Mult (rowStep, buffer.fPixelSize, &rowSize) ||
2244
15
           !SafeUint32Add (bufferSize, rowSize, &bufferSize))
2245
0
          {
2246
          
2247
0
          ThrowMemoryFull ("Arithmetic overflow computing buffer size.");
2248
          
2249
0
          }
2250
15
        }
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
148
      if (buffer.fPixelType == ttFloat)
2256
17
        {
2257
17
        bufferSize = Max_uint32 (bufferSize,
2258
17
                     SafeUint32Mult(sampleCount, 4));
2259
17
        }
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
148
      if (uncompressedBuffer.Get () &&
2266
148
        uncompressedBuffer->LogicalSize () < bufferSize)
2267
0
        {
2268
        
2269
0
        uncompressedBuffer.Reset ();
2270
        
2271
0
        }
2272
        
2273
148
      if (uncompressedBuffer.Get () == NULL)
2274
128
        {
2275
2276
128
        uncompressedBuffer.Reset (host.Allocate (bufferSize));
2277
                      
2278
128
        }
2279
        
2280
148
      buffer.fData = uncompressedBuffer->Buffer ();
2281
      
2282
      // If using floating point predictor, move buffer pointer to second row.
2283
      
2284
148
      if (ifd.fPredictor == cpFloatingPoint   ||
2285
148
        ifd.fPredictor == cpFloatingPointX2 ||
2286
148
        ifd.fPredictor == cpFloatingPointX4)
2287
15
        {
2288
        
2289
15
        buffer.fData = (uint8 *) buffer.fData +
2290
15
                 buffer.fRowStep * buffer.fPixelSize;
2291
                 
2292
15
        }
2293
      
2294
      // Decompress the data.
2295
      
2296
148
      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
148
      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
148
      else
2327
148
        {
2328
        
2329
148
        uLongf dstLen = uncompressedSize;
2330
              
2331
148
        int err = uncompress ((Bytef *) buffer.fData,
2332
148
                    &dstLen,
2333
148
                    (const Bytef *) compressedBuffer->Buffer (),
2334
148
                    tileByteCount);
2335
                    
2336
148
        if (err != Z_OK)
2337
128
          {
2338
          
2339
128
          if (err == Z_MEM_ERROR)
2340
0
            {
2341
0
            ThrowMemoryFull ();
2342
0
            }
2343
            
2344
128
          else if (err == Z_DATA_ERROR)
2345
128
            {
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
128
            }
2351
            
2352
0
          else
2353
0
            {
2354
0
            ThrowBadFormat ();
2355
0
            }
2356
            
2357
128
          }
2358
          
2359
148
        if (dstLen != uncompressedSize)
2360
37
          {
2361
37
          ThrowBadFormat ();
2362
37
          }
2363
        
2364
148
        }
2365
        
2366
      // The floating point predictor is byte order independent.
2367
      
2368
148
      if (ifd.fPredictor == cpFloatingPoint   ||
2369
148
        ifd.fPredictor == cpFloatingPointX2 ||
2370
148
        ifd.fPredictor == cpFloatingPointX4)
2371
11
        {
2372
        
2373
11
        int32 xFactor = 1;
2374
        
2375
11
        if (ifd.fPredictor == cpFloatingPointX2)
2376
0
          {
2377
0
          xFactor = 2;
2378
0
          }
2379
          
2380
11
        else if (ifd.fPredictor == cpFloatingPointX4)
2381
0
          {
2382
0
          xFactor = 4;
2383
0
          }
2384
        
2385
11
        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
11
        buffer.fData = (uint8 *) buffer.fData -
2407
11
                 buffer.fRowStep * buffer.fPixelSize;
2408
                 
2409
11
        }
2410
        
2411
137
      else
2412
137
        {
2413
        
2414
        // Both these compression algorithms are byte based.
2415
        
2416
137
        if (stream.SwapBytes ())
2417
0
          {
2418
          
2419
0
          ByteSwapBuffer (host,
2420
0
                  buffer);
2421
                  
2422
0
          }
2423
          
2424
        // Undo the predictor.
2425
        
2426
137
        DecodePredictor (host,
2427
137
                 ifd,
2428
137
                 buffer);
2429
                 
2430
137
        }
2431
        
2432
      // Expand floating point data, if needed.
2433
      
2434
148
      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
148
      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
148
      image.Put (buffer);
2500
      
2501
148
      return;
2502
      
2503
148
      }
2504
  
2505
1.50k
    case ccUncompressed:
2506
1.50k
      {
2507
      
2508
1.50k
      if (ReadUncompressed (host,
2509
1.50k
                  ifd,
2510
1.50k
                  stream,
2511
1.50k
                  image,
2512
1.50k
                  tileArea,
2513
1.50k
                  plane,
2514
1.50k
                  planes,
2515
1.50k
                  uncompressedBuffer,
2516
1.50k
                  subTileBlockBuffer))
2517
1.05k
        {
2518
        
2519
1.05k
        return;
2520
        
2521
1.05k
        }
2522
        
2523
457
      break;
2524
      
2525
1.50k
      }
2526
      
2527
1.56k
    case ccJPEG:
2528
1.56k
      {
2529
      
2530
1.56k
      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
1.56k
      else
2553
1.56k
        {
2554
        
2555
        // Otherwise is should be lossless JPEG.
2556
        
2557
1.56k
        if (ReadLosslessJPEG (host,
2558
1.56k
                    ifd,
2559
1.56k
                    stream,
2560
1.56k
                    image,
2561
1.56k
                    tileArea,
2562
1.56k
                    plane,
2563
1.56k
                    planes,
2564
1.56k
                    tileByteCount,
2565
1.56k
                    uncompressedBuffer,
2566
1.56k
                    subTileBlockBuffer))
2567
45
          {
2568
          
2569
45
          return;
2570
          
2571
45
          }
2572
        
2573
1.56k
        }
2574
      
2575
1.51k
      break;
2576
      
2577
1.56k
      }
2578
      
2579
1.51k
    case ccLossyJPEG:
2580
55
      {
2581
      
2582
55
      if (ReadBaselineJPEG (host,
2583
55
                  ifd,
2584
55
                  stream,
2585
55
                  image,
2586
55
                  tileArea,
2587
55
                  plane,
2588
55
                  planes,
2589
55
                  tileByteCount,
2590
55
                  compressedBuffer.Get () ? compressedBuffer->Buffer_uint8 () : NULL))
2591
0
        {
2592
        
2593
0
        return;
2594
        
2595
0
        }
2596
              
2597
55
      break;
2598
      
2599
55
      }
2600
      
2601
55
    default:
2602
0
      break;
2603
      
2604
3.27k
    }
2605
    
2606
0
  ThrowBadFormat ();
2607
    
2608
0
  }
2609
2610
/*****************************************************************************/
2611
2612
bool dng_read_image::CanRead (const dng_ifd &ifd)
2613
0
  {
2614
  
2615
0
  if (ifd.fImageWidth  < 1 ||
2616
0
    ifd.fImageLength < 1)
2617
0
    {
2618
0
    return false;
2619
0
    }
2620
    
2621
0
  if (ifd.fSamplesPerPixel < 1)
2622
0
    {
2623
0
    return false;
2624
0
    }
2625
    
2626
0
  if (ifd.fBitsPerSample [0] < 1)
2627
0
    {
2628
0
    return false;
2629
0
    }
2630
  
2631
0
  for (uint32 j = 1; j < Min_uint32 (ifd.fSamplesPerPixel,
2632
0
                     kMaxSamplesPerPixel); j++)
2633
0
    {
2634
    
2635
0
    if (ifd.fBitsPerSample [j] !=
2636
0
      ifd.fBitsPerSample [0])
2637
0
      {
2638
0
      return false;
2639
0
      }
2640
      
2641
0
    if (ifd.fSampleFormat [j] !=
2642
0
      ifd.fSampleFormat [0])
2643
0
      {
2644
0
      return false;
2645
0
      }
2646
2647
0
    }
2648
    
2649
0
  if ((ifd.fPlanarConfiguration != pcInterleaved   ) &&
2650
0
    (ifd.fPlanarConfiguration != pcPlanar        ) &&
2651
0
    (ifd.fPlanarConfiguration != pcRowInterleaved))
2652
0
    {
2653
0
    return false;
2654
0
    }
2655
    
2656
0
  if (ifd.fUsesStrips == ifd.fUsesTiles)
2657
0
    {
2658
0
    return false;
2659
0
    }
2660
    
2661
0
  uint32 tileCount = ifd.TilesPerImage ();
2662
  
2663
0
  if (tileCount < 1)
2664
0
    {
2665
0
    return false;
2666
0
    }
2667
    
2668
0
  bool needTileByteCounts = (ifd.TileByteCount (ifd.TileArea (0, 0)) == 0);
2669
    
2670
0
  if (tileCount == 1)
2671
0
    {
2672
    
2673
0
    if (needTileByteCounts)
2674
0
      {
2675
      
2676
0
      if (ifd.fTileByteCount [0] < 1)
2677
0
        {
2678
0
        return false;
2679
0
        }
2680
      
2681
0
      }
2682
    
2683
0
    }
2684
    
2685
0
  else
2686
0
    {
2687
    
2688
0
    if (ifd.fTileOffsetsCount != tileCount)
2689
0
      {
2690
0
      return false;
2691
0
      }
2692
      
2693
0
    if (needTileByteCounts)
2694
0
      {
2695
      
2696
0
      if (ifd.fTileByteCountsCount != tileCount)
2697
0
        {
2698
0
        return false;
2699
0
        }
2700
      
2701
0
      }
2702
    
2703
0
    }
2704
    
2705
0
  if (!CanReadTile (ifd))
2706
0
    {
2707
0
    return false;
2708
0
    }
2709
    
2710
0
  return true;
2711
  
2712
0
  }
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
3.30k
  {
2921
  
2922
3.30k
  uint32 tileIndex;
2923
  
2924
  // Deal with row interleaved images.
2925
  
2926
3.30k
  if (ifd.fRowInterleaveFactor > 1 &&
2927
3.30k
    ifd.fRowInterleaveFactor < ifd.fImageLength)
2928
46
    {
2929
    
2930
46
    dng_ifd tempIFD (ifd);
2931
    
2932
46
    tempIFD.fRowInterleaveFactor = 1;
2933
    
2934
46
    dng_row_interleaved_image tempImage (image,
2935
46
                       ifd.fRowInterleaveFactor);
2936
    
2937
46
    Read (host,
2938
46
        tempIFD,
2939
46
        stream,
2940
46
        tempImage,
2941
46
        jpegImage,
2942
46
        jpegDigest);
2943
        
2944
46
    return;
2945
    
2946
46
    }
2947
  
2948
  // Figure out inner and outer samples.
2949
  
2950
3.26k
  uint32 innerSamples = 1;
2951
3.26k
  uint32 outerSamples = 1;
2952
  
2953
3.26k
  if (ifd.fPlanarConfiguration == pcPlanar)
2954
0
    {
2955
0
    outerSamples = ifd.fSamplesPerPixel;
2956
0
    }
2957
3.26k
  else
2958
3.26k
    {
2959
3.26k
    innerSamples = ifd.fSamplesPerPixel;
2960
3.26k
    }
2961
  
2962
  // Calculate number of tiles to read.
2963
  
2964
3.26k
  uint32 tilesAcross = ifd.TilesAcross ();
2965
3.26k
  uint32 tilesDown   = ifd.TilesDown   ();
2966
  
2967
3.26k
  uint32 tileCount = SafeUint32Mult (tilesAcross, tilesDown, outerSamples);
2968
  
2969
  // Find the tile offsets.
2970
    
2971
3.26k
  dng_memory_data tileOffsetData (tileCount, sizeof (uint64));
2972
  
2973
3.26k
  uint64 *tileOffset = tileOffsetData.Buffer_uint64 ();
2974
  
2975
3.26k
  if (tileCount <= dng_ifd::kMaxTileInfo)
2976
3.25k
    {
2977
    
2978
7.87k
    for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
2979
4.62k
      {
2980
      
2981
4.62k
      tileOffset [tileIndex] = ifd.fTileOffset [tileIndex];
2982
      
2983
4.62k
      }
2984
    
2985
3.25k
    }
2986
    
2987
8
  else
2988
8
    {
2989
    
2990
8
    stream.SetReadPosition (ifd.fTileOffsetsOffset);
2991
    
2992
8
    for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
2993
0
      {
2994
      
2995
0
      tileOffset [tileIndex] = stream.TagValue_uint32 (ifd.fTileOffsetsType);
2996
      
2997
0
      }
2998
    
2999
8
    }
3000
    
3001
  // Quick validity check on tile offsets.
3002
  
3003
7.09k
  for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3004
3.83k
    {
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
3.83k
    if (tileOffset [tileIndex] >= stream.Length ())
3018
337
      {
3019
      
3020
337
      ThrowBadFormat ();
3021
      
3022
337
      }
3023
    
3024
3.83k
    }
3025
    
3026
  // Buffer to hold the tile byte counts, if needed.
3027
  
3028
3.26k
  dng_memory_data tileByteCountData;
3029
  
3030
3.26k
  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
3.26k
  uint32 uncompressedSize = 0;
3036
3037
3.26k
  uint32 subTileLength = ifd.fTileLength;
3038
  
3039
3.26k
  if (ifd.TileByteCount (ifd.TileArea (0, 0)) != 0)
3040
701
    {
3041
    
3042
701
    uint32 bytesPerPixel = TagTypeSize (ifd.PixelType ());
3043
    
3044
701
    uint32 bytesPerRow = SafeUint32Mult (ifd.fTileWidth, innerSamples,
3045
701
                       bytesPerPixel);
3046
        
3047
701
    subTileLength = Pin_uint32 (ifd.fSubTileBlockRows,
3048
701
                  kImageBufferSize / bytesPerRow, 
3049
701
                  ifd.fTileLength);
3050
                  
3051
701
    subTileLength = subTileLength / ifd.fSubTileBlockRows
3052
701
                    * ifd.fSubTileBlockRows;
3053
                    
3054
701
    uncompressedSize = SafeUint32Mult (subTileLength, bytesPerRow);
3055
                  
3056
701
    }
3057
    
3058
  // Else we need to know the byte counts.
3059
  
3060
2.55k
  else
3061
2.55k
    {
3062
    
3063
2.55k
    tileByteCountData.Allocate (tileCount, sizeof (uint32));
3064
    
3065
2.55k
    tileByteCount = tileByteCountData.Buffer_uint32 ();
3066
    
3067
2.55k
    if (tileCount <= dng_ifd::kMaxTileInfo)
3068
2.14k
      {
3069
      
3070
4.51k
      for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3071
2.36k
        {
3072
        
3073
2.36k
        tileByteCount [tileIndex] = ifd.fTileByteCount [tileIndex];
3074
        
3075
2.36k
        }
3076
      
3077
2.14k
      }
3078
      
3079
411
    else
3080
411
      {
3081
      
3082
411
      stream.SetReadPosition (ifd.fTileByteCountsOffset);
3083
      
3084
411
      for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3085
0
        {
3086
        
3087
0
        tileByteCount [tileIndex] = stream.TagValue_uint32 (ifd.fTileByteCountsType);
3088
        
3089
0
        }
3090
      
3091
411
      }
3092
      
3093
    // Quick validity check on tile byte counts.
3094
    
3095
4.86k
    for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3096
2.30k
      {
3097
      
3098
2.30k
      if (tileByteCount [tileIndex] < 1 ||
3099
2.30k
        tileByteCount [tileIndex] > stream.Length ())
3100
69
        {
3101
        
3102
69
        ThrowBadFormat ();
3103
        
3104
69
        }
3105
      
3106
2.30k
      }
3107
    
3108
2.55k
    }
3109
    
3110
  // Find maximum tile size, if possible.
3111
    
3112
3.26k
  uint32 maxTileByteCount = 0;
3113
  
3114
3.26k
  if (tileByteCount)
3115
2.07k
    {
3116
    
3117
4.29k
    for (tileIndex = 0; tileIndex < tileCount; tileIndex++)
3118
2.21k
      {
3119
      
3120
2.21k
      maxTileByteCount = Max_uint32 (maxTileByteCount,
3121
2.21k
                       tileByteCount [tileIndex]);
3122
                       
3123
2.21k
      }
3124
      
3125
2.07k
    }
3126
    
3127
  // Do we need a compressed data buffer?
3128
3129
3.26k
  uint32 compressedSize = 0;
3130
  
3131
3.26k
  bool needsCompressedBuffer = NeedsCompressedBuffer (ifd);
3132
  
3133
3.26k
  if (needsCompressedBuffer)
3134
152
    {
3135
    
3136
152
    if (!tileByteCount)
3137
0
      {
3138
0
      ThrowBadFormat ();
3139
0
      }
3140
    
3141
152
    compressedSize = maxTileByteCount;
3142
    
3143
152
    }
3144
    
3145
  // Are we keeping the compressed JPEG image data?
3146
  
3147
3.26k
  if (jpegImage)
3148
0
    {
3149
    
3150
0
    if (ifd.IsBaselineJPEG ())
3151
0
      {
3152
      
3153
0
      jpegImage->fImageSize.h = ifd.fImageWidth;
3154
0
      jpegImage->fImageSize.v = ifd.fImageLength;
3155
      
3156
0
      jpegImage->fTileSize.h = ifd.fTileWidth;
3157
0
      jpegImage->fTileSize.v = ifd.fTileLength;
3158
      
3159
0
      jpegImage->fUsesStrips = ifd.fUsesStrips;
3160
      
3161
0
      jpegImage->fJPEGData.Reset (tileCount);
3162
            
3163
0
      }
3164
      
3165
0
    else
3166
0
      {
3167
      
3168
0
      jpegImage = NULL;
3169
      
3170
0
      }
3171
    
3172
0
    }
3173
    
3174
  // Do we need to read the JPEG tables?
3175
  
3176
3.26k
  if (ifd.fJPEGTablesOffset && ifd.fJPEGTablesCount)
3177
49
    {
3178
  
3179
49
    if (ifd.IsBaselineJPEG ())
3180
25
      {
3181
      
3182
25
      fJPEGTables.Reset (host.Allocate (ifd.fJPEGTablesCount));
3183
      
3184
25
      stream.SetReadPosition (ifd.fJPEGTablesOffset);
3185
      
3186
25
      stream.Get (fJPEGTables->Buffer      (),
3187
25
            fJPEGTables->LogicalSize ());
3188
      
3189
25
      }
3190
      
3191
49
    }
3192
    
3193
3.26k
  AutoArray<dng_fingerprint> jpegTileDigest;
3194
  
3195
3.26k
  if (jpegDigest)
3196
113
    {
3197
    
3198
113
    jpegTileDigest.Reset (
3199
113
      SafeUint32Add(tileCount, (fJPEGTables.Get () ? 1 : 0)));
3200
    
3201
113
    }
3202
      
3203
  // Don't read planes we are not actually saving.
3204
  
3205
3.26k
  outerSamples = Min_uint32 (image.Planes (), outerSamples);
3206
    
3207
  // See if we can do this read using multiple threads.
3208
  
3209
3.26k
  bool useMultipleThreads = (outerSamples * tilesDown * tilesAcross >= 2) &&
3210
3.26k
                (host.PerformAreaTaskThreads () > 1) &&
3211
3.26k
                (maxTileByteCount > 0 && maxTileByteCount <= 1024 * 1024) &&
3212
3.26k
                (subTileLength == ifd.fTileLength) &&
3213
3.26k
                (ifd.fCompression != ccUncompressed);
3214
  
3215
#if qImagecore
3216
  useMultipleThreads = false; 
3217
#endif
3218
    
3219
3.26k
  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
3.26k
  else
3249
3.26k
    {
3250
    
3251
3.26k
    AutoPtr<dng_memory_block> compressedBuffer;
3252
3.26k
    AutoPtr<dng_memory_block> uncompressedBuffer;
3253
3.26k
    AutoPtr<dng_memory_block> subTileBlockBuffer;
3254
    
3255
3.26k
    if (uncompressedSize)
3256
701
      {
3257
701
      uncompressedBuffer.Reset (host.Allocate (uncompressedSize));
3258
701
      }
3259
      
3260
3.26k
    if (compressedSize && !jpegImage)
3261
152
      {
3262
152
      compressedBuffer.Reset (host.Allocate (compressedSize));
3263
152
      }
3264
      
3265
3.10k
    else if (jpegDigest)
3266
113
      {
3267
113
      compressedBuffer.Reset (host.Allocate (maxTileByteCount));
3268
113
      }
3269
      
3270
3.26k
    tileIndex = 0;
3271
    
3272
6.03k
    for (uint32 plane = 0; plane < outerSamples; plane++)
3273
2.77k
      {
3274
      
3275
5.68k
      for (uint32 rowIndex = 0; rowIndex < tilesDown; rowIndex++)
3276
2.90k
        {
3277
        
3278
5.89k
        for (uint32 colIndex = 0; colIndex < tilesAcross; colIndex++)
3279
2.99k
          {
3280
          
3281
2.99k
          stream.SetReadPosition (tileOffset [tileIndex]);
3282
          
3283
2.99k
          dng_rect tileArea = ifd.TileArea (rowIndex, colIndex);
3284
          
3285
2.99k
          uint32 subTileCount = (tileArea.H () + subTileLength - 1) /
3286
2.99k
                      subTileLength;
3287
                      
3288
6.26k
          for (uint32 subIndex = 0; subIndex < subTileCount; subIndex++)
3289
3.27k
            {
3290
            
3291
3.27k
            host.SniffForAbort ();
3292
          
3293
3.27k
            dng_rect subArea (tileArea);
3294
            
3295
3.27k
            subArea.t = tileArea.t + subIndex * subTileLength;
3296
            
3297
3.27k
            subArea.b = Min_int32 (subArea.t + subTileLength,
3298
3.27k
                         tileArea.b);
3299
            
3300
3.27k
            uint32 subByteCount;
3301
            
3302
3.27k
            if (tileByteCount)
3303
1.83k
              {
3304
1.83k
              subByteCount = tileByteCount [tileIndex];
3305
1.83k
              }
3306
1.43k
            else
3307
1.43k
              {
3308
1.43k
              subByteCount = ifd.TileByteCount (subArea);
3309
1.43k
              }
3310
              
3311
3.27k
            if (jpegImage)
3312
0
              {
3313
              
3314
0
              jpegImage->fJPEGData [tileIndex].Reset (host.Allocate (subByteCount));
3315
              
3316
0
              stream.Get (jpegImage->fJPEGData [tileIndex]->Buffer (), subByteCount);
3317
              
3318
0
              stream.SetReadPosition (tileOffset [tileIndex]);
3319
              
3320
0
              }
3321
              
3322
3.27k
            else if ((needsCompressedBuffer || jpegDigest) && subByteCount)
3323
195
              {
3324
              
3325
195
              stream.Get (compressedBuffer->Buffer (), subByteCount);
3326
              
3327
195
              if (jpegDigest)
3328
47
                {
3329
                
3330
47
                dng_md5_printer printer;
3331
                
3332
47
                printer.Process (compressedBuffer->Buffer (),
3333
47
                         subByteCount);
3334
                         
3335
47
                jpegTileDigest [tileIndex] = printer.Result ();
3336
                
3337
47
                }
3338
              
3339
195
              }
3340
              
3341
3.27k
            ReadTile (host,
3342
3.27k
                  ifd,
3343
3.27k
                  stream,
3344
3.27k
                  image,
3345
3.27k
                  subArea,
3346
3.27k
                  plane,
3347
3.27k
                  innerSamples,
3348
3.27k
                  subByteCount,
3349
3.27k
                  jpegImage ? jpegImage->fJPEGData [tileIndex] : compressedBuffer,
3350
3.27k
                  uncompressedBuffer,
3351
3.27k
                  subTileBlockBuffer);
3352
                  
3353
3.27k
            }
3354
          
3355
2.99k
          tileIndex++;
3356
          
3357
2.99k
          }
3358
          
3359
2.90k
        }
3360
3361
2.77k
      }
3362
      
3363
3.26k
    }
3364
    
3365
  // Finish up JPEG digest computation, if needed.
3366
  
3367
3.26k
  if (jpegDigest)
3368
66
    {
3369
    
3370
66
    if (fJPEGTables.Get ())
3371
2
      {
3372
      
3373
2
      dng_md5_printer printer;
3374
      
3375
2
      printer.Process (fJPEGTables->Buffer      (),
3376
2
               fJPEGTables->LogicalSize ());
3377
               
3378
2
      jpegTileDigest [tileCount] = printer.Result ();
3379
      
3380
2
      }
3381
      
3382
66
    dng_md5_printer printer2;
3383
    
3384
134
    for (uint32 j = 0; j < tileCount + (fJPEGTables.Get () ? 1 : 0); j++)
3385
68
      {
3386
      
3387
68
      printer2.Process (jpegTileDigest [j].data,
3388
68
                dng_fingerprint::kDNGFingerprintSize);
3389
                
3390
68
      }
3391
      
3392
66
    *jpegDigest = printer2.Result ();
3393
    
3394
66
    }
3395
    
3396
  // Keep the JPEG table in the jpeg image, if any.
3397
  
3398
3.26k
  if (jpegImage)
3399
0
    {
3400
    
3401
0
    jpegImage->fJPEGTables.Reset (fJPEGTables.Release ());
3402
    
3403
0
    }
3404
3405
3.26k
  }
3406
3407
/*****************************************************************************/