Coverage Report

Created: 2021-08-22 09:07

/src/skia/third_party/externals/dng_sdk/source/dng_jpeg_image.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************/
2
// Copyright 2011 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_jpeg_image.cpp#1 $ */ 
10
/* $DateTime: 2012/05/30 13:28:51 $ */
11
/* $Change: 832332 $ */
12
/* $Author: tknoll $ */
13
14
/*****************************************************************************/
15
16
#include "dng_jpeg_image.h"
17
18
#include "dng_abort_sniffer.h"
19
#include "dng_area_task.h"
20
#include "dng_assertions.h"
21
#include "dng_host.h"
22
#include "dng_ifd.h"
23
#include "dng_image.h"
24
#include "dng_image_writer.h"
25
#include "dng_memory_stream.h"
26
#include "dng_mutex.h"
27
#include "dng_safe_arithmetic.h"
28
29
/*****************************************************************************/
30
31
dng_jpeg_image::dng_jpeg_image ()
32
33
  : fImageSize  ()
34
  , fTileSize   ()
35
  , fUsesStrips (false)
36
  , fJPEGTables ()
37
  , fJPEGData   ()
38
  
39
0
  {
40
  
41
0
  }
42
43
/*****************************************************************************/
44
45
class dng_jpeg_image_encode_task : public dng_area_task
46
  {
47
  
48
  private:
49
  
50
    dng_host &fHost;
51
    
52
    dng_image_writer &fWriter;
53
    
54
    const dng_image &fImage;
55
  
56
    dng_jpeg_image &fJPEGImage;
57
    
58
    uint32 fTileCount;
59
    
60
    const dng_ifd &fIFD;
61
        
62
    dng_mutex fMutex;
63
    
64
    uint32 fNextTileIndex;
65
    
66
  public:
67
  
68
    dng_jpeg_image_encode_task (dng_host &host,
69
                  dng_image_writer &writer,
70
                  const dng_image &image,
71
                  dng_jpeg_image &jpegImage,
72
                  uint32 tileCount,
73
                  const dng_ifd &ifd)
74
    
75
      : fHost       (host)
76
      , fWriter       (writer)
77
      , fImage        (image)
78
      , fJPEGImage        (jpegImage)
79
      , fTileCount      (tileCount)
80
      , fIFD          (ifd)
81
      , fMutex        ("dng_jpeg_image_encode_task")
82
      , fNextTileIndex    (0)
83
      
84
0
      {
85
      
86
0
      fMinTaskArea = 16 * 16;
87
0
      fUnitCell    = dng_point (16, 16);
88
0
      fMaxTileSize = dng_point (16, 16);
89
      
90
0
      }
91
  
92
    void Process (uint32 /* threadIndex */,
93
            const dng_rect & /* tile */,
94
            dng_abort_sniffer *sniffer)
95
0
      {
96
      
97
0
      AutoPtr<dng_memory_block> compressedBuffer;
98
0
      AutoPtr<dng_memory_block> uncompressedBuffer;
99
0
      AutoPtr<dng_memory_block> subTileBlockBuffer;
100
0
      AutoPtr<dng_memory_block> tempBuffer;
101
      
102
0
      uint32 uncompressedSize = SafeUint32Mult (
103
0
        fIFD.fTileLength, fIFD.fTileWidth, fIFD.fSamplesPerPixel);
104
      
105
0
      uncompressedBuffer.Reset (fHost.Allocate (uncompressedSize));
106
      
107
0
      uint32 tilesAcross = fIFD.TilesAcross ();
108
  
109
0
      while (true)
110
0
        {
111
        
112
0
        uint32 tileIndex;
113
        
114
0
          {
115
          
116
0
          dng_lock_mutex lock (&fMutex);
117
          
118
0
          if (fNextTileIndex == fTileCount)
119
0
            {
120
0
            return;
121
0
            }
122
            
123
0
          tileIndex = fNextTileIndex++;
124
                    
125
0
          }
126
          
127
0
        dng_abort_sniffer::SniffForAbort (sniffer);
128
        
129
0
        uint32 rowIndex = tileIndex / tilesAcross;
130
0
        uint32 colIndex = tileIndex % tilesAcross;
131
        
132
0
        dng_rect tileArea = fIFD.TileArea (rowIndex, colIndex);
133
        
134
0
        dng_memory_stream stream (fHost.Allocator ());
135
        
136
0
        fWriter.WriteTile (fHost,
137
0
                   fIFD,
138
0
                   stream,
139
0
                   fImage,
140
0
                   tileArea,
141
0
                   1,
142
0
                   compressedBuffer,
143
0
                   uncompressedBuffer,
144
0
                   subTileBlockBuffer,
145
0
                   tempBuffer);
146
                  
147
0
        fJPEGImage.fJPEGData [tileIndex].Reset (stream.AsMemoryBlock (fHost.Allocator ()));
148
          
149
0
        }
150
      
151
0
      }
152
    
153
  private:
154
155
    // Hidden copy constructor and assignment operator.
156
157
    dng_jpeg_image_encode_task (const dng_jpeg_image_encode_task &);
158
159
    dng_jpeg_image_encode_task & operator= (const dng_jpeg_image_encode_task &);
160
    
161
  };
