Coverage Report

Created: 2024-09-11 06:37

/src/freeimage-svn/FreeImage/trunk/Source/OpenEXR/IlmImf/ImfInputFile.cpp
Line
Count
Source (jump to first uncovered line)
1
///////////////////////////////////////////////////////////////////////////
2
//
3
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
4
// Digital Ltd. LLC
5
// 
6
// All rights reserved.
7
// 
8
// Redistribution and use in source and binary forms, with or without
9
// modification, are permitted provided that the following conditions are
10
// met:
11
// *       Redistributions of source code must retain the above copyright
12
// notice, this list of conditions and the following disclaimer.
13
// *       Redistributions in binary form must reproduce the above
14
// copyright notice, this list of conditions and the following disclaimer
15
// in the documentation and/or other materials provided with the
16
// distribution.
17
// *       Neither the name of Industrial Light & Magic nor the names of
18
// its contributors may be used to endorse or promote products derived
19
// from this software without specific prior written permission. 
20
// 
21
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
//
33
///////////////////////////////////////////////////////////////////////////
34
35
//-----------------------------------------------------------------------------
36
//
37
//  class InputFile
38
//
39
//-----------------------------------------------------------------------------
40
41
#include "ImfInputFile.h"
42
#include "ImfScanLineInputFile.h"
43
#include "ImfTiledInputFile.h"
44
#include "ImfChannelList.h"
45
#include "ImfMisc.h"
46
#include "ImfStdIO.h"
47
#include "ImfVersion.h"
48
#include "ImfPartType.h"
49
#include "ImfInputPartData.h"
50
#include "ImfMultiPartInputFile.h"
51
52
#include <ImfCompositeDeepScanLine.h>
53
#include <ImfDeepScanLineInputFile.h>
54
55
#include "ImathFun.h"
56
#include "IlmThreadMutex.h"
57
#include "Iex.h"
58
#include "half.h"
59
60
#include <fstream>
61
#include <algorithm>
62
63
#include "ImfNamespace.h"
64
65
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
66
67
68
using IMATH_NAMESPACE::Box2i;
69
using IMATH_NAMESPACE::divp;
70
using IMATH_NAMESPACE::modp;
71
using ILMTHREAD_NAMESPACE::Mutex;
72
using ILMTHREAD_NAMESPACE::Lock;
73
74
75
//
76
// Struct InputFile::Data stores things that will be
77
// needed between calls to readPixels
78
//
79
80
struct InputFile::Data : public Mutex
81
{
82
    Header              header;
83
    int                 version;
84
    bool                isTiled;
85
86
    TiledInputFile *  tFile;
87
    ScanLineInputFile * sFile;
88
    DeepScanLineInputFile * dsFile;
89
90
    LineOrder   lineOrder;      // the file's lineorder
91
    int     minY;           // data window's min y coord
92
    int     maxY;           // data window's max x coord
93
    
94
    FrameBuffer   tFileBuffer; 
95
    FrameBuffer * cachedBuffer;
96
    CompositeDeepScanLine * compositor; // for loading deep files
97
    
98
    int     cachedTileY;
99
    int                 offset;
100
    
101
    int                 numThreads;
102
103
    int                 partNumber;
104
    InputPartData*      part;
105
106
    bool                multiPartBackwardSupport;
107
    MultiPartInputFile* multiPartFile;
108
    InputStreamMutex    * _streamData;
109
    bool                _deleteStream;
110
111
     Data (int numThreads);
112
    ~Data ();
113
114
    void    deleteCachedBuffer();
115
};
116
117
118
InputFile::Data::Data (int numThreads):
119
    isTiled (false),
120
    tFile (0),
121
    sFile (0),
122
    dsFile(0),
123
    cachedBuffer (0),
124
    compositor(0),
125
    cachedTileY (-1),
126
    numThreads (numThreads),
127
    partNumber (-1),
128
    part(NULL),
129
    multiPartBackwardSupport (false),
130
    multiPartFile (0),
131
    _streamData(0),
132
    _deleteStream(false)
133
           
