📄 imftiledinputfile.cpp
字号:
/////////////////////////////////////////////////////////////////////////////// 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 TiledInputFile////-----------------------------------------------------------------------------#include <ImfTiledInputFile.h>#include <ImfTileDescriptionAttribute.h>#include <ImfChannelList.h>#include <ImfMisc.h>#include <ImfTiledMisc.h>#include <ImfStdIO.h>#include <ImfCompressor.h>#include "ImathBox.h"#include <ImfXdr.h>#include <ImfConvert.h>#include <ImfVersion.h>#include <ImfTileOffsets.h>#include <ImfThreading.h>#include "IlmThreadPool.h"#include "IlmThreadSemaphore.h"#include "IlmThreadMutex.h"#include "ImathVec.h"#include "Iex.h"#include <string>#include <vector>#include <algorithm>#include <assert.h>namespace Imf {using Imath::Box2i;using Imath::V2i;using std::string;using std::vector;using std::min;using std::max;using IlmThread::Mutex;using IlmThread::Lock;using IlmThread::Semaphore;using IlmThread::Task;using IlmThread::TaskGroup;using IlmThread::ThreadPool;namespace {struct TInSliceInfo{ PixelType typeInFrameBuffer; PixelType typeInFile; char * base; size_t xStride; size_t yStride; bool fill; bool skip; double fillValue; int xTileCoords; int yTileCoords; TInSliceInfo (PixelType typeInFrameBuffer = HALF, PixelType typeInFile = HALF, char *base = 0, size_t xStride = 0, size_t yStride = 0, bool fill = false, bool skip = false, double fillValue = 0.0, int xTileCoords = 0, int yTileCoords = 0);};TInSliceInfo::TInSliceInfo (PixelType tifb, PixelType tifl, char *b, size_t xs, size_t ys, bool f, bool s, double fv, int xtc, int ytc): typeInFrameBuffer (tifb), typeInFile (tifl), base (b), xStride (xs), yStride (ys), fill (f), skip (s), fillValue (fv), xTileCoords (xtc), yTileCoords (ytc){ // empty}struct TileBuffer{ const char * uncompressedData; char * buffer; int dataSize; Compressor * compressor; Compressor::Format format; int dx; int dy; int lx; int ly; bool hasException; string exception; TileBuffer (Compressor * const comp); ~TileBuffer (); inline void wait () {_sem.wait();} inline void post () {_sem.post();} protected: Semaphore _sem;};TileBuffer::TileBuffer (Compressor *comp): uncompressedData (0), dataSize (0), compressor (comp), format (defaultFormat (compressor)), dx (-1), dy (-1), lx (-1), ly (-1), hasException (false), exception (), _sem (1){ // empty}TileBuffer::~TileBuffer (){ delete compressor;}} // namespace//// struct TiledInputFile::Data stores things that will be// needed between calls to readTile()//struct TiledInputFile::Data: public Mutex{ Header header; // the image header TileDescription tileDesc; // describes the tile layout int version; // file's version FrameBuffer frameBuffer; // framebuffer to write into LineOrder lineOrder; // the file's lineorder 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 int numXLevels; // number of x levels int numYLevels; // number of y levels int * numXTiles; // number of x tiles at a level int * numYTiles; // number of y tiles at a level TileOffsets tileOffsets; // stores offsets in file for // each tile bool fileIsComplete; // True if no tiles are missing // in the file Int64 currentPosition; // file offset for current tile, // used to prevent unnecessary // seeking vector<TInSliceInfo> slices; // info about channels in file IStream * is; // file stream to read from bool deleteStream; // should we delete the stream // ourselves? or does someone // else do it? size_t bytesPerPixel; // size of an uncompressed pixel size_t maxBytesPerTileLine; // combined size of a line // over all channels vector<TileBuffer*> tileBuffers; // each holds a single tile size_t tileBufferSize; // size of the tile buffers Data (bool deleteStream, int numThreads); ~Data (); inline TileBuffer * getTileBuffer (int number); // hash function from tile indices // into our vector of tile buffers};TiledInputFile::Data::Data (bool del, int numThreads): numXTiles (0), numYTiles (0), is (0), deleteStream (del){ // // We need at least one tileBuffer, but if threading is used, // to keep n threads busy we need 2*n tileBuffers // tileBuffers.resize (max (1, 2 * numThreads));}TiledInputFile::Data::~Data (){ delete [] numXTiles; delete [] numYTiles; if (deleteStream) delete is; for (size_t i = 0; i < tileBuffers.size(); i++) delete tileBuffers[i];}TileBuffer*TiledInputFile::Data::getTileBuffer (int number){ return tileBuffers[number % tileBuffers.size()];}namespace {voidreadTileData (TiledInputFile::Data *ifd, int dx, int dy, int lx, int ly, char *&buffer, int &dataSize){ // // Read a single tile block from the file and into the array pointed // to by buffer. If the file is memory-mapped, then we change where // buffer points instead of writing into the array (hence buffer needs // to be a reference to a char *). // // // Look up the location for this tile in the Index and // seek to that position if necessary // Int64 tileOffset = ifd->tileOffsets (dx, dy, lx, ly); if (tileOffset == 0) { THROW (Iex::InputExc, "Tile (" << dx << ", " << dy << ", " << lx << ", " << ly << ") is missing."); } if (ifd->currentPosition != tileOffset) ifd->is->seekg (tileOffset); // // Read the first few bytes of the tile (the header). // Verify that the tile coordinates and the level number // are correct. // int tileXCoord, tileYCoord, levelX, levelY; Xdr::read <StreamIO> (*ifd->is, tileXCoord); Xdr::read <StreamIO> (*ifd->is, tileYCoord); Xdr::read <StreamIO> (*ifd->is, levelX); Xdr::read <StreamIO> (*ifd->is, levelY); Xdr::read <StreamIO> (*ifd->is, dataSize); if (tileXCoord != dx) throw Iex::InputExc ("Unexpected tile x coordinate."); if (tileYCoord != dy) throw Iex::InputExc ("Unexpected tile y coordinate."); if (levelX != lx) throw Iex::InputExc ("Unexpected tile x level number coordinate."); if (levelY != ly) throw Iex::InputExc ("Unexpected tile y level number coordinate."); if (dataSize > (int) ifd->tileBufferSize) throw Iex::InputExc ("Unexpected tile block length."); // // Read the pixel data. // if (ifd->is->isMemoryMapped ()) buffer = ifd->is->readMemoryMapped (dataSize); else ifd->is->read (buffer, dataSize); // // Keep track of which tile is the next one in // the file, so that we can avoid redundant seekg() // operations (seekg() can be fairly expensive). // ifd->currentPosition = tileOffset + 5 * Xdr::size<int>() + dataSize;}voidreadNextTileData (TiledInputFile::Data *ifd, int &dx, int &dy, int &lx, int &ly, char * & buffer, int &dataSize){ // // Read the next tile block from the file // // // Read the first few bytes of the tile (the header). // Xdr::read <StreamIO> (*ifd->is, dx); Xdr::read <StreamIO> (*ifd->is, dy); Xdr::read <StreamIO> (*ifd->is, lx); Xdr::read <StreamIO> (*ifd->is, ly); Xdr::read <StreamIO> (*ifd->is, dataSize); if (dataSize > (int) ifd->tileBufferSize) throw Iex::InputExc ("Unexpected tile block length."); // // Read the pixel data. // ifd->is->read (buffer, dataSize); // // Keep track of which tile is the next one in // the file, so that we can avoid redundant seekg() // operations (seekg() can be fairly expensive). // ifd->currentPosition += 5 * Xdr::size<int>() + dataSize;}//// A TileBufferTask encapsulates the task of uncompressing// a single tile and copying it into the frame buffer.//class TileBufferTask : public Task{ public: TileBufferTask (TaskGroup *group, TiledInputFile::Data *ifd, TileBuffer *tileBuffer); virtual ~TileBufferTask (); virtual void execute (); private: TiledInputFile::Data * _ifd; TileBuffer * _tileBuffer;};TileBufferTask::TileBufferTask (TaskGroup *group, TiledInputFile::Data *ifd, TileBuffer *tileBuffer): Task (group), _ifd (ifd), _tileBuffer (tileBuffer){ // empty}TileBufferTask::~TileBufferTask (){ // // Signal that the tile buffer is now free
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -