This source file includes following definitions.
- insertChannels
- rgbaChannels
- prefixFromLayerName
- ywFromHeader
- cachePadding
- setYCRounding
- setFrameBuffer
- writePixels
- currentScanLine
- padTmpBuf
- rotateBuffers
- duplicateLastBuffer
- duplicateSecondToLastBuffer
- decimateChromaVertAndWriteScanLine
- _toYca
- _toYca
- _toYca
- _toYca
- setFrameBuffer
- writePixels
- currentScanLine
- header
- frameBuffer
- displayWindow
- dataWindow
- pixelAspectRatio
- screenWindowCenter
- screenWindowWidth
- lineOrder
- compression
- channels
- updatePreviewImage
- setYCRounding
- breakScanLine
- setFrameBuffer
- readPixels
- readPixels
- rotateBuf1
- rotateBuf2
- readYCAScanLine
- padTmpBuf
- _channelNamePrefix
- _channelNamePrefix
- _channelNamePrefix
- _channelNamePrefix
- setFrameBuffer
- setLayerName
- readPixels
- readPixels
- isComplete
- header
- fileName
- frameBuffer
- displayWindow
- dataWindow
- pixelAspectRatio
- screenWindowCenter
- screenWindowWidth
- lineOrder
- compression
- channels
- version
#include <ImfRgbaFile.h>
#include <ImfOutputFile.h>
#include <ImfInputFile.h>
#include <ImfChannelList.h>
#include <ImfRgbaYca.h>
#include <ImfStandardAttributes.h>
#include <ImathFun.h>
#include <IlmThreadMutex.h>
#include <Iex.h>
#include <string.h>
#include <algorithm>
namespace Imf {
using namespace std;
using namespace Imath;
using namespace RgbaYca;
using namespace IlmThread;
namespace {
void
insertChannels (Header &header, RgbaChannels rgbaChannels)
{
ChannelList ch;
if (rgbaChannels & (WRITE_Y | WRITE_C))
{
if (rgbaChannels & WRITE_Y)
{
ch.insert ("Y", Channel (HALF, 1, 1));
}
if (rgbaChannels & WRITE_C)
{
ch.insert ("RY", Channel (HALF, 2, 2, true));
ch.insert ("BY", Channel (HALF, 2, 2, true));
}
}
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;
if (ch.findChannel (channelNamePrefix + "RY") ||
ch.findChannel (channelNamePrefix + "BY"))
i |= WRITE_C;
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);
}
ptrdiff_t
cachePadding (ptrdiff_t size)
{
static int LOG2_CACHE_LINE_SIZE = 8;
static const ptrdiff_t CACHE_LINE_SIZE = (1 << LOG2_CACHE_LINE_SIZE);
int i = LOG2_CACHE_LINE_SIZE + 2;
while ((size >> i) > 1)
++i;
if (size > (1 << (i + 1)) - 64)
return 64 + ((1 << (i + 1)) - size);
if (size < (1 << i) + 64)
return 64 + ((1 << i) - size);
return 0;
}
}
class RgbaOutputFile::ToYca: public Mutex
{
public:
ToYca (OutputFile &outputFile, RgbaChannels rgbaChannels);
~ToYca ();
void setYCRounding (unsigned int roundY,
unsigned int roundC);
void setFrameBuffer (const Rgba *base,
size_t xStride,
size_t yStride);
void writePixels (int numScanLines);
int currentScanLine () const;
private:
void padTmpBuf ();
void rotateBuffers ();
void duplicateLastBuffer ();
void duplicateSecondToLastBuffer ();
void decimateChromaVertAndWriteScanLine ();
OutputFile & _outputFile;
bool _writeY;
bool _writeC;
bool _writeA;
int _xMin;
int _width;
int _height;
int _linesConverted;
LineOrder _lineOrder;
int _currentScanLine;
V3f _yw;
Rgba * _bufBase;
Rgba * _buf[N];
Rgba * _tmpBuf;
const Rgba * _fbBase;
size_t _fbXStride;
size_t _fbYStride;
int _roundY;
int _roundC;
};
RgbaOutputFile::ToYca::ToYca (OutputFile &outputFile,
RgbaChannels rgbaChannels)
:
_outputFile (outputFile)
{
_writeY = (rgbaChannels & WRITE_Y)? true: false;
_writeC = (rgbaChannels & WRITE_C)? true: false;
_writeA = (rgbaChannels & WRITE_A)? true: false;
const Box2i dw = _outputFile.header().dataWindow();
_xMin = dw.min.x;
_width = dw.max.x - dw.min.x + 1;
_height = dw.max.y - dw.min.y + 1;
_linesConverted = 0;
_lineOrder = _outputFile.header().lineOrder();
if (_lineOrder == INCREASING_Y)
_currentScanLine = dw.min.y;
else
_currentScanLine = dw.max.y;
_yw = ywFromHeader (_outputFile.header());
ptrdiff_t pad = cachePadding (_width * sizeof (Rgba)) / sizeof (Rgba);
_bufBase = new Rgba[(_width + pad) * N];
for (int i = 0; i < N; ++i)
_buf[i] = _bufBase + (i * (_width + pad));
_tmpBuf = new Rgba[_width + N - 1];
_fbBase = 0;
_fbXStride = 0;
_fbYStride = 0;
_roundY = 7;
_roundC = 5;
}
RgbaOutputFile::ToYca::~ToYca ()
{
delete [] _bufBase;
delete [] _tmpBuf;
}
void
RgbaOutputFile::ToYca::setYCRounding (unsigned int roundY,
unsigned int roundC)
{
_roundY = roundY;
_roundC = roundC;
}
void
RgbaOutputFile::ToYca::setFrameBuffer (const Rgba *base,
size_t xStride,
size_t yStride)
{
if (_fbBase == 0)
{
FrameBuffer fb;
if (_writeY)
{
fb.insert ("Y",
Slice (HALF,
(char *) &_tmpBuf[-_xMin].g,
sizeof (Rgba),
0,
1,
1));
}
if (_writeC)
{
fb.insert ("RY",
Slice (HALF,
(char *) &_tmpBuf[-_xMin].r,
sizeof (Rgba) * 2,
0,
2,
2));
fb.insert ("BY",
Slice (HALF,
(char *) &_tmpBuf[-_xMin].b,
sizeof (Rgba) * 2,
0,
2,
2));
}
if (_writeA)
{
fb.insert ("A",
Slice (HALF,
(char *) &_tmpBuf[-_xMin].a,
sizeof (Rgba),
0,
1,
1));
}
_outputFile.setFrameBuffer (fb);
}
_fbBase = base;
_fbXStride = xStride;
_fbYStride = yStride;
}
void
RgbaOutputFile::ToYca::writePixels (int numScanLines)
{
if (_fbBase == 0)
{
THROW (Iex::ArgExc, "No frame buffer was specified as the "
"pixel data source for image file "
"\"" << _outputFile.fileName() << "\".");
}
if (_writeY && !_writeC)
{
for (int i = 0; i < numScanLines; ++i)
{
for (int j = 0; j < _width; ++j)
{
_tmpBuf[j] = _fbBase[_fbYStride * _currentScanLine +
_fbXStride * (j + _xMin)];
}
RGBAtoYCA (_yw, _width, _writeA, _tmpBuf, _tmpBuf);
_outputFile.writePixels (1);
++_linesConverted;
if (_lineOrder == INCREASING_Y)
++_currentScanLine;
else
--_currentScanLine;
}
}
else
{
for (int i = 0; i < numScanLines; ++i)
{
for (int j = 0; j < _width; ++j)
{
_tmpBuf[j + N2] = _fbBase[_fbYStride * _currentScanLine +
_fbXStride * (j + _xMin)];
}
RGBAtoYCA (_yw, _width, _writeA, _tmpBuf + N2, _tmpBuf + N2);
padTmpBuf ();
rotateBuffers();
decimateChromaHoriz (_width, _tmpBuf, _buf[N - 1]);
if (_linesConverted == 0)
{
for (int j = 0; j < N2; ++j)
duplicateLastBuffer();
}
++_linesConverted;
if (_linesConverted > N2)
decimateChromaVertAndWriteScanLine();
if (_linesConverted >= _height)
{
for (int j = 0; j < N2 - _height; ++j)
duplicateLastBuffer();
duplicateSecondToLastBuffer();
++_linesConverted;
decimateChromaVertAndWriteScanLine();
for (int j = 1; j < min (_height, N2); ++j)
{
duplicateLastBuffer();
++_linesConverted;
decimateChromaVertAndWriteScanLine();
}
}
if (_lineOrder == INCREASING_Y)
++_currentScanLine;
else
--_currentScanLine;
}
}
}
int
RgbaOutputFile::ToYca::currentScanLine () const
{
return _currentScanLine;
}
void
RgbaOutputFile::ToYca::padTmpBuf ()
{
for (int i = 0; i < N2; ++i)
{
_tmpBuf[i] = _tmpBuf[N2];
_tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2];
}
}
void
RgbaOutputFile::ToYca::rotateBuffers ()
{
Rgba *tmp = _buf[0];
for (int i = 0; i < N - 1; ++i)
_buf[i] = _buf[i + 1];
_buf[N - 1] = tmp;
}
void
RgbaOutputFile::ToYca::duplicateLastBuffer ()
{
rotateBuffers();
memcpy (_buf[N - 1], _buf[N - 2], _width * sizeof (Rgba));
}
void
RgbaOutputFile::ToYca::duplicateSecondToLastBuffer ()
{
rotateBuffers();
memcpy (_buf[N - 1], _buf[N - 3], _width * sizeof (Rgba));
}
void
RgbaOutputFile::ToYca::decimateChromaVertAndWriteScanLine ()
{
if (_linesConverted & 1)
memcpy (_tmpBuf, _buf[N2], _width * sizeof (Rgba));
else
decimateChromaVert (_width, _buf, _tmpBuf);
if (_writeY && _writeC)
roundYCA (_width, _roundY, _roundC, _tmpBuf, _tmpBuf);
_outputFile.writePixels (1);
}
RgbaOutputFile::RgbaOutputFile (const char name[],
const Header &header,
RgbaChannels rgbaChannels,
int numThreads):
_outputFile (0),
_toYca (0)
{
Header hd (header);
insertChannels (hd, rgbaChannels);
_outputFile = new OutputFile (name, hd, numThreads);
if (rgbaChannels & (WRITE_Y | WRITE_C))
_toYca = new ToYca (*_outputFile, rgbaChannels);
}
RgbaOutputFile::RgbaOutputFile (OStream &os,
const Header &header,
RgbaChannels rgbaChannels,
int numThreads):
_outputFile (0),
_toYca (0)
{
Header hd (header);
insertChannels (hd, rgbaChannels);
_outputFile = new OutputFile (os, hd, numThreads);
if (rgbaChannels & (WRITE_Y | WRITE_C))
_toYca = new ToYca (*_outputFile, rgbaChannels);
}
RgbaOutputFile::RgbaOutputFile (const char name[],
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),
_toYca (0)
{
Header hd (displayWindow,
dataWindow.isEmpty()? displayWindow: dataWindow,
pixelAspectRatio,
screenWindowCenter,
screenWindowWidth,
lineOrder,
compression);
insertChannels (hd, rgbaChannels);
_outputFile = new OutputFile (name, hd, numThreads);
if (rgbaChannels & (WRITE_Y | WRITE_C))
_toYca = new ToYca (*_outputFile, rgbaChannels);
}
RgbaOutputFile::RgbaOutputFile (const char name[],
int width,
int height,
RgbaChannels rgbaChannels,
float pixelAspectRatio,
const Imath::V2f screenWindowCenter,
float screenWindowWidth,
LineOrder lineOrder,
Compression compression,
int numThreads):
_outputFile (0),
_toYca (0)
{
Header hd (width,
height,
pixelAspectRatio,
screenWindowCenter,
screenWindowWidth,
lineOrder,
compression);
insertChannels (hd, rgbaChannels);
_outputFile = new OutputFile (name, hd, numThreads);
if (rgbaChannels & (WRITE_Y | WRITE_C))
_toYca = new ToYca (*_outputFile, rgbaChannels);
}
RgbaOutputFile::~RgbaOutputFile ()
{
delete _toYca;
delete _outputFile;
}
void
RgbaOutputFile::setFrameBuffer (const Rgba *base,
size_t xStride,
size_t yStride)
{
if (_toYca)
{
Lock lock (*_toYca);
_toYca->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);
}
}
void
RgbaOutputFile::writePixels (int numScanLines)
{
if (_toYca)
{
Lock lock (*_toYca);
_toYca->writePixels (numScanLines);
}
else
{
_outputFile->writePixels (numScanLines);
}
}
int
RgbaOutputFile::currentScanLine () const
{
if (_toYca)
{
Lock lock (*_toYca);
return _toYca->currentScanLine();
}
else
{
return _outputFile->currentScanLine();
}
}
const Header &
RgbaOutputFile::header () const
{
return _outputFile->header();
}
const FrameBuffer &
RgbaOutputFile::frameBuffer () const
{
return _outputFile->frameBuffer();
}
const Imath::Box2i &
RgbaOutputFile::displayWindow () const
{
return _outputFile->header().displayWindow();
}
const Imath::Box2i &
RgbaOutputFile::dataWindow () const
{
return _outputFile->header().dataWindow();
}
float
RgbaOutputFile::pixelAspectRatio () const
{
return _outputFile->header().pixelAspectRatio();
}
const Imath::V2f
RgbaOutputFile::screenWindowCenter () const
{
return _outputFile->header().screenWindowCenter();
}
float
RgbaOutputFile::screenWindowWidth () const
{
return _outputFile->header().screenWindowWidth();
}
LineOrder
RgbaOutputFile::lineOrder () const
{
return _outputFile->header().lineOrder();
}
Compression
RgbaOutputFile::compression () const
{
return _outputFile->header().compression();
}
RgbaChannels
RgbaOutputFile::channels () const
{
return rgbaChannels (_outputFile->header().channels());
}
void
RgbaOutputFile::updatePreviewImage (const PreviewRgba newPixels[])
{
_outputFile->updatePreviewImage (newPixels);
}
void
RgbaOutputFile::setYCRounding (unsigned int roundY, unsigned int roundC)
{
if (_toYca)
{
Lock lock (*_toYca);
_toYca->setYCRounding (roundY, roundC);
}
}
void
RgbaOutputFile::breakScanLine (int y, int offset, int length, char c)
{
_outputFile->breakScanLine (y, offset, length, c);
}
class RgbaInputFile::FromYca: public Mutex
{
public:
FromYca (InputFile &inputFile, RgbaChannels rgbaChannels);
~FromYca ();
void setFrameBuffer (Rgba *base,
size_t xStride,
size_t yStride,
const string &channelNamePrefix);
void readPixels (int scanLine1, int scanLine2);
private:
void readPixels (int scanLine);
void rotateBuf1 (int d);
void rotateBuf2 (int d);
void readYCAScanLine (int y, Rgba buf[]);
void padTmpBuf ();
InputFile & _inputFile;
bool _readC;
int _xMin;
int _yMin;
int _yMax;
int _width;
int _height;
int _currentScanLine;
LineOrder _lineOrder;
V3f _yw;
Rgba * _bufBase;
Rgba * _buf1[N + 2];
Rgba * _buf2[3];
Rgba * _tmpBuf;
Rgba * _fbBase;
size_t _fbXStride;
size_t _fbYStride;
};
RgbaInputFile::FromYca::FromYca (InputFile &inputFile,
RgbaChannels rgbaChannels)
:
_inputFile (inputFile)
{
_readC = (rgbaChannels & WRITE_C)? true: false;
const Box2i dw = _inputFile.header().dataWindow();
_xMin = dw.min.x;
_yMin = dw.min.y;
_yMax = dw.max.y;
_width = dw.max.x - dw.min.x + 1;
_height = dw.max.y - dw.min.y + 1;
_currentScanLine = dw.min.y - N - 2;
_lineOrder = _inputFile.header().lineOrder();
_yw = ywFromHeader (_inputFile.header());
ptrdiff_t pad = cachePadding (_width * sizeof (Rgba)) / sizeof (Rgba);
_bufBase = new Rgba[(_width + pad) * (N + 2 + 3)];
for (int i = 0; i < N + 2; ++i)
_buf1[i] = _bufBase + (i * (_width + pad));
for (int i = 0; i < 3; ++i)
_buf2[i] = _bufBase + ((i + N + 2) * (_width + pad));
_tmpBuf = new Rgba[_width + N - 1];
_fbBase = 0;
_fbXStride = 0;
_fbYStride = 0;
}
RgbaInputFile::FromYca::~FromYca ()
{
delete [] _bufBase;
delete [] _tmpBuf;
}
void
RgbaInputFile::FromYca::setFrameBuffer (Rgba *base,
size_t xStride,
size_t yStride,
const string &channelNamePrefix)
{
if (_fbBase == 0)
{
FrameBuffer fb;
fb.insert (channelNamePrefix + "Y",
Slice (HALF,
(char *) &_tmpBuf[N2 - _xMin].g,
sizeof (Rgba),
0,
1,
1,
0.5));
if (_readC)
{
fb.insert (channelNamePrefix + "RY",
Slice (HALF,
(char *) &_tmpBuf[N2 - _xMin].r,
sizeof (Rgba) * 2,
0,
2,
2,
0.0));
fb.insert (channelNamePrefix + "BY",
Slice (HALF,
(char *) &_tmpBuf[N2 - _xMin].b,
sizeof (Rgba) * 2,
0,
2,
2,
0.0));
}
fb.insert (channelNamePrefix + "A",
Slice (HALF,
(char *) &_tmpBuf[N2 - _xMin].a,
sizeof (Rgba),
0,
1,
1,
1.0));
_inputFile.setFrameBuffer (fb);
}
_fbBase = base;
_fbXStride = xStride;
_fbYStride = yStride;
}
void
RgbaInputFile::FromYca::readPixels (int scanLine1, int scanLine2)
{
int minY = min (scanLine1, scanLine2);
int maxY = max (scanLine1, scanLine2);
if (_lineOrder == INCREASING_Y)
{
for (int y = minY; y <= maxY; ++y)
readPixels (y);
}
else
{
for (int y = maxY; y >= minY; --y)
readPixels (y);
}
}
void
RgbaInputFile::FromYca::readPixels (int scanLine)
{
if (_fbBase == 0)
{
THROW (Iex::ArgExc, "No frame buffer was specified as the "
"pixel data destination for image file "
"\"" << _inputFile.fileName() << "\".");
}
int dy = scanLine - _currentScanLine;
if (abs (dy) < N + 2)
rotateBuf1 (dy);
if (abs (dy) < 3)
rotateBuf2 (dy);
if (dy < 0)
{
{
int n = min (-dy, N + 2);
int yMin = scanLine - N2 - 1;
for (int i = n - 1; i >= 0; --i)
readYCAScanLine (yMin + i, _buf1[i]);
}
{
int n = min (-dy, 3);
for (int i = 0; i < n; ++i)
{
if ((scanLine + i) & 1)
{
YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]);
}
else
{
reconstructChromaVert (_width, _buf1 + i, _buf2[i]);
YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]);
}
}
}
}
else
{
{
int n = min (dy, N + 2);
int yMax = scanLine + N2 + 1;
for (int i = n - 1; i >= 0; --i)
readYCAScanLine (yMax - i, _buf1[N + 1 - i]);
}
{
int n = min (dy, 3);
for (int i = 2; i > 2 - n; --i)
{
if ((scanLine + i) & 1)
{
YCAtoRGBA (_yw, _width, _buf1[N2 + i], _buf2[i]);
}
else
{
reconstructChromaVert (_width, _buf1 + i, _buf2[i]);
YCAtoRGBA (_yw, _width, _buf2[i], _buf2[i]);
}
}
}
}
fixSaturation (_yw, _width, _buf2, _tmpBuf);
for (int i = 0; i < _width; ++i)
_fbBase[_fbYStride * scanLine + _fbXStride * (i + _xMin)] = _tmpBuf[i];
_currentScanLine = scanLine;
}
void
RgbaInputFile::FromYca::rotateBuf1 (int d)
{
d = modp (d, N + 2);
Rgba *tmp[N + 2];
for (int i = 0; i < N + 2; ++i)
tmp[i] = _buf1[i];
for (int i = 0; i < N + 2; ++i)
_buf1[i] = tmp[(i + d) % (N + 2)];
}
void
RgbaInputFile::FromYca::rotateBuf2 (int d)
{
d = modp (d, 3);
Rgba *tmp[3];
for (int i = 0; i < 3; ++i)
tmp[i] = _buf2[i];
for (int i = 0; i < 3; ++i)
_buf2[i] = tmp[(i + d) % 3];
}
void
RgbaInputFile::FromYca::readYCAScanLine (int y, Rgba *buf)
{
if (y < _yMin)
y = _yMin;
else if (y > _yMax)
y = _yMax - 1;
_inputFile.readPixels (y);
if (!_readC)
{
for (int i = 0; i < _width; ++i)
{
_tmpBuf[i + N2].r = 0;
_tmpBuf[i + N2].b = 0;
}
}
if (y & 1)
{
memcpy (buf, _tmpBuf + N2, _width * sizeof (Rgba));
}
else
{
padTmpBuf();
reconstructChromaHoriz (_width, _tmpBuf, buf);
}
}
void
RgbaInputFile::FromYca::padTmpBuf ()
{
for (int i = 0; i < N2; ++i)
{
_tmpBuf[i] = _tmpBuf[N2];
_tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2];
}
}
RgbaInputFile::RgbaInputFile (const char name[], int numThreads):
_inputFile (new InputFile (name, numThreads)),
_fromYca (0),
_channelNamePrefix ("")
{
RgbaChannels rgbaChannels = channels();
if (rgbaChannels & (WRITE_Y | WRITE_C))
_fromYca = new FromYca (*_inputFile, rgbaChannels);
}
RgbaInputFile::RgbaInputFile (IStream &is, int numThreads):
_inputFile (new InputFile (is, numThreads)),
_fromYca (0),
_channelNamePrefix ("")
{
RgbaChannels rgbaChannels = channels();
if (rgbaChannels & (WRITE_Y | WRITE_C))
_fromYca = new FromYca (*_inputFile, rgbaChannels);
}
RgbaInputFile::RgbaInputFile (const char name[],
const string &layerName,
int numThreads)
:
_inputFile (new InputFile (name, numThreads)),
_fromYca (0),
_channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header()))
{
RgbaChannels rgbaChannels = channels();
if (rgbaChannels & (WRITE_Y | WRITE_C))
_fromYca = new FromYca (*_inputFile, rgbaChannels);
}
RgbaInputFile::RgbaInputFile (IStream &is,
const string &layerName,
int numThreads)
:
_inputFile (new InputFile (is, numThreads)),
_fromYca (0),
_channelNamePrefix (prefixFromLayerName (layerName, _inputFile->header()))
{
RgbaChannels rgbaChannels = channels();
if (rgbaChannels & (WRITE_Y | WRITE_C))
_fromYca = new FromYca (*_inputFile, rgbaChannels);
}
RgbaInputFile::~RgbaInputFile ()
{
delete _inputFile;
delete _fromYca;
}
void
RgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride)
{
if (_fromYca)
{
Lock lock (*_fromYca);
_fromYca->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,
0.0));
fb.insert (_channelNamePrefix + "G",
Slice (HALF,
(char *) &base[0].g,
xs, ys,
1, 1,
0.0));
fb.insert (_channelNamePrefix + "B",
Slice (HALF,
(char *) &base[0].b,
xs, ys,
1, 1,
0.0));
fb.insert (_channelNamePrefix + "A",
Slice (HALF,
(char *) &base[0].a,
xs, ys,
1, 1,
1.0));
_inputFile->setFrameBuffer (fb);
}
}
void
RgbaInputFile::setLayerName (const string &layerName)
{
delete _fromYca;
_fromYca = 0;
_channelNamePrefix = prefixFromLayerName (layerName, _inputFile->header());
RgbaChannels rgbaChannels = channels();
if (rgbaChannels & (WRITE_Y | WRITE_C))
_fromYca = new FromYca (*_inputFile, rgbaChannels);
FrameBuffer fb;
_inputFile->setFrameBuffer (fb);
}
void
RgbaInputFile::readPixels (int scanLine1, int scanLine2)
{
if (_fromYca)
{
Lock lock (*_fromYca);
_fromYca->readPixels (scanLine1, scanLine2);
}
else
{
_inputFile->readPixels (scanLine1, scanLine2);
}
}
void
RgbaInputFile::readPixels (int scanLine)
{
readPixels (scanLine, scanLine);
}
bool
RgbaInputFile::isComplete () const
{
return _inputFile->isComplete();
}
const Header &
RgbaInputFile::header () const
{
return _inputFile->header();
}
const char *
RgbaInputFile::fileName () const
{
return _inputFile->fileName();
}
const FrameBuffer &
RgbaInputFile::frameBuffer () const
{
return _inputFile->frameBuffer();
}
const Imath::Box2i &
RgbaInputFile::displayWindow () const
{
return _inputFile->header().displayWindow();
}
const Imath::Box2i &
RgbaInputFile::dataWindow () const
{
return _inputFile->header().dataWindow();
}
float
RgbaInputFile::pixelAspectRatio () const
{
return _inputFile->header().pixelAspectRatio();
}
const Imath::V2f
RgbaInputFile::screenWindowCenter () const
{
return _inputFile->header().screenWindowCenter();
}
float
RgbaInputFile::screenWindowWidth () const
{
return _inputFile->header().screenWindowWidth();
}
LineOrder
RgbaInputFile::lineOrder () const
{
return _inputFile->header().lineOrder();
}
Compression
RgbaInputFile::compression () const
{
return _inputFile->header().compression();
}
RgbaChannels
RgbaInputFile::channels () const
{
return rgbaChannels (_inputFile->header().channels(), _channelNamePrefix);
}
int
RgbaInputFile::version () const
{
return _inputFile->version();
}
}