blob: 9531c04635c38b093489d9fb51476397e4766fed [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////
//
// 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 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)
{
int i = 0;
if (ch.findChannel ("R"))
i |= WRITE_R;
if (ch.findChannel ("G"))
i |= WRITE_G;
if (ch.findChannel ("B"))
i |= WRITE_B;
if (ch.findChannel ("A"))
i |= WRITE_A;
if (ch.findChannel ("Y"))
i |= WRITE_Y;
return RgbaChannels (i);
}
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);
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)
{
_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 requiested by the caller into _buf.
//
Box2i dw = _inputFile.dataWindowForTile (dx, dy, lx, ly);
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
1, 1, // sampling
1.0)); // fillValue
_inputFile.setFrameBuffer (fb);
_inputFile.readTile (dx, dy, lx, ly);
//
// Convert the luminance/alpha pixels to RGBA
// and copy them into the caller's frame buffer.
//
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)
{
if (channels() & WRITE_Y)
_fromYa = new FromYa (*_inputFile);
}
TiledRgbaInputFile::TiledRgbaInputFile (IStream &is, int numThreads):
_inputFile (new TiledInputFile (is, numThreads)),
_fromYa (0)
{
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);
}
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,
1, 1, // xSampling, ySampling
0.0)); // fillValue
fb.insert ("G", Slice (HALF,
(char *) &base[0].g,
xs, ys,
1, 1, // xSampling, ySampling
0.0)); // fillValue
fb.insert ("B", Slice (HALF,
(char *) &base[0].b,
xs, ys,
1, 1, // xSampling, ySampling
0.0)); // fillValue
fb.insert ("A", Slice (HALF,
(char *) &base[0].a,
xs, ys,
1, 1, // xSampling, ySampling
1.0)); // fillValue
_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());
}
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