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

« back to all changes in this revision

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

  • Committer: Stefano Rivera
  • Date: 2010-07-24 15:35:51 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: stefanor@ubuntu.com-20100724153551-6s3fth1653huk31a
Tags: upstream-3.13.1
ImportĀ upstreamĀ versionĀ 3.31.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
///////////////////////////////////////////////////////////////////////////
2
 
//
3
 
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
4
 
// Digital Ltd. LLC
5
 
// 
6
 
// All rights reserved.
7
 
// 
8
 
// Redistribution and use in source and binary forms, with or without
9
 
// modification, are permitted provided that the following conditions are
10
 
// met:
11
 
// *       Redistributions of source code must retain the above copyright
12
 
// notice, this list of conditions and the following disclaimer.
13
 
// *       Redistributions in binary form must reproduce the above
14
 
// copyright notice, this list of conditions and the following disclaimer
15
 
// in the documentation and/or other materials provided with the
16
 
// distribution.
17
 
// *       Neither the name of Industrial Light & Magic nor the names of
18
 
// its contributors may be used to endorse or promote products derived
19
 
// from this software without specific prior written permission. 
20
 
// 
21
 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
 
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
 
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
 
//
33
 
///////////////////////////////////////////////////////////////////////////
34
 
 
35
 
 
36
 
//-----------------------------------------------------------------------------
37
 
//
38
 
//      class B44Compressor
39
 
//
40
 
//      This compressor is lossy for HALF channels; the compression rate
41
 
//      is fixed at 32/14 (approximately 2.28).  FLOAT and UINT channels
42
 
//      are not compressed; their data are preserved exactly.
43
 
//
44
 
//      Each HALF channel is split into blocks of 4 by 4 pixels.  An
45
 
//      uncompressed block occupies 32 bytes, which are re-interpreted
46
 
//      as sixteen 16-bit unsigned integers, t[0] ... t[15].  Compression
47
 
//      shrinks the block to 14 bytes.  The compressed 14-byte block
48
 
//      contains
49
 
//
50
 
//       - t[0]
51
 
//
52
 
//       - a 6-bit shift value
53
 
//
54
 
//       - 15 densely packed 6-bit values, r[0] ... r[14], which are
55
 
//         computed by subtracting adjacent pixel values and right-
56
 
//         shifting the differences according to the stored shift value.
57
 
//
58
 
//         Differences between adjacent pixels are computed according
59
 
//         to the following diagram:
60
 
//
61
 
//               0 -------->  1 -------->  2 -------->  3
62
 
//               |     3            7           11
63
 
//               |
64
 
//               | 0
65
 
//               |
66
 
//               v 
67
 
//               4 -------->  5 -------->  6 -------->  7
68
 
//               |     4            8           12
69
 
//               |
70
 
//               | 1
71
 
//               |
72
 
//               v
73
 
//               8 -------->  9 --------> 10 --------> 11
74
 
//               |     5            9           13
75
 
//               |
76
 
//               | 2
77
 
//               |
78
 
//               v
79
 
//              12 --------> 13 --------> 14 --------> 15
80
 
//                     6           10           14
81
 
//
82
 
//          Here
83
 
//
84
 
//               5 ---------> 6
85
 
//                     8
86
 
//
87
 
//          means that r[8] is the difference between t[5] and t[6].
88
 
//
89
 
//       - optionally, a 4-by-4 pixel block where all pixels have the
90
 
//         same value can be treated as a special case, where the
91
 
//         compressed block contains only 3 instead of 14 bytes:
92
 
//         t[0], followed by an "impossible" 6-bit shift value and
93
 
//         two padding bits.
94
 
//
95
 
//      This compressor can handle positive and negative pixel values.
96
 
//      NaNs and infinities are replaced with zeroes before compression.
97
 
//
98
 
//-----------------------------------------------------------------------------
99
 
 
100
 
#include <ImfB44Compressor.h>
101
 
#include <ImfHeader.h>
102
 
#include <ImfChannelList.h>
103
 
#include <ImfMisc.h>
104
 
#include <ImathFun.h>
105
 
#include <ImathBox.h>
106
 
#include <Iex.h>
107
 
#include <ImfIO.h>
108
 
#include <ImfXdr.h>
109
 
#include <string.h>
110
 
#include <assert.h>
111
 
#include <algorithm>
112
 
 
113
 
namespace Imf {
114
 
 
115
 
using Imath::divp;
116
 
using Imath::modp;
117
 
using Imath::Box2i;
118
 
using Imath::V2i;
119
 
using std::min;
120
 
 
121
 
namespace {
122
 
 
123
 
//
124
 
// Lookup tables for
125
 
//      y = exp (x / 8)
126
 
// and 
127
 
//      x = 8 * log (y)
128
 
//
129
 
 
130
 
#include "b44ExpLogTable.h"
131
 
 
132
 
 
133
 
inline void
134
 
convertFromLinear (unsigned short s[16])
135
 
{
136
 
    for (int i = 0; i < 16; ++i)
137
 
        s[i] = expTable[s[i]];
138
 
}
139
 
 
140
 
 
141
 
inline void
142
 
convertToLinear (unsigned short s[16])
143
 
{
144
 
    for (int i = 0; i < 16; ++i)
145
 
        s[i] = logTable[s[i]];
146
 
}
147
 
 
148
 
 
149
 
inline int
150
 
shiftAndRound (int x, int shift)
151
 
{
152
 
    //
153
 
    // Compute
154
 
    //
155
 
    //     y = x * pow (2, -shift),
156
 
    //
157
 
    // then round y to the nearest integer.
158
 
    // In case of a tie, where y is exactly
159
 
    // halfway between two integers, round
160
 
    // to the even one.
161
 
    //
162
 
 
163
 
    x <<= 1;
164
 
    int a = (1 << shift) - 1;
165
 
    shift += 1;
166
 
    int b = (x >> shift) & 1;
167
 
    return (x + a + b) >> shift;
168
 
}
169
 
 
170
 
 
171
 
int
172
 
pack (const unsigned short s[16],
173
 
      unsigned char b[14],
174
 
      bool optFlatFields,
175
 
      bool exactMax)
176
 
{
177
 
    //
178
 
    // Pack a block of 4 by 4 16-bit pixels (32 bytes) into
179
 
    // either 14 or 3 bytes.
180
 
    //
181
 
 
182
 
    //
183
 
    // Integers s[0] ... s[15] represent floating-point numbers
184
 
    // in what is essentially a sign-magnitude format.  Convert
185
 
    // s[0] .. s[15] into a new set of integers, t[0] ... t[15],
186
 
    // such that if t[i] is greater than t[j], the floating-point
187
 
    // number that corresponds to s[i] is always greater than
188
 
    // the floating-point number that corresponds to s[j].
189
 
    //
190
 
    // Also, replace any bit patterns that represent NaNs or
191
 
    // infinities with bit patterns that represent floating-point
192
 
    // zeroes.
193
 
    //
194
 
    //  bit pattern     floating-point          bit pattern
195
 
    //  in s[i]         value                   in t[i]
196
 
    //
197
 
    //  0x7fff          NAN                     0x8000
198
 
    //  0x7ffe          NAN                     0x8000
199
 
    //    ...                                     ...
200
 
    //  0x7c01          NAN                     0x8000
201
 
    //  0x7c00          +infinity               0x8000
202
 
    //  0x7bff          +HALF_MAX               0xfbff
203
 
    //  0x7bfe                                  0xfbfe
204
 
    //  0x7bfd                                  0xfbfd
205
 
    //    ...                                     ...
206
 
    //  0x0002          +2 * HALF_MIN           0x8002
207
 
    //  0x0001          +HALF_MIN               0x8001
208
 
    //  0x0000          +0.0                    0x8000
209
 
    //  0x8000          -0.0                    0x7fff
210
 
    //  0x8001          -HALF_MIN               0x7ffe
211
 
    //  0x8002          -2 * HALF_MIN           0x7ffd
212
 
    //    ...                                     ...
213
 
    //  0xfbfd                                  0x0f02
214
 
    //  0xfbfe                                  0x0401
215
 
    //  0xfbff          -HALF_MAX               0x0400
216
 
    //  0xfc00          -infinity               0x8000
217
 
    //  0xfc01          NAN                     0x8000
218
 
    //    ...                                     ...
219
 
    //  0xfffe          NAN                     0x8000
220
 
    //  0xffff          NAN                     0x8000
221
 
    //
222
 
 
223
 
    unsigned short t[16];
224
 
 
225
 
    for (int i = 0; i < 16; ++i)
226
 
    {
227
 
        if ((s[i] & 0x7c00) == 0x7c00)
228
 
            t[i] = 0x8000;
229
 
        else if (s[i] & 0x8000)
230
 
            t[i] = ~s[i];
231
 
        else
232
 
            t[i] = s[i] | 0x8000;
233
 
    }
234
 
    
235
 
    //
236
 
    // Find the maximum, tMax, of t[0] ... t[15].
237
 
    //
238
 
 
239
 
    unsigned short tMax = 0;
240
 
 
241
 
    for (int i = 0; i < 16; ++i)
242
 
        if (tMax < t[i])
243
 
            tMax = t[i];
244
 
 
245
 
    //
246
 
    // Compute a set of running differences, r[0] ... r[14]:
247
 
    // Find a shift value such that after rounding off the
248
 
    // rightmost bits and shifting all differenes are between
249
 
    // -32 and +31.  Then bias the differences so that they
250
 
    // end up between 0 and 63.
251
 
    //
252
 
 
253
 
    int shift = -1;
254
 
    int d[16];
255
 
    int r[15];
256
 
    int rMin;
257
 
    int rMax;
258
 
 
259
 
    const int bias = 0x20;
260
 
 
261
 
    do
262
 
    {
263
 
        shift += 1;
264
 
 
265
 
        //
266
 
        // Compute absolute differences, d[0] ... d[15],
267
 
        // between tMax and t[0] ... t[15].
268
 
        //
269
 
        // Shift and round the absolute differences.
270
 
        //
271
 
 
272
 
        for (int i = 0; i < 16; ++i)
273
 
            d[i] = shiftAndRound (tMax - t[i], shift);
274
 
 
275
 
        //
276
 
        // Convert d[0] .. d[15] into running differences
277
 
        //
278
 
 
279
 
        r[ 0] = d[ 0] - d[ 4] + bias;
280
 
        r[ 1] = d[ 4] - d[ 8] + bias;
281
 
        r[ 2] = d[ 8] - d[12] + bias;
282
 
 
283
 
        r[ 3] = d[ 0] - d[ 1] + bias;
284
 
        r[ 4] = d[ 4] - d[ 5] + bias;
285
 
        r[ 5] = d[ 8] - d[ 9] + bias;
286
 
        r[ 6] = d[12] - d[13] + bias;
287
 
 
288
 
        r[ 7] = d[ 1] - d[ 2] + bias;
289
 
        r[ 8] = d[ 5] - d[ 6] + bias;
290
 
        r[ 9] = d[ 9] - d[10] + bias;
291
 
        r[10] = d[13] - d[14] + bias;
292
 
 
293
 
        r[11] = d[ 2] - d[ 3] + bias;
294
 
        r[12] = d[ 6] - d[ 7] + bias;
295
 
        r[13] = d[10] - d[11] + bias;
296
 
        r[14] = d[14] - d[15] + bias;
297
 
 
298
 
        rMin = r[0];
299
 
        rMax = r[0];
300
 
 
301
 
        for (int i = 1; i < 15; ++i)
302
 
        {
303
 
            if (rMin > r[i])
304
 
                rMin = r[i];
305
 
 
306
 
            if (rMax < r[i])
307
 
                rMax = r[i];
308
 
        }
309
 
    }
310
 
    while (rMin < 0 || rMax > 0x3f);
311
 
 
312
 
    if (rMin == bias && rMax == bias && optFlatFields)
313
 
    {
314
 
        //
315
 
        // Special case - all pixels have the same value.
316
 
        // We encode this in 3 instead of 14 bytes by
317
 
        // storing the value 0xfc in the third output byte,
318
 
        // which cannot occur in the 14-byte encoding.
319
 
        //
320
 
 
321
 
        b[0] = (t[0] >> 8);
322
 
        b[1] =  t[0];
323
 
        b[2] = 0xfc;
324
 
 
325
 
        return 3;
326
 
    }
327
 
 
328
 
    if (exactMax)
329
 
    {
330
 
        //
331
 
        // Adjust t[0] so that the pixel whose value is equal
332
 
        // to tMax gets represented as accurately as possible.
333
 
        //
334
 
 
335
 
        t[0] = tMax - (d[0] << shift);
336
 
    }
337
 
 
338
 
    //
339
 
    // Pack t[0], shift and r[0] ... r[14] into 14 bytes:
340
 
    //
341
 
 
342
 
    b[ 0] = (t[0] >> 8);
343
 
    b[ 1] =  t[0];
344
 
 
345
 
    b[ 2] = (unsigned char) ((shift << 2) | (r[ 0] >> 4));
346
 
    b[ 3] = (unsigned char) ((r[ 0] << 4) | (r[ 1] >> 2));
347
 
    b[ 4] = (unsigned char) ((r[ 1] << 6) |  r[ 2]      );
348
 
 
349
 
    b[ 5] = (unsigned char) ((r[ 3] << 2) | (r[ 4] >> 4));
350
 
    b[ 6] = (unsigned char) ((r[ 4] << 4) | (r[ 5] >> 2));
351
 
    b[ 7] = (unsigned char) ((r[ 5] << 6) |  r[ 6]      );
352
 
 
353
 
    b[ 8] = (unsigned char) ((r[ 7] << 2) | (r[ 8] >> 4));
354
 
    b[ 9] = (unsigned char) ((r[ 8] << 4) | (r[ 9] >> 2));
355
 
    b[10] = (unsigned char) ((r[ 9] << 6) |  r[10]      );
356
 
 
357
 
    b[11] = (unsigned char) ((r[11] << 2) | (r[12] >> 4));
358
 
    b[12] = (unsigned char) ((r[12] << 4) | (r[13] >> 2));
359
 
    b[13] = (unsigned char) ((r[13] << 6) |  r[14]      );
360
 
 
361
 
    return 14;
362
 
}
363
 
 
364
 
 
365
 
inline
366
 
void
367
 
unpack14 (const unsigned char b[14], unsigned short s[16])
368
 
{
369
 
    //
370
 
    // Unpack a 14-byte block into 4 by 4 16-bit pixels.
371
 
    //
372
 
 
373
 
    #if defined (DEBUG)
374
 
        assert (b[2] != 0xfc);
375
 
    #endif
376
 
 
377
 
    s[ 0] = (b[0] << 8) | b[1];
378
 
 
379
 
    unsigned short shift = (b[ 2] >> 2);
380
 
    unsigned short bias = (0x20 << shift);
381
 
 
382
 
    s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) - bias;
383
 
