~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/3rdparty/openexr/IlmImf/ImfPxr24Compressor.cpp

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

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