Coverage Report

Created: 2021-08-22 09:07

/src/skia/third_party/externals/dng_sdk/source/dng_resample.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************/
2
// Copyright 2006 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_resample.cpp#1 $ */ 
10
/* $DateTime: 2012/05/30 13:28:51 $ */
11
/* $Change: 832332 $ */
12
/* $Author: tknoll $ */
13
14
/*****************************************************************************/
15
16
#include "dng_resample.h"
17
18
#include "dng_assertions.h"
19
#include "dng_bottlenecks.h"
20
#include "dng_filter_task.h"
21
#include "dng_host.h"
22
#include "dng_image.h"
23
#include "dng_memory.h"
24
#include "dng_pixel_buffer.h"
25
#include "dng_safe_arithmetic.h"
26
#include "dng_tag_types.h"
27
#include "dng_utils.h"
28
29
/******************************************************************************/
30
31
real64 dng_resample_bicubic::Extent () const
32
0
  {
33
  
34
0
  return 2.0;
35
  
36
0
  }
37
38
/******************************************************************************/
39
40
real64 dng_resample_bicubic::Evaluate (real64 x) const
41
0
  {
42
  
43
0
  const real64 A = -0.75; 
44
  
45
0
  x = Abs_real64 (x);
46
47
0
    if (x >= 2.0)
48
0
        return 0.0;
49
        
50
0
    else if (x >= 1.0)
51
0
        return (((A * x - 5.0 * A) * x + 8.0 * A) * x - 4.0 * A);
52
        
53
0
    else
54
0
        return (((A + 2.0) * x - (A + 3.0)) * x * x + 1.0);
55
    
56
0
  }
57
58
/******************************************************************************/
59
60
const dng_resample_function & dng_resample_bicubic::Get ()
61
0
  {
62
  
63
0
  static dng_resample_bicubic static_dng_resample_bicubic;
64
  
65
0
  return static_dng_resample_bicubic;
66
  
67
0
  }
68
69
/*****************************************************************************/
70
71
dng_resample_coords::dng_resample_coords ()
72
73
  : fOrigin (0)
74
  , fCoords ()
75
  
76
0
  {
77
  
78
0
  }
79
80
/*****************************************************************************/
81
82
dng_resample_coords::~dng_resample_coords ()
83
0
  {
84
  
85
0
  }
86
87
/*****************************************************************************/
88
89
void dng_resample_coords::Initialize (int32 srcOrigin,
90
                    int32 dstOrigin,
91
                    uint32 srcCount,
92
                    uint32 dstCount,
93
                    dng_memory_allocator &allocator)
94
0
  {
95
  
96
0
  fOrigin = dstOrigin;
97
  
98
0
  uint32 dstEntries = 0;
99
0
  uint32 bufferSize = 0;
100
0
  if (!RoundUpUint32ToMultiple(dstCount, 8, &dstEntries) ||
101
0
      !SafeUint32Mult(dstEntries, sizeof(int32), &bufferSize)) {
102
0
    ThrowMemoryFull("Arithmetic overflow computing size for coordinate "
103
0
            "buffer");
104
0
  }
105
0
  fCoords.Reset (allocator.Allocate (bufferSize));
106
  
107
0
  int32 *coords = fCoords->Buffer_int32 ();
108
  
109
0
  real64 invScale = (real64) srcCount /
110
0
            (real64) dstCount;
111
  
112
0
  for (uint32 j = 0; j < dstCount; j++)
113
0
    {
114
    
115
0
    real64 x = (real64) j + 0.5;
116
    
117
0
    real64 y = x * invScale - 0.5 + (real64) srcOrigin;
118
        
119
0
    coords [j] = Round_int32 (y * (real64) kResampleSubsampleCount);
120
    
121
0
    }
122
    
123
  // Pad out table by replicating last entry.
124
  
125
0
  for (uint32 k = dstCount; k < dstEntries; k++)
126
0
    {
127
    
128
0
    coords [k] = coords [dstCount - 1];
129
    
130
0
    }
131
132
0
  }
133
134
/*****************************************************************************/
135
136
dng_resample_weights::dng_resample_weights ()
137
  