    s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) - bias;
384
 
    s[12] = s[ 8] +   ((b[ 4]                       & 0x3f) << shift) - bias;
385
 
    
386
 
    s[ 1] = s[ 0] +   ((b[ 5] >> 2)                         << shift) - bias;
387
 
    s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) - bias;
388
 
    s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) - bias;
389
 
    s[13] = s[12] +   ((b[ 7]                       & 0x3f) << shift) - bias;
390
 
    
391
 
    s[ 2] = s[ 1] +   ((b[ 8] >> 2)                         << shift) - bias;
392
 
    s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) - bias;
393
 
    s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) - bias;
394
 
    s[14] = s[13] +   ((b[10]                       & 0x3f) << shift) - bias;
395
 
    
396
 
    s[ 3] = s[ 2] +   ((b[11] >> 2)                         << shift) - bias;
397
 
    s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) - bias;
398
 
    s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) - bias;
399
 
    s[15] = s[14] +   ((b[13]                       & 0x3f) << shift) - bias;
400
 
 
401
 
    for (int i = 0; i < 16; ++i)
402
 
    {
403
 
        if (s[i] & 0x8000)
404
 
            s[i] &= 0x7fff;
405
 
        else
406
 
            s[i] = ~s[i];
407
 
    }
408
 
}
409
 
 
410
 
 
411
 
inline
412
 
void
413
 
unpack3 (const unsigned char b[3], unsigned short s[16])
414
 
{
415
 
    //
416
 
    // Unpack a 3-byte block into 4 by 4 identical 16-bit pixels.
417
 
    //
418
 
 
419
 
    #if defined (DEBUG)
420
 
        assert (b[2] == 0xfc);
421
 
    #endif
422
 
 
423
 
    s[0] = (b[0] << 8) | b[1];
424
 
 
425
 
    if (s[0] & 0x8000)
426
 
        s[0] &= 0x7fff;
427
 
    else
428
 
        s[0] = ~s[0];
429
 
 
430
 
    for (int i = 1; i < 16; ++i)
431
 
        s[i] = s[0];
432
 
}
433
 
 
434
 
 
435
 
void
436
 
notEnoughData ()
437
 
{
438
 
    throw Iex::InputExc ("Error decompressing data "
439
 
                         "(input data are shorter than expected).");
440
 
}
441
 
 
442
 
 
443
 
void
444
 
tooMuchData ()
445
 
{
446
 
    throw Iex::InputExc ("Error decompressing data "
447
 
                         "(input data are longer than expected).");
448
 
}
449
 
 
450
 
} // namespace
451
 
 
452
 
 
453
 
struct B44Compressor::ChannelData
454
 
{
455
 
    unsigned short *    start;
456
 
    unsigned short *    end;
457
 
    int                 nx;
458
 
    int                 ny;
459
 
    int                 ys;
460
 
    PixelType           type;
461
 
    bool                pLinear;
462
 
    int                 size;
463
 
};
464
 
 
465
 
 
466
 
B44Compressor::B44Compressor
467
 
    (const Header &hdr,
468
 
     int maxScanLineSize,
469
 
     int numScanLines,
470
 
     bool optFlatFields)
471
 
:
472
 
    Compressor (hdr),
473
 
    _maxScanLineSize (maxScanLineSize),
474
 
    _optFlatFields (optFlatFields),
475
 
    _format (XDR),
476
 
    _numScanLines (numScanLines),
477
 
    _tmpBuffer (0),
478
 
    _outBuffer (0),
479
 
    _numChans (0),
480
 
    _channels (hdr.channels()),
481
 
    _channelData (0)
482
 
{
483
 
    //
484
 
    // Allocate buffers for compressed an uncompressed pixel data,
485
 
    // allocate a set of ChannelData structs to help speed up the
486
 
    // compress() and uncompress() functions, below, and determine
487
 
    // if uncompressed pixel data should be in native or Xdr format.
488
 
    //
489
 
 
490
 
    _tmpBuffer = new unsigned short [maxScanLineSize * numScanLines];
491
 
 
492
 
    const ChannelList &channels = header().channels();
493
 
    int numHalfChans = 0;
494
 
 
495
 
    for (ChannelList::ConstIterator c = channels.begin();
496
 
         c != channels.end();
497
 
         ++c)
498
 
    {
499
 
        assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0);
500
 
        ++_numChans;
501
 
 
502
 
        if (c.channel().type == HALF)
503
 
            ++numHalfChans;
504
 
    }
505
 
 
506
 
    //
507
 
    // Compressed data may be larger than the input data
508
 
    //
509
 
 
510
 
    int padding = 12 * numHalfChans * (numScanLines + 3) / 4;
511
 
 
512
 
    _outBuffer = new char [maxScanLineSize * numScanLines + padding];
