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

📄 imfpxr24compressor.cpp

📁 image converter source code
💻 CPP
字号:
///////////////////////////////////////////////////////////////////////////////// Copyright (c) 2004, Pixar Animation Studios//// 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 Pixar Animation Studios 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 Pxr24Compressor////	This compressor is based on source code that was contributed to//	OpenEXR by Pixar Animation Studios.  The compression method was//	developed by Loren Carpenter.////	The compressor preprocesses the pixel data to reduce entropy,//	and then calls zlib.////	Compression of HALF and UINT channels is lossless, but compressing//	FLOAT channels is lossy: 32-bit floating-point numbers are converted//	to 24 bits by rounding the significand to 15 bits.////	When the compressor is invoked, the caller has already arranged//	the pixel data so that the values for each channel appear in a//	contiguous block of memory.  The compressor converts the pixel//	values to unsigned integers: For UINT, this is a no-op.  HALF//	values are simply re-interpreted as 16-bit integers.  FLOAT//	values are converted to 24 bits, and the resulting bit patterns//	are interpreted as integers.  The compressor then replaces each//	value with the difference between the value and its left neighbor.//	This turns flat fields in the image into zeroes, and ramps into//	strings of similar values.  Next, each difference is split into//	2, 3 or 4 bytes, and the bytes are transposed so that all the//	most significant bytes end up in a contiguous block, followed//	by the second most significant bytes, and so on.  The resulting//	string of bytes is compressed with zlib.////-----------------------------------------------------------------------------#include <ImfPxr24Compressor.h>#include <ImfHeader.h>#include <ImfChannelList.h>#include <ImfMisc.h>#include <ImathFun.h>#include <Iex.h>#include <half.h>#include <zlib.h>#include <assert.h>#include <algorithm>using namespace std;using namespace Imath;namespace Imf {namespace {//// Conversion from 32-bit to 24-bit floating-point numbers.// Conversion back to 32 bits is simply an 8-bit shift to the left.//inline unsigned intfloatToFloat24 (float f){    union    {	float		f;	unsigned int	i;    } u;    u.f = f;    //    // Disassemble the 32-bit floating point number, f,    // into sign, s, exponent, e, and significand, m.    //    unsigned int s = u.i & 0x80000000;    unsigned int e = u.i & 0x7f800000;    unsigned int m = u.i & 0x007fffff;    unsigned int i;    if (e == 0x7f800000)    {	if (m)	{	    //	    // F is a NAN; we preserve the sign bit and	    // the 15 leftmost bits of the significand,	    // with one exception: If the 15 leftmost	    // bits are all zero, the NAN would turn	    // into an infinity, so we have to set at	    // least one bit in the significand.	    //	    m >>= 8;	    i = (e >> 8) | m | (m == 0);	}	else	{	    //	    // F is an infinity.	    //	    i = e >> 8;	}    }    else    {	//	// F is finite, round the significand to 15 bits.	//	i = ((e | m) + (m & 0x00000080)) >> 8;	if (i >= 0x7f8000)	{	    //	    // F was close to FLT_MAX, and the significand was	    // rounded up, resulting in an exponent overflow.	    // Avoid the overflow by truncating the significand	    // instead of rounding it.	    //	    i = (e | m) >> 8;	}    }    return (s >> 8) | i;}voidnotEnoughData (){    throw Iex::InputExc ("Error decompressing data "			 "(input data are shorter than expected).");}voidtooMuchData (){    throw Iex::InputExc ("Error decompressing data "			 "(input data are longer than expected).");}} // namespacePxr24Compressor::Pxr24Compressor (const Header &hdr,				  int maxScanLineSize,				  int numScanLines):    Compressor (hdr),    _maxScanLineSize (maxScanLineSize),    _numScanLines (numScanLines),    _tmpBuffer (0),    _outBuffer (0),    _channels (hdr.channels()){    int maxInBytes = maxScanLineSize * numScanLines;    _tmpBuffer = new unsigned char [maxInBytes];    _outBuffer = new char [int (ceil (maxInBytes * 1.01)) + 100];    const Box2i &dataWindow = hdr.dataWindow();    _minX = dataWindow.min.x;    _maxX = dataWindow.max.x;    _maxY = dataWindow.max.y;}Pxr24Compressor::~Pxr24Compressor (){    delete [] _tmpBuffer;    delete [] _outBuffer;}intPxr24Compressor::numScanLines () const{    return _numScanLines;}Compressor::FormatPxr24Compressor::format () const{    return NATIVE;}intPxr24Compressor::compress (const char *inPtr,			   int inSize,			   int minY,			   const char *&outPtr){    return compress (inPtr,	             inSize,		     Box2i (V2i (_minX, minY),			    V2i (_maxX, minY + _numScanLines - 1)),		     outPtr);}	      intPxr24Compressor::compressTile (const char *inPtr,			       int inSize,			       Box2i range,			       const char *&outPtr){    return compress (inPtr, inSize, range, outPtr);}intPxr24Compressor::uncompress (const char *inPtr,			     int inSize,			     int minY,			     const char *&outPtr){    return uncompress (inPtr,	               inSize,		       Box2i (V2i (_minX, minY),			      V2i (_maxX, minY + _numScanLines - 1)),		       outPtr);}		intPxr24Compressor::uncompressTile (const char *inPtr,				 int inSize,				 Box2i range,				 const char *&outPtr){    return uncompress (inPtr, inSize, range, outPtr);}intPxr24Compressor::compress (const char *inPtr,			   int inSize,			   Box2i range,			   const char *&outPtr){    if (inSize == 0)    {	outPtr = _outBuffer;	return 0;    }    int minX = range.min.x;    int maxX = min (range.max.x, _maxX);    int minY = range.min.y;    int maxY = min (range.max.y, _maxY);    unsigned char *tmpBufferEnd = _tmpBuffer;    for (int y = minY; y <= maxY; ++y)    {	for (ChannelList::ConstIterator i = _channels.begin();	     i != _channels.end();	     ++i)	{	    const Channel &c = i.channel();	    if (modp (y, c.ySampling) != 0)		continue;	    int n = numSamples (c.xSampling, minX, maxX);	    unsigned char *ptr[4];	    unsigned int previousPixel = 0;	    switch (c.type)	    {	      case UINT:		ptr[0] = tmpBufferEnd;		ptr[1] = ptr[0] + n;		ptr[2] = ptr[1] + n;		ptr[3] = ptr[2] + n;		tmpBufferEnd = ptr[3] + n;		for (int j = 0; j < n; ++j)		{		    unsigned int pixel;		    char *pPtr = (char *) &pixel;		    for (int k = 0; k < sizeof (pixel); ++k)			*pPtr++ = *inPtr++;		    unsigned int diff = pixel - previousPixel;		    previousPixel = pixel;		    *(ptr[0]++) = diff >> 24;		    *(ptr[1]++) = diff >> 16;		    *(ptr[2]++) = diff >> 8;		    *(ptr[3]++) = diff;		}		break;	      case HALF:		ptr[0] = tmpBufferEnd;		ptr[1] = ptr[0] + n;		tmpBufferEnd = ptr[1] + n;		for (int j = 0; j < n; ++j)		{		    half pixel;		    pixel = *(const half *) inPtr;		    inPtr += sizeof (half);		    unsigned int diff = pixel.bits() - previousPixel;		    previousPixel = pixel.bits();		    *(ptr[0]++) = diff >> 8;		    *(ptr[1]++) = diff;		}		break;	      case FLOAT:		ptr[0] = tmpBufferEnd;		ptr[1] = ptr[0] + n;		ptr[2] = ptr[1] + n;		tmpBufferEnd = ptr[2] + n;		for (int j = 0; j < n; ++j)		{		    float pixel;		    char *pPtr = (char *) &pixel;		    for (int k = 0; k < sizeof (pixel); ++k)			*pPtr++ = *inPtr++;		    unsigned int pixel24 = floatToFloat24 (pixel);		    unsigned int diff = pixel24 - previousPixel;		    previousPixel = pixel24;		    *(ptr[0]++) = diff >> 16;		    *(ptr[1]++) = diff >> 8;		    *(ptr[2]++) = diff;		}		break;	      default:		assert (false);	    }	}    }    uLongf outSize = int (ceil ((tmpBufferEnd - _tmpBuffer) * 1.01)) + 100;    if (Z_OK != ::compress ((Bytef *) _outBuffer,			    &outSize,			    (const Bytef *) _tmpBuffer,			    tmpBufferEnd - _tmpBuffer))    {	throw Iex::BaseExc ("Data compression (zlib) failed.");    }    outPtr = _outBuffer;    return outSize;} int		Pxr24Compressor::uncompress (const char *inPtr,			     int inSize,			     Box2i range,			     const char *&outPtr){    if (inSize == 0)    {	outPtr = _outBuffer;	return 0;    }    uLongf tmpSize = _maxScanLineSize * _numScanLines;    if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer,			      &tmpSize,			      (const Bytef *) inPtr,			      inSize))    {	throw Iex::InputExc ("Data decompression (zlib) failed.");    }    int minX = range.min.x;    int maxX = min (range.max.x, _maxX);    int minY = range.min.y;    int maxY = min (range.max.y, _maxY);    const unsigned char *tmpBufferEnd = _tmpBuffer;    char *writePtr = _outBuffer;    for (int y = minY; y <= maxY; ++y)    {	for (ChannelList::ConstIterator i = _channels.begin();	     i != _channels.end();	     ++i)	{	    const Channel &c = i.channel();	    if (modp (y, c.ySampling) != 0)		continue;	    int n = numSamples (c.xSampling, minX, maxX);	    const unsigned char *ptr[4];	    unsigned int pixel = 0;	    switch (c.type)	    {	      case UINT:		ptr[0] = tmpBufferEnd;		ptr[1] = ptr[0] + n;		ptr[2] = ptr[1] + n;		ptr[3] = ptr[2] + n;		tmpBufferEnd = ptr[3] + n;		if (tmpBufferEnd - _tmpBuffer > tmpSize)		    notEnoughData();		for (int j = 0; j < n; ++j)		{		    unsigned int diff = (*(ptr[0]++) << 24) |					(*(ptr[1]++) << 16) |					(*(ptr[2]++) <<  8) |					 *(ptr[3]++);		    pixel += diff;		    char *pPtr = (char *) &pixel;		    for (int k = 0; k < sizeof (pixel); ++k)			*writePtr++ = *pPtr++;		}		break;	      case HALF:		ptr[0] = tmpBufferEnd;		ptr[1] = ptr[0] + n;		tmpBufferEnd = ptr[1] + n;		if (tmpBufferEnd - _tmpBuffer > tmpSize)		    notEnoughData();		for (int j = 0; j < n; ++j)		{		    unsigned int diff = (*(ptr[0]++) << 8) |					 *(ptr[1]++);		    pixel += diff;		    half * hPtr = (half *) writePtr;		    hPtr->setBits ((unsigned short) pixel);		    writePtr += sizeof (half);		}		break;	      case FLOAT:		ptr[0] = tmpBufferEnd;		ptr[1] = ptr[0] + n;		ptr[2] = ptr[1] + n;		tmpBufferEnd = ptr[2] + n;		if (tmpBufferEnd - _tmpBuffer > tmpSize)		    notEnoughData();		for (int j = 0; j < n; ++j)		{		    unsigned int diff = (*(ptr[0]++) << 24) |					(*(ptr[1]++) << 16) |					(*(ptr[2]++) <<  8);		    pixel += diff;		    char *pPtr = (char *) &pixel;		    for (int k = 0; k < sizeof (pixel); ++k)			*writePtr++ = *pPtr++;		}		break;	      default:		assert (false);	    }	}    }    if (tmpBufferEnd - _tmpBuffer < tmpSize)	tooMuchData();    outPtr = _outBuffer;    return writePtr - _outBuffer;}} // namespace Imf

⌨️ 快捷键说明

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