138
  : fRadius (0)
139
  
140
  , fWeightStep (0)
141
  
142
  , fWeights32 ()
143
  , fWeights16 ()
144
  
145
0
  {
146
  
147
0
  }
148
149
/*****************************************************************************/
150
151
dng_resample_weights::~dng_resample_weights ()
152
0
  {
153
  
154
0
  }
155
156
/*****************************************************************************/
157
158
void dng_resample_weights::Initialize (real64 scale,
159
                     const dng_resample_function &kernel,
160
                     dng_memory_allocator &allocator)
161
0
  {
162
  
163
0
  uint32 j;
164
  
165
  // We only adjust the kernel size for scale factors less than 1.0.
166
  
167
0
  scale = Min_real64 (scale, 1.0);
168
  
169
  // Find radius of this kernel.
170
  
171
0
  fRadius = (uint32) (kernel.Extent () / scale + 0.9999);
172
  
173
  // Width is twice the radius.
174
  
175
0
  uint32 width = fRadius * 2;
176
  
177
  // Round to each set to weights to a multiple of 8 entries.
178
  
179
0
  if (!RoundUpUint32ToMultiple (width, 8, &fWeightStep))
180
0
    {
181
    
182
0
    ThrowMemoryFull ("Arithmetic overflow computing fWeightStep");
183
    
184
0
    }
185
  
186
  // Allocate and zero weight tables.
187
  
188
0
  uint32 bufferSize = 0;
189
  
190
0
  if (!SafeUint32Mult (fWeightStep, kResampleSubsampleCount, &bufferSize) ||
191
0
     !SafeUint32Mult (bufferSize, (uint32) sizeof (real32), &bufferSize))
192
0
    {
193
    
194
0
    ThrowMemoryFull("Arithmetic overflow computing buffer size.");
195
    
196
0
    }
197
  
198
0
  fWeights32.Reset (allocator.Allocate (bufferSize));
199
  
200
0
  DoZeroBytes (fWeights32->Buffer    (),
201
0
         fWeights32->LogicalSize ());
202
         
203
0
  if (!SafeUint32Mult (fWeightStep, kResampleSubsampleCount, &bufferSize) ||
204
0
     !SafeUint32Mult (bufferSize, (uint32) sizeof (int16), &bufferSize))
205
0
    {
206
    
207
0
    ThrowMemoryFull("Arithmetic overflow computing buffer size.");
208
    
209
0
    }
210
    
211
0
  fWeights16.Reset (allocator.Allocate (bufferSize));
212
                    
213
0
  DoZeroBytes (fWeights16->Buffer    (),
214
0
         fWeights16->LogicalSize ());
215
         
216
  // Compute kernel for each subsample values.
217
  
218
0
  for (uint32 sample = 0; sample < kResampleSubsampleCount; sample++)
219
0
    {
220
    
221
0
    real64 fract = sample * (1.0 / (real64) kResampleSubsampleCount);
222
    
223
0
    real32 *w32 = fWeights32->Buffer_real32 () + fWeightStep * sample;
224
    
225
    // Evaluate kernel function for 32 bit weights.
226
    
227
0
      {
228
    
229
0
      real64 t32 = 0.0;
230
    
231
0
      for (j = 0; j < width; j++)
232
0
        {
233
        
234
0
        int32 k = (int32) j - (int32) fRadius + 1;
235
        
236
0
        real64 x = (k - fract) * scale;
237
        
238
0
        w32 [j] = (real32) kernel.Evaluate (x);
239
        
240
0
        t32 += w32 [j];
241
    
242
0
        }
243
        
244
      // Scale 32 bit weights so total of weights is 1.0.
245
        
246
0
      real32 s32 = (real32) (1.0 / t32);
247
        
248
0
      for (j = 0; j < width; j++)
249
0
        {
250
        
251
0
        w32 [j] *= s32;
252
        
253
0
        }
254
        
255
0
      }
256
    
257
    // Round off 32 bit weights to 16 bit weights.
258
    
259
0
      {
260
    
261
0
      int16 *w16 = fWeights16->Buffer_int16 () + fWeightStep * sample;
262
263
0
      int32 t16 = 0;
264
      
265
0
      for (j = 0; j < width; j++)
266
0
        {
267
        
268
0
        w16 [j] = (int16) Round_int32 (w32 [j] * 16384.0);
269
        
270
0
        t16 += w16 [j];
271
        
272
0
        }
273
        
274
      // Adjust center entry for any round off error so total is
275
      // exactly 16384.
276
      
277
0
      w16 [fRadius - (fract >= 0.5 ? 0 : 1)] += (int16) (16384 - t16);
278
            
279
0
      }
280
    
281
0
    }
282
    
283
0
  }
