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

📄 imfrgbafile.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 RgbaOutputFile//	class RgbaInputFile////-----------------------------------------------------------------------------#include <ImfRgbaFile.h>#include <ImfOutputFile.h>#include <ImfInputFile.h>#include <ImfChannelList.h>#include <ImfRgbaYca.h>#include <ImfStandardAttributes.h>#include <ImathFun.h>#include <IlmThreadMutex.h>#include <Iex.h>#include <string.h>#include <algorithm>namespace Imf {using namespace std;using namespace Imath;using namespace RgbaYca;using namespace IlmThread;namespace {voidinsertChannels (Header &header, RgbaChannels rgbaChannels){    ChannelList ch;    if (rgbaChannels & (WRITE_Y | WRITE_C))    {	if (rgbaChannels & WRITE_Y)	{	    ch.insert ("Y", Channel (HALF, 1, 1));	}	if (rgbaChannels & WRITE_C)	{	    ch.insert ("RY", Channel (HALF, 2, 2, true));	    ch.insert ("BY", Channel (HALF, 2, 2, true));	}    }    else    {	if (rgbaChannels & WRITE_R)	    ch.insert ("R", Channel (HALF, 1, 1));	if (rgbaChannels & WRITE_G)	    ch.insert ("G", Channel (HALF, 1, 1));	if (rgbaChannels & WRITE_B)	    ch.insert ("B", Channel (HALF, 1, 1));    }    if (rgbaChannels & WRITE_A)	ch.insert ("A", Channel (HALF, 1, 1));    header.channels() = ch;}RgbaChannelsrgbaChannels (const ChannelList &ch){    int i = 0;    if (ch.findChannel ("R"))	i |= WRITE_R;    if (ch.findChannel ("G"))	i |= WRITE_G;        if (ch.findChannel ("B"))	i |= WRITE_B;    if (ch.findChannel ("A"))	i |= WRITE_A;    if (ch.findChannel ("Y"))	i |= WRITE_Y;    if (ch.findChannel ("RY") || ch.findChannel ("BY"))	i |= WRITE_C;    return RgbaChannels (i);}V3fywFromHeader (const Header &header){    Chromaticities cr;    if (hasChromaticities (header))	cr = chromaticities (header);    return computeYw (cr);}} // namespaceclass RgbaOutputFile::ToYca: public Mutex{  public:     ToYca (OutputFile &outputFile, RgbaChannels rgbaChannels);    ~ToYca ();    void		setYCRounding (unsigned int roundY,	    			       unsigned int roundC);    void		setFrameBuffer (const Rgba *base,					size_t xStride,					size_t yStride);    void		writePixels (int numScanLines);    int			currentScanLine () const;  private:    void		padTmpBuf ();    void		rotateBuffers ();    void		duplicateLastBuffer ();    void		duplicateSecondToLastBuffer ();    void		decimateChromaVertAndWriteScanLine ();    OutputFile &	_outputFile;    bool		_writeY;    bool		_writeC;    bool		_writeA;    int			_xMin;    int			_width;    int			_height;    int			_linesConverted;    LineOrder		_lineOrder;    int			_currentScanLine;    V3f			_yw;    Rgba *		_buf[N];    Rgba *		_tmpBuf;    const Rgba *	_fbBase;    size_t		_fbXStride;    size_t		_fbYStride;    int			_roundY;    int			_roundC;};RgbaOutputFile::ToYca::ToYca (OutputFile &outputFile,			      RgbaChannels rgbaChannels):    _outputFile (outputFile){    _writeY = (rgbaChannels & WRITE_Y)? true: false;    _writeC = (rgbaChannels & WRITE_C)? true: false;    _writeA = (rgbaChannels & WRITE_A)? true: false;    const Box2i dw = _outputFile.header().dataWindow();    _xMin = dw.min.x;    _width  = dw.max.x - dw.min.x + 1;    _height = dw.max.y - dw.min.y + 1;    _linesConverted = 0;    _lineOrder = _outputFile.header().lineOrder();        if (_lineOrder == INCREASING_Y)	_currentScanLine = dw.min.y;    else	_currentScanLine = dw.max.y;    _yw = ywFromHeader (_outputFile.header());    for (int i = 0; i < N; ++i)	_buf[i] = new Rgba[_width];    _tmpBuf = new Rgba[_width + N - 1];    _fbBase = 0;    _fbXStride = 0;    _fbYStride = 0;    _roundY = 7;    _roundC = 5;}RgbaOutputFile::ToYca::~ToYca (){    for (int i = 0; i < N; ++i)	delete [] _buf[i];    delete [] _tmpBuf;}voidRgbaOutputFile::ToYca::setYCRounding (unsigned int roundY,				      unsigned int roundC){    _roundY = roundY;    _roundC = roundC;}voidRgbaOutputFile::ToYca::setFrameBuffer (const Rgba *base,				       size_t xStride,				       size_t yStride){    if (_fbBase == 0)    {	FrameBuffer fb;	if (_writeY)	{	    fb.insert ("Y",		       Slice (HALF,				// type			      (char *) &_tmpBuf[-_xMin].g,	// base			      sizeof (Rgba),			// xStride			      0,				// yStride			      1,				// xSampling			      1));				// ySampling	}	if (_writeC)	{	    fb.insert ("RY",		       Slice (HALF,				// type			      (char *) &_tmpBuf[-_xMin].r,	// base			      sizeof (Rgba) * 2,		// xStride			      0,				// yStride			      2,				// xSampling			      2));				// ySampling	    fb.insert ("BY",		       Slice (HALF,				// type			      (char *) &_tmpBuf[-_xMin].b,	// base			      sizeof (Rgba) * 2,		// xStride			      0,				// yStride			      2,				// xSampling			      2));				// ySampling	}	if (_writeA)	{	    fb.insert ("A",		       Slice (HALF,				// type			      (char *) &_tmpBuf[-_xMin].a,	// base			      sizeof (Rgba),			// xStride			      0,				// yStride			      1,				// xSampling			      1));				// ySampling	}	_outputFile.setFrameBuffer (fb);    }    _fbBase = base;    _fbXStride = xStride;    _fbYStride = yStride;}voidRgbaOutputFile::ToYca::writePixels (int numScanLines){    if (_fbBase == 0)    {	THROW (Iex::ArgExc, "No frame buffer was specified as the "			    "pixel data source for image file "			    "\"" << _outputFile.fileName() << "\".");    }    if (_writeY && !_writeC)    {	//	// We are writing only luminance; filtering	// and subsampling are not necessary.	//	for (int i = 0; i < numScanLines; ++i)	{	    //	    // Copy the next scan line from the caller's	    // frame buffer into _tmpBuf.	    //	    for (int j = 0; j < _width; ++j)	    {		_tmpBuf[j] = _fbBase[_fbYStride * _currentScanLine +				     _fbXStride * (j + _xMin)];	    }	    //	    // Convert the scan line from RGB to luminance/chroma,	    // and store the result in the output file.	    //	    RGBAtoYCA (_yw, _width, _writeA, _tmpBuf, _tmpBuf);	    _outputFile.writePixels (1);	    ++_linesConverted;	    if (_lineOrder == INCREASING_Y)		++_currentScanLine;	    else		--_currentScanLine;	}    }    else    {	//	// We are writing chroma; the pixels must be filtered and subsampled.	//	for (int i = 0; i < numScanLines; ++i)	{	    //	    // Copy the next scan line from the caller's	    // frame buffer into _tmpBuf.	    //	    for (int j = 0; j < _width; ++j)	    {		_tmpBuf[j + N2] = _fbBase[_fbYStride * _currentScanLine +					  _fbXStride * (j + _xMin)];	    }	    //	    // Convert the scan line from RGB to luminance/chroma.	    //	    RGBAtoYCA (_yw, _width, _writeA, _tmpBuf + N2, _tmpBuf + N2);	    //	    // Append N2 copies of the first and last pixel to the	    // beginning and end of the scan line.	    //	    padTmpBuf ();	    //	    // Filter and subsample the scan line's chroma channels	    // horizontally; store the result in _buf.	    //	    rotateBuffers();	    decimateChromaHoriz (_width, _tmpBuf, _buf[N - 1]);	    //	    // If this is the first scan line in the image,	    // store N2 more copies of the scan line in _buf.	    //	    if (_linesConverted == 0)	    {		for (int j = 0; j < N2; ++j)		    duplicateLastBuffer();	    }	    ++_linesConverted;	    //	    // If we have have converted at least N2 scan lines from	    // RGBA to luminance/chroma, then we can start to filter	    // and subsample vertically, and store pixels in the	    // output file.	    //	    if (_linesConverted > N2)		decimateChromaVertAndWriteScanLine();	    //	    // If we have already converted the last scan line in	    // the image to luminance/chroma, filter, subsample and	    // store the remaining scan lines in _buf.	    //	    if (_linesConverted >= _height)	    {		for (int j = 0; j < N2 - _height; ++j)		    duplicateLastBuffer();		duplicateSecondToLastBuffer();		++_linesConverted;		decimateChromaVertAndWriteScanLine();		for (int j = 1; j < min (_height, N2); ++j)		{		    duplicateLastBuffer();		    ++_linesConverted;		    decimateChromaVertAndWriteScanLine();		}	    }	    if (_lineOrder == INCREASING_Y)		++_currentScanLine;	    else		--_currentScanLine;	}    }}intRgbaOutputFile::ToYca::currentScanLine () const{    return _currentScanLine;}voidRgbaOutputFile::ToYca::padTmpBuf (){    for (int i = 0; i < N2; ++i)    {	_tmpBuf[i] = _tmpBuf[N2];	_tmpBuf[_width + N2 + i] = _tmpBuf[_width + N2 - 2];    }}voidRgbaOutputFile::ToYca::rotateBuffers (){    Rgba *tmp = _buf[0];    for (int i = 0; i < N - 1; ++i)	_buf[i] = _buf[i + 1];    _buf[N - 1] = tmp;}voidRgbaOutputFile::ToYca::duplicateLastBuffer (){    rotateBuffers();    memcpy (_buf[N - 1], _buf[N - 2], _width * sizeof (Rgba));}voidRgbaOutputFile::ToYca::duplicateSecondToLastBuffer (){    rotateBuffers();    memcpy (_buf[N - 1], _buf[N - 3], _width * sizeof (Rgba));}voidRgbaOutputFile::ToYca::decimateChromaVertAndWriteScanLine (){    if (_linesConverted & 1)	memcpy (_tmpBuf, _buf[N2], _width * sizeof (Rgba));    else	decimateChromaVert (_width, _buf, _tmpBuf);    if (_writeY && _writeC)	roundYCA (_width, _roundY, _roundC, _tmpBuf, _tmpBuf);    _outputFile.writePixels (1);}RgbaOutputFile::RgbaOutputFile (const char name[],				const Header &header,				RgbaChannels rgbaChannels,                                int numThreads):    _outputFile (0),    _toYca (0){    Header hd (header);    insertChannels (hd, rgbaChannels);    _outputFile = new OutputFile (name, hd, numThreads);    if (rgbaChannels & (WRITE_Y | WRITE_C))	_toYca = new ToYca (*_outputFile, rgbaChannels);}RgbaOutputFile::RgbaOutputFile (OStream &os,				const Header &header,				RgbaChannels rgbaChannels,                                int numThreads):    _outputFile (0),    _toYca (0){    Header hd (header);    insertChannels (hd, rgbaChannels);    _outputFile = new OutputFile (os, hd, numThreads);    if (rgbaChannels & (WRITE_Y | WRITE_C))	_toYca = new ToYca (*_outputFile, rgbaChannels);}RgbaOutputFile::RgbaOutputFile (const char name[],				const Imath::Box2i &displayWindow,				const Imath::Box2i &dataWindow,				RgbaChannels rgbaChannels,				float pixelAspectRatio,				const Imath::V2f screenWindowCenter,				float screenWindowWidth,				LineOrder lineOrder,				Compression compression,                                int numThreads):    _outputFile (0),    _toYca (0){    Header hd (displayWindow,	       dataWindow.isEmpty()? displayWindow: dataWindow,	       pixelAspectRatio,	       screenWindowCenter,	       screenWindowWidth,	       lineOrder,	       compression);    insertChannels (hd, rgbaChannels);    _outputFile = new OutputFile (name, hd, numThreads);    if (rgbaChannels & (WRITE_Y | WRITE_C))	_toYca = new ToYca (*_outputFile, rgbaChannels);}RgbaOutputFile::RgbaOutputFile (const char name[],				int width,				int height,				RgbaChannels rgbaChannels,				float pixelAspectRatio,				const Imath::V2f screenWindowCenter,				float screenWindowWidth,				LineOrder lineOrder,				Compression compression,                                int numThreads):    _outputFile (0),    _toYca (0){    Header hd (width,	       height,	       pixelAspectRatio,	       screenWindowCenter,	       screenWindowWidth,	       lineOrder,	       compression);    insertChannels (hd, rgbaChannels);    _outputFile = new OutputFile (name, hd, numThreads);    if (rgbaChannels & (WRITE_Y | WRITE_C))	_toYca = new ToYca (*_outputFile, rgbaChannels);}RgbaOutputFile::~RgbaOutputFile (){    delete _toYca;    delete _outputFile;}voidRgbaOutputFile::setFrameBuffer (const Rgba *base,				size_t xStride,				size_t yStride){    if (_toYca)    {	Lock lock (*_toYca);	_toYca->setFrameBuffer (base, xStride, yStride);    }    else    {	size_t xs = xStride * sizeof (Rgba);	size_t ys = yStride * sizeof (Rgba);	FrameBuffer fb;	fb.insert ("R", Slice (HALF, (char *) &base[0].r, xs, ys));	fb.insert ("G", Slice (HALF, (char *) &base[0].g, xs, ys));	fb.insert ("B", Slice (HALF, (char *) &base[0].b, xs, ys));	fb.insert ("A", Slice (HALF, (char *) &base[0].a, xs, ys));	_outputFile->setFrameBuffer (fb);    }}void	RgbaOutputFile::writePixels (int numScanLines){    if (_toYca)    {	Lock lock (*_toYca);	_toYca->writePixels (numScanLines);    }    else    {	_outputFile->writePixels (numScanLines);    }}int	RgbaOutputFile::currentScanLine () const{    if (_toYca)    {

⌨️ 快捷键说明

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