Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/OpenEXR/IlmImf/ImfScanLineInputFile.cpp view on Meta::CPAN
/// we need to keep the list sorted in the order they'll be written to memory
bool operator<(const sliceOptimizationData& other ) const
{
return base < other.base;
}
};
} // namespace
struct ScanLineInputFile::Data: public Mutex
{
Header header; // the image header
int version; // file's version
FrameBuffer frameBuffer; // framebuffer to write into
LineOrder lineOrder; // order of the scanlines in file
int minX; // data window's min x coord
int maxX; // data window's max x coord
int minY; // data window's min y coord
int maxY; // data window's max x coord
vector<Int64> lineOffsets; // stores offsets in file for
// each line
bool fileIsComplete; // True if no scanlines are missing
// in the file
int nextLineBufferMinY; // minimum y of the next linebuffer
vector<size_t> bytesPerLine; // combined size of a line over all
// channels
vector<size_t> offsetInLineBuffer; // offset for each scanline in its
// linebuffer
vector<InSliceInfo> slices; // info about channels in file
vector<LineBuffer*> lineBuffers; // each holds one line buffer
int linesInBuffer; // number of scanlines each buffer
// holds
size_t lineBufferSize; // size of the line buffer
int partNumber; // part number
bool memoryMapped; // if the stream is memory mapped
OptimizationMode optimizationMode; // optimizibility of the input file
vector<sliceOptimizationData> optimizationData; ///< channel ordering for optimized reading
Data (int numThreads);
~Data ();
inline LineBuffer * getLineBuffer (int number); // hash function from line
// buffer indices into our
// vector of line buffers
};
ScanLineInputFile::Data::Data (int numThreads):
partNumber(-1),
memoryMapped(false)
{
//
// We need at least one lineBuffer, but if threading is used,
// to keep n threads busy we need 2*n lineBuffers
//
lineBuffers.resize (max (1, 2 * numThreads));
}
ScanLineInputFile::Data::~Data ()
{
for (size_t i = 0; i < lineBuffers.size(); i++)
delete lineBuffers[i];
}
inline LineBuffer *
ScanLineInputFile::Data::getLineBuffer (int lineBufferNumber)
{
return lineBuffers[lineBufferNumber % lineBuffers.size()];
}
namespace {
void
reconstructLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
LineOrder lineOrder,
vector<Int64> &lineOffsets)
{
Int64 position = is.tellg();
try
{
for (unsigned int i = 0; i < lineOffsets.size(); i++)
{
Int64 lineOffset = is.tellg();
int y;
OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, y);
int dataSize;
OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, dataSize);
Xdr::skip <StreamIO> (is, dataSize);
if (lineOrder == INCREASING_Y)
lineOffsets[i] = lineOffset;
else
lineOffsets[lineOffsets.size() - i - 1] = lineOffset;
}
}
catch (...)
{
//
// Suppress all exceptions. This functions is
// called only to reconstruct the line offset
// table for incomplete files, and exceptions
// are likely.
//
}
is.clear();
is.seekg (position);
}
void
readLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is,
LineOrder lineOrder,
vector<Int64> &lineOffsets,
bool &complete)
{
for (unsigned int i = 0; i < lineOffsets.size(); i++)
{
OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read <OPENEXR_IMF_INTERNAL_NAMESPACE::StreamIO> (is, lineOffsets[i]);
}
complete = true;
for (unsigned int i = 0; i < lineOffsets.size(); i++)
{
if (lineOffsets[i] <= 0)
{
//
// Invalid data in the line offset table mean that
// the file is probably incomplete (the table is
// the last thing written to the file). Either
// some process is still busy writing the file,
// or writing the file was aborted.
//
// We should still be able to read the existing
// parts of the file. In order to do this, we
// have to make a sequential scan over the scan
// line data to reconstruct the line offset table.
//
complete = false;
reconstructLineOffsets (is, lineOrder, lineOffsets);
break;
}
}
}
void
readPixelData (InputStreamMutex *streamData,
ScanLineInputFile::Data *ifd,
int minY,
char *&buffer,
int &dataSize)
{
//
// Read a single line buffer from the input file.
//
// If the input file is not memory-mapped, we copy the pixel data into
// into the array pointed to by buffer. If the file is memory-mapped,
// then we change where buffer points to instead of writing into the
// array (hence buffer needs to be a reference to a char *).
//
int lineBufferNumber = (minY - ifd->minY) / ifd->linesInBuffer;
Int64 lineOffset = ifd->lineOffsets[lineBufferNumber];
if (lineOffset == 0)
THROW (IEX_NAMESPACE::InputExc, "Scan line " << minY << " is missing.");
//
// Seek to the start of the scan line in the file,
// if necessary.
//
if ( !isMultiPart(ifd->version) )
{
if (ifd->nextLineBufferMinY != minY)
streamData->is->seekg (lineOffset);
}
else
{
//
// In a multi-part file, the file pointer may have been moved by
// other parts, so we have to ask tellg() where we are.
//
if (streamData->is->tellg() != ifd->lineOffsets[lineBufferNumber])
streamData->is->seekg (lineOffset);
}
//
( run in 1.293 second using v1.01-cache-2.11-cpan-39bf76dae61 )