284
285
/*****************************************************************************/
286
287
dng_resample_weights_2d::dng_resample_weights_2d ()
288
  
289
  : fRadius (0)
290
  
291
  , fRowStep (0)
292
  , fColStep (0)
293
  
294
  , fWeights32 ()
295
  , fWeights16 ()
296
  
297
0
  {
298
  
299
0
  }
300
301
/*****************************************************************************/
302
303
dng_resample_weights_2d::~dng_resample_weights_2d ()
304
0
  {
305
  
306
0
  }
307
308
/*****************************************************************************/
309
310
void dng_resample_weights_2d::Initialize (const dng_resample_function &kernel,
311
                      dng_memory_allocator &allocator)
312
0
  {
313
  
314
  // Find radius of this kernel. Unlike with 1d resample weights (see
315
  // dng_resample_weights), we never scale up the kernel size.
316
  
317
0
  fRadius = (uint32) (kernel.Extent () + 0.9999);
318
  
319
  // Width is twice the radius.
320
  
321
0
  uint32 width    = 0;
322
0
  uint32 widthSqr = 0;
323
0
  uint32 step = 0;
324
  
325
0
  if (!SafeUint32Mult (fRadius, 2, &width) ||
326
0
     !SafeUint32Mult (width, width, &widthSqr) ||
327
0
     !RoundUpUint32ToMultiple (widthSqr, 8, &step) ||
328
0
     !SafeUint32Mult (step, kResampleSubsampleCount2D, &fRowStep))
329
0
      {
330
      
331
0
      ThrowMemoryFull ("Arithmetic overflow computing row step.");
332
      
333
0
      }
334
  
335
0
  fColStep = step;
336
  
337
  // Allocate and zero weight tables.
338
  
339
0
  uint32 bufferSize = 0;
340
341
0
  if (!SafeUint32Mult (step, kResampleSubsampleCount2D, &bufferSize) ||
342
0
     !SafeUint32Mult (bufferSize, kResampleSubsampleCount2D, &bufferSize) ||
343
0
     !SafeUint32Mult (bufferSize, (uint32) sizeof (real32), &bufferSize))
344
0
    {
345
    
346
0
    ThrowMemoryFull ("Arithmetic overflow computing buffer size.");
347
    
348
0
    }
349
  
350
0
  fWeights32.Reset (allocator.Allocate (bufferSize));
351
  
352
0
  DoZeroBytes (fWeights32->Buffer    (),
353
0
         fWeights32->LogicalSize ());
354
         
355
  
356
0
  if (!SafeUint32Mult (step, kResampleSubsampleCount2D, &bufferSize) ||
357
0
     !SafeUint32Mult (bufferSize, kResampleSubsampleCount2D, &bufferSize) ||
358
0
     !SafeUint32Mult (bufferSize, (uint32) sizeof (int16), &bufferSize))
359
0
    {
360
    
361
0
    ThrowMemoryFull ("Arithmetic overflow computing buffer size.");
362
    
363
0
    }
364
  
365
0
  fWeights16.Reset (allocator.Allocate (bufferSize));
366
                    
367
0
  DoZeroBytes (fWeights16->Buffer    (),
368
0
         fWeights16->LogicalSize ());
369
         
370
  // Compute kernel for each subsample values.
371
  
372
0
  for (uint32 y = 0; y < kResampleSubsampleCount2D; y++)
373
0
    {
374
    
375
0
    real64 yFract = y * (1.0 / (real64) kResampleSubsampleCount2D);
376
    
377
0
    for (uint32 x = 0; x < kResampleSubsampleCount2D; x++)
378
0
      {
379
    
380
0
      real64 xFract = x * (1.0 / (real64) kResampleSubsampleCount2D);
381
    
382
0
      real32 *w32 = (real32 *) Weights32 (dng_point ((int32) y, 
383
0
                               (int32) x));
384
    
385
      // Evaluate kernel function for 32 bit weights.
386
    
387
0
        {
388
    
389
0
        real64 t32 = 0.0;
390
391
0
        uint32 index = 0;
392
393
0
        for (uint32 i = 0; i < width; i++)
394
0
          {
395
    
396
0
          int32 yInt = ((int32) i) - (int32) fRadius + 1;
397
0
          real64 yPos = yInt - yFract;
398
399
0
          for (uint32 j = 0; j < width; j++)
400
0
            {
401
        
402
0
            int32 xInt = ((int32) j) - (int32) fRadius + 1;
403
0
            real64 xPos = xInt - xFract;
404
405
            #if 0
406
407
            // Radial.
408
        
409
            real64 dy2 = yPos * yPos;
410
            real64 dx2 = xPos * xPos;
411
412
            real64 r = sqrt (dx2 + dy2);
413
414
            w32 [index] = (real32) kernel.Evaluate (r);
415
416
            #else
417
418
            // Separable.
419
420
0
            w32 [index] = (real32) kernel.Evaluate (xPos) *
421
0
                        (real32) kernel.Evaluate (yPos);
422
        
423
0
            #endif
424
425
0
            t32 += w32 [index];
426
427
0
            index++;
428
    
429
0
            }
430
431
0
          }
432
        
433
        // Scale 32 bit weights so total of weights is 1.0.
434
        
435
0
        const real32 s32 = (real32) (1.0 / t32);
436
        
437
0
        for (uint32 i = 0; i < widthSqr; i++)
438
0
          {
439
          
440
0
          w32 [i] *= s32;
441
          
442
0
          }
443
        
444
0
        }
445
    
446
      // Round off 32 bit weights to 16 bit weights.
447
    
448
0
        {
449
    
450
0
        int16 *w16 = (int16 *) Weights16 (dng_point ((int32) y, 
451
0
                               (int32) x));
452
453
0
        int32 t16 = 0;
454
      
455
0
        for (uint32 j = 0; j < widthSqr; j++)
456
0
          {
457
        
458
0
          w16 [j] = (int16) Round_int32 (w32 [j] * 16384.0);
459
        
460
0
          t16 += w16 [j];
461
        
462
0
          }
463
        
464
        // Adjust one of the center entries for any round off error so total
465
        // is exactly 16384.
466
467
0
        const uint32 xOffset      = fRadius - ((xFract >= 0.5) ? 0 : 1);
468
0
        const uint32 yOffset      = fRadius - ((yFract >= 0.5) ? 0 : 1);
469
0
        const uint32 centerOffset = width * yOffset + xOffset;
470
      
471
0
        w16 [centerOffset] += (int16) (16384 - t16);
472
            
473
0
        }
474
    
475
0
      }
476
    
477
0
    }
478
479
0
  }