134
0
{
135
    // empty
136
0
}
137
138
139
InputFile::Data::~Data ()
140
0
{
141
0
    if (tFile)
142
0
        delete tFile;
143
0
    if (sFile)
144
0
        delete sFile;
145
0
    if (dsFile)
146
0
        delete dsFile;
147
0
    if (compositor)
148
0
        delete compositor;
149
150
0
    deleteCachedBuffer();
151
152
0
    if (multiPartBackwardSupport && multiPartFile)
153
0
        delete multiPartFile;
154
0
}
155
156
157
void  
158
InputFile::Data::deleteCachedBuffer()
159
0
{
160
    //
161
    // Delete the cached frame buffer, and all memory
162
    // allocated for the slices in the cached frameBuffer.
163
    //
164
165
0
    if (cachedBuffer)
166
0
    {
167
0
  for (FrameBuffer::Iterator k = cachedBuffer->begin();
168
0
       k != cachedBuffer->end();
169
0
       ++k)
170
0
  {
171
0
      Slice &s = k.slice();
172
173
0
      switch (s.type)
174
0
      {
175
0
        case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT:
176
177
0
    delete [] (((unsigned int *)s.base) + offset);
178
0
    break;
179
180
0
        case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF:
181
182
0
    delete [] ((half *)s.base + offset);
183
0
    break;
184
185
0
        case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT:
186
187
0
    delete [] (((float *)s.base) + offset);
188
0
    break;
189
0
              case NUM_PIXELTYPES :
190
0
                  throw(IEX_NAMESPACE::ArgExc("Invalid pixel type"));
191
0
      }                
192
0
  }
193
194
  //
195
  // delete the cached frame buffer
196
  //
197
198
0
  delete cachedBuffer;
199
0
  cachedBuffer = 0;
200
0
    }
201
0
}
202
203
204
namespace {
205
206
void
207
bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2)
208
0
{
209
    //
210
    // bufferedReadPixels reads each row of tiles that intersect the
211
    // scan-line range (scanLine1 to scanLine2). The previous row of
212
    // tiles is cached in order to prevent redundent tile reads when
213
    // accessing scanlines sequentially.
214
    //
215
216
0
    int minY = std::min (scanLine1, scanLine2);
217
0
    int maxY = std::max (scanLine1, scanLine2);
218
219
0
    if (minY < ifd->minY || maxY >  ifd->maxY)
220
0
    {
221
0
        throw IEX_NAMESPACE::ArgExc ("Tried to read scan line outside "
222
0
         "the image file's data window.");
223
0
    }
224
225
    //
226
    // The minimum and maximum y tile coordinates that intersect this
227
    // scanline range
228
    //
229
230
0
    int minDy = (minY - ifd->minY) / ifd->tFile->tileYSize();
231
0
    int maxDy = (maxY - ifd->minY) / ifd->tFile->tileYSize();
232
233
    //
234
    // Figure out which one is first in the file so we can read without seeking
235
    //
236
237
0
    int yStart, yEnd, yStep;
238
239
0
    if (ifd->lineOrder == DECREASING_Y)
240
0
    {
241
0
        yStart = maxDy;
242
0
        yEnd = minDy - 1;
243
0
        yStep = -1;
244
0
    }
245
0
    else
246
0
    {
247
0
        yStart = minDy;
248
0
        yEnd = maxDy + 1;
249
0
        yStep = 1;
250
0
    }
251
252
    //
253
    // the number of pixels in a row of tiles
254
    //
255
256
0
    Box2i levelRange = ifd->tFile->dataWindowForLevel(0);
257
    
258
    //
259
    // Read the tiles into our temporary framebuffer and copy them into
260
    // the user's buffer
261
    //
262
263
0
    for (int j = yStart; j != yEnd; j += yStep)
264
0
    {
265
0
        Box2i tileRange = ifd->tFile->dataWindowForTile (0, j, 0);
266
267
0
        int minYThisRow = std::max (minY, tileRange.min.y);
268
0
        int maxYThisRow = std::min (maxY, tileRange.max.y);
269
270
0
        if (j != ifd->cachedTileY)
271
0
        {
272
            //
273
            // We don't have any valid buffered info, so we need to read in
274
            // from the file.
275
            //
276
277
0
            ifd->tFile->readTiles (0, ifd->tFile->numXTiles (0) - 1, j, j);
278
0
            ifd->cachedTileY = j;
279
0
        }
280
281
        //
282
        // Copy the data from our cached framebuffer into the user's
283
        // framebuffer.
284
        //
285
286
0
        for (FrameBuffer::ConstIterator k = ifd->cachedBuffer->begin();
287
0
             k != ifd->cachedBuffer->end();
288
0
             ++k)
289
0
        {
290
0
            Slice fromSlice = k.slice();    // slice to write from
291
0
            Slice toSlice = ifd->tFileBuffer[k.name()]; // slice to write to
292
293
0
            char *fromPtr, *toPtr;
294
0
            int size = pixelTypeSize (toSlice.type);
295
296
0
      int xStart = levelRange.min.x;
297
0
      int yStart = minYThisRow;
298
299
0
      while (modp (xStart, toSlice.xSampling) != 0)
300
0
    ++xStart;
301
302
0
      while (modp (yStart, toSlice.ySampling) != 0)
303
0
    ++yStart;
304
305
0
            for (int y = yStart;
306
0
     y <= maxYThisRow;
307
0
     y += toSlice.ySampling)
308
0
            {
309
    //
310
                // Set the pointers to the start of the y scanline in
311
                // this row of tiles
312
    //
313
                
314
0
                fromPtr = fromSlice.base +
315
0
                          (y - tileRange.min.y) * fromSlice.yStride +
316
0
                          xStart * fromSlice.xStride;
317
318
0
                toPtr = toSlice.base +
319
0
                        divp (y, toSlice.ySampling) * toSlice.yStride +
320
0
                        divp (xStart, toSlice.xSampling) * toSlice.xStride;
321
322
    //
323
                // Copy all pixels for the scanline in this row of tiles
324
    //
325
326
0
                for (int x = xStart;
327
0
         x <= levelRange.max.x;
328
0
         x += toSlice.xSampling)
329
0
                {
330
0
        for (int i = 0; i < size; ++i)
331
0
      toPtr[i] = fromPtr[i];
332
333
0
        fromPtr += fromSlice.xStride * toSlice.xSampling;
334
0
        toPtr += toSlice.xStride;
335
0
                }
336
0
            }
337
0
        }
338
0
    }
339
0
}
340
341
} // namespace
342
343
344
345
InputFile::InputFile (const char fileName[], int numThreads):
346
    _data (new Data (numThreads))
