⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imftiledinputfile.cpp

📁 对gif
💻 CPP
📖 第 1 页 / 共 3 页
字号:
///////////////////////////////////////////////////////////////////////////
//
// 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 {

void
readTileData (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;
}


void
readNextTileData (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 + -