1
/////////////////////////////////////////////////////////////////////////////
3
// Copyright (c) 2004, Pixar Animation Studios
5
// All rights reserved.
7
// Redistribution and use in source and binary forms, with or without
8
// modification, are permitted provided that the following conditions are
10
// * Redistributions of source code must retain the above copyright
11
// notice, this list of conditions and the following disclaimer.
12
// * Redistributions in binary form must reproduce the above
13
// copyright notice, this list of conditions and the following disclaimer
14
// in the documentation and/or other materials provided with the
16
// * Neither the name of Pixar Animation Studios nor the names of
17
// its contributors may be used to endorse or promote products derived
18
// from this software without specific prior written permission.
20
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
/////////////////////////////////////////////////////////////////////////////
34
//-----------------------------------------------------------------------------
36
// class Pxr24Compressor
38
// This compressor is based on source code that was contributed to
39
// OpenEXR by Pixar Animation Studios. The compression method was
40
// developed by Loren Carpenter.
42
// The compressor preprocesses the pixel data to reduce entropy,
43
// and then calls zlib.
45
// Compression of HALF and UINT channels is lossless, but compressing
46
// FLOAT channels is lossy: 32-bit floating-point numbers are converted
47
// to 24 bits by rounding the significand to 15 bits.
49
// When the compressor is invoked, the caller has already arranged
50
// the pixel data so that the values for each channel appear in a
51
// contiguous block of memory. The compressor converts the pixel
52
// values to unsigned integers: For UINT, this is a no-op. HALF
53
// values are simply re-interpreted as 16-bit integers. FLOAT
54
// values are converted to 24 bits, and the resulting bit patterns
55
// are interpreted as integers. The compressor then replaces each
56
// value with the difference between the value and its left neighbor.
57
// This turns flat fields in the image into zeroes, and ramps into
58
// strings of similar values. Next, each difference is split into
59
// 2, 3 or 4 bytes, and the bytes are transposed so that all the
60
// most significant bytes end up in a contiguous block, followed
61
// by the second most significant bytes, and so on. The resulting
62
// string of bytes is compressed with zlib.
64
//-----------------------------------------------------------------------------
67
#include <ImfPxr24Compressor.h>
68
#include <ImfHeader.h>
69
#include <ImfChannelList.h>
71
#include <ImfCheckedArithmetic.h>
80
using namespace Imath;
86
// Conversion from 32-bit to 24-bit floating-point numbers.
87
// Conversion back to 32 bits is simply an 8-bit shift to the left.
91
floatToFloat24 (float f)
102
// Disassemble the 32-bit floating point number, f,
103
// into sign, s, exponent, e, and significand, m.
106
unsigned int s = u.i & 0x80000000;
107
unsigned int e = u.i & 0x7f800000;
108
unsigned int m = u.i & 0x007fffff;
116
// F is a NAN; we preserve the sign bit and
117
// the 15 leftmost bits of the significand,
118
// with one exception: If the 15 leftmost
119
// bits are all zero, the NAN would turn
120
// into an infinity, so we have to set at
121
// least one bit in the significand.
125
i = (e >> 8) | m | (m == 0);
139
// F is finite, round the significand to 15 bits.
142
i = ((e | m) + (m & 0x00000080)) >> 8;
147
// F was close to FLT_MAX, and the significand was
148
// rounded up, resulting in an exponent overflow.
149
// Avoid the overflow by truncating the significand
150
// instead of rounding it.
164
throw Iex::InputExc ("Error decompressing data "
165
"(input data are shorter than expected).");
172
throw Iex::InputExc ("Error decompressing data "
173
"(input data are longer than expected).");
179
Pxr24Compressor::Pxr24Compressor (const Header &hdr,
180
size_t maxScanLineSize,
184
_maxScanLineSize (maxScanLineSize),
185
_numScanLines (numScanLines),
188
_channels (hdr.channels())
191
uiMult (maxScanLineSize, numScanLines);
194
uiAdd (uiAdd (maxInBytes,
195
size_t (ceil (maxInBytes * 0.01))),
198
_tmpBuffer = new unsigned char [maxInBytes];
199
_outBuffer = new char [maxOutBytes];
201
const Box2i &dataWindow = hdr.dataWindow();
203
_minX = dataWindow.min.x;
204
_maxX = dataWindow.max.x;
205
_maxY = dataWindow.max.y;
209
Pxr24Compressor::~Pxr24Compressor ()
211
delete [] _tmpBuffer;
212
delete [] _outBuffer;
217
Pxr24Compressor::numScanLines () const
219
return _numScanLines;
224
Pxr24Compressor::format () const
231
Pxr24Compressor::compress (const char *inPtr,
236
return compress (inPtr,
238
Box2i (V2i (_minX, minY),
239
V2i (_maxX, minY + _numScanLines - 1)),
245
Pxr24Compressor::compressTile (const char *inPtr,
250
return compress (inPtr, inSize, range, outPtr);
255
Pxr24Compressor::uncompress (const char *inPtr,
260
return uncompress (inPtr,
262
Box2i (V2i (_minX, minY),
263
V2i (_maxX, minY + _numScanLines - 1)),
269
Pxr24Compressor::uncompressTile (const char *inPtr,
274
return uncompress (inPtr, inSize, range, outPtr);
279
Pxr24Compressor::compress (const char *inPtr,
290
int minX = range.min.x;
291
int maxX = min (range.max.x, _maxX);
292
int minY = range.min.y;
293
int maxY = min (range.max.y, _maxY);
295
unsigned char *tmpBufferEnd = _tmpBuffer;
297
for (int y = minY; y <= maxY; ++y)
299
for (ChannelList::ConstIterator i = _channels.begin();
300
i != _channels.end();
303
const Channel &c = i.channel();
305
if (modp (y, c.ySampling) != 0)
308
int n = numSamples (c.xSampling, minX, maxX);
310
unsigned char *ptr[4];
311
unsigned int previousPixel = 0;
317
ptr[0] = tmpBufferEnd;
321
tmpBufferEnd = ptr[3] + n;
323
for (int j = 0; j < n; ++j)
326
char *pPtr = (char *) &pixel;
328
for (int k = 0; k < sizeof (pixel); ++k)
331
unsigned int diff = pixel - previousPixel;
332
previousPixel = pixel;
334
*(ptr[0]++) = diff >> 24;
335
*(ptr[1]++) = diff >> 16;
336
*(ptr[2]++) = diff >> 8;
344
ptr[0] = tmpBufferEnd;
346
tmpBufferEnd = ptr[1] + n;
348
for (int j = 0; j < n; ++j)
352
pixel = *(const half *) inPtr;
353
inPtr += sizeof (half);
355
unsigned int diff = pixel.bits() - previousPixel;
356
previousPixel = pixel.bits();
358
*(ptr[0]++) = diff >> 8;
366
ptr[0] = tmpBufferEnd;
369
tmpBufferEnd = ptr[2] + n;
371
for (int j = 0; j < n; ++j)
374
char *pPtr = (char *) &pixel;
376
for (int k = 0; k < sizeof (pixel); ++k)
379
unsigned int pixel24 = floatToFloat24 (pixel);
380
unsigned int diff = pixel24 - previousPixel;
381
previousPixel = pixel24;
383
*(ptr[0]++) = diff >> 16;
384
*(ptr[1]++) = diff >> 8;
397
uLongf outSize = int (ceil ((tmpBufferEnd - _tmpBuffer) * 1.01)) + 100;
399
if (Z_OK != ::compress ((Bytef *) _outBuffer,
401
(const Bytef *) _tmpBuffer,
402
tmpBufferEnd - _tmpBuffer))
404
throw Iex::BaseExc ("Data compression (zlib) failed.");
413
Pxr24Compressor::uncompress (const char *inPtr,
424
uLongf tmpSize = _maxScanLineSize * _numScanLines;
426
if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer,
428
(const Bytef *) inPtr,
431
throw Iex::InputExc ("Data decompression (zlib) failed.");
434
int minX = range.min.x;
435
int maxX = min (range.max.x, _maxX);
436
int minY = range.min.y;
437
int maxY = min (range.max.y, _maxY);
439
const unsigned char *tmpBufferEnd = _tmpBuffer;
440
char *writePtr = _outBuffer;
442
for (int y = minY; y <= maxY; ++y)
444
for (ChannelList::ConstIterator i = _channels.begin();
445
i != _channels.end();
448
const Channel &c = i.channel();
450
if (modp (y, c.ySampling) != 0)
453
int n = numSamples (c.xSampling, minX, maxX);
455
const unsigned char *ptr[4];
456
unsigned int pixel = 0;
462
ptr[0] = tmpBufferEnd;
466
tmpBufferEnd = ptr[3] + n;
468
if (tmpBufferEnd - _tmpBuffer > tmpSize)
471
for (int j = 0; j < n; ++j)
473
unsigned int diff = (*(ptr[0]++) << 24) |
474
(*(ptr[1]++) << 16) |
480
char *pPtr = (char *) &pixel;
482
for (int k = 0; k < sizeof (pixel); ++k)
483
*writePtr++ = *pPtr++;
490
ptr[0] = tmpBufferEnd;
492
tmpBufferEnd = ptr[1] + n;
494
if (tmpBufferEnd - _tmpBuffer > tmpSize)
497
for (int j = 0; j < n; ++j)
499
unsigned int diff = (*(ptr[0]++) << 8) |
504
half * hPtr = (half *) writePtr;
505
hPtr->setBits ((unsigned short) pixel);
506
writePtr += sizeof (half);
513
ptr[0] = tmpBufferEnd;
516
tmpBufferEnd = ptr[2] + n;
518
if (tmpBufferEnd - _tmpBuffer > tmpSize)
521
for (int j = 0; j < n; ++j)
523
unsigned int diff = (*(ptr[0]++) << 24) |
524
(*(ptr[1]++) << 16) |
528
char *pPtr = (char *) &pixel;
530
for (int k = 0; k < sizeof (pixel); ++k)
531
*writePtr++ = *pPtr++;
543
if (tmpBufferEnd - _tmpBuffer < tmpSize)
547
return writePtr - _outBuffer;