513
 
    _channelData = new ChannelData[_numChans];
514
 
 
515
 
    int i = 0;
516
 
 
517
 
    for (ChannelList::ConstIterator c = channels.begin();
518
 
         c != channels.end();
519
 
         ++c, ++i)
520
 
    {
521
 
        _channelData[i].ys = c.channel().ySampling;
522
 
        _channelData[i].type = c.channel().type;
523
 
        _channelData[i].pLinear = c.channel().pLinear;
524
 
        _channelData[i].size =
525
 
            pixelTypeSize (c.channel().type) / pixelTypeSize (HALF);
526
 
    }
527
 
 
528
 
    const Box2i &dataWindow = hdr.dataWindow();
529
 
 
530
 
    _minX = dataWindow.min.x;
531
 
    _maxX = dataWindow.max.x;
532
 
    _maxY = dataWindow.max.y;
533
 
 
534
 
    //
535
 
    // We can support uncompressed data in the machine's native
536
 
    // format only if all image channels are of type HALF.
537
 
    //
538
 
 
539
 
    assert (sizeof (unsigned short) == pixelTypeSize (HALF));
540
 
 
541
 
    if (_numChans == numHalfChans)
542
 
        _format = NATIVE;
543
 
}
544
 
 
545
 
 
546
 
B44Compressor::~B44Compressor ()
547
 
{
548
 
    delete [] _tmpBuffer;
549
 
    delete [] _outBuffer;
550
 
    delete [] _channelData;
551
 
}
552
 
 
553
 
 
554
 
int
555
 
B44Compressor::numScanLines () const
556
 
{
557
 
    return _numScanLines;
558
 
}
559
 
 
560
 
 
561
 
Compressor::Format
562
 
B44Compressor::format () const
563
 
{
564
 
    return _format;
565
 
}
566
 
 
567
 
 
568
 
int
569
 
B44Compressor::compress (const char *inPtr,
570
 
                         int inSize,
571
 
                         int minY,
572
 
                         const char *&outPtr)
573
 
{
574
 
    return compress (inPtr,
575
 
                     inSize,
576
 
                     Box2i (V2i (_minX, minY),
577
 
                            V2i (_maxX, minY + numScanLines() - 1)),
578
 
                     outPtr);
579
 
}
580
 
 
581
 
 
582
 
int
583
 
B44Compressor::compressTile (const char *inPtr,
584
 
                             int inSize,
585
 
                             Imath::Box2i range,
586
 
                             const char *&outPtr)
587
 
{
588
 
    return compress (inPtr, inSize, range, outPtr);
589
 
}
590
 
 
591
 
 
592
 
int
593
 
B44Compressor::uncompress (const char *inPtr,
594
 
                           int inSize,
595
 
                           int minY,
596
 
                           const char *&outPtr)
597
 
{
598
 
    return uncompress (inPtr,
599
 
                       inSize,
600
 
                       Box2i (V2i (_minX, minY),
601
 
                              V2i (_maxX, minY + numScanLines() - 1)),
602
 
                       outPtr);
603
 
}
604
 
 
605
 
 
606
 
int
607
 
B44Compressor::uncompressTile (const char *inPtr,
608
 
                               int inSize,
609
 
                               Imath::Box2i range,
610
 
                               const char *&outPtr)
611
 
{
612
 
    return uncompress (inPtr, inSize, range, outPtr);
613
 
}
614
 
 
615
 
 
616
 
int
617
 
B44Compressor::compress (const char *inPtr,
618
 
                         int inSize,
619
 
                         Imath::Box2i range,
620
 
                         const char *&outPtr)
621
 
{
622
 
    //
623
 
    // Compress a block of pixel data:  First copy the input pixels
624
 
    // from the input buffer into _tmpBuffer, rearranging them such
625
 
    // that blocks of 4x4 pixels of a single channel can be accessed
626
 
    // conveniently.  Then compress each 4x4 block of HALF pixel data
627
 
    // and append the result to the output buffer.  Copy UINT and
628
 
    // FLOAT data to the output buffer without compressing them.
629
 
    //
630
 
 
631
 
    outPtr = _outBuffer;
632
 
 
633
 
    if (inSize == 0)
634
 
    {
635
 
        //
636
 
        // Special case - empty input buffer.
637
 
        //
638
 
 
639
 
        return 0;
640
 
    }
641
 
 
642
 
    //
643
 
    // For each channel, detemine how many pixels are stored
644
 
    // in the input buffer, and where those pixels will be
645
 
    // placed in _tmpBuffer.
646
 
    //
647
 
 
648
 
    int minX = range.min.x;
649
 
    int maxX = min (range.max.x, _maxX);
650
 
    int minY = range.min.y;
651
 
    int maxY = min (range.max.y, _maxY);
652
 
    
653
 
    unsigned short *tmpBufferEnd = _tmpBuffer;
654
 
    int i = 0;
655
 
 
656
 
    for (ChannelList::ConstIterator c = _channels.begin();
657
 
         c != _channels.end();
658
 
         ++c, ++i)
659
 
    {
660
 
        ChannelData &cd = _channelData[i];
661
 
 
662
 
        cd.start = tmpBufferEnd;
663
 
        cd.end = cd.start;
664
 
 
665
 
        cd.nx = numSamples (c.channel().xSampling, minX, maxX);
666
 
        cd.ny = numSamples (c.channel().ySampling, minY, maxY);
667
 
 
668
 
        tmpBufferEnd += cd.nx * cd.ny * cd.size;
669
 
    }
670
 
 
671
 
    if (_format == XDR)
672
 
    {
673
 
        //
674
 
        // The data in the input buffer are in the machine-independent
675
 
        // Xdr format.  Copy the HALF channels into _tmpBuffer and
676
 
        // convert them back into native format for compression.
677
 
        // Copy UINT and FLOAT channels verbatim into _tmpBuffer.
678
 
        //
679
 
 
680
 
        for (int y = minY; y <= maxY; ++y)
681
 
        {
682
 
            for (int i = 0; i < _numChans; ++i)
683
 
            {
684
 
                ChannelData &cd = _channelData[i];
685
 
 
686
 
                if (modp (y, cd.ys) != 0)
687
 
                    continue;
688
 
 
689
 
                if (cd.type == HALF)
690
 
                {
691
 
                    for (int x = cd.nx; x > 0; --x)
692
 
                    {
693
 
                        Xdr::read <CharPtrIO> (inPtr, *cd.end);
694
 
                        ++cd.end;
695
 
                    }
696
 
                }
697
 
                else
698
 
                {
699
 
                    int n = cd.nx * cd.size;
700
 
                    memcpy (cd.end, inPtr, n * sizeof (unsigned short));
701
 
                    inPtr += n * sizeof (unsigned short);
702
 
                    cd.end += n;
703
 
                }
704
 
            }
705
 
        }
706
 
    }
707
 
    else
708
 
    {
709
 
        //
710
 
        // The input buffer contains only HALF channels, and they
711
 
        // are in native, machine-dependent format.  Copy the pixels
712
 
        // into _tmpBuffer.
713
 
        //
714
 
 
715
 
        for (int y = minY; y <= maxY; ++y)
716
 
        {
717
 
            for (int i = 0; i < _numChans; ++i)
718
 
            {
719
 
                ChannelData &cd = _channelData[i];
720
 
 
721
 
                #if defined (DEBUG)
722
 
                    assert (cd.type == HALF);
723
 
                #endif
724
 
 
725
 
                if (modp (y, cd.ys) != 0)
726
 
                    continue;
727
 
 
728
 
                int n = cd.nx * cd.size;
729
 
                memcpy (cd.end, inPtr, n * sizeof (unsigned short));
730
 
                inPtr  += n * sizeof (unsigned short);
731
 
                cd.end += n;
732
 
            }
733
 
        }
734
 
    }
735
 
 
736
 
    //
737
 
    // The pixels for each channel have been packed into a contiguous
738
 
    // block in _tmpBuffer.  HALF channels are in native format; UINT
739
 
    // and FLOAT channels are in Xdr format.
740
 
    //
741
 
 
742
 
    #if defined (DEBUG)
743
 
 
744
 
        for (int i = 1; i < _numChans; ++i)
745
 
            assert (_channelData[i-1].end == _channelData[i].start);
746
 
 
747
 
        assert (_channelData[_numChans-1].end == tmpBufferEnd);
748
 
 
749
 
    #endif
750
 
 
751
 
    //
752
 
    // For each HALF channel, split the data in _tmpBuffer into 4x4
753
 
    // pixel blocks.  Compress each block and append the compressed
754
 
    // data to the output buffer.
755
 
    //
756
 
    // UINT and FLOAT channels are copied from _tmpBuffer into the
757
 
    // output buffer without further processing.
758
 
    //
759
 
 
760
 
    char *outEnd = _outBuffer;
761
 
 
762
 
    for (int i = 0; i < _numChans; ++i)
763
 
    {
764
 
        ChannelData &cd = _channelData[i];
765
 
        
766
 
        if (cd.type != HALF)
767
 
        {
768
 
            //
769
 
            // UINT or FLOAT channel.
770
 
            //
771
 
 
772
 
            int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
773
 
            memcpy (outEnd, cd.start, n);
774
 
            outEnd += n;
775
 
 
776
 
            continue;
777
 
        }
778
 
        
779
 
        //
780
 
        // HALF channel
781
 
        //
782
 
 
783
 
        for (int y = 0; y < cd.ny; y += 4)
784
 
        {
785
 
            //
786
 
            // Copy the next 4x4 pixel block into array s.
787
 
            // If the width, cd.nx, or the height, cd.ny, of
788
 
            // the pixel data in _tmpBuffer is not divisible
789
 
            // by 4, then pad the data by repeating the
790
 
            // rightmost column and the bottom row.
791
 
            // 
792
 
 
793
 
            unsigned short *row0 = cd.start + y * cd.nx;
794
 
            unsigned short *row1 = row0 + cd.nx;
795
 
            unsigned short *row2 = row1 + cd.nx;
796
 
            unsigned short *row3 = row2 + cd.nx;
797
 
 
798
 
            if (y + 3 >= cd.ny)
799
 
            {
800
 
                if (y + 1 >= cd.ny)
801
 
                    row1 = row0;
802
 
 
803
 
                if (y + 2 >= cd.ny)
804
 
                    row2 = row1;
805
 
 
806
 
                row3 = row2;
807
 
            }
808
 
 
809
 
            for (int x = 0; x < cd.nx; x += 4)
810
 
            {
811
 
                unsigned short s[16];
812
 
 
813
 
                if (x + 3 >= cd.nx)
814
 
                {
815
 
                    int n = cd.nx - x;
816
 
 
817
 
                    for (int i = 0; i < 4; ++i)
818
 
                    {
819
 
                        int j = min (i, n - 1);
820
 
 
821
 
                        s[i +  0] = row0[j];
822
 
                        s[i +  4] = row1[j];
823
 
                        s[i +  8] = row2[j];
824
 
                        s[i + 12] = row3[j];
825
 
                    }
826
 
                }
827
 
                else
828
 
                {
829
 
                    memcpy (&s[ 0], row0, 4 * sizeof (unsigned short));
830
 
                    memcpy (&s[ 4], row1, 4 * sizeof (unsigned short));
831
 
                    memcpy (&s[ 8], row2, 4 * sizeof (unsigned short));
832
 
                    memcpy (&s[12], row3, 4 * sizeof (unsigned short));
833
 
                }
834
 
 
835
 
                row0 += 4;
836
 
                row1 += 4;
837
 
                row2 += 4;
838
 
                row3 += 4;
839
 
 
840
 
                //
841
 
                // Compress the contents of array s and append the
842
 
                // results to the output buffer.
843
 
                //
844
 
 
845
 
                if (cd.pLinear)
846
 
                    convertFromLinear (s);
847
 
 
848
 
                outEnd += pack (s, (unsigned char *) outEnd,
849
 
                                _optFlatFields, !cd.pLinear);
850
 
            }
851
 
        }
852
 
    }
853
 
 
854
 
    return outEnd - _outBuffer;
855
 
}
856
 
 
857
 
 
858
 