347
0
{
348
0
    _data->_streamData = NULL;
349
0
    _data->_deleteStream=true;
350
    
351
0
    OPENEXR_IMF_INTERNAL_NAMESPACE::IStream* is = 0;
352
0
    try
353
0
    {
354
0
        is = new StdIFStream (fileName);
355
0
        readMagicNumberAndVersionField(*is, _data->version);
356
357
        //
358
        // compatibility to read multipart file.
359
        //
360
0
        if (isMultiPart(_data->version))
361
0
        {
362
0
            compatibilityInitialize(*is);
363
0
        }
364
0
        else
365
0
        {
366
0
            _data->_streamData = new InputStreamMutex();
367
0
            _data->_streamData->is = is;
368
0
            _data->header.readFrom (*_data->_streamData->is, _data->version);
369
            
370
            // fix type attribute in single part regular image types
371
            // (may be wrong if an old version of OpenEXR converts
372
            // a tiled image to scanline or vice versa)
373
0
            if(!isNonImage(_data->version)  && 
374
0
               !isMultiPart(_data->version) && 
375
0
               _data->header.hasType())
376
0
            {
377
0
                _data->header.setType(isTiled(_data->version) ? TILEDIMAGE : SCANLINEIMAGE);
378
0
            }
379
            
380
0
            _data->header.sanityCheck (isTiled (_data->version));
381
382
0
            initialize();
383
0
        }
384
0
    }
385
0
    catch (IEX_NAMESPACE::BaseExc &e)
386
0
    {
387
0
        if (is)          delete is;
388
         
389
0
        if ( _data && !_data->multiPartBackwardSupport  && _data->_streamData)
390
0
        {
391
0
            delete _data->_streamData;
392
0
            _data->_streamData=NULL;
393
0
        }
394
        
395
0
        if (_data)       delete _data;
396
0
        _data=NULL;
397
398
0
        REPLACE_EXC (e, "Cannot read image file "
399
0
      "\"" << fileName << "\". " << e);
400
0
        throw;
401
0
    }
402
0
    catch (...)
403
0
    {
404
0
        if (is)          delete is;
405
0
        if (_data && !_data->multiPartBackwardSupport && _data->_streamData)
406
0
        {
407
0
            delete _data->_streamData;
408
0
        }
409
0
        if (_data)       delete _data;
410
411
0
        throw;
412
0
    }
413
0
}
414
415
416
InputFile::InputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int numThreads):
417
    _data (new Data (numThreads))
