Coverage Report

Created: 2025-01-23 06:31

/src/dng_sdk/source/dng_image.cpp
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************/
2
// Copyright 2006-2008 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_image.cpp#1 $ */ 
10
/* $DateTime: 2012/05/30 13:28:51 $ */
11
/* $Change: 832332 $ */
12
/* $Author: tknoll $ */
13
14
/*****************************************************************************/
15
16
#include "dng_image.h"
17
18
#include "dng_assertions.h"
19
#include "dng_exceptions.h"
20
#include "dng_orientation.h"
21
#include "dng_pixel_buffer.h"
22
#include "dng_tag_types.h"
23
#include "dng_tile_iterator.h"
24
#include "dng_utils.h"
25
             
26
/*****************************************************************************/
27
28
dng_tile_buffer::dng_tile_buffer (const dng_image &image,
29
                  const dng_rect &tile,
30
                  bool dirty)
31
                  
32
2.01M
  : fImage   (image)
33
  , fRefData (NULL)
34
  
35
2.01M
  {
36
  
37
2.01M
  fImage.AcquireTileBuffer (*this,
38
2.01M
                tile,
39
2.01M
                dirty);
40
  
41
2.01M
  }
42
43
/*****************************************************************************/
44
45
dng_tile_buffer::~dng_tile_buffer ()
46
2.01M
  {
47
  
48
2.01M
  fImage.ReleaseTileBuffer (*this);
49
  
50
2.01M
  }
51
52
/*****************************************************************************/
53
54
dng_const_tile_buffer::dng_const_tile_buffer (const dng_image &image,
55
                          const dng_rect &tile)
56
                          
57
1.79M
  :   dng_tile_buffer (image, tile, false)
58
  
59
1.79M
  {
60
  
61
1.79M
  }
62
63
/*****************************************************************************/
64
65
dng_const_tile_buffer::~dng_const_tile_buffer ()
66
  {
67
  
68
  }
69
70
/*****************************************************************************/
71
72
dng_dirty_tile_buffer::dng_dirty_tile_buffer (dng_image &image,
73
                          const dng_rect &tile)
74
                          
75
218k
  :   dng_tile_buffer (image, tile, true)
76
  
77
218k
  {
78
  
79
218k
  }
80
81
/*****************************************************************************/
82
83
dng_dirty_tile_buffer::~dng_dirty_tile_buffer ()
84
  {
85
  
86
  }
87
88
/*****************************************************************************/
89
90
dng_image::dng_image (const dng_rect &bounds,
91
              uint32 planes,
92
              uint32 pixelType)
93
94
59.5k
  :   fBounds    (bounds)
95
59.5k
  , fPlanes    (planes)
96
59.5k
  , fPixelType (pixelType)
97
  
98
59.5k
  {
99
  
100
59.5k
  if (bounds.IsEmpty () || planes == 0 || PixelSize () == 0)
101
252
    {
102
    
103
    #if qDNGValidate
104
    
105
    ReportError ("Fuzz: Attempt to create zero size image");
106
    
107
    #endif
108
    
109
252
    ThrowBadFormat ();
110
    
111
252
    }
112
    
113
59.5k
  }
114
115
/*****************************************************************************/
116
117
dng_image::~dng_image ()
118
59.2k
  {
119
  
120
59.2k
  }
121
122
/*****************************************************************************/
123
124
dng_image * dng_image::Clone () const
125
0
  {
126
  
127
0
  ThrowProgramError ("Clone is not supported by this dng_image subclass");
128
129
0
  return NULL;
130
  
131
0
  }
132
133
/*****************************************************************************/
134
135
void dng_image::SetPixelType (uint32 pixelType)
136
0
  {
137
  
138
0
  if (TagTypeSize (pixelType) != PixelSize ())
139
0
    {
140
    
141
0
    ThrowProgramError ("Cannot change pixel size for existing image");
142
    
143
0
    }
144
  
145
0
  fPixelType = pixelType;
146
  
147
0
  }
148
    
149
/*****************************************************************************/
150
151
uint32 dng_image::PixelSize () const
152
64.8k
  {
153
  
154
64.8k
  return TagTypeSize (PixelType ());
155
  
156
64.8k
  }