int
859
 
B44Compressor::uncompress (const char *inPtr,
860
 
                           int inSize,
861
 
                           Imath::Box2i range,
862
 
                           const char *&outPtr)
863
 
{
864
 
    //
865
 
    // This function is the reverse of the compress() function,
866
 
    // above.  First all pixels are moved from the input buffer
867
 
    // into _tmpBuffer.  UINT and FLOAT channels are copied
868
 
    // verbatim; HALF channels are uncompressed in blocks of
869
 
    // 4x4 pixels.  Then the pixels in _tmpBuffer are copied
870
 
    // into the output buffer and rearranged such that the data
871
 
    // for for each scan line form a contiguous block.
872
 
    //
873
 
 
874
 
    outPtr = _outBuffer;
875
 
 
876
 
    if (inSize == 0)
877
 
    {
878
 
        return 0;
879
 
    }
880
 
 
881
 
    int minX = range.min.x;
882
 
    int maxX = min (range.max.x, _maxX);
883
 
    int minY = range.min.y;
884
 
    int maxY = min (range.max.y, _maxY);
885
 
    
886
 
    unsigned short *tmpBufferEnd = _tmpBuffer;
887
 
    int i = 0;
888
 
 
889
 
    for (ChannelList::ConstIterator c = _channels.begin();
890
 
         c != _channels.end();
891
 
         ++c, ++i)
892
 
    {
893
 
        ChannelData &cd = _channelData[i];
894
 
 
895
 
        cd.start = tmpBufferEnd;
896
 
        cd.end = cd.start;
897
 
 
898
 
        cd.nx = numSamples (c.channel().xSampling, minX, maxX);
899
 
        cd.ny = numSamples (c.channel().ySampling, minY, maxY);
900
 
 
901
 
        tmpBufferEnd += cd.nx * cd.ny * cd.size;
902
 
    }
903
 
 
904
 
    for (int i = 0; i < _numChans; ++i)
905
 
    {
906
 
        ChannelData &cd = _channelData[i];
907
 
 
908
 
        if (cd.type != HALF)
909
 
        {
910
 
            //
911
 
            // UINT or FLOAT channel.
912
 
            //
913
 
 
914
 
            int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
915
 
 
916
 
            if (inSize < n)
917
 
                notEnoughData();
918
 
 
919
 
            memcpy (cd.start, inPtr, n);
920
 
            inPtr += n;
921
 
            inSize -= n;
922
 
 
923
 
            continue;
924
 
        }
925
 
 
926
 
        //
927
 
        // HALF channel
928
 
        //
929
 
 
930
 
        for (int y = 0; y < cd.ny; y += 4)
931
 
        {
932
 
            unsigned short *row0 = cd.start + y * cd.nx;
933
 
            unsigned short *row1 = row0 + cd.nx;
934
 
            unsigned short *row2 = row1 + cd.nx;
935
 
            unsigned short *row3 = row2 + cd.nx;
936
 
 
937
 
            for (int x = 0; x < cd.nx; x += 4)
938
 
            {
939
 
                unsigned short s[16]; 
940
 
 
941
 
                if (inSize < 3)
942
 
                    notEnoughData();
943
 
 
944
 
                if (((const unsigned char *)inPtr)[2] == 0xfc)
945
 
                {
946
 
                    unpack3 ((const unsigned char *)inPtr, s);
947
 
                    inPtr += 3;
948
 
                    inSize -= 3;
949
 
                }
950
 
                else
951
 
                {
952
 
                    if (inSize < 14)
953
 
                        notEnoughData();
954
 
 
955
 
                    unpack14 ((const unsigned char *)inPtr, s);
956
 
                    inPtr += 14;
957
 
                    inSize -= 14;
958
 
                }
959
 
 
960
 
                if (cd.pLinear)
961
 
                    convertToLinear (s);
962
 
 
963
 
                int n = (x + 3 < cd.nx)?
964
 
                            4 * sizeof (unsigned short) :
965
 
                            (cd.nx - x) * sizeof (unsigned short);
966
 
 
967
 
                if (y + 3 < cd.ny)
968
 
                {
969
 
                    memcpy (row0, &s[ 0], n);
970
 
                    memcpy (row1, &s[ 4], n);
971
 
                    memcpy (row2, &s[ 8], n);
972
 
                    memcpy (row3, &s[12], n);
973
 
                }
974
 
                else
975
 
                {
976
 
                    memcpy (row0, &s[ 0], n);
977
 
 
978
 
                    if (y + 1 < cd.ny)
979
 
                        memcpy (row1, &s[ 4], n);
980
 
 
981
 
                    if (y + 2 < cd.ny)
982
 
                        memcpy (row2, &s[ 8], n);
983
 
                }
984
 
 
985
 
                row0 += 4;
986
 
                row1 += 4;
987
 
                row2 += 4;
988
 
                row3 += 4;
989
 
            }
990
 
        }
991
 
    }
992
 
 
993
 
    char *outEnd = _outBuffer;
994
 
 
995
 
    if (_format == XDR)
996
 
    {
997
 
        for (int y = minY; y <= maxY; ++y)
998
 
        {
999
 
            for (int i = 0; i < _numChans; ++i)
1000
 
            {
1001
 
                ChannelData &cd = _channelData[i];
1002
 
 
1003
 
                if (modp (y, cd.ys) != 0)
1004
 
                    continue;
1005
 
 
1006
 
                if (cd.type == HALF)
1007
 
                {
1008
 
                    for (int x = cd.nx; x > 0; --x)
1009
 
                    {
1010
 
                        Xdr::write <CharPtrIO> (outEnd, *cd.end);
1011
 
                        ++cd.end;
1012
 
                    }
1013
 
                }
1014
 
                else
1015
 
                {
1016
 
                    int n = cd.nx * cd.size;
1017
 
                    memcpy (outEnd, cd.end, n * sizeof (unsigned short));
1018
 
                    outEnd += n * sizeof (unsigned short);
1019
 
                    cd.end += n;
1020
 
                }
1021
 
            }
1022
 
        }
1023
 
    }
1024
 
    else
1025
 
    {
1026
 
        for (int y = minY; y <= maxY; ++y)
1027
 
        {
1028
 
            for (int i = 0; i < _numChans; ++i)
1029
 
            {
1030
 
                ChannelData &cd = _channelData[i];
1031
 
 
1032
 
                #if defined (DEBUG)
1033
 
                    assert (cd.type == HALF);
1034
 
                #endif
1035
 
 
1036
 
                if (modp (y, cd.ys) != 0)
1037
 
                    continue;
1038
 
 
1039
 
                int n = cd.nx * cd.size;
1040
 
                memcpy (outEnd, cd.end, n * sizeof (unsigned short));
1041
 
                outEnd += n * sizeof (unsigned short);
1042
 
                cd.end += n;
1043
 
            }
1044
 
        }
1045
 
    }
1046
 
 
1047
 
    #if defined (DEBUG)
1048
 
 
1049
 
        for (int i = 1; i < _numChans; ++i)
1050
 
            assert (_channelData[i-1].end == _channelData[i].start);
1051
 
 
1052
 
        assert (_channelData[_numChans-1].end == tmpBufferEnd);
1053
 
 
1054
 
    #endif
1055
 
 
1056
 
    if (inSize > 0)
1057
 
        tooMuchData();
1058
 
 
1059
 
    outPtr = _outBuffer;
1060
 
    return outEnd - _outBuffer;
1061
 
}
1062
 
 
1063
 
 
1064
 
} // namespace Imf
 