480
481
/*****************************************************************************/
482
483
class dng_resample_task: public dng_filter_task
484
  {
485
  
486
  protected:
487
  
488
    dng_rect fSrcBounds;
489
    dng_rect fDstBounds;
490
    
491
    const dng_resample_function &fKernel;
492
    
493
    real64 fRowScale;
494
    real64 fColScale;
495
    
496
    dng_resample_coords fRowCoords;
497
    dng_resample_coords fColCoords;
498
    
499
    dng_resample_weights fWeightsV;
500
    dng_resample_weights fWeightsH;
501
    
502
    dng_point fSrcTileSize;
503
    
504
    AutoPtr<dng_memory_block> fTempBuffer [kMaxMPThreads];
505
    
506
  public:
507
  
508
    dng_resample_task (const dng_image &srcImage,
509
               dng_image &dstImage,
510
               const dng_rect &srcBounds,
511
               const dng_rect &dstBounds,
512
               const dng_resample_function &kernel);
513
  
514
    virtual dng_rect SrcArea (const dng_rect &dstArea);
515
      
516
    virtual dng_point SrcTileSize (const dng_point &dstTileSize);
517
      
518
    virtual void Start (uint32 threadCount,
519
              const dng_point &tileSize,
520
              dng_memory_allocator *allocator,
521
              dng_abort_sniffer *sniffer);
522
              
523
    virtual void ProcessArea (uint32 threadIndex,
524
                  dng_pixel_buffer &srcBuffer,
525
                  dng_pixel_buffer &dstBuffer);
526
                  
527
  };