157
158
/*****************************************************************************/
159
160
uint32 dng_image::PixelRange () const
161
10.8k
  {
162
  
163
10.8k
  switch (fPixelType)
164
10.8k
    {
165
    
166
0
    case ttByte:
167
0
    case ttSByte:
168
0
      {
169
0
      return 0x0FF;
170
0
      }
171
      
172
10.8k
    case ttShort:
173
10.8k
    case ttSShort:
174
10.8k
      {
175
10.8k
      return 0x0FFFF;
176
10.8k
      }
177
      
178
0
    case ttLong:
179
0
    case ttSLong:
180
0
      {
181
0
      return 0xFFFFFFFF;
182
0
      }
183
      
184
0
    default:
185
0
      break;
186
      
187
10.8k
    }
188
  
189
0
  return 0;
190
  
191
10.8k
  }
192
193
/*****************************************************************************/
194
195
dng_rect dng_image::RepeatingTile () const
196
1.88M
  {
197
  
198
1.88M
  return fBounds;
199
  
200
1.88M
  }
201
202
/*****************************************************************************/
203
204
void dng_image::AcquireTileBuffer (dng_tile_buffer & /* buffer */,
205
                   const dng_rect & /* area */,
206
                   bool /* dirty */) const
207
0
  {
208
  
209
0
  ThrowProgramError ();
210
  
211
0
  }
212
213
/*****************************************************************************/
214
215
void dng_image::ReleaseTileBuffer (dng_tile_buffer & /* buffer */) const
216
2.01M
  {
217
  
218
2.01M
  }
219
220
/*****************************************************************************/
221
222
void dng_image::DoGet (dng_pixel_buffer &buffer) const
223
1.68M
  {
224
  
225
1.68M
  dng_rect tile;
226
  
227
1.68M
  dng_tile_iterator iter (*this, buffer.fArea);
228
  
229
3.37M
  while (iter.GetOneTile (tile))
230
1.68M
    {
231
    
232
1.68M
    dng_const_tile_buffer tileBuffer (*this, tile);
233
    
234
1.68M
    buffer.CopyArea (tileBuffer,
235
1.68M
               tile,
236
1.68M
               buffer.fPlane,
237
1.68M
               buffer.fPlanes);
238
    
239
1.68M
    }
240
  
241
1.68M
  }
242
243
/*****************************************************************************/
244
245
void dng_image::DoPut (const dng_pixel_buffer &buffer)
246
115k
  {
247
  
248
115k
  dng_rect tile;
249
  
250
115k
  dng_tile_iterator iter (*this, buffer.fArea);
251
  
252
231k
  while (iter.GetOneTile (tile))
253
115k
    {
254
    
255
115k
    dng_dirty_tile_buffer tileBuffer (*this, tile);
256
    
257
115k
    tileBuffer.CopyArea (buffer,
258
115k
                   tile,
259
115k
                   buffer.fPlane,
260
115k
                   buffer.fPlanes);
261
    
262
115k
    }
263
  
264
115k
  }
265
  
266
/*****************************************************************************/
267
268
void dng_image::GetRepeat (dng_pixel_buffer &buffer,
269
                   const dng_rect &srcArea,
270
                   const dng_rect &dstArea) const
