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

📄 imftiledinputfile.cpp

📁 对gif
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    //

    _tileBuffer->post ();
}


void
TileBufferTask::execute ()
{
    try
    {
        //
        // Calculate information about the tile
        //
    
        Box2i tileRange = Imf::dataWindowForTile (_ifd->tileDesc,
                                                  _ifd->minX, _ifd->maxX,
                                                  _ifd->minY, _ifd->maxY,
                                                  _tileBuffer->dx,
                                                  _tileBuffer->dy,
                                                  _tileBuffer->lx,
                                                  _tileBuffer->ly);
    
        int numPixelsPerScanLine = tileRange.max.x - tileRange.min.x + 1;
    
        int numPixelsInTile = numPixelsPerScanLine *
                            (tileRange.max.y - tileRange.min.y + 1);
    
        int sizeOfTile = _ifd->bytesPerPixel * numPixelsInTile;
    
    
        //
        // Uncompress the data, if necessary
        //
    
        if (_tileBuffer->compressor && _tileBuffer->dataSize < sizeOfTile)
        {
            _tileBuffer->format = _tileBuffer->compressor->format();

            _tileBuffer->dataSize = _tileBuffer->compressor->uncompressTile
		(_tileBuffer->buffer, _tileBuffer->dataSize,
		 tileRange, _tileBuffer->uncompressedData);
        }
        else
        {
            //
            // If the line is uncompressed, it's in XDR format,
            // regardless of the compressor's output format.
            //
    
            _tileBuffer->format = Compressor::XDR;
            _tileBuffer->uncompressedData = _tileBuffer->buffer;
        }
    
        //
        // Convert the tile of pixel data back from the machine-independent
	// representation, and store the result in the frame buffer.
        //
    
        const char *readPtr = _tileBuffer->uncompressedData;
                                                        // points to where we
                                                        // read from in the
                                                        // tile block
        
        //
        // 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 < _ifd->slices.size(); ++i)
            {
                const TInSliceInfo &slice = _ifd->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 frame buffer with pixel data.
                //
    
                if (slice.skip)
                {
                    //
                    // The file contains data for this channel, but
                    // the frame buffer contains no slice for this channel.
                    //
    
                    skipChannel (readPtr, slice.typeInFile,
                                 numPixelsPerScanLine);
                }
                else
                {
                    //
                    // The frame buffer contains a slice for this channel.
                    //
    
                    char *writePtr = slice.base +
                                     (y - yOffset) * slice.yStride +
                                     (tileRange.min.x - xOffset) *
                                     slice.xStride;

                    char *endPtr = writePtr +
                                   (numPixelsPerScanLine - 1) * slice.xStride;
                                    
                    copyIntoFrameBuffer (readPtr, writePtr, endPtr,
                                         slice.xStride,
                                         slice.fill, slice.fillValue,
                                         _tileBuffer->format,
                                         slice.typeInFrameBuffer,
                                         slice.typeInFile);
                }
            }
        }
    }
    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;
        }
    }
}


TileBufferTask *
newTileBufferTask
    (TaskGroup *group,
     TiledInputFile::Data *ifd,
     int number,
     int dx, int dy,
     int lx, int ly)
{
    //
    // Wait for a tile buffer to become available,
    // fill the buffer with raw data from the file,
    // and create a new TileBufferTask whose execute()
    // method will uncompress the tile and copy the
    // tile's pixels into the frame buffer.
    //

    TileBuffer *tileBuffer = ifd->getTileBuffer (number);

    try
    {
	tileBuffer->wait();
	
	tileBuffer->dx = dx;
	tileBuffer->dy = dy;
	tileBuffer->lx = lx;
	tileBuffer->ly = ly;

	tileBuffer->uncompressedData = 0;

	readTileData (ifd, dx, dy, lx, ly,
		      tileBuffer->buffer,
		      tileBuffer->dataSize);
    }
    catch (...)
    {
	//
	// Reading from the file caused an exception.
	// Signal that the tile buffer is free, and
	// re-throw the exception.
	//

	tileBuffer->post();
	throw;
    }

    return new TileBufferTask (group, ifd, tileBuffer);
}


} // namespace


TiledInputFile::TiledInputFile (const char fileName[], int numThreads):
    _data (new Data (true, numThreads))
{
    //
    // This constructor is called when a user
    // explicitly wants to read a tiled file.
    //

    try
    {
	_data->is = new StdIFStream (fileName);
	_data->header.readFrom (*_data->is, _data->version);
	initialize();
    }
    catch (Iex::BaseExc &e)
    {
	delete _data;

	REPLACE_EXC (e, "Cannot open image file "
			"\"" << fileName << "\". " << e);
	throw;
    }
    catch (...)
    {
	delete _data;
        throw;
    }
}


TiledInputFile::TiledInputFile (IStream &is, int numThreads):
    _data (new Data (false, numThreads))
{
    //
    // This constructor is called when a user
    // explicitly wants to read a tiled file.
    //

    try
    {
	_data->is = &is;
	_data->header.readFrom (*_data->is, _data->version);
	initialize();
    }
    catch (Iex::BaseExc &e)
    {
	delete _data;

	REPLACE_EXC (e, "Cannot open image file "
			"\"" << is.fileName() << "\". " << e);
	throw;
    }
    catch (...)
    {
	delete _data;
        throw;
    }
}


TiledInputFile::TiledInputFile
    (const Header &header,
     IStream *is,
     int version,
     int numThreads)
:
    _data (new Data (false, numThreads))
{
    //
    // This constructor called by class Imf::InputFile
    // when a user wants to just read an image file, and
    // doesn't care or know if the file is tiled.
    //

    _data->is = is;
    _data->header = header;
    _data->version = version;
    initialize();
}


void
TiledInputFile::initialize ()
{
    if (!isTiled (_data->version))
	throw Iex::ArgExc ("Expected a tiled file but the file is not tiled.");

    _data->header.sanityCheck (true);

    _data->tileDesc = _data->header.tileDescription();
    _data->lineOrder = _data->header.lineOrder();

    //
    // 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);    

    _data->bytesPerPixel = calculateBytesPerPixel (_data->header);

    _data->maxBytesPerTileLine = _data->bytesPerPixel * _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));

        if (!_data->is->isMemoryMapped ())
            _data->tileBuffers[i]->buffer = new char [_data->tileBufferSize];
    }

    _data->tileOffsets = TileOffsets (_data->tileDesc.mode,
				      _data->numXLevels,
				      _data->numYLevels,
				      _data->numXTiles,
				      _data->numYTiles);

    _data->tileOffsets.readFrom (*(_data->is), _data->fileIsComplete);

    _data->currentPosition = _data->is->tellg();
}


TiledInputFile::~TiledInputFile ()
{
    if (!_data->is->isMemoryMapped())
        for (size_t i = 0; i < _data->tileBuffers.size(); i++)
            delete [] _data->tileBuffers[i]->buffer;

    delete _data;
}


const char *
TiledInputFile::fileName () const
{
    return _data->is->fileName();
}


const Header &
TiledInputFile::header () const
{
    return _data->header;
}


int
TiledInputFile::version () const
{
    return _data->version;
}


void	
TiledInputFile::setFrameBuffer (const FrameBuffer &frameBuffer)
{
    Lock lock (*_data);

    //
    // Set the frame buffer
    //

    //
    // Check if the new frame buffer descriptor is
    // compatible with the image file header.
    //

    const ChannelList &channels = _data->header.channels();

    for (FrameBuffer::ConstIterator j = frameBuffer.begin();
         j != frameBuffer.end();
         ++j)
    {
        ChannelList::ConstIterator i = channels.find (j.name());

        if (i == channels.end())
            continue;

        if (i.channel().xSampling != j.slice().xSampling ||
            i.channel().ySampling != j.slice().ySampling)
            THROW (Iex::ArgExc, "X and/or y subsampling factors "
				"of \"" << i.name() << "\" channel "
				"of input file \"" << fileName() << "\" are "
				"not compatible with the frame buffer's "
				"subsampling factors.");
    }

    //
    // Initialize the slice table for readPixels().
    //

    vector<TInSliceInfo> slices;
    ChannelList::ConstIterator i = channels.begin();

    for (FrameBuffer::ConstIterator j = frameBuffer.begin();
         j != frameBuffer.end();
         ++j)
    {
        while (i != channels.end() && strcmp (i.name(), j.name()) < 0)
        {
            //
            // Channel i is present in the file but not
            // in the frame buffer; data for channel i
            // will be skipped during readPixels().
            //

            slices.push_back (TInSliceInfo (i.channel().type,
					    i.channel().type,
					    0,      // base
					    0,      // xStride
					    0,      // yStride
					    false,  // fill
					    true,   // skip
					    0.0));  // fillValue
            ++i;
        }

⌨️ 快捷键说明

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