528
              
529
/*****************************************************************************/
530
531
dng_resample_task::dng_resample_task (const dng_image &srcImage,
532
                      dng_image &dstImage,
533
                      const dng_rect &srcBounds,
534
                      const dng_rect &dstBounds,
535
                    const dng_resample_function &kernel)
536
                      
537
  : dng_filter_task (srcImage,
538
             dstImage)
539
               
540
  , fSrcBounds (srcBounds)
541
  , fDstBounds (dstBounds)
542
  
543
  , fKernel (kernel)
544
  
545
  , fRowScale ((srcBounds.H () != 0) ? dstBounds.H () / (real64) srcBounds.H () : 0)
546
  , fColScale ((srcBounds.W () != 0) ? dstBounds.W () / (real64) srcBounds.W () : 0)
547
  
548
  , fRowCoords ()
549
  , fColCoords ()
550
  
551
  , fWeightsV ()
552
  , fWeightsH ()
553
  
554
  , fSrcTileSize ()
555
  
556
0
  {
557
0
  if (fRowScale == 0 || fColScale == 0)
558
0
    {
559
0
     ThrowBadFormat ();
560
0
  }
561
  
562
0
  if (srcImage.PixelSize  () <= 2 &&
563
0
    dstImage.PixelSize  () <= 2 &&
564
0
    srcImage.PixelRange () == dstImage.PixelRange ())
565
0
    {
566
0
    fSrcPixelType = ttShort;
567
0
    fDstPixelType = ttShort;
568
0
    }
569
    
570
0
  else
571
0
    {
572
0
    fSrcPixelType = ttFloat;
573
0
    fDstPixelType = ttFloat;
574
0
    }
575
  
576
0
  fUnitCell = dng_point (8, 8);
577
  
578
0
  fMaxTileSize.v = Pin_int32 (fUnitCell.v,
579
0
                Round_int32 (fMaxTileSize.v * fRowScale),
580
0
                fMaxTileSize.v);
581
  
582
0
  fMaxTileSize.h = Pin_int32 (fUnitCell.h,
583
0
                Round_int32 (fMaxTileSize.h * fColScale),
584
0
                fMaxTileSize.h);
585
  
586
0
  }
587
              
588
/*****************************************************************************/
589
590
dng_rect dng_resample_task::SrcArea (const dng_rect &dstArea)
591
0
  {
592
  
593
0
  int32 offsetV = fWeightsV.Offset ();
594
0
  int32 offsetH = fWeightsH.Offset ();
595
  
596
0
  uint32 widthV = fWeightsV.Width ();
597
0
  uint32 widthH = fWeightsH.Width ();
598
  
599
0
  dng_rect srcArea;
600
  
601
0
  srcArea.t = SafeInt32Add (fRowCoords.Pixel (dstArea.t), offsetV);
602
0
  srcArea.l = SafeInt32Add (fColCoords.Pixel (dstArea.l), offsetH);
603
604
0
  srcArea.b = SafeInt32Add (SafeInt32Add (
605
0
            fRowCoords.Pixel (SafeInt32Sub (dstArea.b, 1)),
606
0
            offsetV),
607
0
          ConvertUint32ToInt32 (widthV));;
608
0
  srcArea.r = SafeInt32Add(SafeInt32Add(
609
0
            fColCoords.Pixel (SafeInt32Sub (dstArea.r, 1)),
610
0
            offsetH),
611
0
          ConvertUint32ToInt32(widthH));;
612
  
613
0
  return srcArea;
614
  
615
0
  }
616
      