271
68.6k
  {
272
  
273
  // If we already have the entire srcArea in the
274
  // buffer, we can just repeat that.
275
  
276
68.6k
  if ((srcArea & buffer.fArea) == srcArea)
277
68.6k
    {
278
    
279
68.6k
    buffer.RepeatArea (srcArea,
280
68.6k
               dstArea);
281
    
282
68.6k
    }
283
    
284
  // Else we first need to get the srcArea into the buffer area.
285
  
286
0
  else
287
0
    {
288
    
289
    // Find repeating pattern size.
290
    
291
0
    dng_point repeat = srcArea.Size ();
292
    
293
    // Find pattern phase at top-left corner of destination area.
294
    
295
0
    dng_point phase = dng_pixel_buffer::RepeatPhase (srcArea,
296
0
                               dstArea);
297
      
298
    // Find new source area at top-left of dstArea.
299
    
300
0
    dng_rect newArea = srcArea + (dstArea.TL () -
301
0
                      srcArea.TL ());
302
                     
303
    // Find quadrant split coordinates.
304
    
305
0
    int32 splitV = newArea.t + repeat.v - phase.v;
306
0
    int32 splitH = newArea.l + repeat.h - phase.h;
307
      
308
    // Top-left quadrant.
309
    
310
0
    dng_rect dst1 (dng_rect (newArea.t,
311
0
                   newArea.l,
312
0
                   splitV,
313
0
                   splitH) & dstArea);
314
              
315
0
    if (dst1.NotEmpty ())
316
0
      {
317
      
318
0
      dng_pixel_buffer temp (buffer);
319
      
320
0
      temp.fArea = dst1 + (srcArea.TL () -
321
0
                 dstArea.TL () +
322
0
                 dng_point (phase.v, phase.h));
323
      
324
0
      temp.fData = buffer.DirtyPixel (dst1.t,
325
0
                          dst1.l,
326
0
                          buffer.fPlane);
327
                          
328
0
      DoGet (temp);
329
      
330
0
      }
331
      
332
    // Top-right quadrant.
333
    
334
0
    dng_rect dst2 (dng_rect (newArea.t,
335
0
                 splitH,
336
0
                 splitV,
337
0
                 newArea.r) & dstArea);
338
                 
339
0
    if (dst2.NotEmpty ())
340
0
      {
341
      
342
0
      dng_pixel_buffer temp (buffer);
343
      
344
0
      temp.fArea = dst2 + (srcArea.TL () -
345
0
                 dstArea.TL () +
346
0
                 dng_point (phase.v, -phase.h));
347
      
348
0
      temp.fData = buffer.DirtyPixel (dst2.t,
349
0
                          dst2.l,
350
0
                          buffer.fPlane);
351
                          
352
0
      DoGet (temp);
353
      
354
0
      }
355
      
356
    // Bottom-left quadrant.
357
    
358
0
    dng_rect dst3 (dng_rect (splitV,
359
0
                 newArea.l,
360
0
                 newArea.b,
361
0
                 splitH) & dstArea);
362
                 
363
0
    if (dst3.NotEmpty ())
364
0
      {
365
      
366
0
      dng_pixel_buffer temp (buffer);
367
      
368
0
      temp.fArea = dst3 + (srcArea.TL () -
369
0
                 dstArea.TL () +
370
0
                 dng_point (-phase.v, phase.h));
371
      
372
0
      temp.fData = buffer.DirtyPixel (dst3.t,
373
0
                          dst3.l,
374
0
                          buffer.fPlane);
375
                          
376
0
      DoGet (temp);
377
      
378
0
      }
379
      
380
    // Bottom-right quadrant.
381
    
382
0
    dng_rect dst4 (dng_rect (splitV,
383
0
                 splitH,
384
0
                 newArea.b,
385
0
                 newArea.r) & dstArea);
386
                 
387
0
    if (dst4.NotEmpty ())
388
0
      {
389
      
390
0
      dng_pixel_buffer temp (buffer);
391
      
392
0
      temp.fArea = dst4 + (srcArea.TL () -
393
0
                 dstArea.TL () +
394
0
                 dng_point (-phase.v, -phase.h));
395
      
396
0
      temp.fData = buffer.DirtyPixel (dst4.t,
397
0
                          dst4.l,
398
0
                          buffer.fPlane);
399
                          
400
0
      DoGet (temp);
401
      
402
0
      } 
403
             
404
    // Replicate this new source area.
405
    
406
0
    buffer.RepeatArea (newArea,
407
0
               dstArea);
408
    
409
0
    }
410
      
411
68.6k
  }
412
  
413
/*****************************************************************************/
414
415
void dng_image::GetEdge (dng_pixel_buffer &buffer,
416
               edge_option edgeOption,
417
                 const dng_rect &srcArea,
418
                 const dng_rect &dstArea) const