162
163
/*****************************************************************************/
164
165
void dng_jpeg_image::Encode (dng_host &host,
166
               const dng_negative &negative,
167
               dng_image_writer &writer,
168
               const dng_image &image)
169
0
  {
170
  
171
  #if qDNGValidate
172
  dng_timer timer ("Encode JPEG Proxy time");
173
  #endif
174
  
175
0
  DNG_ASSERT (image.PixelType () == ttByte, "Cannot JPEG encode non-byte image");
176
  
177
0
  fImageSize = image.Bounds ().Size ();
178
  
179
0
  dng_ifd ifd;
180
  
181
0
  ifd.fImageWidth  = fImageSize.h;
182
0
  ifd.fImageLength = fImageSize.v;
183
  
184
0
  ifd.fSamplesPerPixel = image.Planes ();
185
  
186
0
  ifd.fBitsPerSample [0] = 8;
187
0
  ifd.fBitsPerSample [1] = 8;
188
0
  ifd.fBitsPerSample [2] = 8;
189
0
  ifd.fBitsPerSample [3] = 8;
190
  
191
0
  ifd.fPhotometricInterpretation = piLinearRaw;
192
  
193
0
  ifd.fCompression = ccLossyJPEG;
194
  
195
0
  ifd.FindTileSize (512 * 512 * ifd.fSamplesPerPixel);
196
  
197
0
  fTileSize.h = ifd.fTileWidth;
198
0
  fTileSize.v = ifd.fTileLength;
199
  
200
  // Need a higher quality for raw proxies than non-raw proxies,
201
  // since users often perform much greater color changes.  Also, use
202
  // we are targeting a "large" size proxy (larger than 5MP pixels), or this
203
  // is a full size proxy, then use a higher quality.
204
  
205
0
  bool useHigherQuality = (uint64) ifd.fImageWidth *
206
0
              (uint64) ifd.fImageLength > 5000000 ||
207
0
              image.Bounds ().Size () == negative.OriginalDefaultFinalSize ();
208
  
209
0
  if (negative.ColorimetricReference () == crSceneReferred)
210
0
    {
211
0
    ifd.fCompressionQuality = useHigherQuality ? 11 : 10;
212
0
    }
213
0
  else
214
0
    {
215
0
    ifd.fCompressionQuality = useHigherQuality ? 10 : 8;
216
0
    }
217
  
218
0
  uint32 tilesAcross = ifd.TilesAcross ();
219
0
  uint32 tilesDown   = ifd.TilesDown   ();
220
  
221
0
  uint32 tileCount = tilesAcross * tilesDown;
222
  
223
0
  fJPEGData.Reset (tileCount);
224
  
225
0
  uint32 threadCount = Min_uint32 (tileCount,
226
0
                   host.PerformAreaTaskThreads ());
227
                     
228
0
  dng_jpeg_image_encode_task task (host,
229
0
                   writer,
230
0
                   image,
231
0
                   *this,
232
0
                   tileCount,
233
0
                   ifd);
234
                    
235
0
  host.PerformAreaTask (task,
236
0
              dng_rect (0, 0, 16, 16 * threadCount));
237
    
238
0
  }
239
      