1
///////////////////////////////////////////////////////////////////////////
 
2
//
 
3
// Copyright (c) 2006, Industrial Light & Magic, a division of Lucas
 
4
// Digital Ltd. LLC
 
5
// 
 
6
// All rights reserved.
 
7
// 
 
8
// Redistribution and use in source and binary forms, with or without
 
9
// modification, are permitted provided that the following conditions are
 
10
// met:
 
11
// *       Redistributions of source code must retain the above copyright
 
12
// notice, this list of conditions and the following disclaimer.
 
13
// *       Redistributions in binary form must reproduce the above
 
14
// copyright notice, this list of conditions and the following disclaimer
 
15
// in the documentation and/or other materials provided with the
 
16
// distribution.
 
17
// *       Neither the name of Industrial Light & Magic nor the names of
 
18
// its contributors may be used to endorse or promote products derived
 
19
// from this software without specific prior written permission. 
 
20
// 
 
21
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
22
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
23
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
24
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 
25
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
26
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
27
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
28
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
29
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
30
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
31
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
32
//
 
33
///////////////////////////////////////////////////////////////////////////
 
34
 
 
35
 
 
36
//-----------------------------------------------------------------------------
 
37
//
 
38
//      class B44Compressor
 
39
//
 
40
//      This compressor is lossy for HALF channels; the compression rate
 
41
//      is fixed at 32/14 (approximately 2.28).  FLOAT and UINT channels
 
42
//      are not compressed; their data are preserved exactly.
 
43
//
 
44
//      Each HALF channel is split into blocks of 4 by 4 pixels.  An
 
45
//      uncompressed block occupies 32 bytes, which are re-interpreted
 
46
//      as sixteen 16-bit unsigned integers, t[0] ... t[15].  Compression
 
47
//      shrinks the block to 14 bytes.  The compressed 14-byte block
 
48
//      contains
 
49
//
 
50
//       - t[0]
 
51
//
 
52
//       - a 6-bit shift value
 
53
//
 
54
//       - 15 densely packed 6-bit values, r[0] ... r[14], which are
 
55
//         computed by subtracting adjacent pixel values and right-
 
56
//         shifting the differences according to the stored shift value.
 
57
//
 
58
//         Differences between adjacent pixels are computed according
 
59
//         to the following diagram:
 
60
//
 
61
//               0 -------->  1 -------->  2 -------->  3
 
62
//               |     3            7           11
 
63
//               |
 
64
//               | 0
 
65
//               |
 
66
//               v 
 
67
//               4 -------->  5 -------->  6 -------->  7
 
68
//               |     4            8           12
 
69
//               |
 
70
//               | 1
 
71
//               |
 
72
//               v
 
73
//               8 -------->  9 --------> 10 --------> 11
 
74
//               |     5            9           13
 
75
//               |
 
76
//               | 2
 
77
//               |
 
78
//               v
 
79
//              12 --------> 13 --------> 14 --------> 15
 
80
//                     6           10           14
 
81
//
 
82
//          Here
 
83
//
 
84
//               5 ---------> 6
 
85
//                     8
 
86
//
 
87
//          means that r[8] is the difference between t[5] and t[6].
 
88
//
 
89
//       - optionally, a 4-by-4 pixel block where all pixels have the
 
90
//         same value can be treated as a special case, where the
 
91
//         compressed block contains only 3 instead of 14 bytes:
 
92
//         t[0], followed by an "impossible" 6-bit shift value and
 
93
//         two padding bits.
 
94
//
 
95
//      This compressor can handle positive and negative pixel values.
 
96
//      NaNs and infinities are replaced with zeroes before compression.
 
97
//
 
98
//-----------------------------------------------------------------------------
 
99
 
 
100
#include <ImfB44Compressor.h>
 
101
#include <ImfHeader.h>
 
102
#include <ImfChannelList.h>
 
103
#include <ImfMisc.h>
 
104
#include <ImathFun.h>
 
105
#include <ImathBox.h>
 
106
#include <Iex.h>
 
107
#include <ImfIO.h>
 
108
#include <ImfXdr.h>
 
109
#include <string.h>
 
110
#include <assert.h>
 
111
#include <algorithm>
 
112
 
 
113
namespace Imf {
 
114
 
 
115
using Imath::divp;
 
116
using Imath::modp;
 
117
using Imath::Box2i;
 
118
using Imath::V2i;
 
119
using std::min;
 
120
 
 
121
namespace {
 
122
 
 
123
//
 
124
// Lookup tables for
 
125
//      y = exp (x / 8)
 
126
// and 
 
127
//      x = 8 * log (y)
 
128
//
 
129
 
 
130
#include "b44ExpLogTable.h"
 
131
 
 
132
 
 
133
inline void
 
134
convertFromLinear (unsigned short s[16])
 
135
{
 
136
    for (int i = 0; i < 16; ++i)
 
137
        s[i] = expTable[s[i]];
 
138
}
 
139
 
 
140
 
 
141
inline void
 
142
convertToLinear (unsigned short s[16])
 
143
{
 
144
    for (int i = 0; i < 16; ++i)
 
145
        s[i] = logTable[s[i]];
 
146
}
 
147
 
 
148
 
 
149
inline int
 
150
shiftAndRound (int x, int shift)
 
151
{
 
152
    //
 
153
    // Compute
 
154
    //
 
155
    //     y = x * pow (2, -shift),
 
156
    //
 
157
    // then round y to the nearest integer.
 
158
    // In case of a tie, where y is exactly
 
159
    // halfway between two integers, round
 
160
    // to the even one.
 
161
    //
 
162
 
 
163
    x <<= 1;
 
164
    int a = (1 << shift) - 1;
 
165
    shift += 1;
 
166
    int b = (x >> shift) & 1;
 
167
    return (x + a + b) >> shift;
 
168
}
 
169
 
 
170
 
 
171
int
 
172
pack (const unsigned short s[16],
 
173
      unsigned char b[14],
 
174
      bool optFlatFields,
 
175
      bool exactMax)
 
176
{
 
177
    //
 
178
    // Pack a block of 4 by 4 16-bit pixels (32 bytes) into
 
179
    // either 14 or 3 bytes.
 
180
    //
 
181
 
 
182
    //
 
183
    // Integers s[0] ... s[15] represent floating-point numbers
 
184
    // in what is essentially a sign-magnitude format.  Convert
 
185
    // s[0] .. s[15] into a new set of integers, t[0] ... t[15],
 
186
    // such that if t[i] is greater than t[j], the floating-point
 
187
    // number that corresponds to s[i] is always greater than
 
188
    // the floating-point number that corresponds to s[j].
 
189
    //
 
190
    // Also, replace any bit patterns that represent NaNs or
 
191
    // infinities with bit patterns that represent floating-point
 
192
    // zeroes.
 
193
    //
 
194
    //  bit pattern     floating-point          bit pattern
 
195
    //  in s[i]         value                   in t[i]
 
196
    //
 
197
    //  0x7fff          NAN                     0x8000
 
198
    //  0x7ffe          NAN                     0x8000
 
199
    //    ...                                     ...
 
200
    //  0x7c01          NAN                     0x8000
 
201
    //  0x7c00          +infinity               0x8000
 
202
    //  0x7bff          +HALF_MAX               0xfbff
 
203
    //  0x7bfe                                  0xfbfe
 
204
    //  0x7bfd                                  0xfbfd
 
205
    //    ...                                     ...
 
206
    //  0x0002          +2 * HALF_MIN           0x8002
 
207
    //  0x0001          +HALF_MIN               0x8001
 
208
    //  0x0000          +0.0                    0x8000
 
209
    //  0x8000          -0.0                    0x7fff
 
210
    //  0x8001          -HALF_MIN               0x7ffe
 
211
    //  0x8002          -2 * HALF_MIN           0x7ffd
 
212
    //    ...                                     ...
 
213
    //  0xfbfd                                  0x0f02
 
214
    //  0xfbfe                                  0x0401
 
215
    //  0xfbff          -HALF_MAX               0x0400
 
216
    //  0xfc00          -infinity               0x8000
 
217
    //  0xfc01          NAN                     0x8000
 
218
    //    ...                                     ...
 
219
    //  0xfffe          NAN                     0x8000
 
220
    //  0xffff          NAN                     0x8000
 
221
    //
 
222
 
 
223
    unsigned short t[16];
 
224
 
 
225
    for (int i = 0; i < 16; ++i)
 
226
    {
 
227
        if ((s[i] & 0x7c00) == 0x7c00)
 
228
            t[i] = 0x8000;
 
229
        else if (s[i] & 0x8000)
 
230
            t[i] = ~s[i];
 
231
        else
 
232
            t[i] = s[i] | 0x8000;
 
233
    }
 
234
    
 
235
    //
 
236
    // Find the maximum, tMax, of t[0] ... t[15].
 
237
    //
 
238
 
 
239
    unsigned short tMax = 0;
 
240
 
 
241
    for (int i = 0; i < 16; ++i)
 
242
        if (tMax < t[i])
 
243
            tMax = t[i];
 
244
 
 
245
    //
 
246
    // Compute a set of running differences, r[0] ... r[14]:
 
247
    // Find a shift value such that after rounding off the
 
248
    // rightmost bits and shifting all differenes are between
 
249
    // -32 and +31.  Then bias the differences so that they
 
250
    // end up between 0 and 63.
 
251
    //
 
252
 
 
253
    int shift = -1;
 
254
    int d[16];
 
255
    int r[15];
 
256
    int rMin;
 
257
    int rMax;
 
258
 
 
259
    const int bias = 0x20;
 
260
 
 
261
    do
 
262
    {
 
263
        shift += 1;
 
264
 
 
265
        //
 
266
        // Compute absolute differences, d[0] ... d[15],
 
267
        // between tMax and t[0] ... t[15].
 
268
        //
 
269
        // Shift and round the absolute differences.
 
270
        //
 
271
 
 
272
        for (int i = 0; i < 16; ++i)
 
273
            d[i] = shiftAndRound (tMax - t[i], shift);
 
274
 
 
275
        //
 
276
        // Convert d[0] .. d[15] into running differences
 
277
        //
 
278
 
 
279
        r[ 0] = d[ 0] - d[ 4] + bias;
 
280
        r[ 1] = d[ 4] - d[ 8] + bias;
 
281
        r[ 2] = d[ 8] - d[12] + bias;
 
282
 
 
283
        r[ 3] = d[ 0] - d[ 1] + bias;
 
284
        r[ 4] = d[ 4] - d[ 5] + bias;
 
285
        r[ 5] = d[ 8] - d[ 9] + bias;
 
286
        r[ 6] = d[12] - d[13] + bias;
 
287
 
 
288
        r[ 7] = d[ 1] - d[ 2] + bias;
 
289
        r[ 8] = d[ 5] - d[ 6] + bias;
 
290
        r[ 9] = d[ 9] - d[10] + bias;
 
291
        r[10] = d[13] - d[14] + bias;
 
292
 
 
293
        r[11] = d[ 2] - d[ 3] + bias;
 
294
        r[12] = d[ 6] - d[ 7] + bias;
 
295
        r[13] = d[10] - d[11] + bias;
 
296
        r[14] = d[14] - d[15] + bias;
 
297
 
 
298
        rMin = r[0];
 
299
        rMax = r[0];
 
300
 
 
301
        for (int i = 1; i < 15; ++i)
 
302
        {
 
303
            if (rMin > r[i])
 
304
                rMin = r[i];
 
305
 
 
306
            if (rMax < r[i])
 
307
                rMax = r[i];
 
308
        }
 
309
    }
 
310
    while (rMin < 0 || rMax > 0x3f);
 
311
 
 
312
    if (rMin == bias && rMax == bias && optFlatFields)
 
313
    {
 
314
        //
 
315
        // Special case - all pixels have the same value.
 
316
        // We encode this in 3 instead of 14 bytes by
 
317
        // storing the value 0xfc in the third output byte,
 
318
        // which cannot occur in the 14-byte encoding.
 
319
        //
 
320
 
 
321
        b[0] = (t[0] >> 8);
 
322
        b[1] =  t[0];
 
323
        b[2] = 0xfc;
 
324
 
 
325
        return 3;
 
326
    }
 
327
 
 
328
    if (exactMax)
 
329
    {
 
330
        //
 
331
        // Adjust t[0] so that the pixel whose value is equal
 
332
        // to tMax gets represented as accurately as possible.
 
333
        //
 
334
 
 
335
        t[0] = tMax - (d[0] << shift);
 
336
    }
 
337
 
 
338
    //
 
339
    // Pack t[0], shift and r[0] ... r[14] into 14 bytes:
 
340
    //
 
341
 
 
342
    b[ 0] = (t[0] >> 8);
 
343
    b[ 1] =  t[0];
 
344
 
 
345
    b[ 2] = (unsigned char) ((shift << 2) | (r[ 0] >> 4));
 
346
    b[ 3] = (unsigned char) ((r[ 0] << 4) | (r[ 1] >> 2));
 
347
    b[ 4] = (unsigned char) ((r[ 1] << 6) |  r[ 2]      );
 
348
 
 
349
    b[ 5] = (unsigned char) ((r[ 3] << 2) | (r[ 4] >> 4));
 
350
    b[ 6] = (unsigned char) ((r[ 4] << 4) | (r[ 5] >> 2));
 
351
    b[ 7] = (unsigned char) ((r[ 5] << 6) |  r[ 6]      );
 
352
 
 
353
    b[ 8] = (unsigned char) ((r[ 7] << 2) | (r[ 8] >> 4));
 
354
    b[ 9] = (unsigned char) ((r[ 8] << 4) | (r[ 9] >> 2));
 
355
    b[10] = (unsigned char) ((r[ 9] << 6) |  r[10]      );
 
356
 
 
357
    b[11] = (unsigned char) ((r[11] << 2) | (r[12] >> 4));
 
358
    b[12] = (unsigned char) ((r[12] << 4) | (r[13] >> 2));
 
359
    b[13] = (unsigned char) ((r[13] << 6) |  r[14]      );
 
360
 
 
361
    return 14;
 
362
}
 
363
 
 
364
 
 
365
inline
 
366
void
 
367
unpack14 (const unsigned char b[14], unsigned short s[16])
 
368
{
 
369
    //
 
370
    // Unpack a 14-byte block into 4 by 4 16-bit pixels.
 
371
    //
 
372
 
 
373
    #if defined (DEBUG)
 
374
        assert (b[2] != 0xfc);
 
375
    #endif
 
376
 
 
377
    s[ 0] = (b[0] << 8) | b[1];
 
378
 
 
379
    unsigned short shift = (b[ 2] >> 2);
 
380
    unsigned short bias = (0x20 << shift);
 
381
 
 
382
    s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) - bias;
 
383
    s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) - bias;
 
384
    s[12] = s[ 8] +   ((b[ 4]                       & 0x3f) << shift) - bias;
 
385
    
 
386
    s[ 1] = s[ 0] +   ((b[ 5] >> 2)                         << shift) - bias;
 
387
    s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) - bias;
 
