1///////////////////////////////////////////////////////////////////////////
2//
3// Copyright (c) 2004, 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//
39//	class ZipCompressor
40//
41//-----------------------------------------------------------------------------
42//#define ZLIB_WINAPI
43
44#include <ImfZipCompressor.h>
45#include <ImfCheckedArithmetic.h>
46#include "Iex.h"
47#include <zlib.h>
48
49namespace Imf {
50
51
52ZipCompressor::ZipCompressor
53    (const Header &hdr,
54     size_t maxScanLineSize,
55     size_t numScanLines)
56:
57    Compressor (hdr),
58    _maxScanLineSize (maxScanLineSize),
59    _numScanLines (numScanLines),
60    _tmpBuffer (0),
61    _outBuffer (0)
62{
63    size_t maxInBytes =
64        uiMult (maxScanLineSize, numScanLines);
65
66    size_t maxOutBytes =
67        uiAdd (uiAdd (maxInBytes,
68                      size_t (ceil (maxInBytes * 0.01))),
69               size_t (100));
70
71    _tmpBuffer =
72    new char [maxInBytes];
73
74    _outBuffer =
75    new char [maxOutBytes];
76}
77
78
79ZipCompressor::~ZipCompressor ()
80{
81    delete [] _tmpBuffer;
82    delete [] _outBuffer;
83}
84
85
86int
87ZipCompressor::numScanLines () const
88{
89    return _numScanLines;
90}
91
92
93int
94ZipCompressor::compress (const char *inPtr,
95             int inSize,
96             int /*minY*/,
97             const char *&outPtr)
98{
99    //
100    // Special case �- empty input buffer
101    //
102
103    if (inSize == 0)
104    {
105    outPtr = _outBuffer;
106    return 0;
107    }
108
109    //
110    // Reorder the pixel data.
111    //
112
113    {
114    char *t1 = _tmpBuffer;
115    char *t2 = _tmpBuffer + (inSize + 1) / 2;
116    const char *stop = inPtr + inSize;
117
118    while (true)
119    {
120        if (inPtr < stop)
121        *(t1++) = *(inPtr++);
122        else
123        break;
124
125        if (inPtr < stop)
126        *(t2++) = *(inPtr++);
127        else
128        break;
129    }
130    }
131
132    //
133    // Predictor.
134    //
135
136    {
137    unsigned char *t = (unsigned char *) _tmpBuffer + 1;
138    unsigned char *stop = (unsigned char *) _tmpBuffer + inSize;
139    int p = t[-1];
140
141    while (t < stop)
142    {
143        int d = int (t[0]) - p + (128 + 256);
144        p = t[0];
145        t[0] = d;
146        ++t;
147    }
148    }
149
150    //
151    // Compress the data using zlib
152    //
153
154    uLongf outSize = int(ceil(inSize * 1.01)) + 100;
155
156    if (Z_OK != ::compress ((Bytef *)_outBuffer, &outSize,
157                (const Bytef *) _tmpBuffer, inSize))
158    {
159    throw Iex::BaseExc ("Data compression (zlib) failed.");
160    }
161
162    outPtr = _outBuffer;
163    return outSize;
164}
165
166
167int
168ZipCompressor::uncompress (const char *inPtr,
169               int inSize,
170               int /*minY*/,
171               const char *&outPtr)
172{
173    //
174    // Special case �- empty input buffer
175    //
176
177    if (inSize == 0)
178    {
179    outPtr = _outBuffer;
180    return 0;
181    }
182
183    //
184    // Decompress the data using zlib
185    //
186
187    uLongf outSize = _maxScanLineSize * _numScanLines;
188
189    if (Z_OK != ::uncompress ((Bytef *)_tmpBuffer, &outSize,
190                  (const Bytef *) inPtr, inSize))
191    {
192    throw Iex::InputExc ("Data decompression (zlib) failed.");
193    }
194
195    //
196    // Predictor.
197    //
198
199    {
200    unsigned char *t = (unsigned char *) _tmpBuffer + 1;
201    unsigned char *stop = (unsigned char *) _tmpBuffer + outSize;
202
203    while (t < stop)
204    {
205        int d = int (t[-1]) + int (t[0]) - 128;
206        t[0] = d;
207        ++t;
208    }
209    }
210
211    //
212    // Reorder the pixel data.
213    //
214
215    {
216    const char *t1 = _tmpBuffer;
217    const char *t2 = _tmpBuffer + (outSize + 1) / 2;
218    char *s = _outBuffer;
219    char *stop = s + outSize;
220
221    while (true)
222    {
223        if (s < stop)
224        *(s++) = *(t1++);
225        else
226        break;
227
228        if (s < stop)
229        *(s++) = *(t2++);
230        else
231        break;
232    }
233    }
234
235    outPtr = _outBuffer;
236    return outSize;
237}
238
239
240} // namespace Imf
241