root/3rdparty/openexr/IlmImf/ImfTiledRgbaFile.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. insertChannels
  2. rgbaChannels
  3. prefixFromLayerName
  4. ywFromHeader
  5. setFrameBuffer
  6. writeTile
  7. _toYa
  8. _toYa
  9. _toYa
  10. _toYa
  11. setFrameBuffer
  12. header
  13. frameBuffer
  14. displayWindow
  15. dataWindow
  16. pixelAspectRatio
  17. screenWindowCenter
  18. screenWindowWidth
  19. lineOrder
  20. compression
  21. channels
  22. tileXSize
  23. tileYSize
  24. levelMode
  25. levelRoundingMode
  26. numLevels
  27. numXLevels
  28. numYLevels
  29. isValidLevel
  30. levelWidth
  31. levelHeight
  32. numXTiles
  33. numYTiles
  34. dataWindowForLevel
  35. dataWindowForLevel
  36. dataWindowForTile
  37. dataWindowForTile
  38. writeTile
  39. writeTile
  40. setFrameBuffer
  41. readTile
  42. _channelNamePrefix
  43. _channelNamePrefix
  44. _channelNamePrefix
  45. _channelNamePrefix
  46. setFrameBuffer
  47. setLayerName
  48. header
  49. fileName
  50. frameBuffer
  51. displayWindow
  52. dataWindow
  53. pixelAspectRatio
  54. screenWindowCenter
  55. screenWindowWidth
  56. lineOrder
  57. compression
  58. channels
  59. version
  60. isComplete
  61. tileXSize
  62. tileYSize
  63. levelMode
  64. levelRoundingMode
  65. numLevels
  66. numXLevels
  67. numYLevels
  68. isValidLevel
  69. levelWidth
  70. levelHeight
  71. numXTiles
  72. numYTiles
  73. dataWindowForLevel
  74. dataWindowForLevel
  75. dataWindowForTile
  76. dataWindowForTile
  77. readTile
  78. readTile
  79. readTiles
  80. readTiles
  81. updatePreviewImage
  82. breakTile

///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// *       Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// *       Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// *       Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------------
//
//      class TiledRgbaOutputFile
//      class TiledRgbaInputFile
//
//-----------------------------------------------------------------------------

#include <ImfTiledRgbaFile.h>
#include <ImfRgbaFile.h>
#include <ImfTiledOutputFile.h>
#include <ImfTiledInputFile.h>
#include <ImfChannelList.h>
#include <ImfTileDescriptionAttribute.h>
#include <ImfStandardAttributes.h>
#include <ImfRgbaYca.h>
#include <ImfArray.h>
#include "IlmThreadMutex.h"
#include "Iex.h"


namespace Imf {

using namespace std;
using namespace Imath;
using namespace RgbaYca;
using namespace IlmThread;

namespace {

void
insertChannels (Header &header,
        RgbaChannels rgbaChannels,
        const char fileName[])
{
    ChannelList ch;

    if (rgbaChannels & (WRITE_Y | WRITE_C))
    {
    if (rgbaChannels & WRITE_Y)
    {
        ch.insert ("Y", Channel (HALF, 1, 1));
    }

    if (rgbaChannels & WRITE_C)
    {
        THROW (Iex::ArgExc, "Cannot open file \"" << fileName << "\" "
                "for writing.  Tiled image files do not "
                "support subsampled chroma channels.");
    }
    }
    else
    {
    if (rgbaChannels & WRITE_R)
        ch.insert ("R", Channel (HALF, 1, 1));

    if (rgbaChannels & WRITE_G)
        ch.insert ("G", Channel (HALF, 1, 1));

    if (rgbaChannels & WRITE_B)
        ch.insert ("B", Channel (HALF, 1, 1));
    }

    if (rgbaChannels & WRITE_A)
    ch.insert ("A", Channel (HALF, 1, 1));

    header.channels() = ch;
}


RgbaChannels
rgbaChannels (const ChannelList &ch, const string &channelNamePrefix = "")
{
    int i = 0;

    if (ch.findChannel (channelNamePrefix + "R"))
    i |= WRITE_R;

    if (ch.findChannel (channelNamePrefix + "G"))
    i |= WRITE_G;

    if (ch.findChannel (channelNamePrefix + "B"))
    i |= WRITE_B;

    if (ch.findChannel (channelNamePrefix + "A"))
    i |= WRITE_A;

    if (ch.findChannel (channelNamePrefix + "Y"))
    i |= WRITE_Y;

    return RgbaChannels (i);
}


string
prefixFromLayerName (const string &layerName, const Header &header)
{
    if (layerName.empty())
    return "";

    if (hasMultiView (header) && multiView(header)[0] == layerName)
    return "";

    return layerName + ".";
}


V3f
ywFromHeader (const Header &header)
{
    Chromaticities cr;

    if (hasChromaticities (header))
    cr = chromaticities (header);

    return computeYw (cr);
}

} // namespace


class TiledRgbaOutputFile::ToYa: public Mutex
{
  public:

     ToYa (TiledOutputFile &outputFile, RgbaChannels rgbaChannels);

     void       setFrameBuffer (const Rgba *base,
                size_t xStride,
                size_t yStride);

     void       writeTile (int dx, int dy, int lx, int ly);

  private:

     TiledOutputFile &  _outputFile;
     bool               _writeA;
     unsigned int       _tileXSize;
     unsigned int       _tileYSize;
     V3f                _yw;
     Array2D <Rgba>     _buf;
     const Rgba *       _fbBase;
     size_t             _fbXStride;
     size_t             _fbYStride;
};


TiledRgbaOutputFile::ToYa::ToYa (TiledOutputFile &outputFile,
                 RgbaChannels rgbaChannels)
:
    _outputFile (outputFile)
{
    _writeA = (rgbaChannels & WRITE_A)? true: false;

    const TileDescription &td = outputFile.header().tileDescription();

    _tileXSize = td.xSize;
    _tileYSize = td.ySize;
    _yw = ywFromHeader (_outputFile.header());
    _buf.resizeErase (_tileYSize, _tileXSize);
    _fbBase = 0;
    _fbXStride = 0;
    _fbYStride = 0;
}


void
TiledRgbaOutputFile::ToYa::setFrameBuffer (const Rgba *base,
                       size_t xStride,
                       size_t yStride)
{
    _fbBase = base;
    _fbXStride = xStride;
    _fbYStride = yStride;
}


void
TiledRgbaOutputFile::ToYa::writeTile (int dx, int dy, int lx, int ly)
{
    if (_fbBase == 0)
    {
    THROW (Iex::ArgExc, "No frame buffer was specified as the "
                "pixel data source for image file "
                "\"" << _outputFile.fileName() << "\".");
    }

    //
    // Copy the tile's RGBA pixels into _buf and convert
    // them to luminance/alpha format
    //

    Box2i dw = _outputFile.dataWindowForTile (dx, dy, lx, ly);
    int width = dw.max.x - dw.min.x + 1;

    for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1)
    {
    for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1)
        _buf[y1][x1] = _fbBase[x * _fbXStride + y * _fbYStride];

    RGBAtoYCA (_yw, width, _writeA, _buf[y1], _buf[y1]);
    }

    //
    // Store the contents of _buf in the output file
    //

    FrameBuffer fb;

    fb.insert ("Y", Slice (HALF,                                   // type
               (char *) &_buf[-dw.min.y][-dw.min.x].g, // base
               sizeof (Rgba),                      // xStride
               sizeof (Rgba) * _tileXSize));       // yStride

    fb.insert ("A", Slice (HALF,                                   // type
               (char *) &_buf[-dw.min.y][-dw.min.x].a, // base
               sizeof (Rgba),                      // xStride
               sizeof (Rgba) * _tileXSize));       // yStride

    _outputFile.setFrameBuffer (fb);
    _outputFile.writeTile (dx, dy, lx, ly);
}