418
0
{
419
0
    _data->_streamData=NULL;
420
0
    _data->_deleteStream=false;
421
0
    try
422
0
    {
423
0
        readMagicNumberAndVersionField(is, _data->version);
424
425
        //
426
        // Backward compatibility to read multpart file.
427
        //
428
0
        if (isMultiPart(_data->version))
429
0
        {
430
0
            compatibilityInitialize(is);
431
0
        }
432
0
        else
433
0
        {
434
0
            _data->_streamData = new InputStreamMutex();
435
0
            _data->_streamData->is = &is;
436
0
            _data->header.readFrom (*_data->_streamData->is, _data->version);
437
            
438
            // fix type attribute in single part regular image types
439
            // (may be wrong if an old version of OpenEXR converts
440
            // a tiled image to scanline or vice versa)
441
0
            if(!isNonImage(_data->version)  && 
442
0
               !isMultiPart(_data->version) &&  
443
0
               _data->header.hasType())
444
0
            {
445
0
                _data->header.setType(isTiled(_data->version) ? TILEDIMAGE : SCANLINEIMAGE);
446
0
            }
447
            
448
0
            _data->header.sanityCheck (isTiled (_data->version));
449
450
0
            initialize();
451
0
        }
452
0
    }
453
0
    catch (IEX_NAMESPACE::BaseExc &e)
454
0
    {
455
0
        if (_data && !_data->multiPartBackwardSupport && _data->_streamData) delete _data->_streamData;
456
0
        if (_data)       delete _data;
457
0
        _data=NULL; 
458
459
0
        REPLACE_EXC (e, "Cannot read image file "
460
0
      "\"" << is.fileName() << "\". " << e);
461
0
        throw;
462
0
    }
463
0
    catch (...)
464
0
    {
465
0
        if (_data &&  !_data->multiPartBackwardSupport  && _data->_streamData) delete _data->_streamData;
466
0
        if (_data)       delete _data;
467
0
        _data=NULL;
468
0
        throw;
469
0
    }
470
0
}
471
472
473
InputFile::InputFile (InputPartData* part) :
474
    _data (new Data (part->numThreads))
