Coverage Report

Created: 2025-01-23 06:31

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