TiledRgbaOutputFile::TiledRgbaOutputFile
    (const char name[],
     const Header &header,
     RgbaChannels rgbaChannels,
     int tileXSize,
     int tileYSize,
     LevelMode mode,
     LevelRoundingMode rmode,
     int numThreads)
:
    _outputFile (0),
    _toYa (0)
{
    Header hd (header);
    insertChannels (hd, rgbaChannels, name);
    hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
    _outputFile = new TiledOutputFile (name, hd, numThreads);

    if (rgbaChannels & WRITE_Y)
    _toYa = new ToYa (*_outputFile, rgbaChannels);
}



TiledRgbaOutputFile::TiledRgbaOutputFile
    (OStream &os,
     const Header &header,
     RgbaChannels rgbaChannels,
     int tileXSize,
     int tileYSize,
     LevelMode mode,
     LevelRoundingMode rmode,
     int numThreads)
:
    _outputFile (0),
    _toYa (0)
{
    Header hd (header);
    insertChannels (hd, rgbaChannels, os.fileName());
    hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
    _outputFile = new TiledOutputFile (os, hd, numThreads);

    if (rgbaChannels & WRITE_Y)
    _toYa = new ToYa (*_outputFile, rgbaChannels);
}



TiledRgbaOutputFile::TiledRgbaOutputFile
    (const char name[],
     int tileXSize,
     int tileYSize,
     LevelMode mode,
     LevelRoundingMode rmode,
     const Imath::Box2i &displayWindow,
     const Imath::Box2i &dataWindow,
     RgbaChannels rgbaChannels,
     float pixelAspectRatio,
     const Imath::V2f screenWindowCenter,
     float screenWindowWidth,
     LineOrder lineOrder,
     Compression compression,
     int numThreads)
:
    _outputFile (0),
    _toYa (0)
{
    Header hd (displayWindow,
           dataWindow.isEmpty()? displayWindow: dataWindow,
           pixelAspectRatio,
           screenWindowCenter,
           screenWindowWidth,
           lineOrder,
           compression);

    insertChannels (hd, rgbaChannels, name);
    hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
    _outputFile = new TiledOutputFile (name, hd, numThreads);

    if (rgbaChannels & WRITE_Y)
    _toYa = new ToYa (*_outputFile, rgbaChannels);
}


TiledRgbaOutputFile::TiledRgbaOutputFile
    (const char name[],
     int width,
     int height,
     int tileXSize,
     int tileYSize,
     LevelMode mode,
     LevelRoundingMode rmode,
     RgbaChannels rgbaChannels,
     float pixelAspectRatio,
     const Imath::V2f screenWindowCenter,
     float screenWindowWidth,
     LineOrder lineOrder,
     Compression compression,
     int numThreads)
:
    _outputFile (0),
    _toYa (0)
{
    Header hd (width,
           height,
           pixelAspectRatio,
           screenWindowCenter,
           screenWindowWidth,
           lineOrder,
           compression);

    insertChannels (hd, rgbaChannels, name);
    hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode));
    _outputFile = new TiledOutputFile (name, hd, numThreads);

    if (rgbaChannels & WRITE_Y)
    _toYa = new ToYa (*_outputFile, rgbaChannels);
}


TiledRgbaOutputFile::~TiledRgbaOutputFile ()
{
    delete _outputFile;
    delete _toYa;
}


void
TiledRgbaOutputFile::setFrameBuffer (const Rgba *base,
                     size_t xStride,
                     size_t yStride)
{
    if (_toYa)
    {
    Lock lock (*_toYa);
    _toYa->setFrameBuffer (base, xStride, yStride);
    }
    else
    {
    size_t xs = xStride * sizeof (Rgba);
    size_t ys = yStride * sizeof (Rgba);

    FrameBuffer fb;

    fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys));
    fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys));
    fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys));
    fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys));

    _outputFile->setFrameBuffer (fb);
    }
}


const Header &
TiledRgbaOutputFile::header () const
{
    return _outputFile->header();
}


const FrameBuffer &
TiledRgbaOutputFile::frameBuffer () const
{
    return _outputFile->frameBuffer();
}


