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

📄 imftiledoutputfile.cpp

📁 image converter source code
💻 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 TiledOutputFile////-----------------------------------------------------------------------------#include <ImfTiledOutputFile.h>#include <ImfTiledInputFile.h>#include <ImfInputFile.h>#include <ImfTileDescriptionAttribute.h>#include <ImfPreviewImageAttribute.h>#include <ImfChannelList.h>#include <ImfMisc.h>#include <ImfTiledMisc.h>#include <ImfStdIO.h>#include <ImfCompressor.h>#include "ImathBox.h"#include <ImfArray.h>#include <ImfXdr.h>#include <ImfVersion.h>#include <ImfTileOffsets.h>#include <ImfThreading.h>#include "IlmThreadPool.h"#include "IlmThreadSemaphore.h"#include "IlmThreadMutex.h"#include "Iex.h"#include <string>#include <vector>#include <fstream>#include <assert.h>#include <map>namespace Imf {using Imath::Box2i;using Imath::V2i;using std::string;using std::vector;using std::ofstream;using std::map;using std::min;using std::max;using std::swap;using IlmThread::Mutex;using IlmThread::Lock;using IlmThread::Semaphore;using IlmThread::Task;using IlmThread::TaskGroup;using IlmThread::ThreadPool;namespace {struct TOutSliceInfo{    PixelType		type;    const char *	base;    size_t		xStride;    size_t		yStride;    bool		zero;    int                 xTileCoords;    int                 yTileCoords;    TOutSliceInfo (PixelType type = HALF,	           const char *base = 0,	           size_t xStride = 0,	           size_t yStride = 0,	           bool zero = false,                   int xTileCoords = 0,                   int yTileCoords = 0);};TOutSliceInfo::TOutSliceInfo (PixelType t,		              const char *b,			      size_t xs, size_t ys,			      bool z,                              int xtc,                              int ytc):    type (t),    base (b),    xStride (xs),    yStride (ys),    zero (z),    xTileCoords (xtc),    yTileCoords (ytc){    // empty}struct TileCoord{    int		dx;    int		dy;    int		lx;    int		ly;        TileCoord (int xTile = 0, int yTile = 0,	       int xLevel = 0, int yLevel = 0)    :        dx (xTile),  dy (yTile),	lx (xLevel), ly (yLevel)    {        // empty    }        bool    operator < (const TileCoord &other) const    {        return (ly < other.ly) ||	       (ly == other.ly && lx < other.lx) ||	       ((ly == other.ly && lx == other.lx) &&		    ((dy < other.dy) || (dy == other.dy && dx < other.dx)));    }    bool    operator == (const TileCoord &other) const    {        return lx == other.lx &&	       ly == other.ly &&	       dx == other.dx &&	       dy == other.dy;    }};struct BufferedTile{    char *	pixelData;    int		pixelDataSize;    BufferedTile (const char *data, int size):	pixelData (0),	pixelDataSize(size)    {	pixelData = new char[pixelDataSize];	memcpy (pixelData, data, pixelDataSize);    }    ~BufferedTile()    {	delete [] pixelData;    }};typedef map <TileCoord, BufferedTile *> TileMap;struct TileBuffer{    Array<char>		buffer;    const char *	dataPtr;    int			dataSize;    Compressor *	compressor;    TileCoord		tileCoord;    bool		hasException;    string		exception;     TileBuffer (Compressor *comp);    ~TileBuffer ();    inline void		wait () {_sem.wait();}    inline void		post () {_sem.post();}  protected:    Semaphore		_sem;};TileBuffer::TileBuffer (Compressor *comp):    dataPtr (0),    dataSize (0),    compressor (comp),    hasException (false),    exception (),    _sem (1){    // empty}TileBuffer::~TileBuffer (){    delete compressor;}} // namespacestruct TiledOutputFile::Data: public Mutex{    Header		header;			// the image header    int			version;		// file format version    TileDescription	tileDesc;		// describes the tile layout    FrameBuffer		frameBuffer;		// framebuffer to write into    Int64		previewPosition;    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    Compressor::Format	format;			// compressor's data format    vector<TOutSliceInfo> slices;		// info about channels in file    OStream *		os;			// file stream to write to    bool		deleteStream;    size_t		maxBytesPerTileLine;	// combined size of a tile line						// over all channels        vector<TileBuffer*> tileBuffers;    size_t		tileBufferSize;         // size of a tile buffer    Int64		tileOffsetsPosition;	// position of the tile index    Int64		currentPosition;	// current position in the file        TileMap		tileMap;    TileCoord		nextTileToWrite;     Data (bool del, int numThreads);    ~Data ();        inline TileBuffer *	getTileBuffer (int number);    						// hash function from tile						// buffer coords into our						// vector of tile buffers        TileCoord		nextTileCoord (const TileCoord &a);};TiledOutputFile::Data::Data (bool del, int numThreads):    numXTiles(0),    numYTiles(0),    os (0),    deleteStream (del),    tileOffsetsPosition (0){    //    // 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));}TiledOutputFile::Data::~Data (){    delete [] numXTiles;    delete [] numYTiles;    if (deleteStream)	delete os;        //    // Delete all the tile buffers, if any still happen to exist    //        for (TileMap::iterator i = tileMap.begin(); i != tileMap.end(); ++i)	delete i->second;    for (size_t i = 0; i < tileBuffers.size(); i++)        delete tileBuffers[i];}TileBuffer*TiledOutputFile::Data::getTileBuffer (int number){    return tileBuffers[number % tileBuffers.size()];}TileCoordTiledOutputFile::Data::nextTileCoord (const TileCoord &a){    TileCoord b = a;        if (lineOrder == INCREASING_Y)    {        b.dx++;        if (b.dx >= numXTiles[b.lx])        {            b.dx = 0;            b.dy++;            if (b.dy >= numYTiles[b.ly])            {		//		// the next tile is in the next level		//                b.dy = 0;                switch (tileDesc.mode)                {                  case ONE_LEVEL:                  case MIPMAP_LEVELS:                    b.lx++;                    b.ly++;                    break;                  case RIPMAP_LEVELS:                    b.lx++;                    if (b.lx >= numXLevels)                    {                        b.lx = 0;                        b.ly++;			#ifdef DEBUG			    assert (b.ly <= numYLevels);			#endif                    }                    break;                }            }        }    }    else if (lineOrder == DECREASING_Y)    {        b.dx++;        if (b.dx >= numXTiles[b.lx])        {            b.dx = 0;            b.dy--;            if (b.dy < 0)            {		//		// the next tile is in the next level		//                switch (tileDesc.mode)                {                  case ONE_LEVEL:                  case MIPMAP_LEVELS:                    b.lx++;                    b.ly++;                    break;                  case RIPMAP_LEVELS:                    b.lx++;                    if (b.lx >= numXLevels)                    {                        b.lx = 0;                        b.ly++;			#ifdef DEBUG			    assert (b.ly <= numYLevels);			#endif                    }                    break;                }		if (b.ly < numYLevels)		    b.dy = numYTiles[b.ly] - 1;            }        }    }        return b;   }namespace {voidwriteTileData (TiledOutputFile::Data *ofd,               int dx, int dy,	       int lx, int ly,                const char pixelData[],               int pixelDataSize){    //    // Store a block of pixel data in the output file, and try    // to keep track of the current writing position the file,    // without calling tellp() (tellp() can be fairly expensive).    //    Int64 currentPosition = ofd->currentPosition;    ofd->currentPosition = 0;    if (currentPosition == 0)        currentPosition = ofd->os->tellp();    ofd->tileOffsets (dx, dy, lx, ly) = currentPosition;    #ifdef DEBUG	assert (ofd->os->tellp() == currentPosition);    #endif    //    // Write the tile header.    //    Xdr::write <StreamIO> (*ofd->os, dx);    Xdr::write <StreamIO> (*ofd->os, dy);    Xdr::write <StreamIO> (*ofd->os, lx);    Xdr::write <StreamIO> (*ofd->os, ly);    Xdr::write <StreamIO> (*ofd->os, pixelDataSize);    ofd->os->write (pixelData, pixelDataSize);        //    // Keep current position in the file so that we can avoid     // redundant seekg() operations (seekg() can be fairly expensive).    //    ofd->currentPosition = currentPosition +                           5 * Xdr::size<int>() +                           pixelDataSize;}voidbufferedTileWrite (TiledOutputFile::Data *ofd,                   int dx, int dy,		   int lx, int ly,                    const char pixelData[],                   int pixelDataSize){    //    // Check if a tile with coordinates (dx,dy,lx,ly) has already been written.    //    if (ofd->tileOffsets (dx, dy, lx, ly))    {	THROW (Iex::ArgExc,	       "Attempt to write tile "	       "(" << dx << ", " << dy << ", " << lx << "," << ly << ") "	       "more than once.");    }    //    // If tiles can be written in random order, then don't buffer anything.    //        if (ofd->lineOrder == RANDOM_Y)    {        writeTileData (ofd, dx, dy, lx, ly, pixelData, pixelDataSize);        return;    }        //    // If the tiles cannot be written in random order, then check if a    // tile with coordinates (dx,dy,lx,ly) has already been buffered.    //    TileCoord currentTile = TileCoord(dx, dy, lx, ly);    if (ofd->tileMap.find (currentTile) != ofd->tileMap.end())    {	THROW (Iex::ArgExc,	       "Attempt to write tile "	       "(" << dx << ", " << dy << ", " << lx << "," << ly << ") "	       "more than once.");    }    //    // If all the tiles before this one have already been written to the file,    // then write this tile immediately and check if we have buffered tiles    // that can be written after this tile.    //    // Otherwise, buffer the tile so it can be written to file later.    //        if (ofd->nextTileToWrite == currentTile)    {        writeTileData (ofd, dx, dy, lx, ly, pixelData, pixelDataSize);                ofd->nextTileToWrite = ofd->nextTileCoord (ofd->nextTileToWrite);        TileMap::iterator i = ofd->tileMap.find (ofd->nextTileToWrite);                //        // Step through the tiles and write all successive buffered tiles after        // the current one.        //                while(i != ofd->tileMap.end())        {            //            // Write the tile, and then delete the tile's buffered data            //            writeTileData (ofd,			   i->first.dx, i->first.dy,			   i->first.lx, i->first.ly,			   i->second->pixelData,			   i->second->pixelDataSize);            delete i->second;            ofd->tileMap.erase (i);                        //            // Proceed to the next tile            //                        ofd->nextTileToWrite = ofd->nextTileCoord (ofd->nextTileToWrite);            i = ofd->tileMap.find (ofd->nextTileToWrite);        }    }    else    {        //

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -