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

📄 imftiledoutputfile.cpp

📁 image converter source code
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        // Create a new BufferedTile, copy the pixelData into it, and        // insert it into the tileMap.        //	ofd->tileMap[currentTile] =	    new BufferedTile ((const char *)pixelData, pixelDataSize);    }}voidconvertToXdr (TiledOutputFile::Data *ofd,              Array<char>& tileBuffer,	      int numScanLines,	      int numPixelsPerScanLine){    //    // Convert the contents of a TiledOutputFile's tileBuffer from the     // machine's native representation to Xdr format. This function is called    // by writeTile(), below, if the compressor wanted its input pixel data    // in the machine's native format, but then failed to compress the data    // (most compressors will expand rather than compress random input data).    //    // Note that this routine assumes that the machine's native representation    // of the pixel data has the same size as the Xdr representation.  This    // makes it possible to convert the pixel data in place, without an    // intermediate temporary buffer.    //    //    // Set these to point to the start of the tile.    // We will write to toPtr, and read from fromPtr.    //    char *writePtr = tileBuffer;    const char *readPtr = writePtr;    //    // Iterate over all scan lines in the tile.    //    for (int y = 0; y < numScanLines; ++y)    {	//	// Iterate over all slices in the file.	//	for (unsigned int i = 0; i < ofd->slices.size(); ++i)	{	    const TOutSliceInfo &slice = ofd->slices[i];	    //	    // Convert the samples in place.	    //                        convertInPlace (writePtr, readPtr, slice.type,                            numPixelsPerScanLine);	}    }    #ifdef DEBUG	assert (writePtr == readPtr);    #endif}//// A TileBufferTask encapsulates the task of copying a tile from// the user's framebuffer into a LineBuffer and compressing the data// if necessary.//class TileBufferTask: public Task{  public:                        TileBufferTask (TaskGroup *group,                    TiledOutputFile::Data *ofd,                    int number,		    int dx, int dy,		    int lx, int ly);                        virtual ~TileBufferTask ();    virtual void		execute ();      private:    TiledOutputFile::Data *	_ofd;    TileBuffer *		_tileBuffer;};TileBufferTask::TileBufferTask    (TaskGroup *group,     TiledOutputFile::Data *ofd,     int number,     int dx, int dy,     int lx, int ly):    Task (group),    _ofd (ofd),    _tileBuffer (_ofd->getTileBuffer (number)){    //    // Wait for the tileBuffer to become available    //    _tileBuffer->wait ();    _tileBuffer->tileCoord = TileCoord (dx, dy, lx, ly);}TileBufferTask::~TileBufferTask (){    //    // Signal that the tile buffer is now free    //    _tileBuffer->post ();}voidTileBufferTask::execute (){    try    {        //        // First copy the pixel data from the frame buffer	// into the tile buffer        //        // Convert one tile's worth of pixel data to        // a machine-independent representation, and store        // the result in _tileBuffer->buffer.        //            char *writePtr = _tileBuffer->buffer;            Box2i tileRange = Imf::dataWindowForTile (_ofd->tileDesc,                                                  _ofd->minX, _ofd->maxX,                                                  _ofd->minY, _ofd->maxY,                                                  _tileBuffer->tileCoord.dx,                                                  _tileBuffer->tileCoord.dy,                                                  _tileBuffer->tileCoord.lx,                                                  _tileBuffer->tileCoord.ly);            int numScanLines = tileRange.max.y - tileRange.min.y + 1;        int numPixelsPerScanLine = tileRange.max.x - tileRange.min.x + 1;            //        // Iterate over the scan lines in the tile.        //                for (int y = tileRange.min.y; y <= tileRange.max.y; ++y)        {            //            // Iterate over all image channels.            //                for (unsigned int i = 0; i < _ofd->slices.size(); ++i)            {                const TOutSliceInfo &slice = _ofd->slices[i];                    //                // These offsets are used to facilitate both absolute                // and tile-relative pixel coordinates.                //                            int xOffset = slice.xTileCoords * tileRange.min.x;                int yOffset = slice.yTileCoords * tileRange.min.y;    		//		// Fill the tile buffer with pixel data.		//                if (slice.zero)                {                    //                    // The frame buffer contains no data for this channel.                    // Store zeroes in _data->tileBuffer.                    //                                        fillChannelWithZeroes (writePtr, _ofd->format, slice.type,                                           numPixelsPerScanLine);                }                else                {                    //                    // The frame buffer contains data for this channel.                    //                        const char *readPtr = slice.base +                                          (y - yOffset) * slice.yStride +                                          (tileRange.min.x - xOffset) *                                          slice.xStride;                    const char *endPtr  = readPtr +                                          (numPixelsPerScanLine - 1) *                                          slice.xStride;                                                            copyFromFrameBuffer (writePtr, readPtr, endPtr,                                         slice.xStride, _ofd->format,                                         slice.type);                }            }        }                //        // Compress the contents of the tileBuffer,         // and store the compressed data in the output file.        //            _tileBuffer->dataSize = writePtr - _tileBuffer->buffer;        _tileBuffer->dataPtr = _tileBuffer->buffer;            if (_tileBuffer->compressor)        {            const char *compPtr;            int compSize = _tileBuffer->compressor->compressTile                                                (_tileBuffer->dataPtr,                                                 _tileBuffer->dataSize,                                                 tileRange, compPtr);                if (compSize < _tileBuffer->dataSize)            {                _tileBuffer->dataSize = compSize;                _tileBuffer->dataPtr = compPtr;            }            else if (_ofd->format == Compressor::NATIVE)            {                //                // The data did not shrink during compression, but                // we cannot write to the file using native format,                // so we need to convert the lineBuffer to Xdr.                //                    convertToXdr (_ofd, _tileBuffer->buffer, numScanLines,                              numPixelsPerScanLine);            }        }    }    catch (std::exception &e)    {        if (!_tileBuffer->hasException)        {            _tileBuffer->exception = e.what ();            _tileBuffer->hasException = true;        }    }    catch (...)    {        if (!_tileBuffer->hasException)        {            _tileBuffer->exception = "unrecognized exception";            _tileBuffer->hasException = true;        }    }}} // namespaceTiledOutputFile::TiledOutputFile    (const char fileName[],     const Header &header,     int numThreads):    _data (new Data (true, numThreads)){    try    {	header.sanityCheck (true);	_data->os = new StdOFStream (fileName);	initialize (header);    }    catch (Iex::BaseExc &e)    {	delete _data;	REPLACE_EXC (e, "Cannot open image file "			"\"" << fileName << "\". " << e);	throw;    }    catch (...)    {	delete _data;        throw;    }}TiledOutputFile::TiledOutputFile    (OStream &os,     const Header &header,     int numThreads):    _data (new Data (false, numThreads)){    try    {	header.sanityCheck(true);	_data->os = &os;	initialize (header);    }    catch (Iex::BaseExc &e)    {	delete _data;	REPLACE_EXC (e, "Cannot open image file "			"\"" << os.fileName() << "\". " << e);	throw;    }    catch (...)    {	delete _data;        throw;    }}voidTiledOutputFile::initialize (const Header &header){    _data->header = header;    _data->lineOrder = _data->header.lineOrder();    //    // Check that the file is indeed tiled    //    _data->tileDesc = _data->header.tileDescription();    //    // Save the dataWindow information    //    const Box2i &dataWindow = _data->header.dataWindow();    _data->minX = dataWindow.min.x;    _data->maxX = dataWindow.max.x;    _data->minY = dataWindow.min.y;    _data->maxY = dataWindow.max.y;    //    // Precompute level and tile information to speed up utility functions    //    precalculateTileInfo (_data->tileDesc,			  _data->minX, _data->maxX,			  _data->minY, _data->maxY,			  _data->numXTiles, _data->numYTiles,			  _data->numXLevels, _data->numYLevels);               //    // Determine the first tile coordinate that we will be writing    // if the file is not RANDOM_Y.    //        _data->nextTileToWrite = (_data->lineOrder == INCREASING_Y)?			       TileCoord (0, 0, 0, 0):			       TileCoord (0, _data->numYTiles[0] - 1, 0, 0);    _data->maxBytesPerTileLine =	    calculateBytesPerPixel (_data->header) * _data->tileDesc.xSize;    _data->tileBufferSize = _data->maxBytesPerTileLine * _data->tileDesc.ySize;        //    // Create all the TileBuffers and allocate their internal buffers    //    for (size_t i = 0; i < _data->tileBuffers.size(); i++)    {        _data->tileBuffers[i] = new TileBuffer (newTileCompressor						  (_data->header.compression(),						   _data->maxBytesPerTileLine,						   _data->tileDesc.ySize,						   _data->header));        _data->tileBuffers[i]->buffer.resizeErase(_data->tileBufferSize);    }    _data->format = defaultFormat (_data->tileBuffers[0]->compressor);    _data->tileOffsets = TileOffsets (_data->tileDesc.mode,				      _data->numXLevels,				      _data->numYLevels,				      _data->numXTiles,				      _data->numYTiles);    _data->previewPosition = _data->header.writeTo (*_data->os, true);    _data->tileOffsetsPosition = _data->tileOffsets.writeTo (*_data->os);    _data->currentPosition = _data->os->tellp();}TiledOutputFile::~TiledOutputFile (){    if (_data)    {        {            if (_data->tileOffsetsPosition > 0)            {                try                {                    _data->os->seekp (_data->tileOffsetsPosition);                    _data->tileOffsets.writeTo (*_data->os);                }                catch (...)                {                    //                    // We cannot safely throw any exceptions from here.                    // This destructor may have been called because the                    // stack is currently being unwound for another                    // exception.                    //                }            }        }                delete _data;    }}const char *TiledOutputFile::fileName () const{    return _data->os->fileName();}const Header &TiledOutputFile::header () const{    return _data->header;}void	TiledOutputFile::setFrameBuffer (const FrameBuffer &frameBuffer){    Lock lock (*_data);    //    // Check if the new frame buffer descriptor    // is compatible with the image file header.    //    const ChannelList &channels = _data->header.channels();    for (ChannelList::ConstIterator i = channels.begin();	 i != channels.end();	 ++i)    {	FrameBuffer::ConstIterator j = frameBuffer.find (i.name());	if (j == frameBuffer.end())	    continue;	if (i.channel().type != j.slice().type)	    THROW (Iex::ArgExc, "Pixel type of \"" << i.name() << "\" channel "				"of output file \"" << fileName() << "\" is "				"not compatible with the frame buffer's "				"pixel type.");	if (j.slice().xSampling != 1 || j.slice().ySampling != 1)	    THROW (Iex::ArgExc, "All channels in a tiled file must have"				"sampling (1,1).");    }        //    // Initialize slice table for writePixels().    //    vector<TOutSliceInfo> slices;    for (ChannelList::ConstIterator i = channels.begin();	 i != channels.end();	 ++i)    {	FrameBuffer::ConstIterator j = frameBuffer.find (i.name());	if (j == frameBuffer.end())	{	    //	    // Channel i is not present in the frame buffer.	    // In the file, channel i will contain only zeroes.	    //	    slices.push_back (TOutSliceInfo (i.channel().type,					     0, // base					     0, // xStride,					     0, // yStride,					     true)); // zero	}	else	{	    //	    // Channel i is present in the frame buffer.	    //	    slices.push_back (TOutSliceInfo (j.slice().type,					     j.slice().base,					     j.slice().xStride,					     j.slice().yStride,					     false, // zero                                             (j.slice().xTileCoords)? 1: 0,                                             (j.slice().yTileCoords)? 1: 0));	}    }    //    // Store the new frame buffer.    //    _data->frameBuffer = frameBuffer;    _data->slices = slices;}const FrameBuffer &TiledOutputFile::frameBuffer () const{    Lock lock (*_data);    return _data->frameBuffer;}void	TiledOutputFile::writeTiles (int dx1, int dx2, int dy1, int dy2,                             int lx, int ly){    try    {        Lock lock (*_data);        if (_data->slices.size() == 0)	    throw Iex::ArgExc ("No frame buffer specified "			       "as pixel data source.");	if (!isValidTile (dx1, dy1, lx, ly) || !isValidTile (dx2, dy2, lx, ly))	    throw Iex::ArgExc ("Tile coordinates are invalid.");        //        // Determine the first and last tile coordinates in both dimensions        // based on the file's lineOrder        //                                       if (dx1 > dx2)            swap (dx1, dx2);                if (dy1 > dy2)            swap (dy1, dy2);                int dyStart = dy1;	int dyStop  = dy2 + 1;	int dY      = 1;            if (_data->lineOrder == DECREASING_Y)        {

⌨️ 快捷键说明

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