240
/*****************************************************************************/
241
242
class dng_jpeg_image_find_digest_task : public dng_area_task
243
  {
244
  
245
  private:
246
  
247
    const dng_jpeg_image &fJPEGImage;
248
    
249
    uint32 fTileCount;
250
    
251
    dng_fingerprint *fDigests;
252
        
253
    dng_mutex fMutex;
254
    
255
    uint32 fNextTileIndex;
256
    
257
  public:
258
  
259
    dng_jpeg_image_find_digest_task (const dng_jpeg_image &jpegImage,
260
                     uint32 tileCount,
261
                     dng_fingerprint *digests)
262
    
263
      : fJPEGImage        (jpegImage)
264
      , fTileCount      (tileCount)
265
      , fDigests      (digests)
266
      , fMutex        ("dng_jpeg_image_find_digest_task")
267
      , fNextTileIndex    (0)
268
      
269
0
      {
270
      
271
0
      fMinTaskArea = 16 * 16;
272
0
      fUnitCell    = dng_point (16, 16);
273
0
      fMaxTileSize = dng_point (16, 16);
274
      
275
0
      }
276
  
277
    void Process (uint32 /* threadIndex */,
278
            const dng_rect & /* tile */,
279
            dng_abort_sniffer *sniffer)
280
0
      {
281
      
282
0
      while (true)
283
0
        {
284
        
285
0
        uint32 tileIndex;
286
        
287
0
          {
288
          
289
0
          dng_lock_mutex lock (&fMutex);
290
          
291
0
          if (fNextTileIndex == fTileCount)
292
0
            {
293
0
            return;
294
0
            }
295
            
296
0
          tileIndex = fNextTileIndex++;
297
                    
298
0
          }
299
          
300
0
        dng_abort_sniffer::SniffForAbort (sniffer);
301
        
302
0
        dng_md5_printer printer;
303
        
304
0
        printer.Process (fJPEGImage.fJPEGData [tileIndex]->Buffer      (),
305
0
                 fJPEGImage.fJPEGData [tileIndex]->LogicalSize ());
306
                 
307
0
        fDigests [tileIndex] = printer.Result ();
308
          
309
0
        }
310
      
311
0
      }
312
    
313
  private:
314
315
    // Hidden copy constructor and assignment operator.
316
317
    dng_jpeg_image_find_digest_task (const dng_jpeg_image_find_digest_task &);
318
319
    dng_jpeg_image_find_digest_task & operator= (const dng_jpeg_image_find_digest_task &);
320
    
321
  };
322
323
/*****************************************************************************/
324
325
dng_fingerprint dng_jpeg_image::FindDigest (dng_host &host) const
326
0
  {
327
  
328
0
  uint32 tileCount = TileCount ();
329
  
330
0
  uint32 arrayCount = tileCount + (fJPEGTables.Get () ? 1 : 0);
331
  
332
0
  AutoArray<dng_fingerprint> digests (arrayCount);
333
  
334
  // Compute digest of each compressed tile.
335
336
0
    {
337
    
338
0
    uint32 threadCount = Min_uint32 (tileCount,
339
0
                     host.PerformAreaTaskThreads ());
340
                     
341
0
    dng_jpeg_image_find_digest_task task (*this,
342
0
                        tileCount,
343
0
                        digests.Get ());
344
                      
345
0
    host.PerformAreaTask (task,
346
0
                dng_rect (0, 0, 16, 16 * threadCount));
347
    
348
0
    }
349
  
350
  // Compute digest of JPEG tables, if any.
351
    
352
0
  if (fJPEGTables.Get ())
353
0
    {
354
    
355
0
    dng_md5_printer printer;
356
    
357
0
    printer.Process (fJPEGTables->Buffer      (),
358
0
             fJPEGTables->LogicalSize ());
359
             
360
0
    digests [tileCount] = printer.Result ();
361
    
362
0
    }
363
    
364
  // Combine digests into a single digest.
365
  
366
0
    {
367
    
368
0
    dng_md5_printer printer;
369
    
370
0
    for (uint32 k = 0; k < arrayCount; k++)
371
0
      {
372
    
373
0
      printer.Process (digests [k].data,
374
0
               dng_fingerprint::kDNGFingerprintSize);
375
               
376
0
      }
377
      
378
0
    return printer.Result ();
379
    
380
0
    }
381
  
382
0
  }
383
      
384
/*****************************************************************************/
385