475
0
{
476
0
    _data->_deleteStream=false;
477
0
    multiPartInitialize (part);
478
0
}
479
480
481
void
482
InputFile::compatibilityInitialize (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream& is)
483
0
{
484
0
    is.seekg(0);
485
486
    //
487
    // Construct a MultiPartInputFile, initialize InputFile
488
    // with the part 0 data.
489
    // (TODO) may want to have a way to set the reconstruction flag.
490
    //
491
0
    _data->multiPartBackwardSupport = true;
492
0
    _data->multiPartFile = new MultiPartInputFile(is, _data->numThreads);
493
0
    InputPartData* part = _data->multiPartFile->getPart(0);
494
495
0
    multiPartInitialize (part);
496
0
}
497
498
499
void
500
InputFile::multiPartInitialize (InputPartData* part)
501
0
{
502
0
    _data->_streamData = part->mutex;
503
0
    _data->version = part->version;
504
0
    _data->header = part->header;
505
0
    _data->partNumber = part->partNumber;
506
0
    _data->part = part;
507
508
0
    initialize();
509
0
}
510
511
512
void
513
InputFile::initialize ()
514
0
{
515
0
    if (!_data->part)
516
0
    {
517
0
        if(_data->header.hasType() && _data->header.type()==DEEPSCANLINE)
518
0
        {
519
0
            _data->isTiled=false;
520
0
            const Box2i &dataWindow = _data->header.dataWindow();
521
0
            _data->minY = dataWindow.min.y;
522
0
            _data->maxY = dataWindow.max.y;
523
            
524
0
            _data->dsFile = new DeepScanLineInputFile (_data->header,
525
0
                                               _data->_streamData->is,
526
0
                                               _data->version,
527
0
                                               _data->numThreads);
528
0
            _data->compositor = new CompositeDeepScanLine;
529
0
            _data->compositor->addSource(_data->dsFile);
530
0
        }
531
        
532
0
        else if (isTiled (_data->version))
533
0
        {
534
0
            _data->isTiled = true;
535
0
            _data->lineOrder = _data->header.lineOrder();
536
537
            //
538
            // Save the dataWindow information
539
            //
540
    
541
0
            const Box2i &dataWindow = _data->header.dataWindow();
542
0
            _data->minY = dataWindow.min.y;
543
0
            _data->maxY = dataWindow.max.y;
544
545
0
            _data->tFile = new TiledInputFile (_data->header,
546
0
                                               _data->_streamData->is,
547
0
                                               _data->version,
548
0
                                               _data->numThreads);
549
0
        }
550
        
551
0
        else if(!_data->header.hasType() || _data->header.type()==SCANLINEIMAGE)
552
0
        {
553
0
            _data->sFile = new ScanLineInputFile (_data->header,
554
0
                                                  _data->_streamData->is,
555
0
                                                  _data->numThreads);
556
0
        }else{
557
            // type set but not recognised
558
            
559
0
            THROW(IEX_NAMESPACE::ArgExc, "InputFile cannot handle parts of type " << _data->header.type());
560
0
        }
561
0
    }
562
0
    else
563
0
    {
564
0
        if(_data->header.hasType() && _data->header.type()==DEEPSCANLINE)
565
0
        {
566
0
            _data->isTiled=false;
567
0
            const Box2i &dataWindow = _data->header.dataWindow();
568
0
            _data->minY = dataWindow.min.y;
569
0
            _data->maxY = dataWindow.max.y;
570
            
571
0
            _data->dsFile = new DeepScanLineInputFile (_data->part);
572
0
            _data->compositor = new CompositeDeepScanLine;
573
0
            _data->compositor->addSource(_data->dsFile);
574
0
        }
575
0
        else if (isTiled (_data->header.type()))
576
0
        {
577
0
            _data->isTiled = true;
578
0
            _data->lineOrder = _data->header.lineOrder();
579
580
            //
581
            // Save the dataWindow information
582
            //
583
584
0
            const Box2i &dataWindow = _data->header.dataWindow();
585
0
            _data->minY = dataWindow.min.y;
586
0
            _data->maxY = dataWindow.max.y;
587
588
0
            _data->tFile = new TiledInputFile (_data->part);
589
0
        }
590
0
        else if(!_data->header.hasType() || _data->header.type()==SCANLINEIMAGE)
591
0
        {
592
0
            _data->sFile = new ScanLineInputFile (_data->part);
593
0
        }else{
594
0
            THROW(IEX_NAMESPACE::ArgExc, "InputFile cannot handle parts of type " << _data->header.type());
595
            
596
0
        }
597
0
    }
598
0
}
599
600
#include <iostream>
601
InputFile::~InputFile ()
602
0
{
603
0
    if (_data->_deleteStream)
604
0
        delete _data->_streamData->is;
605
606
    // unless this file was opened via the multipart API,
607
    // delete the streamData object too
608
0
    if (_data->partNumber==-1 && _data->_streamData)
609
0
        delete _data->_streamData;
610
611
0
    if (_data)  delete _data;
612
0
}
613
614
const char *
615
InputFile::fileName () const
616
0
{
617
0
    return _data->_streamData->is->fileName();
618
0
}
619
620
621
const Header &
622
InputFile::header () const
623
0
{
624
0
    return _data->header;
625
0
}
626
627
628
int
629
InputFile::version () const
630
0
{
631
0
    return _data->version;
632
0
}
633
634
635
void
636
InputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
637
0
{
638
0
    if (_data->isTiled)
639
0
    {
640
0
  Lock lock (*_data);
641
642
  //
643
        // We must invalidate the cached buffer if the new frame
644
  // buffer has a different set of channels than the old
645
  // frame buffer, or if the type of a channel has changed.
646
  //
647
648
0
  const FrameBuffer &oldFrameBuffer = _data->tFileBuffer;
649
650
0
  FrameBuffer::ConstIterator i = oldFrameBuffer.begin();
651
0
  FrameBuffer::ConstIterator j = frameBuffer.begin();
652
653
0
  while (i != oldFrameBuffer.end() && j != frameBuffer.end())
654
0
  {
655
0
      if (strcmp (i.name(), j.name()) || i.slice().type != j.slice().type)
656
0
    break;
657
658
0
      ++i;
659
0
      ++j;
660
0
  }
661
662
0
  if (i != oldFrameBuffer.end() || j != frameBuffer.end())
663
0
        {
664
      //
665
      // Invalidate the cached buffer.
666
      //
667
668
0
            _data->deleteCachedBuffer ();
669
0
      _data->cachedTileY = -1;
670
671
      //
672
      // Create new a cached frame buffer.  It can hold a single
673
      // row of tiles.  The cached buffer can be reused for each
674
      // row of tiles because we set the yTileCoords parameter of
675
      // each Slice to true.
676
      //
677
678
0
      const Box2i &dataWindow = _data->header.dataWindow();
679
0
      _data->cachedBuffer = new FrameBuffer();
680
0
      _data->offset = dataWindow.min.x;
681
      
682
0
      int tileRowSize = (dataWindow.max.x - dataWindow.min.x + 1) *
683
0
            _data->tFile->tileYSize();
684
685
0
      for (FrameBuffer::ConstIterator k = frameBuffer.begin();
686
0
     k != frameBuffer.end();
687
0
     ++k)
688
0
      {
689
0
    Slice s = k.slice();
690
691
0
    switch (s.type)
692
0
    {
693
0
      case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT:
694
695
0
        _data->cachedBuffer->insert
696
0
      (k.name(),
697
0
       Slice (UINT,
698
0
        (char *)(new unsigned int[tileRowSize] - 
699
0
          _data->offset),
700
0
        sizeof (unsigned int),
701
0
        sizeof (unsigned int) *
702
0
            _data->tFile->levelWidth(0),
703
0
        1, 1,
704
0
        s.fillValue,
705
0
        false, true));
706
0
        break;
707
708
0
      case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF:
709
710
0
        _data->cachedBuffer->insert
711
0
      (k.name(),
712
0
       Slice (HALF,
713
0
        (char *)(new half[tileRowSize] - 
714
0
          _data->offset),
715
0
        sizeof (half),
716
0
        sizeof (half) *
717
0
            _data->tFile->levelWidth(0),
718
0
        1, 1,
719
0
        s.fillValue,
720
0
        false, true));
721
0
        break;
722
723
0
      case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT:
724
725
0
        _data->cachedBuffer->insert
726
0
      (k.name(),
727
0
       Slice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT,
728
0
        (char *)(new float[tileRowSize] - 
729
0
          _data->offset),
730
0
        sizeof(float),
731
0
        sizeof(float) *
732
0
            _data->tFile->levelWidth(0),
733
0
        1, 1,
734
0
        s.fillValue,
735
0
        false, true));
736
0
        break;
737
738
0
      default:
739
740
0
        throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type.");
741
0
    }
742
0
      }
743
744
0
      _data->tFile->setFrameBuffer (*_data->cachedBuffer);
745
0
        }
746
747
0
  _data->tFileBuffer = frameBuffer;
748
0
    }