419
197k
  {
420
  
421
197k
  switch (edgeOption)
422
197k
    {
423
    
424
128k
    case edge_zero:
425
128k
      {
426
      
427
128k
      buffer.SetZero (dstArea,
428
128k
              buffer.fPlane,
429
128k
              buffer.fPlanes);
430
              
431
128k
      break;
432
      
433
0
      }
434
      
435
68.6k
    case edge_repeat:
436
68.6k
      {
437
      
438
68.6k
      GetRepeat (buffer,
439
68.6k
             srcArea,
440
68.6k
             dstArea);
441
             
442
68.6k
      break;
443
            
444
0
      }
445
      
446
0
    case edge_repeat_zero_last:
447
0
      {
448
      
449
0
      if (buffer.fPlanes > 1)
450
0
        {
451
      
452
0
        dng_pixel_buffer buffer1 (buffer);
453
        
454
0
        buffer1.fPlanes--;
455
        
456
0
        GetEdge (buffer1,
457
0
             edge_repeat,
458
0
             srcArea,
459
0
             dstArea);
460
             
461
0
        }
462
        
463
0
      dng_pixel_buffer buffer2 (buffer);
464
      
465
0
      buffer2.fPlane  = buffer.fPlanes - 1;
466
0
      buffer2.fPlanes = 1;
467
      
468
0
      buffer2.fData = buffer.DirtyPixel (buffer2.fArea.t,
469
0
                           buffer2.fArea.l,
470
0
                           buffer2.fPlane);
471
                      
472
0
      GetEdge (buffer2,
473
0
           edge_zero,
474
0
           srcArea,
475
0
           dstArea);
476
           
477
0
      break;
478
      
479
0
      }
480
      
481
0
    default:
482
0
      {
483
      
484
0
      ThrowProgramError ();
485
      
486
0
      }
487
      
488
197k
    }
489
  
490
197k
  }
491
    
492
/*****************************************************************************/
493
494
void dng_image::Get (dng_pixel_buffer &buffer,
495
           edge_option edgeOption,
496
             uint32 repeatV,
497
             uint32 repeatH) const