const Imath::Box2i &
TiledRgbaOutputFile::displayWindow () const
{
    return _outputFile->header().displayWindow();
}


const Imath::Box2i &
TiledRgbaOutputFile::dataWindow () const
{
    return _outputFile->header().dataWindow();
}


float
TiledRgbaOutputFile::pixelAspectRatio () const
{
    return _outputFile->header().pixelAspectRatio();
}


const Imath::V2f
TiledRgbaOutputFile::screenWindowCenter () const
{
    return _outputFile->header().screenWindowCenter();
}


float
TiledRgbaOutputFile::screenWindowWidth () const
{
    return _outputFile->header().screenWindowWidth();
}


LineOrder
TiledRgbaOutputFile::lineOrder () const
{
    return _outputFile->header().lineOrder();
}


Compression
TiledRgbaOutputFile::compression () const
{
    return _outputFile->header().compression();
}


RgbaChannels
TiledRgbaOutputFile::channels () const
{
    return rgbaChannels (_outputFile->header().channels());
}


unsigned int
TiledRgbaOutputFile::tileXSize () const
{
     return _outputFile->tileXSize();
}


unsigned int
TiledRgbaOutputFile::tileYSize () const
{
     return _outputFile->tileYSize();
}


LevelMode
TiledRgbaOutputFile::levelMode () const
{
     return _outputFile->levelMode();
}


LevelRoundingMode
TiledRgbaOutputFile::levelRoundingMode () const
{
     return _outputFile->levelRoundingMode();
}


int
TiledRgbaOutputFile::numLevels () const
{
     return _outputFile->numLevels();
}


int
TiledRgbaOutputFile::numXLevels () const
{
     return _outputFile->numXLevels();
}


int
TiledRgbaOutputFile::numYLevels () const
{
     return _outputFile->numYLevels();
}


bool
TiledRgbaOutputFile::isValidLevel (int lx, int ly) const
{
    return _outputFile->isValidLevel (lx, ly);
}


int
TiledRgbaOutputFile::levelWidth (int lx) const
{
     return _outputFile->levelWidth (lx);
}


int
TiledRgbaOutputFile::levelHeight (int ly) const
{
     return _outputFile->levelHeight (ly);
}


int
TiledRgbaOutputFile::numXTiles (int lx) const
{
     return _outputFile->numXTiles (lx);
}


int
TiledRgbaOutputFile::numYTiles (int ly) const
{
     return _outputFile->numYTiles (ly);
}


Imath::Box2i
TiledRgbaOutputFile::dataWindowForLevel (int l) const
{
     return _outputFile->dataWindowForLevel (l);
}


Imath::Box2i
TiledRgbaOutputFile::dataWindowForLevel (int lx, int ly) const
{
     return _outputFile->dataWindowForLevel (lx, ly);
}


Imath::Box2i
TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int l) const
{
     return _outputFile->dataWindowForTile (dx, dy, l);
}


Imath::Box2i
TiledRgbaOutputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
{
     return _outputFile->dataWindowForTile (dx, dy, lx, ly);
}


void
TiledRgbaOutputFile::writeTile (int dx, int dy, int l)
{
    if (_toYa)
    {
    Lock lock (*_toYa);
    _toYa->writeTile (dx, dy, l, l);
    }
    else
    {
     _outputFile->writeTile (dx, dy, l);
    }
}


void
TiledRgbaOutputFile::writeTile (int dx, int dy, int lx, int ly)
{
    if (_toYa)
    {
    Lock lock (*_toYa);
    _toYa->writeTile (dx, dy, lx, ly);
    }
    else
    {
     _outputFile->writeTile (dx, dy, lx, ly);
    }
}


void
TiledRgbaOutputFile::writeTiles
    (int dxMin, int dxMax, int dyMin, int dyMax, int lx, int ly)
{
    if (_toYa)
    {
    Lock lock (*_toYa);

        for (int dy = dyMin; dy <= dyMax; dy++)
            for (int dx = dxMin; dx <= dxMax; dx++)
            _toYa->writeTile (dx, dy, lx, ly);
    }
    else
    {
        _outputFile->writeTiles (dxMin, dxMax, dyMin, dyMax, lx, ly);
    }
}