749
0
    else if(_data->compositor)
750
0
    {
751
0
        _data->compositor->setFrameBuffer(frameBuffer);
752
0
    }else {
753
0
        _data->sFile->setFrameBuffer(frameBuffer);
754
0
        _data->tFileBuffer = frameBuffer;
755
0
    }
756
0
}
757
758
759
const FrameBuffer &
760
InputFile::frameBuffer () const
761
0
{
762
0
    if(_data->compositor)
763
0
    {
764
0
        return _data->compositor->frameBuffer();
765
0
    }
766
0
    else if(_data->isTiled)
767
0
    {
768
0
  Lock lock (*_data);
769
0
  return _data->tFileBuffer;
770
0
    }
771
0
    else
772
0
    {
773
0
  return _data->sFile->frameBuffer();
774
0
    }
775
0
}
776
777
778
bool
779
InputFile::isComplete () const
780
0
{
781
0
    if (_data->dsFile)
782
0
        return _data->dsFile->isComplete();
783
0
    else if (_data->isTiled)
784
0
  return _data->tFile->isComplete();
785
0
    else
786
0
  return _data->sFile->isComplete();
787
0
}
788
789
bool
790
InputFile::isOptimizationEnabled() const
791
0
{
792
0
   if(_data->sFile)
793
0
   {
794
0
       return _data->sFile->isOptimizationEnabled();
795
0
   }else{
796
0
       return false;
797
0
   }
798
0
}
799
800
801
void
802
InputFile::readPixels (int scanLine1, int scanLine2)
803
0
{
804
0
    if (_data->compositor)
805
0
    {
806
0
        _data->compositor->readPixels(scanLine1,scanLine2);
807
0
    }
808
0
    else if (_data->isTiled)
809
0
    {
810
0
  Lock lock (*_data);
811
0
        bufferedReadPixels (_data, scanLine1, scanLine2);
812
0
    }
813
0
    else
814
0
    {
815
0
        _data->sFile->readPixels (scanLine1, scanLine2);
816
0
    }
817
0
}
818
819
820
void
821
InputFile::readPixels (int scanLine)
822
0
{
823
0
    readPixels (scanLine, scanLine);
824
0
}
825
826
827
void
828
InputFile::rawPixelData (int firstScanLine,
829
       const char *&pixelData,
830
       int &pixelDataSize)