388
    s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) - bias;
 
389
    s[13] = s[12] +   ((b[ 7]                       & 0x3f) << shift) - bias;
 
390
    
 
391
    s[ 2] = s[ 1] +   ((b[ 8] >> 2)                         << shift) - bias;
 
392
    s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) - bias;
 
393
    s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) - bias;
 
394
    s[14] = s[13] +   ((b[10]                       & 0x3f) << shift) - bias;
 
395
    
 
396
    s[ 3] = s[ 2] +   ((b[11] >> 2)                         << shift) - bias;
 
397
    s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) - bias;
 
398
    s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) - bias;
 
399
    s[15] = s[14] +   ((b[13]                       & 0x3f) << shift) - bias;
 
400
 
 
401
    for (int i = 0; i < 16; ++i)
 
402
    {
 
403
        if (s[i] & 0x8000)
 
404
            s[i] &= 0x7fff;
 
405
        else
 
406
            s[i] = ~s[i];
 
407
    }
 
408
}
 
409
 
 
410
 
 
411
inline
 
412
void
 
413
unpack3 (const unsigned char b[3], unsigned short s[16])
 
414
{
 
415
    //
 
416
    // Unpack a 3-byte block into 4 by 4 identical 16-bit pixels.
 
417
    //
 
418
 
 
419
    #if defined (DEBUG)
 
420
        assert (b[2] == 0xfc);
 
421
    #endif
 
422
 
 
423
    s[0] = (b[0] << 8) | b[1];
 
424
 
 
425
    if (s[0] & 0x8000)
 
426
        s[0] &= 0x7fff;
 
427
    else
 
428
        s[0] = ~s[0];
 
429
 
 
430
    for (int i = 1; i < 16; ++i)
 
431
        s[i] = s[0];
 
432
}
 
433
 
 
434
 
 
435
void
 
436
notEnoughData ()
 
437
{
 
438
    throw Iex::InputExc ("Error decompressing data "
 
439
                         "(input data are shorter than expected).");
 
440
}
 
441
 
 
442
 
 
443
void
 
444
tooMuchData ()
 
445
{
 
446
    throw Iex::InputExc ("Error decompressing data "
 
447
                         "(input data are longer than expected).");
 
448
}
 
449
 
 
450
} // namespace
 
451
 
 
452
 
 
453
struct B44Compressor::ChannelData
 
454
{
 
455
    unsigned short *    start;
 
456
    unsigned short *    end;
 
457
    int                 nx;
 
458
    int                 ny;
 
459
    int                 ys;
 
460
    PixelType           type;
 
461
    bool                pLinear;
 
462
    int                 size;
 
463
};
 
464
 
 
465
 
 
466
B44Compressor::B44Compressor
 
467
    (const Header &hdr,
 
468
     int maxScanLineSize,
 
469
     int numScanLines,
 
470
     bool optFlatFields)
 
471
:
 
472
    Compressor (hdr),
 
473
    _maxScanLineSize (maxScanLineSize),
 
474
    _optFlatFields (optFlatFields),
 
475
    _format (XDR),
 
476
    _numScanLines (numScanLines),
 
477
    _tmpBuffer (0),
 
478
    _outBuffer (0),
 
479
    _numChans (0),
 
480
    _channels (hdr.channels()),
 
481
    _channelData (0)
 
482
{
 
483
    //
 
484
    // Allocate buffers for compressed an uncompressed pixel data,
 
485
    // allocate a set of ChannelData structs to help speed up the
 
486
    // compress() and uncompress() functions, below, and determine
 
487
    // if uncompressed pixel data should be in native or Xdr format.
 
488
    //
 
489
 
 
490
    _tmpBuffer = new unsigned short [maxScanLineSize * numScanLines];
 
491
 
 
492
    const ChannelList &channels = header().channels();
 
493
    int numHalfChans = 0;
 
494
 
 
495
    for (ChannelList::ConstIterator c = channels.begin();
 
496
         c != channels.end();
 
497
         ++c)
 
498
    {
 
499
        assert (pixelTypeSize (c.channel().type) % pixelTypeSize (HALF) == 0);
 
500
        ++_numChans;
 
501
 
 
502
        if (c.channel().type == HALF)
 
503
            ++numHalfChans;
 
504
    }
 
505
 
 
506
    //
 
507
    // Compressed data may be larger than the input data
 
508
    //
 
509
 
 
510
    int padding = 12 * numHalfChans * (numScanLines + 3) / 4;
 
511
 
 
512
    _outBuffer = new char [maxScanLineSize * numScanLines + padding];
 
513
    _channelData = new ChannelData[_numChans];
 
514
 
 
515
    int i = 0;
 
516
 
 
517
    for (ChannelList::ConstIterator c = channels.begin();
 
518
         c != channels.end();
 
519
         ++c, ++i)
 
520
    {
 
521
        _channelData[i].ys = c.channel().ySampling;
 
522
        _channelData[i].type = c.channel().type;
 
523
        _channelData[i].pLinear = c.channel().pLinear;
 
524
        _channelData[i].size =
 
525
            pixelTypeSize (c.channel().type) / pixelTypeSize (HALF);
 
526
    }
 
527
 
 
528
    const Box2i &dataWindow = hdr.dataWindow();
 
529
 
 
530
    _minX = dataWindow.min.x;
 
531
    _maxX = dataWindow.max.x;
 
532
    _maxY = dataWindow.max.y;
 
533
 
 
534
    //
 
535
    // We can support uncompressed data in the machine's native
 
536
    // format only if all image channels are of type HALF.
 
537
    //
 
538
 
 
539
    assert (sizeof (unsigned short) == pixelTypeSize (HALF));
 
540
 
 
541
    if (_numChans == numHalfChans)
 
542
        _format = NATIVE;
 
543
}
 