void
TiledRgbaOutputFile::writeTiles
    (int dxMin, int dxMax, int dyMin, int dyMax, int l)
{
    writeTiles (dxMin, dxMax, dyMin, dyMax, l, l);
}


class TiledRgbaInputFile::FromYa: public Mutex
{
  public:

     FromYa (TiledInputFile &inputFile);

     void       setFrameBuffer (Rgba *base,
                size_t xStride,
                size_t yStride,
                const string &channelNamePrefix);

     void       readTile (int dx, int dy, int lx, int ly);

  private:

     TiledInputFile &   _inputFile;
     unsigned int       _tileXSize;
     unsigned int       _tileYSize;
     V3f                _yw;
     Array2D <Rgba>     _buf;
     Rgba *             _fbBase;
     size_t             _fbXStride;
     size_t             _fbYStride;
};


TiledRgbaInputFile::FromYa::FromYa (TiledInputFile &inputFile)
:
    _inputFile (inputFile)
{
    const TileDescription &td = inputFile.header().tileDescription();

    _tileXSize = td.xSize;
    _tileYSize = td.ySize;
    _yw = ywFromHeader (_inputFile.header());
    _buf.resizeErase (_tileYSize, _tileXSize);
    _fbBase = 0;
    _fbXStride = 0;
    _fbYStride = 0;
}


void
TiledRgbaInputFile::FromYa::setFrameBuffer (Rgba *base,
                        size_t xStride,
                        size_t yStride,
                        const string &channelNamePrefix)
{
    if (_fbBase == 0)
{
    FrameBuffer fb;

    fb.insert (channelNamePrefix + "Y",
           Slice (HALF,                         // type
              (char *) &_buf[0][0].g,   // base
              sizeof (Rgba),            // xStride
              sizeof (Rgba) * _tileXSize,       // yStride
              1, 1,                             // sampling
              0.0,                              // fillValue
              true, true));                     // tileCoordinates

    fb.insert (channelNamePrefix + "A",
           Slice (HALF,                         // type
              (char *) &_buf[0][0].a,   // base
              sizeof (Rgba),            // xStride
              sizeof (Rgba) * _tileXSize,       // yStride
              1, 1,                             // sampling
              1.0,                              // fillValue
              true, true));                     // tileCoordinates

    _inputFile.setFrameBuffer (fb);
    }

    _fbBase = base;
    _fbXStride = xStride;
    _fbYStride = yStride;
}


void
TiledRgbaInputFile::FromYa::readTile (int dx, int dy, int lx, int ly)
{
    if (_fbBase == 0)
    {
    THROW (Iex::ArgExc, "No frame buffer was specified as the "
                "pixel data destination for image file "
                "\"" << _inputFile.fileName() << "\".");
    }

    //
    // Read the tile requested by the caller into _buf.
    //

    _inputFile.readTile (dx, dy, lx, ly);

    //
    // Convert the luminance/alpha pixels to RGBA
    // and copy them into the caller's frame buffer.
    //

    Box2i dw = _inputFile.dataWindowForTile (dx, dy, lx, ly);
    int width = dw.max.x - dw.min.x + 1;

    for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1)
    {
    for (int x1 = 0; x1 < width; ++x1)
    {
        _buf[y1][x1].r = 0;
        _buf[y1][x1].b = 0;
    }

    YCAtoRGBA (_yw, width, _buf[y1], _buf[y1]);

    for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1)
    {
        _fbBase[x * _fbXStride + y * _fbYStride] = _buf[y1][x1];
    }
    }
}


TiledRgbaInputFile::TiledRgbaInputFile (const char name[], int numThreads):
    _inputFile (new TiledInputFile (name, numThreads)),
    _fromYa (0),
    _channelNamePrefix ("")
{
    if (channels() & WRITE_Y)
    _fromYa = new FromYa (*_inputFile);
}


