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

📄 imfscanlineinputfile.cpp

📁 image converter source code
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////// 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 ScanLineInputFile////-----------------------------------------------------------------------------#include <ImfScanLineInputFile.h>#include <ImfChannelList.h>#include <ImfMisc.h>#include <ImfStdIO.h>#include <ImfCompressor.h>#include "ImathBox.h"#include "ImathFun.h"#include <ImfXdr.h>#include <ImfConvert.h>#include <ImfThreading.h>#include "IlmThreadPool.h"#include "IlmThreadSemaphore.h"#include "IlmThreadMutex.h"#include "Iex.h"#include <string>#include <vector>#include <assert.h>namespace Imf {using Imath::Box2i;using Imath::divp;using Imath::modp;using std::string;using std::vector;using std::ifstream;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 InSliceInfo{    PixelType	typeInFrameBuffer;    PixelType	typeInFile;    char *	base;    size_t	xStride;    size_t	yStride;    int		xSampling;    int		ySampling;    bool	fill;    bool	skip;    double	fillValue;    InSliceInfo (PixelType typeInFrameBuffer = HALF,		 PixelType typeInFile = HALF,	         char *base = 0,	         size_t xStride = 0,	         size_t yStride = 0,	         int xSampling = 1,	         int ySampling = 1,	         bool fill = false,	         bool skip = false,	         double fillValue = 0.0);};InSliceInfo::InSliceInfo (PixelType tifb,			  PixelType tifl,			  char *b,			  size_t xs, size_t ys,			  int xsm, int ysm,			  bool f, bool s,			  double fv):    typeInFrameBuffer (tifb),    typeInFile (tifl),    base (b),    xStride (xs),    yStride (ys),    xSampling (xsm),    ySampling (ysm),    fill (f),    skip (s),    fillValue (fv){    // empty}struct LineBuffer{    const char *	uncompressedData;    char *		buffer;    int			dataSize;    int			minY;    int			maxY;    Compressor *	compressor;    Compressor::Format	format;    int			number;    bool		hasException;    string		exception;    LineBuffer (Compressor * const comp);    ~LineBuffer ();    inline void		wait () {_sem.wait();}    inline void		post () {_sem.post();}  private:    Semaphore		_sem;};LineBuffer::LineBuffer (Compressor *comp):    uncompressedData (0),    buffer (0),    dataSize (0),    compressor (comp),    format (defaultFormat(compressor)),    number (-1),    hasException (false),    exception (),    _sem (1){    // empty}LineBuffer::~LineBuffer (){    delete compressor;}} // namespacestruct ScanLineInputFile::Data: public Mutex{    Header		header;		    // the image header    int			version;            // file's version    FrameBuffer		frameBuffer;	    // framebuffer to write into    LineOrder		lineOrder;          // order of the scanlines in file    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    vector<Int64>	lineOffsets;	    // stores offsets in file for					    // each line    bool		fileIsComplete;	    // True if no scanlines are missing    					    // in the file    int			nextLineBufferMinY; // minimum y of the next linebuffer    vector<size_t>	bytesPerLine;       // combined size of a line over all                                            // channels    vector<size_t>	offsetInLineBuffer; // offset for each scanline in its                                            // linebuffer    vector<InSliceInfo>	slices;             // info about channels in file    IStream *		is;                 // file stream to read from        vector<LineBuffer*> lineBuffers;        // each holds one line buffer    int			linesInBuffer;      // number of scanlines each buffer                                            // holds    size_t		lineBufferSize;     // size of the line buffer     Data (IStream *is, int numThreads);    ~Data ();        inline LineBuffer * getLineBuffer (int number); // hash function from line    						    // buffer indices into our						    // vector of line buffers};ScanLineInputFile::Data::Data (IStream *is, int numThreads):    is (is){    //    // We need at least one lineBuffer, but if threading is used,    // to keep n threads busy we need 2*n lineBuffers    //    lineBuffers.resize (max (1, 2 * numThreads));}ScanLineInputFile::Data::~Data (){    for (size_t i = 0; i < lineBuffers.size(); i++)        delete lineBuffers[i];}inline LineBuffer *ScanLineInputFile::Data::getLineBuffer (int lineBufferNumber){    return lineBuffers[lineBufferNumber % lineBuffers.size()];}namespace {voidreconstructLineOffsets (IStream &is,			LineOrder lineOrder,			vector<Int64> &lineOffsets){    Int64 position = is.tellg();    try    {	for (unsigned int i = 0; i < lineOffsets.size(); i++)	{	    Int64 lineOffset = is.tellg();	    int y;	    Xdr::read <StreamIO> (is, y);	    int dataSize;	    Xdr::read <StreamIO> (is, dataSize);	    Xdr::skip <StreamIO> (is, dataSize);	    if (lineOrder == INCREASING_Y)		lineOffsets[i] = lineOffset;	    else		lineOffsets[lineOffsets.size() - i - 1] = lineOffset;	}    }    catch (...)    {	//	// Suppress all exceptions.  This functions is	// called only to reconstruct the line offset	// table for incomplete files, and exceptions	// are likely.	//    }    is.clear();    is.seekg (position);}voidreadLineOffsets (IStream &is,		 LineOrder lineOrder,		 vector<Int64> &lineOffsets,		 bool &complete){    for (unsigned int i = 0; i < lineOffsets.size(); i++)    {	Xdr::read <StreamIO> (is, lineOffsets[i]);    }    complete = true;    for (unsigned int i = 0; i < lineOffsets.size(); i++)    {	if (lineOffsets[i] <= 0)	{	    //	    // Invalid data in the line offset table mean that	    // the file is probably incomplete (the table is	    // the last thing written to the file).  Either	    // some process is still busy writing the file,	    // or writing the file was aborted.	    //	    // We should still be able to read the existing	    // parts of the file.  In order to do this, we	    // have to make a sequential scan over the scan	    // line data to reconstruct the line offset table.	    //	    complete = false;	    reconstructLineOffsets (is, lineOrder, lineOffsets);	    break;	}    }}voidreadPixelData (ScanLineInputFile::Data *ifd,	       int minY,	       char *&buffer,	       int &dataSize){    //    // Read a single line buffer from the input file.    //    // If the input file is not memory-mapped, we copy the pixel data into    // into the array pointed to by buffer.  If the file is memory-mapped,    // then we change where buffer points to instead of writing into the    // array (hence buffer needs to be a reference to a char *).    //    Int64 lineOffset =	ifd->lineOffsets[(minY - ifd->minY) / ifd->linesInBuffer];    if (lineOffset == 0)	THROW (Iex::InputExc, "Scan line " << minY << " is missing.");    //    // Seek to the start of the scan line in the file,    // if necessary.    //    if (ifd->nextLineBufferMinY != minY)	ifd->is->seekg (lineOffset);    //    // Read the data block's header.    //    int yInFile;    Xdr::read <StreamIO> (*ifd->is, yInFile);    Xdr::read <StreamIO> (*ifd->is, dataSize);        if (yInFile != minY)        throw Iex::InputExc ("Unexpected data block y coordinate.");    if (dataSize > (int) ifd->lineBufferSize)	throw Iex::InputExc ("Unexpected data 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 scan line is the next one in    // the file, so that we can avoid redundant seekg()    // operations (seekg() can be fairly expensive).    //    if (ifd->lineOrder == INCREASING_Y)	ifd->nextLineBufferMinY = minY + ifd->linesInBuffer;    else	ifd->nextLineBufferMinY = minY - ifd->linesInBuffer;}//// A LineBufferTask encapsulates the task uncompressing a set of// scanlines (line buffer) and copying them into the frame buffer.//class LineBufferTask : public Task{  public:    LineBufferTask (TaskGroup *group,                    ScanLineInputFile::Data *ifd,		    LineBuffer *lineBuffer,                    int scanLineMin,		    int scanLineMax);    virtual ~LineBufferTask ();    virtual void		execute ();  private:    ScanLineInputFile::Data *	_ifd;    LineBuffer *		_lineBuffer;    int				_scanLineMin;    int				_scanLineMax;};LineBufferTask::LineBufferTask    (TaskGroup *group,     ScanLineInputFile::Data *ifd,     LineBuffer *lineBuffer,     int scanLineMin,     int scanLineMax):    Task (group),    _ifd (ifd),    _lineBuffer (lineBuffer),    _scanLineMin (scanLineMin),    _scanLineMax (scanLineMax){    // empty}LineBufferTask::~LineBufferTask (){    //    // Signal that the line buffer is now free    //    _lineBuffer->post ();}voidLineBufferTask::execute (){    try    {        //        // Uncompress the data, if necessary        //            if (_lineBuffer->uncompressedData == 0)        {            int uncompressedSize = 0;            int maxY = min (_lineBuffer->maxY, _ifd->maxY);                for (int i = _lineBuffer->minY - _ifd->minY;                 i <= maxY - _ifd->minY;		 ++i)	    {                uncompressedSize += (int) _ifd->bytesPerLine[i];	    }                if (_lineBuffer->compressor &&                _lineBuffer->dataSize < uncompressedSize)            {                _lineBuffer->format = _lineBuffer->compressor->format();                _lineBuffer->dataSize = _lineBuffer->compressor->uncompress                    (_lineBuffer->buffer, _lineBuffer->dataSize,		     _lineBuffer->minY, _lineBuffer->uncompressedData);            }            else            {                //                // If the line is uncompressed, it's in XDR format,                // regardless of the compressor's output format.                //                    _lineBuffer->format = Compressor::XDR;                _lineBuffer->uncompressedData = _lineBuffer->buffer;            }        }                int yStart, yStop, dy;        if (_ifd->lineOrder == INCREASING_Y)        {            yStart = _scanLineMin;            yStop = _scanLineMax + 1;            dy = 1;        }        else        {            yStart = _scanLineMax;            yStop = _scanLineMin - 1;            dy = -1;        }            for (int y = yStart; y != yStop; y += dy)        {            //            // Convert one scan line's worth of pixel data back            // from the machine-independent representation, and            // store the result in the frame buffer.

⌨️ 快捷键说明

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