~cosme/ubuntu/precise/freeimage/freeimage-3.15.1

« back to all changes in this revision

Viewing changes to Source/OpenEXR/IlmImf/ImfPxr24Compressor.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cosme Domínguez Díaz
  • Date: 2010-07-20 13:42:15 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100720134215-xt1454zaedv3b604
Tags: 3.13.1-0ubuntu1
* New upstream release. Closes: (LP: #607800)
 - Updated debian/freeimage-get-orig-source script.
 - Removing no longer necessary debian/patches/* and
   the patch system in debian/rules.
 - Updated debian/rules to work with the new Makefiles.
 - Drop from -O3 to -O2 and use lzma compression saves
   ~10 MB of free space. 
* lintian stuff
 - fixed debhelper-but-no-misc-depends
 - fixed ldconfig-symlink-missing-for-shlib

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/////////////////////////////////////////////////////////////////////////////
2
 
//
3
 
// Copyright (c) 2004, Pixar Animation Studios
4
 
//
5
 
// All rights reserved.
6
 
//
7
 
// Redistribution and use in source and binary forms, with or without
8
 
// modification, are permitted provided that the following conditions  are
9
 
// met:
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
15
 
// distribution.
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.
19
 
//
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.
31
 
//
32
 
/////////////////////////////////////////////////////////////////////////////
33
 
 
34
 
//-----------------------------------------------------------------------------
35
 
//
36
 
//      class Pxr24Compressor
37
 
//
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.
41
 
//
42
 
//      The compressor preprocesses the pixel data to reduce entropy,
43
 
//      and then calls zlib.
44
 
//
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.
48
 
//
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.
63
 
//
64
 
//-----------------------------------------------------------------------------
65
 
 
66
 
#include <ImfPxr24Compressor.h>
67
 
#include <ImfHeader.h>
68
 
#include <ImfChannelList.h>
69
 
#include <ImfMisc.h>
70
 
#include <ImathFun.h>
71
 
#include <Iex.h>
72
 
#include <half.h>
73
 
#include <zlib.h>
74
 
#include <assert.h>
75
 
#include <algorithm>
76
 
 
77
 
using namespace std;
78
 
using namespace Imath;
79
 
 
80
 
namespace Imf {
81
 
namespace {
82
 
 
83
 
//
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.
86
 
//
87
 
 
88
 
inline unsigned int
89
 
floatToFloat24 (float f)
90
 
{
91
 
    union
92
 
    {
93
 
        float           f;
94
 
        unsigned int    i;
95
 
    } u;
96
 
 
97
 
    u.f = f;
98
 
 
99
 
    //
100
 
    // Disassemble the 32-bit floating point number, f,
101
 
    // into sign, s, exponent, e, and significand, m.
102
 
    //
103
 
 
104
 
    unsigned int s = u.i & 0x80000000;
105
 
    unsigned int e = u.i & 0x7f800000;
106
 
    unsigned int m = u.i & 0x007fffff;
107
 
    unsigned int i;
108
 
 
109
 
    if (e == 0x7f800000)
110
 
    {
111
 
        if (m)
112
 
        {
113
 
            //
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.
120
 
            //
121
 
 
122
 
            m >>= 8;
123
 
            i = (e >> 8) | m | (m == 0);
124
 
        }
125
 
        else
126
 
        {
127
 
            //
128
 
            // F is an infinity.
129
 
            //
130
 
 
131
 
            i = e >> 8;
132
 
        }
133
 
    }
134
 
    else
135
 
    {
136
 
        //
137
 
        // F is finite, round the significand to 15 bits.
138
 
        //
139
 
 
140
 
        i = ((e | m) + (m & 0x00000080)) >> 8;
141
 
 
142
 
        if (i >= 0x7f8000)
143
 
        {
144
 
            //
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.
149
 
            //
150
 
 
151
 
            i = (e | m) >> 8;
152
 
        }
153
 
    }
154
 
 
155
 
    return (s >> 8) | i;
156
 
}
157
 
 
158
 
 
159
 
void
160
 
notEnoughData ()
161
 
{
162
 
    throw Iex::InputExc ("Error decompressing data "
163
 
                         "(input data are shorter than expected).");
164
 
}
165
 
 
166
 
 
167
 
void
168
 
tooMuchData ()
169
 
{
170
 
    throw Iex::InputExc ("Error decompressing data "
171
 
                         "(input data are longer than expected).");
172
 
}
173
 
 
174
 
} // namespace
175
 
 
176
 
 
177
 
Pxr24Compressor::Pxr24Compressor (const Header &hdr,
178
 
                                  int maxScanLineSize,
179
 
                                  int numScanLines)
180
 
:
181
 
    Compressor (hdr),
182
 
    _maxScanLineSize (maxScanLineSize),
183
 
    _numScanLines (numScanLines),
184
 
    _tmpBuffer (0),
185
 
    _outBuffer (0),
186
 
    _channels (hdr.channels())
187
 
{
188
 
    int maxInBytes = maxScanLineSize * numScanLines;
189
 
 
190
 
    _tmpBuffer = new unsigned char [maxInBytes];
191
 
    _outBuffer = new char [int (ceil (maxInBytes * 1.01)) + 100];
192
 
 
193
 
    const Box2i &dataWindow = hdr.dataWindow();
194
 
 
195
 
    _minX = dataWindow.min.x;
196
 
    _maxX = dataWindow.max.x;
197
 
    _maxY = dataWindow.max.y;
198
 
}
199
 
 
200
 
 
201
 
Pxr24Compressor::~Pxr24Compressor ()
202
 
{
203
 
    delete [] _tmpBuffer;
204
 
    delete [] _outBuffer;
205
 
}
206
 
 
207
 
 
208
 
int
209
 
Pxr24Compressor::numScanLines () const
210
 
{
211
 
    return _numScanLines;
212
 
}
213
 
 
214
 
 
215
 
Compressor::Format
216
 
Pxr24Compressor::format () const
217
 
{
218
 
    return NATIVE;
219
 
}
220
 
 
221
 
 
222
 
int
223
 
Pxr24Compressor::compress (const char *inPtr,
224
 
                           int inSize,
225
 
                           int minY,
226
 
                           const char *&outPtr)
227
 
{
228
 
    return compress (inPtr,
229
 
                     inSize,
230
 
                     Box2i (V2i (_minX, minY),
231
 
                            V2i (_maxX, minY + _numScanLines - 1)),
232
 
                     outPtr);
233
 
}
234
 
 
235
 
              
236
 
int
237
 
Pxr24Compressor::compressTile (const char *inPtr,
238
 
                               int inSize,
239
 
                               Box2i range,
240
 
                               const char *&outPtr)
241
 
{
242
 
    return compress (inPtr, inSize, range, outPtr);
243
 
}
244
 
 
245
 
 
246
 
int
247
 
Pxr24Compressor::uncompress (const char *inPtr,
248
 
                             int inSize,
249
 
                             int minY,
250
 
                             const char *&outPtr)
251
 
{
252
 
    return uncompress (inPtr,
253
 
                       inSize,
254
 
                       Box2i (V2i (_minX, minY),
255
 
                              V2i (_maxX, minY + _numScanLines - 1)),
256
 
                       outPtr);
257
 
}
258
 
 
259
 
                
260
 
int
261
 
Pxr24Compressor::uncompressTile (const char *inPtr,
262
 
                                 int inSize,
263
 
                                 Box2i range,
264
 
                                 const char *&outPtr)
265
 
{
266
 
    return uncompress (inPtr, inSize, range, outPtr);
267
 
}
268
 
 
269
 
 
270
 
int
271
 
Pxr24Compressor::compress (const char *inPtr,
272
 
                           int inSize,
273
 
                           Box2i range,
274
 
                           const char *&outPtr)
275
 
{
276
 
    if (inSize == 0)
277
 
    {
278
 
        outPtr = _outBuffer;
279
 
        return 0;
280
 
    }
281
 
 
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);
286
 
 
287
 
    unsigned char *tmpBufferEnd = _tmpBuffer;
288
 
 
289
 
    for (int y = minY; y <= maxY; ++y)
290
 
    {
291
 
        for (ChannelList::ConstIterator i = _channels.begin();
292
 
             i != _channels.end();
293
 
             ++i)
294
 
        {
295
 
            const Channel &c = i.channel();
296
 
 
297
 
            if (modp (y, c.ySampling) != 0)
298
 
                continue;
299
 
 
300
 
            int n = numSamples (c.xSampling, minX, maxX);
301
 
 
302
 
            unsigned char *ptr[4];
303
 
            unsigned int previousPixel = 0;
304
 
 
305
 
            switch (c.type)
306
 
            {
307
 
              case UINT:
308
 
 
309
 
                ptr[0] = tmpBufferEnd;
310
 
                ptr[1] = ptr[0] + n;
311
 
                ptr[2] = ptr[1] + n;
312
 
                ptr[3] = ptr[2] + n;
313
 
                tmpBufferEnd = ptr[3] + n;
314
 
 
315
 
                for (int j = 0; j < n; ++j)
316
 
                {
317
 
                    unsigned int pixel;
318
 
                    char *pPtr = (char *) &pixel;
319
 
 
320
 
                    for (int k = 0; k < sizeof (pixel); ++k)
321
 
                        *pPtr++ = *inPtr++;
322
 
 
323
 
                    unsigned int diff = pixel - previousPixel;
324
 
                    previousPixel = pixel;
325
 
 
326
 
                    *(ptr[0]++) = diff >> 24;
327
 
                    *(ptr[1]++) = diff >> 16;
328
 
                    *(ptr[2]++) = diff >> 8;
329
 
                    *(ptr[3]++) = diff;
330
 
                }
331
 
 
332
 
                break;
333
 
 
334
 
              case HALF:
335
 
 
336
 
                ptr[0] = tmpBufferEnd;
337
 
                ptr[1] = ptr[0] + n;
338
 
                tmpBufferEnd = ptr[1] + n;
339
 
 
340
 
                for (int j = 0; j < n; ++j)
341
 
                {
342
 
                    half pixel;
343
 
 
344
 
                    pixel = *(const half *) inPtr;
345
 
                    inPtr += sizeof (half);
346
 
 
347
 
                    unsigned int diff = pixel.bits() - previousPixel;
348
 
                    previousPixel = pixel.bits();
349
 
 
350
 
                    *(ptr[0]++) = diff >> 8;
351
 
                    *(ptr[1]++) = diff;
352
 
                }
353
 
 
354
 
                break;
355
 
 
356
 
              case FLOAT:
357
 
 
358
 
                ptr[0] = tmpBufferEnd;
359
 
                ptr[1] = ptr[0] + n;
360
 
                ptr[2] = ptr[1] + n;
361
 
                tmpBufferEnd = ptr[2] + n;
362
 
 
363
 
                for (int j = 0; j < n; ++j)
364
 
                {
365
 
                    float pixel;
366
 
                    char *pPtr = (char *) &pixel;
367
 
 
368
 
                    for (int k = 0; k < sizeof (pixel); ++k)
369
 
                        *pPtr++ = *inPtr++;
370
 
 
371
 
                    unsigned int pixel24 = floatToFloat24 (pixel);
372
 
                    unsigned int diff = pixel24 - previousPixel;
373
 
                    previousPixel = pixel24;
374
 
 
375
 
                    *(ptr[0]++) = diff >> 16;
376
 
                    *(ptr[1]++) = diff >> 8;
377
 
                    *(ptr[2]++) = diff;
378
 
                }
379
 
 
380
 
                break;
381
 
 
382
 
              default:
383
 
 
384
 
                assert (false);
385
 
            }
386
 
        }
387
 
    }
388
 
 
389
 
    uLongf outSize = int (ceil ((tmpBufferEnd - _tmpBuffer) * 1.01)) + 100;
390
 
 
391
 
    if (Z_OK != ::compress ((Bytef *) _outBuffer,
392
 
                            &outSize,
393
 
                            (const Bytef *) _tmpBuffer,
394
 
                            tmpBufferEnd - _tmpBuffer))
395
 
    {
396
 
        throw Iex::BaseExc ("Data compression (zlib) failed.");
397
 
    }
398
 
 
399
 
    outPtr = _outBuffer;
400
 
    return outSize;
401
 
}
402
 
 
403
 
 
404
 
int             
405
 
Pxr24Compressor::uncompress (const char *inPtr,
406
 
                             int inSize,
407
 
                             Box2i range,
408
 
                             const char *&outPtr)
409
 
{
410
 
    if (inSize == 0)
411
 
    {
412
 
        outPtr = _outBuffer;
413
 
        return 0;
414
 
    }
415
 
 
416
 
    uLongf tmpSize = _maxScanLineSize * _numScanLines;
417
 
 
418
 
    if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer,
419
 
                              &tmpSize,
420
 
                              (const Bytef *) inPtr,
421
 
                              inSize))
422
 
    {
423
 
        throw Iex::InputExc ("Data decompression (zlib) failed.");
424
 
    }
425
 
 
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);
430
 
 
431
 
    const unsigned char *tmpBufferEnd = _tmpBuffer;
432
 
    char *writePtr = _outBuffer;
433
 
 
434
 
    for (int y = minY; y <= maxY; ++y)
435
 
    {
436
 
        for (ChannelList::ConstIterator i = _channels.begin();
437
 
             i != _channels.end();
438
 
             ++i)
439
 
        {
440
 
            const Channel &c = i.channel();
441
 
 
442
 
            if (modp (y, c.ySampling) != 0)
443
 
                continue;
444
 
 
445
 
            int n = numSamples (c.xSampling, minX, maxX);
446
 
 
447
 
            const unsigned char *ptr[4];
448
 
            unsigned int pixel = 0;
449
 
 
450
 
            switch (c.type)
451
 
            {
452
 
              case UINT:
453
 
 
454
 
                ptr[0] = tmpBufferEnd;
455
 
                ptr[1] = ptr[0] + n;
456
 
                ptr[2] = ptr[1] + n;
457
 
                ptr[3] = ptr[2] + n;
458
 
                tmpBufferEnd = ptr[3] + n;
459
 
 
460
 
                if (tmpBufferEnd - _tmpBuffer > tmpSize)
461
 
                    notEnoughData();
462
 
 
463
 
                for (int j = 0; j < n; ++j)
464
 
                {
465
 
                    unsigned int diff = (*(ptr[0]++) << 24) |
466
 
                                        (*(ptr[1]++) << 16) |
467
 
                                        (*(ptr[2]++) <<  8) |
468
 
                                         *(ptr[3]++);
469
 
 
470
 
                    pixel += diff;
471
 
 
472
 
                    char *pPtr = (char *) &pixel;
473
 
 
474
 
                    for (int k = 0; k < sizeof (pixel); ++k)
475
 
                        *writePtr++ = *pPtr++;
476
 
                }
477
 
 
478
 
                break;
479
 
 
480
 
              case HALF:
481
 
 
482
 
                ptr[0] = tmpBufferEnd;
483
 
                ptr[1] = ptr[0] + n;
484
 
                tmpBufferEnd = ptr[1] + n;
485
 
 
486
 
                if (tmpBufferEnd - _tmpBuffer > tmpSize)
487
 
                    notEnoughData();
488
 
 
489
 
                for (int j = 0; j < n; ++j)
490
 
                {
491
 
                    unsigned int diff = (*(ptr[0]++) << 8) |
492
 
                                         *(ptr[1]++);
493
 
 
494
 
                    pixel += diff;
495
 
 
496
 
                    half * hPtr = (half *) writePtr;
497
 
                    hPtr->setBits ((unsigned short) pixel);
498
 
                    writePtr += sizeof (half);
499
 
                }
500
 
 
501
 
                break;
502
 
 
503
 
              case FLOAT:
504
 
 
505
 
                ptr[0] = tmpBufferEnd;
506
 
                ptr[1] = ptr[0] + n;
507
 
                ptr[2] = ptr[1] + n;
508
 
                tmpBufferEnd = ptr[2] + n;
509
 
 
510
 
                if (tmpBufferEnd - _tmpBuffer > tmpSize)
511
 
                    notEnoughData();
512
 
 
513
 
                for (int j = 0; j < n; ++j)
514
 
                {
515
 
                    unsigned int diff = (*(ptr[0]++) << 24) |
516
 
                                        (*(ptr[1]++) << 16) |
517
 
                                        (*(ptr[2]++) <<  8);
518
 
                    pixel += diff;
519
 
 
520
 
                    char *pPtr = (char *) &pixel;
521
 
 
522
 
                    for (int k = 0; k < sizeof (pixel); ++k)
523
 
                        *writePtr++ = *pPtr++;
524
 
                }
525
 
 
526
 
                break;
527
 
 
528
 
              default:
529
 
 
530
 
                assert (false);
531
 
            }
532
 
        }
533
 
    }
534
 
 
535
 
    if (tmpBufferEnd - _tmpBuffer < tmpSize)
536
 
        tooMuchData();
537
 
 
538
 
    outPtr = _outBuffer;
539
 
    return writePtr - _outBuffer;
540
 
}
541
 
 
542
 
} // namespace Imf
 
1
/////////////////////////////////////////////////////////////////////////////
 
2
//
 
3
// Copyright (c) 2004, Pixar Animation Studios
 
4
//
 
5
// All rights reserved.
 
6
//
 
7
// Redistribution and use in source and binary forms, with or without
 
8
// modification, are permitted provided that the following conditions  are
 
9
// met:
 
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
 
15
// distribution.
 
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.
 
19
//
 
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.
 
31
//
 
32
/////////////////////////////////////////////////////////////////////////////
 
33
 
 
34
//-----------------------------------------------------------------------------
 
35
//
 
36
//      class Pxr24Compressor
 
37
//
 
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.
 
41
//
 
42
//      The compressor preprocesses the pixel data to reduce entropy,
 
43
//      and then calls zlib.
 
44
//
 
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.
 
48
//
 
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.
 
63
//
 
64
//-----------------------------------------------------------------------------
 
65
 
 
66
#include <ImfPxr24Compressor.h>
 
67
#include <ImfHeader.h>
 
68
#include <ImfChannelList.h>
 
69
#include <ImfMisc.h>
 
70
#include <ImathFun.h>
 
71
#include <Iex.h>
 
72
#include <half.h>
 
73
#include <zlib.h>
 
74
#include <assert.h>
 
75
#include <algorithm>
 
76
 
 
77
using namespace std;
 
78
using namespace Imath;
 
79
 
 
80
namespace Imf {
 
81
namespace {
 
82
 
 
83
//
 
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.
 
86
//
 
87
 
 
88
inline unsigned int
 
89
floatToFloat24 (float f)
 
90
{
 
91
    union
 
92
    {
 
93
        float           f;
 
94
        unsigned int    i;
 
95
    } u;
 
96
 
 
97
    u.f = f;
 
98
 
 
99
    //
 
100
    // Disassemble the 32-bit floating point number, f,
 
101
    // into sign, s, exponent, e, and significand, m.
 
102
    //
 
103
 
 
104
    unsigned int s = u.i & 0x80000000;
 
105
    unsigned int e = u.i & 0x7f800000;
 
106
    unsigned int m = u.i & 0x007fffff;
 
107
    unsigned int i;
 
108
 
 
109
    if (e == 0x7f800000)
 
110
    {
 
111
        if (m)
 
112
        {
 
113
            //
 
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.
 
120
            //
 
121
 
 
122
            m >>= 8;
 
123
            i = (e >> 8) | m | (m == 0);
 
124
        }
 
125
        else
 
126
        {
 
127
            //
 
128
            // F is an infinity.
 
129
            //
 
130
 
 
131
            i = e >> 8;
 
132
        }
 
133
    }
 
134
    else
 
135
    {
 
136
        //
 
137
        // F is finite, round the significand to 15 bits.
 
138
        //
 
139
 
 
140
        i = ((e | m) + (m & 0x00000080)) >> 8;
 
141
 
 
142
        if (i >= 0x7f8000)
 
143
        {
 
144
            //
 
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.
 
149
            //
 
150
 
 
151
            i = (e | m) >> 8;
 
152
        }
 
153
    }
 
154
 
 
155
    return (s >> 8) | i;
 
156
}
 
157
 
 
158
 
 
159
void
 
160
notEnoughData ()
 
161
{
 
162
    throw Iex::InputExc ("Error decompressing data "
 
163
                         "(input data are shorter than expected).");
 
164
}
 
165
 
 
166
 
 
167
void
 
168
tooMuchData ()
 
169
{
 
170
    throw Iex::InputExc ("Error decompressing data "
 
171
                         "(input data are longer than expected).");
 
172
}
 
173
 
 
174
} // namespace
 
175
 
 
176
 
 
177
Pxr24Compressor::Pxr24Compressor (const Header &hdr,
 
178
                                  int maxScanLineSize,
 
179
                                  int numScanLines)
 
180
:
 
181
    Compressor (hdr),
 
182
    _maxScanLineSize (maxScanLineSize),
 
183
    _numScanLines (numScanLines),
 
184
    _tmpBuffer (0),
 
185
    _outBuffer (0),
 
186
    _channels (hdr.channels())
 
187
{
 
188
    int maxInBytes = maxScanLineSize * numScanLines;
 
189
 
 
190
    _tmpBuffer = new unsigned char [maxInBytes];
 
191
    _outBuffer = new char [int (ceil (maxInBytes * 1.01)) + 100];
 
192
 
 
193
    const Box2i &dataWindow = hdr.dataWindow();
 
194
 
 
195
    _minX = dataWindow.min.x;
 
196
    _maxX = dataWindow.max.x;
 
197
    _maxY = dataWindow.max.y;
 
198
}
 
199
 
 
200
 
 
201
Pxr24Compressor::~Pxr24Compressor ()
 
202
{
 
203
    delete [] _tmpBuffer;
 
204
    delete [] _outBuffer;
 
205
}
 
206
 
 
207
 
 
208
int
 
209
Pxr24Compressor::numScanLines () const
 
210
{
 
211
    return _numScanLines;
 
212
}
 
213
 
 
214
 
 
215
Compressor::Format
 
216
Pxr24Compressor::format () const
 
217
{
 
218
    return NATIVE;
 
219
}
 
220
 
 
221
 
 
222
int
 
223
Pxr24Compressor::compress (const char *inPtr,
 
224
                           int inSize,
 
225
                           int minY,
 
226
                           const char *&outPtr)
 
227
{
 
228
    return compress (inPtr,
 
229
                     inSize,
 
230
                     Box2i (V2i (_minX, minY),
 
231
                            V2i (_maxX, minY + _numScanLines - 1)),
 
232
                     outPtr);
 
233
}
 
234
 
 
235
              
 
236
int
 
237
Pxr24Compressor::compressTile (const char *inPtr,
 
238
                               int inSize,
 
239
                               Box2i range,
 
240
                               const char *&outPtr)
 
241
{
 
242
    return compress (inPtr, inSize, range, outPtr);
 
243
}
 
244
 
 
245
 
 
246
int
 
247
Pxr24Compressor::uncompress (const char *inPtr,
 
248
                             int inSize,
 
249
                             int minY,
 
250
                             const char *&outPtr)
 
251
{
 
252
    return uncompress (inPtr,
 
253
                       inSize,
 
254
                       Box2i (V2i (_minX, minY),
 
255
                              V2i (_maxX, minY + _numScanLines - 1)),
 
256
                       outPtr);
 
257
}
 
258
 
 
259
                
 
260
int
 
261
Pxr24Compressor::uncompressTile (const char *inPtr,
 
262
                                 int inSize,
 
263
                                 Box2i range,
 
264
                                 const char *&outPtr)
 
265
{
 
266
    return uncompress (inPtr, inSize, range, outPtr);
 
267
}
 
268
 
 
269
 
 
270
int
 
271
Pxr24Compressor::compress (const char *inPtr,
 
272
                           int inSize,
 
273
                           Box2i range,
 
274
                           const char *&outPtr)
 
275
{
 
276
    if (inSize == 0)
 
277
    {
 
278
        outPtr = _outBuffer;
 
279
        return 0;
 
280
    }
 
281
 
 
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);
 
286
 
 
287
    unsigned char *tmpBufferEnd = _tmpBuffer;
 
288
 
 
289
    for (int y = minY; y <= maxY; ++y)
 
290
    {
 
291
        for (ChannelList::ConstIterator i = _channels.begin();
 
292
             i != _channels.end();
 
293
             ++i)
 
294
        {
 
295
            const Channel &c = i.channel();
 
296
 
 
297
            if (modp (y, c.ySampling) != 0)
 
298
                continue;
 
299
 
 
300
            int n = numSamples (c.xSampling, minX, maxX);
 
301
 
 
302
            unsigned char *ptr[4];
 
303
            unsigned int previousPixel = 0;
 
304
 
 
305
            switch (c.type)
 
306
            {
 
307
              case UINT:
 
308
 
 
309
                ptr[0] = tmpBufferEnd;
 
310
                ptr[1] = ptr[0] + n;
 
311
                ptr[2] = ptr[1] + n;
 
312
                ptr[3] = ptr[2] + n;
 
313
                tmpBufferEnd = ptr[3] + n;
 
314
 
 
315
                for (int j = 0; j < n; ++j)
 
316
                {
 
317
                    unsigned int pixel;
 
318
                    char *pPtr = (char *) &pixel;
 
319
 
 
320
                    for (int k = 0; k < sizeof (pixel); ++k)
 
321
                        *pPtr++ = *inPtr++;
 
322
 
 
323
                    unsigned int diff = pixel - previousPixel;
 
324
                    previousPixel = pixel;
 
325
 
 
326
                    *(ptr[0]++) = diff >> 24;
 
327
                    *(ptr[1]++) = diff >> 16;
 
328
                    *(ptr[2]++) = diff >> 8;
 
329
                    *(ptr[3]++) = diff;
 
330
                }
 
331
 
 
332
                break;
 
333
 
 
334
              case HALF:
 
335
 
 
336
                ptr[0] = tmpBufferEnd;
 
337
                ptr[1] = ptr[0] + n;
 
338
                tmpBufferEnd = ptr[1] + n;
 
339
 
 
340
                for (int j = 0; j < n; ++j)
 
341
                {
 
342
                    half pixel;
 
343
 
 
344
                    pixel = *(const half *) inPtr;
 
345
                    inPtr += sizeof (half);
 
346
 
 
347
                    unsigned int diff = pixel.bits() - previousPixel;
 
348
                    previousPixel = pixel.bits();
 
349
 
 
350
                    *(ptr[0]++) = diff >> 8;
 
351
                    *(ptr[1]++) = diff;
 
352
                }
 
353
 
 
354
                break;
 
355
 
 
356
              case FLOAT:
 
357
 
 
358
                ptr[0] = tmpBufferEnd;
 
359
                ptr[1] = ptr[0] + n;
 
360
                ptr[2] = ptr[1] + n;
 
361
                tmpBufferEnd = ptr[2] + n;
 
362
 
 
363
                for (int j = 0; j < n; ++j)
 
364
                {
 
365
                    float pixel;
 
366
                    char *pPtr = (char *) &pixel;
 
367
 
 
368
                    for (int k = 0; k < sizeof (pixel); ++k)
 
369
                        *pPtr++ = *inPtr++;
 
370
 
 
371
                    unsigned int pixel24 = floatToFloat24 (pixel);
 
372
                    unsigned int diff = pixel24 - previousPixel;
 
373
                    previousPixel = pixel24;
 
374
 
 
375
                    *(ptr[0]++) = diff >> 16;
 
376
                    *(ptr[1]++) = diff >> 8;
 
377
                    *(ptr[2]++) = diff;
 
378
                }
 
379
 
 
380
                break;
 
381
 
 
382
              default:
 
383
 
 
384
                assert (false);
 
385
            }
 
386
        }
 
387
    }
 
388
 
 
389
    uLongf outSize = int (ceil ((tmpBufferEnd - _tmpBuffer) * 1.01)) + 100;
 
390
 
 
391
    if (Z_OK != ::compress ((Bytef *) _outBuffer,
 
392
                            &outSize,
 
393
                            (const Bytef *) _tmpBuffer,
 
394
                            tmpBufferEnd - _tmpBuffer))
 
395
    {
 
396
        throw Iex::BaseExc ("Data compression (zlib) failed.");
 
397
    }
 
398
 
 
399
    outPtr = _outBuffer;
 
400
    return outSize;
 
401
}
 
402
 
 
403
 
 
404
int             
 
405
Pxr24Compressor::uncompress (const char *inPtr,
 
406
                             int inSize,
 
407
                             Box2i range,
 
408
                             const char *&outPtr)
 
409
{
 
410
    if (inSize == 0)
 
411
    {
 
412
        outPtr = _outBuffer;
 
413
        return 0;
 
414
    }
 
415
 
 
416
    uLongf tmpSize = _maxScanLineSize * _numScanLines;
 
417
 
 
418
    if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer,
 
419
                              &tmpSize,
 
420
                              (const Bytef *) inPtr,
 
421
                              inSize))
 
422
    {
 
423
        throw Iex::InputExc ("Data decompression (zlib) failed.");
 
424
    }
 
425
 
 
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);
 
430
 
 
431
    const unsigned char *tmpBufferEnd = _tmpBuffer;
 
432
    char *writePtr = _outBuffer;
 
433
 
 
434
    for (int y = minY; y <= maxY; ++y)
 
435
    {
 
436
        for (ChannelList::ConstIterator i = _channels.begin();
 
437
             i != _channels.end();
 
438
             ++i)
 
439
        {
 
440
            const Channel &c = i.channel();
 
441
 
 
442
            if (modp (y, c.ySampling) != 0)
 
443
                continue;
 
444
 
 
445
            int n = numSamples (c.xSampling, minX, maxX);
 
446
 
 
447
            const unsigned char *ptr[4];
 
448
            unsigned int pixel = 0;
 
449
 
 
450
            switch (c.type)
 
451
            {
 
452
              case UINT:
 
453
 
 
454
                ptr[0] = tmpBufferEnd;
 
455
                ptr[1] = ptr[0] + n;
 
456
                ptr[2] = ptr[1] + n;
 
457
                ptr[3] = ptr[2] + n;
 
458
                tmpBufferEnd = ptr[3] + n;
 
459
 
 
460
                if (tmpBufferEnd - _tmpBuffer > tmpSize)
 
461
                    notEnoughData();
 
462
 
 
463
                for (int j = 0; j < n; ++j)
 
464
                {
 
465
                    unsigned int diff = (*(ptr[0]++) << 24) |
 
466
                                        (*(ptr[1]++) << 16) |
 
467
                                        (*(ptr[2]++) <<  8) |
 
468
                                         *(ptr[3]++);
 
469
 
 
470
                    pixel += diff;
 
471
 
 
472
                    char *pPtr = (char *) &pixel;
 
473
 
 
474
                    for (int k = 0; k < sizeof (pixel); ++k)
 
475
                        *writePtr++ = *pPtr++;
 
476
                }
 
477
 
 
478
                break;
 
479
 
 
480
              case HALF:
 
481
 
 
482
                ptr[0] = tmpBufferEnd;
 
483
                ptr[1] = ptr[0] + n;
 
484
                tmpBufferEnd = ptr[1] + n;
 
485
 
 
486
                if (tmpBufferEnd - _tmpBuffer > tmpSize)
 
487
                    notEnoughData();
 
488
 
 
489
                for (int j = 0; j < n; ++j)
 
490
                {
 
491
                    unsigned int diff = (*(ptr[0]++) << 8) |
 
492
                                         *(ptr[1]++);
 
493
 
 
494
                    pixel += diff;
 
495
 
 
496
                    half * hPtr = (half *) writePtr;
 
497
                    hPtr->setBits ((unsigned short) pixel);
 
498
                    writePtr += sizeof (half);
 
499
                }
 
500
 
 
501
                break;
 
502
 
 
503
              case FLOAT:
 
504
 
 
505
                ptr[0] = tmpBufferEnd;
 
506
                ptr[1] = ptr[0] + n;
 
507
                ptr[2] = ptr[1] + n;
 
508
                tmpBufferEnd = ptr[2] + n;
 
509
 
 
510
                if (tmpBufferEnd - _tmpBuffer > tmpSize)
 
511
                    notEnoughData();
 
512
 
 
513
                for (int j = 0; j < n; ++j)
 
514
                {
 
515
                    unsigned int diff = (*(ptr[0]++) << 24) |
 
516
                                        (*(ptr[1]++) << 16) |
 
517
                                        (*(ptr[2]++) <<  8);
 
518
                    pixel += diff;
 
519
 
 
520
                    char *pPtr = (char *) &pixel;
 
521
 
 
522
                    for (int k = 0; k < sizeof (pixel); ++k)
 
523
                        *writePtr++ = *pPtr++;
 
524
                }
 
525
 
 
526
                break;
 
527
 
 
528
              default:
 
529
 
 
530
                assert (false);
 
531
            }
 
532
        }
 
533
    }
 
534
 
 
535
    if (tmpBufferEnd - _tmpBuffer < tmpSize)
 
536
        tooMuchData();
 
537
 
 
538
    outPtr = _outBuffer;
 
539
    return writePtr - _outBuffer;
 
540
}
 
541
 
 
542
} // namespace Imf