TiledRgbaInputFile::TiledRgbaInputFile (IStream &is, int numThreads):
    _inputFile (new TiledInputFile (is, numThreads)),
    _fromYa (0),
    _channelNamePrefix ("")
{
    if (channels() & WRITE_Y)
    _fromYa = new FromYa (*_inputFile);
}


TiledRgbaInputFile::TiledRgbaInputFile (const char name[],
                    const string &layerName,
                    int numThreads)
:
    _inputFile (new TiledInputFile (name, numThreads)),
    _fromYa (0),
    _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header()))
{
    if (channels() & WRITE_Y)
    _fromYa = new FromYa (*_inputFile);
}


TiledRgbaInputFile::TiledRgbaInputFile (IStream &is,
                    const string &layerName,
                    int numThreads)
:
    _inputFile (new TiledInputFile (is, numThreads)),
    _fromYa (0),
    _channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header()))
{
    if (channels() & WRITE_Y)
    _fromYa = new FromYa (*_inputFile);
}


TiledRgbaInputFile::~TiledRgbaInputFile ()
{
    delete _inputFile;
    delete _fromYa;
}


void
TiledRgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride)
{
    if (_fromYa)
    {
    Lock lock (*_fromYa);
    _fromYa->setFrameBuffer (base, xStride, yStride, _channelNamePrefix);
    }
    else
    {
    size_t xs = xStride * sizeof (Rgba);
    size_t ys = yStride * sizeof (Rgba);

    FrameBuffer fb;

    fb.insert (_channelNamePrefix + "R",
           Slice (HALF,
                   (char *) &base[0].r,
                   xs, ys,
                   1, 1,        // xSampling, ySampling
                   0.0));       // fillValue

    fb.insert (_channelNamePrefix + "G",
           Slice (HALF,
                   (char *) &base[0].g,
                   xs, ys,
                   1, 1,        // xSampling, ySampling
                   0.0));       // fillValue

    fb.insert (_channelNamePrefix + "B",
           Slice (HALF,
                   (char *) &base[0].b,
                   xs, ys,
                   1, 1,        // xSampling, ySampling
                   0.0));       // fillValue

    fb.insert (_channelNamePrefix + "A",
           Slice (HALF,
                   (char *) &base[0].a,
                   xs, ys,
                   1, 1,        // xSampling, ySampling
                   1.0));       // fillValue

    _inputFile->setFrameBuffer (fb);
    }
}


void
TiledRgbaInputFile::setLayerName (const std::string &layerName)
{
    delete _fromYa;
    _fromYa = 0;

    _channelNamePrefix = prefixFromLayerName (layerName, _inputFile->header());

    if (channels() & WRITE_Y)
    _fromYa = new FromYa (*_inputFile);

    FrameBuffer fb;
    _inputFile->setFrameBuffer (fb);
}


const Header &
TiledRgbaInputFile::header () const
{
    return _inputFile->header();
}


const char *
TiledRgbaInputFile::fileName () const
{
    return _inputFile->fileName();
}


const FrameBuffer &
TiledRgbaInputFile::frameBuffer () const
{
    return _inputFile->frameBuffer();
}


const Imath::Box2i &
TiledRgbaInputFile::displayWindow () const
{
    return _inputFile->header().displayWindow();
}


const Imath::Box2i &
TiledRgbaInputFile::dataWindow () const
{
    return _inputFile->header().dataWindow();
}


float
TiledRgbaInputFile::pixelAspectRatio () const
{
    return _inputFile->header().pixelAspectRatio();
}


const Imath::V2f
TiledRgbaInputFile::screenWindowCenter () const
{
    return _inputFile->header().screenWindowCenter();
}


float
TiledRgbaInputFile::screenWindowWidth () const
{
    return _inputFile->header().screenWindowWidth();
}


LineOrder
TiledRgbaInputFile::lineOrder () const
{
    return _inputFile->header().lineOrder();
}


Compression
TiledRgbaInputFile::compression () const
{
    return _inputFile->header().compression();
}