498
1.68M
  {
499
  
500
  // Find the overlap with the image bounds.
501
  
502
1.68M
  dng_rect overlap = buffer.fArea & fBounds;
503
  
504
  // Move the overlapping pixels.
505
  
506
1.68M
  if (overlap.NotEmpty ())
507
1.68M
    {
508
  
509
1.68M
    dng_pixel_buffer temp (buffer);
510
    
511
1.68M
    temp.fArea = overlap;
512
    
513
1.68M
    temp.fData = buffer.DirtyPixel (overlap.t,
514
1.68M
                      overlap.l,
515
1.68M
                      buffer.fPlane);
516
  
517
1.68M
    DoGet (temp);
518
    
519
1.68M
    }
520
    
521
  // See if we need to pad the edge values.
522
  
523
1.68M
  if ((edgeOption != edge_none) && (overlap != buffer.fArea))
524
129k
    {
525
    
526
129k
    dng_rect areaT (buffer.fArea);
527
129k
    dng_rect areaL (buffer.fArea);
528
129k
    dng_rect areaB (buffer.fArea);
529
129k
    dng_rect areaR (buffer.fArea);
530
    
531
129k
    areaT.b = Min_int32 (areaT.b, fBounds.t);
532
129k
    areaL.r = Min_int32 (areaL.r, fBounds.l);
533
129k
    areaB.t = Max_int32 (areaB.t, fBounds.b);
534
129k
    areaR.l = Max_int32 (areaR.l, fBounds.r);
535
    
536
129k
    dng_rect areaH (buffer.fArea);
537
129k
    dng_rect areaV (buffer.fArea);
538
    
539
129k
    areaH.l = Max_int32 (areaH.l, fBounds.l);
540
129k
    areaH.r = Min_int32 (areaH.r, fBounds.r);
541
    
542
129k
    areaV.t = Max_int32 (areaV.t, fBounds.t);
543
129k
    areaV.b = Min_int32 (areaV.b, fBounds.b);
544
    
545
    // Top left.
546
    
547
129k
    dng_rect areaTL = areaT & areaL;
548
    
549
129k
    if (areaTL.NotEmpty ())
550
3.63k
      {
551
      
552
3.63k
      GetEdge (buffer,
553
3.63k
           edgeOption,
554
3.63k
           dng_rect (fBounds.t,
555
3.63k
                 fBounds.l,
556
3.63k
                 fBounds.t + (int32)repeatV,
557
3.63k
                 fBounds.l + (int32)repeatH),
558
3.63k
           areaTL);
559
      
560
3.63k
      }
561
      
562
    // Top middle.
563
    
564
129k
    dng_rect areaTM = areaT & areaH;
565
    
566
129k
    if (areaTM.NotEmpty ())
567
20.9k
      {
568
      
569
20.9k
      GetEdge (buffer,
570
20.9k
           edgeOption,
571
20.9k
           dng_rect (fBounds.t,
572
20.9k
                 areaTM.l,
573
20.9k
                 fBounds.t + (int32)repeatV,
574
20.9k
                 areaTM.r),
575
20.9k
           areaTM);
576
      
577
20.9k
      }
578
    
579
    // Top right.
580
    
581
129k
    dng_rect areaTR = areaT & areaR;
582
    
583
129k
    if (areaTR.NotEmpty ())
584
3.66k
      {
585
      
586
3.66k
      GetEdge (buffer,
587
3.66k
           edgeOption,
588
3.66k
           dng_rect (fBounds.t,
589
3.66k
                 fBounds.r - (int32)repeatH,
590
3.66k
                 fBounds.t + (int32)repeatV,
591
3.66k
                 fBounds.r),
592
3.66k
           areaTR);
593
      
594
3.66k
      }
595
      
596
    // Left middle.
597
    
598
129k
    dng_rect areaLM = areaL & areaV;
599
    
600
129k
    if (areaLM.NotEmpty ())
601
6.00k
      {
602
      
603
6.00k
      GetEdge (buffer,
604
6.00k
           edgeOption,
605
6.00k
           dng_rect (areaLM.t,
606
6.00k
                 fBounds.l,
607
6.00k
                 areaLM.b,
608
6.00k
                 fBounds.l + (int32)repeatH),
609
6.00k
           areaLM);
610
      
611
6.00k
      }
612
    
613
    // Right middle.
614
    
615
129k
    dng_rect areaRM = areaR & areaV;
616
    
617
129k
    if (areaRM.NotEmpty ())
618
27.4k
      {
619
      
620
27.4k
      GetEdge (buffer,
621
27.4k
           edgeOption,
622
27.4k
           dng_rect (areaRM.t,
623
27.4k
                 fBounds.r - (int32)repeatH,
624
27.4k
                 areaRM.b,
625
27.4k
                 fBounds.r),
626
27.4k
           areaRM);
627
      
628
27.4k
      }
629
    
630
    // Bottom left.
631
    
632
129k
    dng_rect areaBL = areaB & areaL;
633
    
634
129k
    if (areaBL.NotEmpty ())
635
3.63k
      {
636
      
637
3.63k
      GetEdge (buffer,
638
3.63k
           edgeOption,
639
3.63k
           dng_rect (fBounds.b - (int32)repeatV,
640
3.63k
                 fBounds.l,
641
3.63k
                 fBounds.b,
642
3.63k
                 fBounds.l + (int32)repeatH),
643
3.63k
           areaBL);
644
      
645
3.63k
      }
646
      
647
    // Bottom middle.
648
    
649
129k
    dng_rect areaBM = areaB & areaH;
650
    
651
129k
    if (areaBM.NotEmpty ())
652
116k
      {
653
      
654
116k
      GetEdge (buffer,
655
116k
           edgeOption,
656
116k
           dng_rect (fBounds.b - (int32)repeatV,
657
116k
                 areaBM.l,
658
116k
                 fBounds.b,
659
116k
                 areaBM.r),
660
116k
           areaBM);
661
      
662
116k
      }
663
    
664
    // Bottom right.
665
    
666
129k
    dng_rect areaBR = areaB & areaR;
667
    
668
129k
    if (areaBR.NotEmpty ())
669
15.1k
      {
670
      
671
15.1k
      GetEdge (buffer,
672
15.1k
           edgeOption,
673
15.1k
           dng_rect (fBounds.b - (int32)repeatV,
674
15.1k
                 fBounds.r - (int32)repeatH,
675
15.1k
                 fBounds.b,
676
15.1k
                 fBounds.r),
677
15.1k
           areaBR);
678
      
679
15.1k
      }
680
      
681
129k
    }
682
  
683
1.68M
  }
684
    