544
 
 
545
 
 
546
B44Compressor::~B44Compressor ()
 
547
{
 
548
    delete [] _tmpBuffer;
 
549
    delete [] _outBuffer;
 
550
    delete [] _channelData;
 
551
}
 
552
 
 
553
 
 
554
int
 
555
B44Compressor::numScanLines () const
 
556
{
 
557
    return _numScanLines;
 
558
}
 
559
 
 
560
 
 
561
Compressor::Format
 
562
B44Compressor::format () const
 
563
{
 
564
    return _format;
 
565
}
 
566
 
 
567
 
 
568
int
 
569
B44Compressor::compress (const char *inPtr,
 
570
                         int inSize,
 
571
                         int minY,
 
572
                         const char *&outPtr)
 
573
{
 
574
    return compress (inPtr,
 
575
                     inSize,
 
576
                     Box2i (V2i (_minX, minY),
 
577
                            V2i (_maxX, minY + numScanLines() - 1)),
 
578
                     outPtr);
 
579
}
 
580
 
 
581
 
 
582
int
 
583
B44Compressor::compressTile (const char *inPtr,
 
584
                             int inSize,
 
585
                             Imath::Box2i range,
 
586
                             const char *&outPtr)
 
587
{
 
588
    return compress (inPtr, inSize, range, outPtr);
 
589
}
 
590
 
 
591
 
 
592
int
 
593
B44Compressor::uncompress (const char *inPtr,
 
594
                           int inSize,
 
595
                           int minY,
 
596
                           const char *&outPtr)
 
597
{
 
598
    return uncompress (inPtr,
 
599
                       inSize,
 
600
                       Box2i (V2i (_minX, minY),
 
601
                              V2i (_maxX, minY + numScanLines() - 1)),
 
602
                       outPtr);
 
603
}
 
604
 
 
605
 
 
606
int
 
607
B44Compressor::uncompressTile (const char *inPtr,
 
608
                               int inSize,
 
609
                               Imath::Box2i range,
 
610
                               const char *&outPtr)
 
611
{
 
612
    return uncompress (inPtr, inSize, range, outPtr);
 
613
}
 
614
 
 
615
 
 
616
int
 
617
B44Compressor::compress (const char *inPtr,
 
618
                         int inSize,
 
619
                         Imath::Box2i range,
 
620
                         const char *&outPtr)
 
621
{
 
622
    //
 
623
    // Compress a block of pixel data:  First copy the input pixels
 
624
    // from the input buffer into _tmpBuffer, rearranging them such
 
625
    // that blocks of 4x4 pixels of a single channel can be accessed
 
626
    // conveniently.  Then compress each 4x4 block of HALF pixel data
 
627
    // and append the result to the output buffer.  Copy UINT and
 
628
    // FLOAT data to the output buffer without compressing them.
 
629
    //
 
630
 
 
631
    outPtr = _outBuffer;
 
632
 
 
633
    if (inSize == 0)
 
634
    {
 
635
        //
 
636
        // Special case - empty input buffer.
 
637
        //
 
638
 
 
639
        return 0;
 
640
    }
 
641
 
 
642
    //
 
643
    // For each channel, detemine how many pixels are stored
 
644
    // in the input buffer, and where those pixels will be
 
645
    // placed in _tmpBuffer.
 
646
    //
 
647
 
 
648
    int minX = range.min.x;
 
649
    int maxX = min (range.max.x, _maxX);
 
650
    int minY = range.min.y;
 
651
    int maxY = min (range.max.y, _maxY);
 
652
    
 
653
    unsigned short *tmpBufferEnd = _tmpBuffer;
 
654
    int i = 0;
 
655
 
 
656
    for (ChannelList::ConstIterator c = _channels.begin();
 
657
         c != _channels.end();
 
658
         ++c, ++i)
 
659
    {
 
660
        ChannelData &cd = _channelData[i];
 
661
 
 
662
        cd.start = tmpBufferEnd;
 
663
        cd.end = cd.start;
 
664
 
 
665
        cd.nx = numSamples (c.channel().xSampling, minX, maxX);
 
666
        cd.ny = numSamples (c.channel().ySampling, minY, maxY);
 
667
 
 
668
        tmpBufferEnd += cd.nx * cd.ny * cd.size;
 
669
    }
 
670
 
 
671
    if (_format == XDR)
 
672
    {
 
673
        //
 
674
        // The data in the input buffer are in the machine-independent
 
675
        // Xdr format.  Copy the HALF channels into _tmpBuffer and
 
676
        // convert them back into native format for compression.
 
677
        // Copy UINT and FLOAT channels verbatim into _tmpBuffer.
 
678
        //
 
679
 
 
680
        for (int y = minY; y <= maxY; ++y)
 
681
        {
 
682
            for (int i = 0; i < _numChans; ++i)
 
683
            {
 
684
                ChannelData &cd = _channelData[i];
 
685
 
 
686
                if (modp (y, cd.ys) != 0)
 
687
                    continue;
 
688
 
 
689
                if (cd.type == HALF)
 
690
                {
 
691
                    for (int x = cd.nx; x > 0; --x)
 
692
                    {
 
693
                        Xdr::read <CharPtrIO> (inPtr, *cd.end);
 
694
                        ++cd.end;
 
695
                    }
 
696
                }
 
697
                else
 
698
                {
 
699
                    int n = cd.nx * cd.size;
 
700
                    memcpy (cd.end, inPtr, n * sizeof (unsigned short));
 
701
                    inPtr += n * sizeof (unsigned short);
 
702
                    cd.end += n;
 
703
                }
 
704
            }
 
705
        }
 
706
    }
 
707
    else
 
708
    {
 
709
        //
 
710
        // The input buffer contains only HALF channels, and they
 
711
        // are in native, machine-dependent format.  Copy the pixels
 
712
        // into _tmpBuffer.
 
713
        //
 
714
 
 
715
        for (int y = minY; y <= maxY; ++y)
 
716
        {
 
717
            for (int i = 0; i < _numChans; ++i)
 
718
            {
 
719
                ChannelData &cd = _channelData[i];
 
720
 
 
721
                #if defined (DEBUG)
 
722
                    assert (cd.type == HALF);
 
723
                #endif
 
724
 
 
725
                if (modp (y, cd.ys) != 0)
 
726
                    continue;
 
727
 
 
728
                int n = cd.nx * cd.size;
 
729
                memcpy (cd.end, inPtr, n * sizeof (unsigned short));
 
730
                inPtr  += n * sizeof (unsigned short);
 
731
                cd.end += n;
 
732
            }
 
733
        }
 
734
    }
 
735
 
 
736
    //
 
737
    // The pixels for each channel have been packed into a contiguous
 
738
    // block in _tmpBuffer.  HALF channels are in native format; UINT
 
739
    // and FLOAT channels are in Xdr format.
 
740
    //
 
741
 
 
742
    #if defined (DEBUG)
 
743
 
 
744
        for (int i = 1; i < _numChans; ++i)
 
745
            assert (_channelData[i-1].end == _channelData[i].start);
 
746
 
 
747
        assert (_channelData[_numChans-1].end == tmpBufferEnd);
 
748
 
 
749
    #endif
 
750
 
 
751
    //
 
752
    // For each HALF channel, split the data in _tmpBuffer into 4x4
 
753
    // pixel blocks.  Compress each block and append the compressed
 
754
    // data to the output buffer.
 
755
    //
 
756
    // UINT and FLOAT channels are copied from _tmpBuffer into the
 
757
    // output buffer without further processing.
 
758
    //
 
759
 
 
760
    char *outEnd = _outBuffer;
 
761
 
 
762
    for (int i = 0; i < _numChans; ++i)
 
763
    {
 
764
        ChannelData &cd = _channelData[i];
 
765
        
 
766
        if (cd.type != HALF)
 
767
        {
 
768
            //
 
769
            // UINT or FLOAT channel.
 
770
            //
 
771
 
 
772
            int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
 
773
            memcpy (outEnd, cd.start, n);
 
774
            outEnd += n;
 
775
 
 
776
            continue;
 
777
        }
 
778
        
 
779
        //
 
780
        // HALF channel
 
781
        //
 
782
 
 
783
        for (int y = 0; y < cd.ny; y += 4)
 
784
        {
 
785
            //
 
786
            // Copy the next 4x4 pixel block into array s.
 
787
            // If the width, cd.nx, or the height, cd.ny, of
 
788
            // the pixel data in _tmpBuffer is not divisible
 
789
            // by 4, then pad the data by repeating the
 
790
            // rightmost column and the bottom row.
 
791
            // 
 
792
 
 
793
            unsigned short *row0 = cd.start + y * cd.nx;
 
794
            unsigned short *row1 = row0 + cd.nx;
 
795
            unsigned short *row2 = row1 + cd.nx;
 
796
            unsigned short *row3 = row2 + cd.nx;
 
797
 
 
798
            if (y + 3 >= cd.ny)
 
799
            {
 
800
                if (y + 1 >= cd.ny)
 
801
                    row1 = row0;
 
802
 
 
803
                if (y + 2 >= cd.ny)
 
804
                    row2 = row1;
 
805
 
 
806
                row3 = row2;
 
807
            }
 
808
 
 
809
            for (int x = 0; x < cd.nx; x += 4)
 
810
            {
 
811
                unsigned short s[16];
 
812
 
 
813
                if (x + 3 >= cd.nx)
 
814
                {
 
815
                    int n = cd.nx - x;
 
816
 
 
817
                    for (int i = 0; i < 4; ++i)
 
818
                    {
 
819
                        int j = min (i, n - 1);
 
820
 
 
821
                        s[i +  0] = row0[j];
 
822
                        s[i +  4] = row1[j];
 
823
                        s[i +  8] = row2[j];
 
824
                        s[i + 12] = row3[j];
 
825
                    }
 
826
                }
 
827
                else
 
828
                {
 
829
                    memcpy (&s[ 0], row0, 4 * sizeof (unsigned short));
 
830
                    memcpy (&s[ 4], row1, 4 * sizeof (unsigned short));
 
831
                    memcpy (&s[ 8], row2, 4 * sizeof (unsigned short));
 
832
                    memcpy (&s[12], row3, 4 * sizeof (unsigned short));
 
833
                }
 
834
 
 
835
                row0 += 4;
 
836
                row1 += 4;
 
837
                row2 += 4;
 
838
                row3 += 4;
 
839
 
 
840
                //
 
841
                // Compress the contents of array s and append the
 
842
                // results to the output buffer.
 
843
                //
 
844
 
 
845
                if (cd.pLinear)
 
846
                    convertFromLinear (s);
 
847
 
 
848
                outEnd += pack (s, (unsigned char *) outEnd,
 
849
                                _optFlatFields, !cd.pLinear);
 
850
            }
 
851
        }
 
852
    }
 
853
 
 
854
    return outEnd - _outBuffer;
 
855
}
 