617
/*****************************************************************************/
618
619
dng_point dng_resample_task::SrcTileSize (const dng_point & /* dstTileSize */)
620
0
  {
621
622
0
  return fSrcTileSize;
623
624
0
  }
625
      
626
/*****************************************************************************/
627
628
void dng_resample_task::Start (uint32 threadCount,
629
                 const dng_point &tileSize,
630
                 dng_memory_allocator *allocator,
631
                 dng_abort_sniffer *sniffer)
632
0
  {
633
  
634
  // Compute sub-pixel resolution coordinates in the source image for
635
  // each row and column of the destination area.
636
  
637
0
  fRowCoords.Initialize (fSrcBounds.t,
638
0
               fDstBounds.t,
639
0
               fSrcBounds.H (),
640
0
               fDstBounds.H (),
641
0
               *allocator);
642
  
643
0
  fColCoords.Initialize (fSrcBounds.l,
644
0
               fDstBounds.l,
645
0
               fSrcBounds.W (),
646
0
               fDstBounds.W (),
647
0
               *allocator);
648
      
649
  // Compute resampling kernels.
650
  
651
0
  fWeightsV.Initialize (fRowScale,
652
0
              fKernel,
653
0
              *allocator);
654
              
655
0
  fWeightsH.Initialize (fColScale,
656
0
              fKernel,
657
0
              *allocator);
658
    
659
  // Find upper bound on source source tile.
660
    
661
0
  fSrcTileSize.v = Round_int32 (tileSize.v / fRowScale) + fWeightsV.Width () + 2;
662
0
  fSrcTileSize.h = Round_int32 (tileSize.h / fColScale) + fWeightsH.Width () + 2;
663
  
664
  // Allocate temp buffers.
665
  
666
0
  uint32 tempBufferSize = 0;
667
0
  if (!RoundUpUint32ToMultiple (fSrcTileSize.h, 8, &tempBufferSize) ||
668
0
     !SafeUint32Mult (tempBufferSize,
669
0
       static_cast<uint32> (sizeof (real32)),
670
0
       &tempBufferSize))
671
0
    {
672
    
673
0
    ThrowMemoryFull("Arithmetic overflow computing buffer size.");
674
    
675
0
    }
676
  
677
0
  for (uint32 threadIndex = 0; threadIndex < threadCount; threadIndex++)
678
0
    {
679
    
680
0
    fTempBuffer [threadIndex] . Reset (allocator->Allocate (tempBufferSize));
681
    
682
0
    }
683
    
684
  // Allocate the pixel buffers.
685
686
0
  dng_filter_task::Start (threadCount,
687
0
              tileSize,
688
0
              allocator,
689
0
              sniffer);
690
              
691
0
  }
692
              
693
/*****************************************************************************/
694
695
void dng_resample_task::ProcessArea (uint32 threadIndex,
696
                     dng_pixel_buffer &srcBuffer,
697
                     dng_pixel_buffer &dstBuffer)
