Disabled external gits
This commit is contained in:
553
cs440-acg/ext/openexr/OpenEXR/IlmImf/ImfPxr24Compressor.cpp
Normal file
553
cs440-acg/ext/openexr/OpenEXR/IlmImf/ImfPxr24Compressor.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "ImfCheckedArithmetic.h"
|
||||
#include "ImfNamespace.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;
|
||||
|
||||
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
|
||||
|
||||
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 int
|
||||
floatToFloat24 (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;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
notEnoughData ()
|
||||
{
|
||||
throw IEX_NAMESPACE::InputExc ("Error decompressing data "
|
||||
"(input data are shorter than expected).");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tooMuchData ()
|
||||
{
|
||||
throw IEX_NAMESPACE::InputExc ("Error decompressing data "
|
||||
"(input data are longer than expected).");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Pxr24Compressor::Pxr24Compressor (const Header &hdr,
|
||||
size_t maxScanLineSize,
|
||||
size_t numScanLines)
|
||||
:
|
||||
Compressor (hdr),
|
||||
_maxScanLineSize (maxScanLineSize),
|
||||
_numScanLines (numScanLines),
|
||||
_tmpBuffer (0),
|
||||
_outBuffer (0),
|
||||
_channels (hdr.channels())
|
||||
{
|
||||
size_t maxInBytes =
|
||||
uiMult (maxScanLineSize, numScanLines);
|
||||
|
||||
size_t maxOutBytes =
|
||||
uiAdd (uiAdd (maxInBytes,
|
||||
size_t (ceil (maxInBytes * 0.01))),
|
||||
size_t (100));
|
||||
|
||||
_tmpBuffer = new unsigned char [maxInBytes];
|
||||
_outBuffer = new char [maxOutBytes];
|
||||
|
||||
const Box2i &dataWindow = hdr.dataWindow();
|
||||
|
||||
_minX = dataWindow.min.x;
|
||||
_maxX = dataWindow.max.x;
|
||||
_maxY = dataWindow.max.y;
|
||||
}
|
||||
|
||||
|
||||
Pxr24Compressor::~Pxr24Compressor ()
|
||||
{
|
||||
delete [] _tmpBuffer;
|
||||
delete [] _outBuffer;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Pxr24Compressor::numScanLines () const
|
||||
{
|
||||
return _numScanLines;
|
||||
}
|
||||
|
||||
|
||||
Compressor::Format
|
||||
Pxr24Compressor::format () const
|
||||
{
|
||||
return NATIVE;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Pxr24Compressor::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);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Pxr24Compressor::compressTile (const char *inPtr,
|
||||
int inSize,
|
||||
Box2i range,
|
||||
const char *&outPtr)
|
||||
{
|
||||
return compress (inPtr, inSize, range, outPtr);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Pxr24Compressor::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);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Pxr24Compressor::uncompressTile (const char *inPtr,
|
||||
int inSize,
|
||||
Box2i range,
|
||||
const char *&outPtr)
|
||||
{
|
||||
return uncompress (inPtr, inSize, range, outPtr);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Pxr24Compressor::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 OPENEXR_IMF_INTERNAL_NAMESPACE::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 (size_t 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 OPENEXR_IMF_INTERNAL_NAMESPACE::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 OPENEXR_IMF_INTERNAL_NAMESPACE::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 (size_t 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_NAMESPACE::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_NAMESPACE::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 OPENEXR_IMF_INTERNAL_NAMESPACE::UINT:
|
||||
|
||||
ptr[0] = tmpBufferEnd;
|
||||
ptr[1] = ptr[0] + n;
|
||||
ptr[2] = ptr[1] + n;
|
||||
ptr[3] = ptr[2] + n;
|
||||
tmpBufferEnd = ptr[3] + n;
|
||||
|
||||
if ( (uLongf)(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 (size_t k = 0; k < sizeof (pixel); ++k)
|
||||
*writePtr++ = *pPtr++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF:
|
||||
|
||||
ptr[0] = tmpBufferEnd;
|
||||
ptr[1] = ptr[0] + n;
|
||||
tmpBufferEnd = ptr[1] + n;
|
||||
|
||||
if ( (uLongf)(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 OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT:
|
||||
|
||||
ptr[0] = tmpBufferEnd;
|
||||
ptr[1] = ptr[0] + n;
|
||||
ptr[2] = ptr[1] + n;
|
||||
tmpBufferEnd = ptr[2] + n;
|
||||
|
||||
if ( (uLongf) (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 (size_t k = 0; k < sizeof (pixel); ++k)
|
||||
*writePtr++ = *pPtr++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
assert (false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((uLongf) (tmpBufferEnd - _tmpBuffer) < tmpSize)
|
||||
tooMuchData();
|
||||
|
||||
outPtr = _outBuffer;
|
||||
return writePtr - _outBuffer;
|
||||
}
|
||||
|
||||
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
|
Reference in New Issue
Block a user