This source file includes following definitions.
- numThreads
- deleteCachedBuffer
- bufferedReadPixels
- initialize
- fileName
- header
- version
- setFrameBuffer
- frameBuffer
- isComplete
- readPixels
- readPixels
- rawPixelData
- rawTileData
#include <ImfInputFile.h>
#include <ImfScanLineInputFile.h>
#include <ImfTiledInputFile.h>
#include <ImfChannelList.h>
#include <ImfMisc.h>
#include <ImfStdIO.h>
#include <ImfVersion.h>
#include "ImathFun.h"
#include "IlmThreadMutex.h"
#include "Iex.h"
#include "half.h"
#include <fstream>
#include <algorithm>
namespace Imf {
using Imath::Box2i;
using Imath::divp;
using Imath::modp;
using IlmThread::Mutex;
using IlmThread::Lock;
struct InputFile::Data: public Mutex
{
Header header;
int version;
IStream * is;
bool deleteStream;
TiledInputFile * tFile;
ScanLineInputFile * sFile;
LineOrder lineOrder;
int minY;
int maxY;
FrameBuffer tFileBuffer;
FrameBuffer * cachedBuffer;
int cachedTileY;
int offset;
int numThreads;
Data (bool del, int numThreads);
~Data ();
void deleteCachedBuffer();
};
InputFile::Data::Data (bool del, int numThreads):
is (0),
deleteStream (del),
tFile (0),
sFile (0),
cachedBuffer (0),
cachedTileY (-1),
numThreads (numThreads)
{
}
InputFile::Data::~Data ()
{
delete tFile;
delete sFile;
if (deleteStream)
delete is;
deleteCachedBuffer();
}
void
InputFile::Data::deleteCachedBuffer()
{
if (cachedBuffer)
{
for (FrameBuffer::Iterator k = cachedBuffer->begin();
k != cachedBuffer->end();
++k)
{
Slice &s = k.slice();
switch (s.type)
{
case UINT:
delete [] (((unsigned int *)s.base) + offset);
break;
case HALF:
delete [] ((half *)s.base + offset);
break;
case FLOAT:
delete [] (((float *)s.base) + offset);
break;
}
}
delete cachedBuffer;
cachedBuffer = 0;
}
}
namespace {
void
bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2)
{
int minY = std::min (scanLine1, scanLine2);
int maxY = std::max (scanLine1, scanLine2);
if (minY < ifd->minY || maxY > ifd->maxY)
{
throw Iex::ArgExc ("Tried to read scan line outside "
"the image file's data window.");
}
int minDy = (minY - ifd->minY) / ifd->tFile->tileYSize();
int maxDy = (maxY - ifd->minY) / ifd->tFile->tileYSize();
int yStart, yEnd, yStep;
if (ifd->lineOrder == DECREASING_Y)
{
yStart = maxDy;
yEnd = minDy - 1;
yStep = -1;
}
else
{
yStart = minDy;
yEnd = maxDy + 1;
yStep = 1;
}
Box2i levelRange = ifd->tFile->dataWindowForLevel(0);
for (int j = yStart; j != yEnd; j += yStep)
{
Box2i tileRange = ifd->tFile->dataWindowForTile (0, j, 0);
int minYThisRow = std::max (minY, tileRange.min.y);
int maxYThisRow = std::min (maxY, tileRange.max.y);
if (j != ifd->cachedTileY)
{
ifd->tFile->readTiles (0, ifd->tFile->numXTiles (0) - 1, j, j);
ifd->cachedTileY = j;
}
for (FrameBuffer::ConstIterator k = ifd->cachedBuffer->begin();
k != ifd->cachedBuffer->end();
++k)
{
Slice fromSlice = k.slice();
Slice toSlice = ifd->tFileBuffer[k.name()];
char *fromPtr, *toPtr;
int size = pixelTypeSize (toSlice.type);
int xStart = levelRange.min.x;
int yStart = minYThisRow;
while (modp (xStart, toSlice.xSampling) != 0)
++xStart;
while (modp (yStart, toSlice.ySampling) != 0)
++yStart;
for (int y = yStart;
y <= maxYThisRow;
y += toSlice.ySampling)
{
fromPtr = fromSlice.base +
(y - tileRange.min.y) * fromSlice.yStride +
xStart * fromSlice.xStride;
toPtr = toSlice.base +
divp (y, toSlice.ySampling) * toSlice.yStride +
divp (xStart, toSlice.xSampling) * toSlice.xStride;
for (int x = xStart;
x <= levelRange.max.x;
x += toSlice.xSampling)
{
for (size_t i = 0; i < size; ++i)
toPtr[i] = fromPtr[i];
fromPtr += fromSlice.xStride * toSlice.xSampling;
toPtr += toSlice.xStride;
}
}
}
}
}
}
InputFile::InputFile (const char fileName[], int numThreads):
_data (new Data (true, numThreads))
{
try
{
_data->is = new StdIFStream (fileName);
initialize();
}
catch (Iex::BaseExc &e)
{
delete _data;
REPLACE_EXC (e, "Cannot read image file "
"\"" << fileName << "\". " << e);
throw;
}
catch (...)
{
delete _data;
throw;
}
}
InputFile::InputFile (IStream &is, int numThreads):
_data (new Data (false, numThreads))
{
try
{
_data->is = &is;
initialize();
}
catch (Iex::BaseExc &e)
{
delete _data;
REPLACE_EXC (e, "Cannot read image file "
"\"" << is.fileName() << "\". " << e);
throw;
}
catch (...)
{
delete _data;
throw;
}
}
void
InputFile::initialize ()
{
_data->header.readFrom (*_data->is, _data->version);
_data->header.sanityCheck (isTiled (_data->version));
if (isTiled (_data->version))
{
_data->lineOrder = _data->header.lineOrder();
const Box2i &dataWindow = _data->header.dataWindow();
_data->minY = dataWindow.min.y;
_data->maxY = dataWindow.max.y;
_data->tFile = new TiledInputFile (_data->header,
_data->is,
_data->version,
_data->numThreads);
}
else
{
_data->sFile = new ScanLineInputFile (_data->header,
_data->is,
_data->numThreads);
}
}
InputFile::~InputFile ()
{
delete _data;
}
const char *
InputFile::fileName () const
{
return _data->is->fileName();
}
const Header &
InputFile::header () const
{
return _data->header;
}
int
InputFile::version () const
{
return _data->version;
}
void
InputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
{
if (isTiled (_data->version))
{
Lock lock (*_data);
const FrameBuffer &oldFrameBuffer = _data->tFileBuffer;
FrameBuffer::ConstIterator i = oldFrameBuffer.begin();
FrameBuffer::ConstIterator j = frameBuffer.begin();
while (i != oldFrameBuffer.end() && j != frameBuffer.end())
{
if (strcmp (i.name(), j.name()) || i.slice().type != j.slice().type)
break;
++i;
++j;
}
if (i != oldFrameBuffer.end() || j != frameBuffer.end())
{
_data->deleteCachedBuffer ();
_data->cachedTileY = -1;
const Box2i &dataWindow = _data->header.dataWindow();
_data->cachedBuffer = new FrameBuffer();
_data->offset = dataWindow.min.x;
int tileRowSize = (dataWindow.max.x - dataWindow.min.x + 1) *
_data->tFile->tileYSize();
for (FrameBuffer::ConstIterator k = frameBuffer.begin();
k != frameBuffer.end();
++k)
{
Slice s = k.slice();
switch (s.type)
{
case UINT:
_data->cachedBuffer->insert
(k.name(),
Slice (UINT,
(char *)(new unsigned int[tileRowSize] -
_data->offset),
sizeof (unsigned int),
sizeof (unsigned int) *
_data->tFile->levelWidth(0),
1, 1,
s.fillValue,
false, true));
break;
case HALF:
_data->cachedBuffer->insert
(k.name(),
Slice (HALF,
(char *)(new half[tileRowSize] -
_data->offset),
sizeof (half),
sizeof (half) *
_data->tFile->levelWidth(0),
1, 1,
s.fillValue,
false, true));
break;
case FLOAT:
_data->cachedBuffer->insert
(k.name(),
Slice (FLOAT,
(char *)(new float[tileRowSize] -
_data->offset),
sizeof(float),
sizeof(float) *
_data->tFile->levelWidth(0),
1, 1,
s.fillValue,
false, true));
break;
default:
throw Iex::ArgExc ("Unknown pixel data type.");
}
}
_data->tFile->setFrameBuffer (*_data->cachedBuffer);
}
_data->tFileBuffer = frameBuffer;
}
else
{
_data->sFile->setFrameBuffer (frameBuffer);
}
}
const FrameBuffer &
InputFile::frameBuffer () const
{
if (isTiled (_data->version))
{
Lock lock (*_data);
return _data->tFileBuffer;
}
else
{
return _data->sFile->frameBuffer();
}
}
bool
InputFile::isComplete () const
{
if (isTiled (_data->version))
return _data->tFile->isComplete();
else
return _data->sFile->isComplete();
}
void
InputFile::readPixels (int scanLine1, int scanLine2)
{
if (isTiled (_data->version))
{
Lock lock (*_data);
bufferedReadPixels (_data, scanLine1, scanLine2);
}
else
{
_data->sFile->readPixels (scanLine1, scanLine2);
}
}
void
InputFile::readPixels (int scanLine)
{
readPixels (scanLine, scanLine);
}
void
InputFile::rawPixelData (int firstScanLine,
const char *&pixelData,
int &pixelDataSize)
{
try
{
if (isTiled (_data->version))
{
throw Iex::ArgExc ("Tried to read a raw scanline "
"from a tiled image.");
}
_data->sFile->rawPixelData (firstScanLine, pixelData, pixelDataSize);
}
catch (Iex::BaseExc &e)
{
REPLACE_EXC (e, "Error reading pixel data from image "
"file \"" << fileName() << "\". " << e);
throw;
}
}
void
InputFile::rawTileData (int &dx, int &dy,
int &lx, int &ly,
const char *&pixelData,
int &pixelDataSize)
{
try
{
if (!isTiled (_data->version))
{
throw Iex::ArgExc ("Tried to read a raw tile "
"from a scanline-based image.");
}
_data->tFile->rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize);
}
catch (Iex::BaseExc &e)
{
REPLACE_EXC (e, "Error reading tile data from image "
"file \"" << fileName() << "\". " << e);
throw;
}
}
TiledInputFile*
InputFile::tFile()
{
if (!isTiled (_data->version))
{
throw Iex::ArgExc ("Cannot get a TiledInputFile pointer "
"from an InputFile that is not tiled.");
}
return _data->tFile;
}
}