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
//-----------------------------------------------------------------------------
66
#include <ImfPxr24Compressor.h>
67
#include <ImfHeader.h>
68
#include <ImfChannelList.h>
78
using namespace Imath;
84
// Conversion from 32-bit to 24-bit floating-point numbers.
85
// Conversion back to 32 bits is simply an 8-bit shift to the left.
89
floatToFloat24 (float f)
100
// Disassemble the 32-bit floating point number, f,
101
// into sign, s, exponent, e, and significand, m.
104
unsigned int s = u.i & 0x80000000;
105
unsigned int e = u.i & 0x7f800000;
106
unsigned int m = u.i & 0x007fffff;
114
// F is a NAN; we preserve the sign bit and
115
// the 15 leftmost bits of the significand,
116
// with one exception: If the 15 leftmost
117
// bits are all zero, the NAN would turn
118
// into an infinity, so we have to set at
119
// least one bit in the significand.
123
i = (e >> 8) | m | (m == 0);
137
// F is finite, round the significand to 15 bits.
140
i = ((e | m) + (m & 0x00000080)) >> 8;
145
// F was close to FLT_MAX, and the significand was
146
// rounded up, resulting in an exponent overflow.
147
// Avoid the overflow by truncating the significand
148
// instead of rounding it.
162
throw Iex::InputExc ("Error decompressing data "
163
"(input data are shorter than expected).");
170
throw Iex::InputExc ("Error decompressing data "
171
"(input data are longer than expected).");
177
Pxr24Compressor::Pxr24Compressor (const Header &hdr,
182
_maxScanLineSize (maxScanLineSize),
183
_numScanLines (numScanLines),
186
_channels (hdr.channels())
188
int maxInBytes = maxScanLineSize * numScanLines;
190
_tmpBuffer = new unsigned char [maxInBytes];
191
_outBuffer = new char [int (ceil (maxInBytes * 1.01)) + 100];
193
const Box2i &dataWindow = hdr.dataWindow();
195
_minX = dataWindow.min.x;
196
_maxX = dataWindow.max.x;
197
_maxY = dataWindow.max.y;
201
Pxr24Compressor::~Pxr24Compressor ()
203
delete [] _tmpBuffer;
204
delete [] _outBuffer;
209
Pxr24Compressor::numScanLines () const
211
return _numScanLines;
216
Pxr24Compressor::format () const
223
Pxr24Compressor::compress (const char *inPtr,
228
return compress (inPtr,
230
Box2i (V2i (_minX, minY),
231
V2i (_maxX, minY + _numScanLines - 1)),
237
Pxr24Compressor::compressTile (const char *inPtr,
242
return compress (inPtr, inSize, range, outPtr);
247
Pxr24Compressor::uncompress (const char *inPtr,
252
return uncompress (inPtr,
254
Box2i (V2i (_minX, minY),
255
V2i (_maxX, minY + _numScanLines - 1)),
261
Pxr24Compressor::uncompressTile (const char *inPtr,
266
return uncompress (inPtr, inSize, range, outPtr);
271
Pxr24Compressor::compress (const char *inPtr,
282
int minX = range.min.x;
283
int maxX = min (range.max.x, _maxX);
284
int minY = range.min.y;
285
int maxY = min (range.max.y, _maxY);
287
unsigned char *tmpBufferEnd = _tmpBuffer;
289
for (int y = minY; y <= maxY; ++y)
291
for (ChannelList::ConstIterator i = _channels.begin();
292
i != _channels.end();
295
const Channel &c = i.channel();
297
if (modp (y, c.ySampling) != 0)
300
int n = numSamples (c.xSampling, minX, maxX);
302
unsigned char *ptr[4];
303
unsigned int previousPixel = 0;
309
ptr[0] = tmpBufferEnd;
313
tmpBufferEnd = ptr[3] + n;
315
for (int j = 0; j < n; ++j)
318
char *pPtr = (char *) &pixel;
320
for (int k = 0; k < sizeof (pixel); ++k)
323
unsigned int diff = pixel - previousPixel;
324
previousPixel = pixel;
326
*(ptr[0]++) = diff >> 24;
327
*(ptr[1]++) = diff >> 16;
328
*(ptr[2]++) = diff >> 8;
336
ptr[0] = tmpBufferEnd;
338
tmpBufferEnd = ptr[1] + n;
340
for (int j = 0; j < n; ++j)
344
pixel = *(const half *) inPtr;
345
inPtr += sizeof (half);
347
unsigned int diff = pixel.bits() - previousPixel;
348
previousPixel = pixel.bits();
350
*(ptr[0]++) = diff >> 8;
358
ptr[0] = tmpBufferEnd;
361
tmpBufferEnd = ptr[2] + n;
363
for (int j = 0; j < n; ++j)
366
char *pPtr = (char *) &pixel;
368
for (int k = 0; k < sizeof (pixel); ++k)
371
unsigned int pixel24 = floatToFloat24 (pixel);
372
unsigned int diff = pixel24 - previousPixel;
373
previousPixel = pixel24;
375
*(ptr[0]++) = diff >> 16;
376
*(ptr[1]++) = diff >> 8;
389
uLongf outSize = int (ceil ((tmpBufferEnd - _tmpBuffer) * 1.01)) + 100;
391
if (Z_OK != ::compress ((Bytef *) _outBuffer,
393
(const Bytef *) _tmpBuffer,
394
tmpBufferEnd - _tmpBuffer))
396
throw Iex::BaseExc ("Data compression (zlib) failed.");
405
Pxr24Compressor::uncompress (const char *inPtr,
416
uLongf tmpSize = _maxScanLineSize * _numScanLines;
418
if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer,
420
(const Bytef *) inPtr,
423
throw Iex::InputExc ("Data decompression (zlib) failed.");
426
int minX = range.min.x;
427
int maxX = min (range.max.x, _maxX);
428
int minY = range.min.y;
429
int maxY = min (range.max.y, _maxY);
431
const unsigned char *tmpBufferEnd = _tmpBuffer;
432
char *writePtr = _outBuffer;
434
for (int y = minY; y <= maxY; ++y)
436
for (ChannelList::ConstIterator i = _channels.begin();
437
i != _channels.end();
440
const Channel &c = i.channel();
442
if (modp (y, c.ySampling) != 0)
445
int n = numSamples (c.xSampling, minX, maxX);
447
const unsigned char *ptr[4];
448
unsigned int pixel = 0;
454
ptr[0] = tmpBufferEnd;
458
tmpBufferEnd = ptr[3] + n;
460
if (tmpBufferEnd - _tmpBuffer > tmpSize)
463
for (int j = 0; j < n; ++j)
465
unsigned int diff = (*(ptr[0]++) << 24) |
466
(*(ptr[1]++) << 16) |
472
char *pPtr = (char *) &pixel;
474
for (int k = 0; k < sizeof (pixel); ++k)
475
*writePtr++ = *pPtr++;
482
ptr[0] = tmpBufferEnd;
484
tmpBufferEnd = ptr[1] + n;
486
if (tmpBufferEnd - _tmpBuffer > tmpSize)
489
for (int j = 0; j < n; ++j)
491
unsigned int diff = (*(ptr[0]++) << 8) |
496
half * hPtr = (half *) writePtr;
497
hPtr->setBits ((unsigned short) pixel);
498
writePtr += sizeof (half);
505
ptr[0] = tmpBufferEnd;
508
tmpBufferEnd = ptr[2] + n;
510
if (tmpBufferEnd - _tmpBuffer > tmpSize)
513
for (int j = 0; j < n; ++j)
515
unsigned int diff = (*(ptr[0]++) << 24) |
516
(*(ptr[1]++) << 16) |
520
char *pPtr = (char *) &pixel;
522
for (int k = 0; k < sizeof (pixel); ++k)
523
*writePtr++ = *pPtr++;
535
if (tmpBufferEnd - _tmpBuffer < tmpSize)
539
return writePtr - _outBuffer;
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
//-----------------------------------------------------------------------------
66
#include <ImfPxr24Compressor.h>
67
#include <ImfHeader.h>
68
#include <ImfChannelList.h>
78
using namespace Imath;
84
// Conversion from 32-bit to 24-bit floating-point numbers.
85
// Conversion back to 32 bits is simply an 8-bit shift to the left.
89
floatToFloat24 (float f)
100
// Disassemble the 32-bit floating point number, f,
101
// into sign, s, exponent, e, and significand, m.
104
unsigned int s = u.i & 0x80000000;
105
unsigned int e = u.i & 0x7f800000;
106
unsigned int m = u.i & 0x007fffff;
114
// F is a NAN; we preserve the sign bit and
115
// the 15 leftmost bits of the significand,
116
// with one exception: If the 15 leftmost
117
// bits are all zero, the NAN would turn
118
// into an infinity, so we have to set at
119
// least one bit in the significand.
123
i = (e >> 8) | m | (m == 0);
137
// F is finite, round the significand to 15 bits.
140
i = ((e | m) + (m & 0x00000080)) >> 8;
145
// F was close to FLT_MAX, and the significand was
146
// rounded up, resulting in an exponent overflow.
147
// Avoid the overflow by truncating the significand
148
// instead of rounding it.
162
throw Iex::InputExc ("Error decompressing data "
163
"(input data are shorter than expected).");
170
throw Iex::InputExc ("Error decompressing data "
171
"(input data are longer than expected).");
177
Pxr24Compressor::Pxr24Compressor (const Header &hdr,
182
_maxScanLineSize (maxScanLineSize),
183
_numScanLines (numScanLines),
186
_channels (hdr.channels())
188
int maxInBytes = maxScanLineSize * numScanLines;
190
_tmpBuffer = new unsigned char [maxInBytes];
191
_outBuffer = new char [int (ceil (maxInBytes * 1.01)) + 100];
193
const Box2i &dataWindow = hdr.dataWindow();
195
_minX = dataWindow.min.x;
196
_maxX = dataWindow.max.x;
197
_maxY = dataWindow.max.y;
201
Pxr24Compressor::~Pxr24Compressor ()
203
delete [] _tmpBuffer;
204
delete [] _outBuffer;
209
Pxr24Compressor::numScanLines () const
211
return _numScanLines;
216
Pxr24Compressor::format () const
223
Pxr24Compressor::compress (const char *inPtr,
228
return compress (inPtr,
230
Box2i (V2i (_minX, minY),
231
V2i (_maxX, minY + _numScanLines - 1)),
237
Pxr24Compressor::compressTile (const char *inPtr,
242
return compress (inPtr, inSize, range, outPtr);
247
Pxr24Compressor::uncompress (const char *inPtr,
252
return uncompress (inPtr,
254
Box2i (V2i (_minX, minY),
255
V2i (_maxX, minY + _numScanLines - 1)),
261
Pxr24Compressor::uncompressTile (const char *inPtr,
266
return uncompress (inPtr, inSize, range, outPtr);
271
Pxr24Compressor::compress (const char *inPtr,
282
int minX = range.min.x;
283
int maxX = min (range.max.x, _maxX);
284
int minY = range.min.y;
285
int maxY = min (range.max.y, _maxY);
287
unsigned char *tmpBufferEnd = _tmpBuffer;
289
for (int y = minY; y <= maxY; ++y)
291
for (ChannelList::ConstIterator i = _channels.begin();
292
i != _channels.end();
295
const Channel &c = i.channel();
297
if (modp (y, c.ySampling) != 0)
300
int n = numSamples (c.xSampling, minX, maxX);
302
unsigned char *ptr[4];
303
unsigned int previousPixel = 0;
309
ptr[0] = tmpBufferEnd;
313
tmpBufferEnd = ptr[3] + n;
315
for (int j = 0; j < n; ++j)
318
char *pPtr = (char *) &pixel;
320
for (int k = 0; k < sizeof (pixel); ++k)
323
unsigned int diff = pixel - previousPixel;
324
previousPixel = pixel;
326
*(ptr[0]++) = diff >> 24;
327
*(ptr[1]++) = diff >> 16;
328
*(ptr[2]++) = diff >> 8;
336
ptr[0] = tmpBufferEnd;
338
tmpBufferEnd = ptr[1] + n;
340
for (int j = 0; j < n; ++j)
344
pixel = *(const half *) inPtr;
345
inPtr += sizeof (half);
347
unsigned int diff = pixel.bits() - previousPixel;
348
previousPixel = pixel.bits();
350
*(ptr[0]++) = diff >> 8;
358
ptr[0] = tmpBufferEnd;
361
tmpBufferEnd = ptr[2] + n;
363
for (int j = 0; j < n; ++j)
366
char *pPtr = (char *) &pixel;
368
for (int k = 0; k < sizeof (pixel); ++k)
371
unsigned int pixel24 = floatToFloat24 (pixel);
372
unsigned int diff = pixel24 - previousPixel;
373
previousPixel = pixel24;
375
*(ptr[0]++) = diff >> 16;
376
*(ptr[1]++) = diff >> 8;
389
uLongf outSize = int (ceil ((tmpBufferEnd - _tmpBuffer) * 1.01)) + 100;
391
if (Z_OK != ::compress ((Bytef *) _outBuffer,
393
(const Bytef *) _tmpBuffer,
394
tmpBufferEnd - _tmpBuffer))
396
throw Iex::BaseExc ("Data compression (zlib) failed.");
405
Pxr24Compressor::uncompress (const char *inPtr,
416
uLongf tmpSize = _maxScanLineSize * _numScanLines;
418
if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer,
420
(const Bytef *) inPtr,
423
throw Iex::InputExc ("Data decompression (zlib) failed.");
426
int minX = range.min.x;
427
int maxX = min (range.max.x, _maxX);
428
int minY = range.min.y;
429
int maxY = min (range.max.y, _maxY);
431
const unsigned char *tmpBufferEnd = _tmpBuffer;
432
char *writePtr = _outBuffer;
434
for (int y = minY; y <= maxY; ++y)
436
for (ChannelList::ConstIterator i = _channels.begin();
437
i != _channels.end();
440
const Channel &c = i.channel();
442
if (modp (y, c.ySampling) != 0)
445
int n = numSamples (c.xSampling, minX, maxX);
447
const unsigned char *ptr[4];
448
unsigned int pixel = 0;
454
ptr[0] = tmpBufferEnd;
458
tmpBufferEnd = ptr[3] + n;
460
if (tmpBufferEnd - _tmpBuffer > tmpSize)
463
for (int j = 0; j < n; ++j)
465
unsigned int diff = (*(ptr[0]++) << 24) |
466
(*(ptr[1]++) << 16) |
472
char *pPtr = (char *) &pixel;
474
for (int k = 0; k < sizeof (pixel); ++k)
475
*writePtr++ = *pPtr++;
482
ptr[0] = tmpBufferEnd;
484
tmpBufferEnd = ptr[1] + n;
486
if (tmpBufferEnd - _tmpBuffer > tmpSize)
489
for (int j = 0; j < n; ++j)
491
unsigned int diff = (*(ptr[0]++) << 8) |
496
half * hPtr = (half *) writePtr;
497
hPtr->setBits ((unsigned short) pixel);
498
writePtr += sizeof (half);
505
ptr[0] = tmpBufferEnd;
508
tmpBufferEnd = ptr[2] + n;
510
if (tmpBufferEnd - _tmpBuffer > tmpSize)
513
for (int j = 0; j < n; ++j)
515
unsigned int diff = (*(ptr[0]++) << 24) |
516
(*(ptr[1]++) << 16) |
520
char *pPtr = (char *) &pixel;
522
for (int k = 0; k < sizeof (pixel); ++k)
523
*writePtr++ = *pPtr++;
535
if (tmpBufferEnd - _tmpBuffer < tmpSize)
539
return writePtr - _outBuffer;