856
 
 
857
 
 
858
int
 
859
B44Compressor::uncompress (const char *inPtr,
 
860
                           int inSize,
 
861
                           Imath::Box2i range,
 
862
                           const char *&outPtr)
 
863
{
 
864
    //
 
865
    // This function is the reverse of the compress() function,
 
866
    // above.  First all pixels are moved from the input buffer
 
867
    // into _tmpBuffer.  UINT and FLOAT channels are copied
 
868
    // verbatim; HALF channels are uncompressed in blocks of
 
869
    // 4x4 pixels.  Then the pixels in _tmpBuffer are copied
 
870
    // into the output buffer and rearranged such that the data
 
871
    // for for each scan line form a contiguous block.
 
872
    //
 
873
 
 
874
    outPtr = _outBuffer;
 
875
 
 
876
    if (inSize == 0)
 
877
    {
 
878
        return 0;
 
879
    }
 
880
 
 
881
    int minX = range.min.x;
 
882
    int maxX = min (range.max.x, _maxX);
 
883
    int minY = range.min.y;
 
884
    int maxY = min (range.max.y, _maxY);
 
885
    
 
886
    unsigned short *tmpBufferEnd = _tmpBuffer;
 
887
    int i = 0;
 
888
 
 
889
    for (ChannelList::ConstIterator c = _channels.begin();
 
890
         c != _channels.end();
 
891
         ++c, ++i)
 
892
    {
 
893
        ChannelData &cd = _channelData[i];
 
894
 
 
895
        cd.start = tmpBufferEnd;
 
896
        cd.end = cd.start;
 
897
 
 
898
        cd.nx = numSamples (c.channel().xSampling, minX, maxX);
 
899
        cd.ny = numSamples (c.channel().ySampling, minY, maxY);
 
900
 
 
901
        tmpBufferEnd += cd.nx * cd.ny * cd.size;
 
902
    }
 
903
 
 
904
    for (int i = 0; i < _numChans; ++i)
 
905
    {
 
906
        ChannelData &cd = _channelData[i];
 
907
 
 
908
        if (cd.type != HALF)
 
909
        {
 
910
            //
 
911
            // UINT or FLOAT channel.
 
912
            //
 
913
 
 
914
            int n = cd.nx * cd.ny * cd.size * sizeof (unsigned short);
 
915
 
 
916
            if (inSize < n)
 
917
                notEnoughData();
 
918
 
 
919
            memcpy (cd.start, inPtr, n);
 
920
            inPtr += n;
 
921
            inSize -= n;
 
922
 
 
923
            continue;
 
924
        }
 
925
 
 
926
        //
 
927
        // HALF channel
 
928
        //
 
929
 
 
930
        for (int y = 0; y < cd.ny; y += 4)
 
931
        {
 
932
            unsigned short *row0 = cd.start + y * cd.nx;
 
933
            unsigned short *row1 = row0 + cd.nx;
 
934
            unsigned short *row2 = row1 + cd.nx;
 
935
            unsigned short *row3 = row2 + cd.nx;
 
936
 
 
937
            for (int x = 0; x < cd.nx; x += 4)
 
938
            {
 
939
                unsigned short s[16]; 
 
940
 
 
941
                if (inSize < 3)
 
942
                    notEnoughData();
 
943
 
 
944
                if (((const unsigned char *)inPtr)[2] == 0xfc)
 
945
                {
 
946
                    unpack3 ((const unsigned char *)inPtr, s);
 
947
                    inPtr += 3;
 
948
                    inSize -= 3;
 
949
                }
 
950
                else
 
951
                {
 
952
                    if (inSize < 14)
 
953
                        notEnoughData();
 
954
 
 
955
                    unpack14 ((const unsigned char *)inPtr, s);
 
956
                    inPtr += 14;
 
957
                    inSize -= 14;
 
958
                }
 
959
 
 
960
                if (cd.pLinear)
 
961
                    convertToLinear (s);
 
962
 
 
963
                int n = (x + 3 < cd.nx)?
 
964
                            4 * sizeof (unsigned short) :
 
965
                            (cd.nx - x) * sizeof (unsigned short);
 
966
 
 
967
                if (y + 3 < cd.ny)
 
968
                {
 
969
                    memcpy (row0, &s[ 0], n);
 
970
                    memcpy (row1, &s[ 4], n);
 
971
                    memcpy (row2, &s[ 8], n);
 
972
                    memcpy (row3, &s[12], n);
 
973
                }
 
974
                else
 
975
                {
 
976
                    memcpy (row0, &s[ 0], n);
 
977
 
 
978
                    if (y + 1 < cd.ny)
 
979
                        memcpy (row1, &s[ 4], n);
 
980
 
 
981
                    if (y + 2 < cd.ny)
 
982
                        memcpy (row2, &s[ 8], n);
 
983
                }
 
984
 
 
985
                row0 += 4;
 
986
                row1 += 4;
 
987
                row2 += 4;
 
988
                row3 += 4;
 
989
            }
 
990
        }
 
991
    }
 
992
 
 
993
    char *outEnd = _outBuffer;
 
994
 
 
995
    if (_format == XDR)
 
996
    {
 
997
        for (int y = minY; y <= maxY; ++y)
 
998
        {
 
999
            for (int i = 0; i < _numChans; ++i)
 
1000
            {
 
1001
                ChannelData &cd = _channelData[i];
 
1002
 
 
1003
                if (modp (y, cd.ys) != 0)
 
1004
                    continue;
 
1005
 
 
1006
                if (cd.type == HALF)
 
1007
                {
 
1008
                    for (int x = cd.nx; x > 0; --x)
 
1009
                    {
 
1010
                        Xdr::write <CharPtrIO> (outEnd, *cd.end);
 
1011
                        ++cd.end;
 
1012
                    }
 
1013
                }
 
1014
                else
 
1015
                {
 
1016
                    int n = cd.nx * cd.size;
 
1017
                    memcpy (outEnd, cd.end, n * sizeof (unsigned short));
 
1018
                    outEnd += n * sizeof (unsigned short);
 
1019
                    cd.end += n;
 
1020
                }
 
1021
            }
 
1022
        }
 
1023
    }
 
1024
    else
 
1025
    {
 
1026
        for (int y = minY; y <= maxY; ++y)
 
1027
        {
 
1028
            for (int i = 0; i < _numChans; ++i)
 
1029
            {
 
1030
                ChannelData &cd = _channelData[i];
 
1031
 
 
1032
                #if defined (DEBUG)
 
1033
                    assert (cd.type == HALF);
 
1034
                #endif
 
1035
 
 
1036
                if (modp (y, cd.ys) != 0)
 
1037
                    continue;
 
1038
 
 
1039
                int n = cd.nx * cd.size;
 
1040
                memcpy (outEnd, cd.end, n * sizeof (unsigned short));
 
1041
                outEnd += n * sizeof (unsigned short);
 
1042
                cd.end += n;
 
1043
            }
 
1044
        }
 
1045
    }
 
1046
 
 
1047
    #if defined (DEBUG)
 
1048
 
 
1049
        for (int i = 1; i < _numChans; ++i)
 
1050
            assert (_channelData[i-1].end == _channelData[i].start);
 
1051
 
 
1052
        assert (_channelData[_numChans-1].end == tmpBufferEnd);
 
1053
 
 
1054
    #endif
 
1055
 
 
1056
    if (inSize > 0)
 
1057
        tooMuchData();
 
1058
 
 
1059
    outPtr = _outBuffer;
 
1060
    return outEnd - _outBuffer;
 
1061
}
 
1062
 
 
1063
 
 
1064
} // namespace Imf