698
0
  {
699
  
700
0
  dng_rect srcArea = srcBuffer.fArea;
701
0
  dng_rect dstArea = dstBuffer.fArea;
702
  
703
0
  uint32 srcCols = srcArea.W ();
704
0
  uint32 dstCols = dstArea.W ();
705
  
706
0
  uint32 widthV = fWeightsV.Width ();
707
0
  uint32 widthH = fWeightsH.Width ();
708
  
709
0
  int32 offsetV = fWeightsV.Offset ();
710
0
  int32 offsetH = fWeightsH.Offset ();
711
  
712
0
  uint32 stepH = fWeightsH.Step ();
713
  
714
0
  const int32 *rowCoords = fRowCoords.Coords (0        );
715
0
  const int32 *colCoords = fColCoords.Coords (dstArea.l);
716
  
717
0
  if (fSrcPixelType == ttFloat)
718
0
    {
719
  
720
0
    const real32 *weightsH = fWeightsH.Weights32 (0);
721
        
722
0
    real32 *tPtr = fTempBuffer [threadIndex]->Buffer_real32 ();
723
    
724
0
    real32 *ttPtr = tPtr + offsetH - srcArea.l;
725
    
726
0
    for (int32 dstRow = dstArea.t; dstRow < dstArea.b; dstRow++)
727
0
      {
728
      
729
0
      int32 rowCoord = rowCoords [dstRow];
730
      
731
0
      int32 rowFract = rowCoord & kResampleSubsampleMask;
732
      
733
0
      const real32 *weightsV = fWeightsV.Weights32 (rowFract); 
734
      
735
0
      int32 srcRow = (rowCoord >> kResampleSubsampleBits) + offsetV;
736
      
737
0
      for (uint32 plane = 0; plane < dstBuffer.fPlanes; plane++)
738
0
        {
739
        
740
0
        const real32 *sPtr = srcBuffer.ConstPixel_real32 (srcRow,
741
0
                                  srcArea.l,
742
0
                                  plane);
743
744
0
        DoResampleDown32 (sPtr,
745
0
                  tPtr,
746
0
                  srcCols,
747
0
                  srcBuffer.fRowStep,
748
0
                  weightsV,
749
0
                  widthV);
750
751
0
        real32 *dPtr = dstBuffer.DirtyPixel_real32 (dstRow,
752
0
                              dstArea.l,
753
0
                              plane);
754
                              
755
0
        DoResampleAcross32 (ttPtr,
756
0
                  dPtr,
757
0
                  dstCols,
758
0
                  colCoords,
759
0
                  weightsH,
760
0
                  widthH,
761
0
                  stepH);
762
763
0
        }
764
      
765
0
      }
766
      
767
0
    }
768
    
769
0
  else
770
0
    {
771
    
772
0
    const int16 *weightsH = fWeightsH.Weights16 (0);
773
        
774
0
    uint16 *tPtr = fTempBuffer [threadIndex]->Buffer_uint16 ();
775
    
776
0
    uint16 *ttPtr = tPtr + offsetH - srcArea.l;
777
    
778
0
    uint32 pixelRange = fDstImage.PixelRange ();
779
    
780
0
    for (int32 dstRow = dstArea.t; dstRow < dstArea.b; dstRow++)
781
0
      {
782
      
783
0
      int32 rowCoord = rowCoords [dstRow];
784
      
785
0
      int32 rowFract = rowCoord & kResampleSubsampleMask;
786
      
787
0
      const int16 *weightsV = fWeightsV.Weights16 (rowFract); 
788
      
789
0
      int32 srcRow = (rowCoord >> kResampleSubsampleBits) + offsetV;
790
      
791
0
      for (uint32 plane = 0; plane < dstBuffer.fPlanes; plane++)
792
0
        {
793
        
794
0
        const uint16 *sPtr = srcBuffer.ConstPixel_uint16 (srcRow,
795
0
                                  srcArea.l,
796
0
                                  plane);
797
798
0
        DoResampleDown16 (sPtr,
799
0
                  tPtr,
800
0
                  srcCols,
801
0
                  srcBuffer.fRowStep,
802
0
                  weightsV,
803
0
                  widthV,
804
0
                  pixelRange);
805
806
0
        uint16 *dPtr = dstBuffer.DirtyPixel_uint16 (dstRow,
807
0
                              dstArea.l,
808
0
                              plane);
809
                              
810
0
        DoResampleAcross16 (ttPtr,
811
0
                  dPtr,
812
0
                  dstCols,
813
0
                  colCoords,
814
0
                  weightsH,
815
0
                  widthH,
816
0
                  stepH,
817
0
                  pixelRange);
818
819
0
        }
820
      
821
0
      }
822
      
823
0
    }
824
  
825
0
  }
826
    
827
/*****************************************************************************/
828
829
void ResampleImage (dng_host &host,
830
          const dng_image &srcImage,
831
          dng_image &dstImage,
832
          const dng_rect &srcBounds,
833
          const dng_rect &dstBounds,
834
          const dng_resample_function &kernel)
835
0
  {
836
  
837
0
  dng_resample_task task (srcImage,
838
0
              dstImage,
839
0
              srcBounds,
840
0
              dstBounds,
841
0
              kernel);
842
              
843
0
  host.PerformAreaTask (task,
844
0
              dstBounds);
845
  
846
0
  }
847
848
/*****************************************************************************/