685
/*****************************************************************************/
686
687
void dng_image::Put (const dng_pixel_buffer &buffer)
688
117k
  {
689
  
690
  // Move the overlapping pixels.
691
  
692
117k
  dng_rect overlap = buffer.fArea & fBounds;
693
  
694
117k
  if (overlap.NotEmpty ())
695
115k
    {
696
  
697
115k
    dng_pixel_buffer temp (buffer);
698
    
699
115k
    temp.fArea = overlap;
700
    
701
115k
    temp.fData = (void *) buffer.ConstPixel (overlap.t,
702
115k
                           overlap.l,
703
115k
                           buffer.fPlane);
704
                         
705
    // Move the overlapping planes.
706
                         
707
115k
    if (temp.fPlane < Planes ())
708
115k
      {
709
      
710
115k
      temp.fPlanes = Min_uint32 (temp.fPlanes,
711
115k
                     Planes () - temp.fPlane);
712
  
713
115k
      DoPut (temp);
714
      
715
115k
      }
716
    
717
115k
    }
718
    
719
117k
  }
720
    
721
/*****************************************************************************/
722
723
void dng_image::Trim (const dng_rect &r)
724
0
  {
725
  
726
0
  if (r != Bounds ())
727
0
    {
728
    
729
0
    ThrowProgramError ("Trim is not support by this dng_image subclass");
730
    
731
0
    }
732
  
733
0
  }
734
    
735
/*****************************************************************************/
736
737
void dng_image::Rotate (const dng_orientation &orientation)
738
0
  {
739
  
740
0
  if (orientation != dng_orientation::Normal ())
741
0
    {
742
    
743
0
    ThrowProgramError ("Rotate is not support by this dng_image subclass");
744
    
745
0
    }
746
  
747
0
  }
748
    
749
/*****************************************************************************/
750
751
void dng_image::CopyArea (const dng_image &src,
752
              const dng_rect &area,
753
              uint32 srcPlane,
754
              uint32 dstPlane,
755
              uint32 planes)
756
0
  {
757
758
0
  if (&src == this)
759
0
    return;
760
761
0
  dng_tile_iterator destIter(*this, area);
762
0
  dng_rect destTileArea;
763
764
0
  while (destIter.GetOneTile(destTileArea))
765
0
    {
766
0
    dng_tile_iterator srcIter(src, destTileArea);
767
0
    dng_rect srcTileArea;
768
769
0
    while (srcIter.GetOneTile(srcTileArea))
770
0
      {
771
772
0
      dng_dirty_tile_buffer destTile(*this, srcTileArea);
773
0
      dng_const_tile_buffer srcTile(src, srcTileArea);
774
775
0
      destTile.CopyArea (srcTile, srcTileArea, srcPlane, dstPlane, planes);
776
777
0
      }
778
779
0
    }
780
781
0
  }
782
783
/*****************************************************************************/
784
785
bool dng_image::EqualArea (const dng_image &src,
786
               const dng_rect &area,
787
               uint32 plane,
788
               uint32 planes) const
789
0
  {
790
791
0
  if (&src == this)
792
0
    return true;
793
794
0
  dng_tile_iterator destIter (*this, area);
795
  
796
0
  dng_rect destTileArea;
797
798
0
  while (destIter.GetOneTile (destTileArea))
799
0
    {
800
    
801
0
    dng_tile_iterator srcIter (src, destTileArea);
802
    
803
0
    dng_rect srcTileArea;
804
805
0
    while (srcIter.GetOneTile (srcTileArea))
806
0
      {
807
808
0
      dng_const_tile_buffer destTile (*this, srcTileArea);
809
0
      dng_const_tile_buffer srcTile  (src  , srcTileArea);
810
811
0
      if (!destTile.EqualArea (srcTile, srcTileArea, plane, planes))
812
0
        {
813
0
        return false;
814
0
        }
815
816
0
      }
817
818
0
    }
819
820
0
  return true;
821
822
0
  }
823
824
/*****************************************************************************/
825
826
void dng_image::SetConstant (uint32 value,
827
               const dng_rect &area)
828
0
  {
829
  
830
0
  dng_tile_iterator iter (*this, area);
831
              
832
0
  dng_rect tileArea;
833
  
834
0
  while (iter.GetOneTile (tileArea))
835
0
    {
836
    
837
0
    dng_dirty_tile_buffer buffer (*this, tileArea);
838
    
839
0
    buffer.SetConstant (tileArea,
840
0
              0,
841
0
              fPlanes,
842
0
              value);
843
          
844
0
    }
845
846
0
  }
847
848
/*****************************************************************************/