RgbaChannels
TiledRgbaInputFile::channels () const
{
    return rgbaChannels (_inputFile->header().channels(), _channelNamePrefix);
}


int
TiledRgbaInputFile::version () const
{
    return _inputFile->version();
}


bool
TiledRgbaInputFile::isComplete () const
{
    return _inputFile->isComplete();
}


unsigned int
TiledRgbaInputFile::tileXSize () const
{
     return _inputFile->tileXSize();
}


unsigned int
TiledRgbaInputFile::tileYSize () const
{
     return _inputFile->tileYSize();
}


LevelMode
TiledRgbaInputFile::levelMode () const
{
     return _inputFile->levelMode();
}


LevelRoundingMode
TiledRgbaInputFile::levelRoundingMode () const
{
     return _inputFile->levelRoundingMode();
}


int
TiledRgbaInputFile::numLevels () const
{
     return _inputFile->numLevels();
}


int
TiledRgbaInputFile::numXLevels () const
{
     return _inputFile->numXLevels();
}


int
TiledRgbaInputFile::numYLevels () const
{
     return _inputFile->numYLevels();
}


bool
TiledRgbaInputFile::isValidLevel (int lx, int ly) const
{
    return _inputFile->isValidLevel (lx, ly);
}


int
TiledRgbaInputFile::levelWidth (int lx) const
{
     return _inputFile->levelWidth (lx);
}


int
TiledRgbaInputFile::levelHeight (int ly) const
{
     return _inputFile->levelHeight (ly);
}


int
TiledRgbaInputFile::numXTiles (int lx) const
{
     return _inputFile->numXTiles(lx);
}


int
TiledRgbaInputFile::numYTiles (int ly) const
{
     return _inputFile->numYTiles(ly);
}


Imath::Box2i
TiledRgbaInputFile::dataWindowForLevel (int l) const
{
     return _inputFile->dataWindowForLevel (l);
}


Imath::Box2i
TiledRgbaInputFile::dataWindowForLevel (int lx, int ly) const
{
     return _inputFile->dataWindowForLevel (lx, ly);
}


Imath::Box2i
TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int l) const
{
     return _inputFile->dataWindowForTile (dx, dy, l);
}


Imath::Box2i
TiledRgbaInputFile::dataWindowForTile (int dx, int dy, int lx, int ly) const
{
     return _inputFile->dataWindowForTile (dx, dy, lx, ly);
}


void
TiledRgbaInputFile::readTile (int dx, int dy, int l)
{
    if (_fromYa)
    {
    Lock lock (*_fromYa);
    _fromYa->readTile (dx, dy, l, l);
    }
    else
    {
     _inputFile->readTile (dx, dy, l);
    }
}


void
TiledRgbaInputFile::readTile (int dx, int dy, int lx, int ly)
{
    if (_fromYa)
    {
    Lock lock (*_fromYa);
    _fromYa->readTile (dx, dy, lx, ly);
    }
    else
    {
     _inputFile->readTile (dx, dy, lx, ly);
    }
}


void
TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax,
                               int lx, int ly)
{
    if (_fromYa)
    {
    Lock lock (*_fromYa);

        for (int dy = dyMin; dy <= dyMax; dy++)
            for (int dx = dxMin; dx <= dxMax; dx++)
            _fromYa->readTile (dx, dy, lx, ly);
    }
    else
    {
        _inputFile->readTiles (dxMin, dxMax, dyMin, dyMax, lx, ly);
    }
}

void
TiledRgbaInputFile::readTiles (int dxMin, int dxMax, int dyMin, int dyMax,
                               int l)
{
    readTiles (dxMin, dxMax, dyMin, dyMax, l, l);
}


void
TiledRgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
{
    _outputFile->updatePreviewImage (newPixels);
}


void
TiledRgbaOutputFile::breakTile  (int dx, int dy, int lx, int ly,
                 int offset, int length, char c)
{
    _outputFile->breakTile (dx, dy, lx, ly, offset, length, c);
}


} // namespace Imf

/* [<][>][^][v][top][bottom][index][help] */