Coverage Report

Created: 2026-01-17 06:44

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