831
0
{
832
0
    try
833
0
    {
834
0
        if (_data->dsFile)
835
0
        {
836
0
            throw IEX_NAMESPACE::ArgExc ("Tried to read a raw scanline "
837
0
            "from a deep image.");
838
0
        }
839
        
840
0
  else if (_data->isTiled)
841
0
  {
842
0
      throw IEX_NAMESPACE::ArgExc ("Tried to read a raw scanline "
843
0
             "from a tiled image.");
844
0
  }
845
        
846
0
        _data->sFile->rawPixelData (firstScanLine, pixelData, pixelDataSize);
847
0
    }
848
0
    catch (IEX_NAMESPACE::BaseExc &e)
849
0
    {
850
0
  REPLACE_EXC (e, "Error reading pixel data from image "
851
0
            "file \"" << fileName() << "\". " << e);
852
0
  throw;
853
0
    }
854
0
}
855
856
857
void
858
InputFile::rawTileData (int &dx, int &dy,
859
      int &lx, int &ly,
860
      const char *&pixelData,
861
      int &pixelDataSize)
862
0
{
863
0
    try
864
0
    {
865
0
  if (!_data->isTiled)
866
0
  {
867
0
      throw IEX_NAMESPACE::ArgExc ("Tried to read a raw tile "
868
0
             "from a scanline-based image.");
869
0
  }
870
        
871
0
        _data->tFile->rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize);
872
0
    }
873
0
    catch (IEX_NAMESPACE::BaseExc &e)
874
0
    {
875
0
  REPLACE_EXC (e, "Error reading tile data from image "
876
0
            "file \"" << fileName() << "\". " << e);
877
0
  throw;
878
0
    }
879
0
}
880
881
882
TiledInputFile*
883
InputFile::tFile()
884
0
{
885
0
    if (!_data->isTiled)
886
0
    {
887
0
  throw IEX_NAMESPACE::ArgExc ("Cannot get a TiledInputFile pointer "
888
0
         "from an InputFile that is not tiled.");
889
0
    }
890
891
0
    return _data->tFile;
892
0
}
893
894
895
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT