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

📄 imfoutputfile.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 OutputFile////-----------------------------------------------------------------------------#include <ImfOutputFile.h>#include <ImfInputFile.h>#include <ImfChannelList.h>#include <ImfMisc.h>#include <ImfStdIO.h>#include <ImfCompressor.h>#include "ImathBox.h"#include "ImathFun.h"#include <ImfArray.h>#include <ImfXdr.h>#include <ImfPreviewImageAttribute.h>#include "IlmThreadPool.h"#include "IlmThreadSemaphore.h"#include "IlmThreadMutex.h"#include "Iex.h"#include <string>#include <vector>#include <fstream>#include <assert.h>namespace Imf {using Imath::Box2i;using Imath::divp;using Imath::modp;using std::string;using std::vector;using std::ofstream;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 OutSliceInfo{    PixelType		type;    const char *	base;    size_t		xStride;    size_t		yStride;    int			xSampling;    int			ySampling;    bool		zero;    OutSliceInfo (PixelType type = HALF,	          const char *base = 0,	          size_t xStride = 0,	          size_t yStride = 0,	          int xSampling = 1,	          int ySampling = 1,	          bool zero = false);};OutSliceInfo::OutSliceInfo (PixelType t,		            const char *b,		            size_t xs, size_t ys,		            int xsm, int ysm,		            bool z):    type (t),    base (b),    xStride (xs),    yStride (ys),    xSampling (xsm),    ySampling (ysm),    zero (z){    // empty}struct LineBuffer{    Array<char>		buffer;    const char *	dataPtr;    int			dataSize;    char *		endOfLineBufferData;    int			minY;    int			maxY;    int			scanLineMin;    int			scanLineMax;    Compressor *	compressor;    bool		partiallyFull;        // has incomplete data    bool		hasException;    string		exception;    LineBuffer (Compressor *comp);    ~LineBuffer ();    void		wait () {_sem.wait();}    void		post () {_sem.post();}  private:    Semaphore		_sem;};LineBuffer::LineBuffer (Compressor *comp) :    dataPtr (0),    dataSize (0),    compressor (comp),    partiallyFull (false),    hasException (false),    exception (),    _sem (1){    // empty}LineBuffer::~LineBuffer (){    delete compressor;}} // namespacestruct OutputFile::Data: public Mutex{    Header		 header;		// the image header    int			 version;		// file format version    Int64		 previewPosition;       // file position for preview    FrameBuffer		 frameBuffer;           // framebuffer to write into    int			 currentScanLine;       // next scanline to be written    int			 missingScanLines;      // number of lines to write    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    vector<Int64>	 lineOffsets;		// stores offsets in file for						// each scanline    vector<size_t>	 bytesPerLine;          // combined size of a line over                                                // all channels    vector<size_t>	 offsetInLineBuffer;    // offset for each scanline in                                                // its linebuffer    Compressor::Format	 format;                // compressor's data format    vector<OutSliceInfo> slices;		// info about channels in file    OStream *		 os;			// file stream to write to    bool		 deleteStream;    Int64		 lineOffsetsPosition;   // file position for line                                                // offset table    Int64		 currentPosition;       // current file position    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 (bool deleteStream, int numThreads);    ~Data ();    inline LineBuffer *	getLineBuffer (int number); // hash function from line    						    // buffer indices into our						    // vector of line buffers};OutputFile::Data::Data (bool deleteStream, int numThreads):    os (0),    deleteStream (deleteStream),    lineOffsetsPosition (0){    //    // 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));}OutputFile::Data::~Data (){    if (deleteStream)	delete os;    for (size_t i = 0; i < lineBuffers.size(); i++)        delete lineBuffers[i];}LineBuffer*OutputFile::Data::getLineBuffer (int number){    return lineBuffers[number % lineBuffers.size()];}namespace {Int64writeLineOffsets (OStream &os, const vector<Int64> &lineOffsets){    Int64 pos = os.tellp();    if (pos == -1)	Iex::throwErrnoExc ("Cannot determine current file position (%T).");    for (unsigned int i = 0; i < lineOffsets.size(); i++)	Xdr::write <StreamIO> (os, lineOffsets[i]);    return pos;}voidwritePixelData (OutputFile::Data *ofd,                int lineBufferMinY,		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->lineOffsets[(ofd->currentScanLine - ofd->minY) / ofd->linesInBuffer] =	currentPosition;    #ifdef DEBUG	assert (ofd->os->tellp() == currentPosition);    #endif    Xdr::write <StreamIO> (*ofd->os, lineBufferMinY);    Xdr::write <StreamIO> (*ofd->os, pixelDataSize);    ofd->os->write (pixelData, pixelDataSize);    ofd->currentPosition = currentPosition +			   Xdr::size<int>() +			   Xdr::size<int>() +			   pixelDataSize;}inline voidwritePixelData (OutputFile::Data *ofd, const LineBuffer *lineBuffer){    writePixelData (ofd,		    lineBuffer->minY,                    lineBuffer->dataPtr,		    lineBuffer->dataSize);}voidconvertToXdr (OutputFile::Data *ofd,              Array<char> &lineBuffer,              int lineBufferMinY,              int lineBufferMaxY,              int inSize){    //    // Convert the contents of a lineBuffer from the machine's native    // representation to Xdr format.  This function is called by    // CompressLineBuffer::execute(), 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.    //       int startY, endY;		// The first and last scanlines in    				// the file that are in the lineBuffer.    int step;        if (ofd->lineOrder == INCREASING_Y)    {	startY = max (lineBufferMinY, ofd->minY);	endY = min (lineBufferMaxY, ofd->maxY) + 1;        step = 1;    }    else    {	startY = min (lineBufferMaxY, ofd->maxY);	endY = max (lineBufferMinY, ofd->minY) - 1;        step = -1;    }    //    // Iterate over all scanlines in the lineBuffer to convert.    //    for (int y = startY; y != endY; y += step)    {	//        // Set these to point to the start of line y.        // We will write to writePtr from readPtr.	//	        char *writePtr = lineBuffer + ofd->offsetInLineBuffer[y - ofd->minY];        const char *readPtr = writePtr;        	//        // Iterate over all slices in the file.	//	        for (unsigned int i = 0; i < ofd->slices.size(); ++i)        {            //            // Test if scan line y of this channel is            // contains any data (the scan line contains            // data only if y % ySampling == 0).            //            const OutSliceInfo &slice = ofd->slices[i];            if (modp (y, slice.ySampling) != 0)                continue;            //            // Find the number of sampled pixels, dMaxX-dMinX+1, for	    // slice i in scan line y (i.e. pixels within the data window            // for which x % xSampling == 0).            //            int dMinX = divp (ofd->minX, slice.xSampling);            int dMaxX = divp (ofd->maxX, slice.xSampling);            	    //            // Convert the samples in place.	    //                        convertInPlace (writePtr, readPtr, slice.type, dMaxX - dMinX + 1);        }    }}//// A LineBufferTask encapsulates the task of copying a set of scanlines// from the user's frame buffer into a LineBuffer object, compressing// the data if necessary.//class LineBufferTask: public Task{  public:    LineBufferTask (TaskGroup *group,                    OutputFile::Data *ofd,		    int number,                    int scanLineMin,		    int scanLineMax);    virtual ~LineBufferTask ();     virtual void	execute ();  private:    OutputFile::Data *	_ofd;    LineBuffer *	_lineBuffer;};LineBufferTask::LineBufferTask    (TaskGroup *group,     OutputFile::Data *ofd,     int number,     int scanLineMin,     int scanLineMax):    Task (group),

⌨️ 快捷键说明

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