PageRenderTime 27ms CodeModel.GetById 1ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FreeImage/Source/OpenEXR/IlmImf/ImfRleCompressor.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 331 lines | 188 code | 63 blank | 80 comment | 28 complexity | fbfe52074b696f954c806d52581a3227 MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////
  2//
  3// Copyright (c) 2002, 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 RleCompressor
 40//
 41//-----------------------------------------------------------------------------
 42
 43#include <ImfRleCompressor.h>
 44#include <ImfCheckedArithmetic.h>
 45#include "Iex.h"
 46
 47namespace Imf {
 48namespace {
 49
 50const int MIN_RUN_LENGTH = 3;
 51const int MAX_RUN_LENGTH = 127;
 52
 53
 54//
 55// Compress an array of bytes, using run-length encoding,
 56// and return the length of the compressed data.
 57//
 58
 59int
 60rleCompress (int inLength, const char in[], signed char out[])
 61{
 62    const char *inEnd = in + inLength;
 63    const char *runStart = in;
 64    const char *runEnd = in + 1;
 65    signed char *outWrite = out;
 66
 67    while (runStart < inEnd)
 68    {
 69	while (runEnd < inEnd &&
 70	       *runStart == *runEnd &&
 71	       runEnd - runStart - 1 < MAX_RUN_LENGTH)
 72	{
 73	    ++runEnd;
 74	}
 75
 76	if (runEnd - runStart >= MIN_RUN_LENGTH)
 77	{
 78	    //
 79	    // Compressable run
 80	    //
 81
 82	    *outWrite++ = (runEnd - runStart) - 1;
 83	    *outWrite++ = *(signed char *) runStart;
 84	    runStart = runEnd;
 85	}
 86	else
 87	{
 88	    //
 89	    // Uncompressable run
 90	    //
 91
 92	    while (runEnd < inEnd &&
 93		   ((runEnd + 1 >= inEnd ||
 94		     *runEnd != *(runEnd + 1)) ||
 95		    (runEnd + 2 >= inEnd ||
 96		     *(runEnd + 1) != *(runEnd + 2))) &&
 97		   runEnd - runStart < MAX_RUN_LENGTH)
 98	    {
 99		++runEnd;
100	    }
101
102	    *outWrite++ = runStart - runEnd;
103
104	    while (runStart < runEnd)
105	    {
106		*outWrite++ = *(signed char *) (runStart++);
107	    }
108	}
109
110	++runEnd;
111    }
112
113    return outWrite - out;
114}
115
116
117//
118// Uncompress an array of bytes compressed with rleCompress().
119// Returns the length of the oncompressed data, or 0 if the
120// length of the uncompressed data would be more than maxLength.
121//
122
123int
124rleUncompress (int inLength, int maxLength, const signed char in[], char out[])
125{
126    char *outStart = out;
127
128    while (inLength > 0)
129    {
130	if (*in < 0)
131	{
132	    int count = -((int)*in++);
133	    inLength -= count + 1;
134
135	    if (0 > (maxLength -= count))
136		return 0;
137
138	    while (count-- > 0)
139		*out++ = *(char *) (in++);
140	}
141	else
142	{
143	    int count = *in++;
144	    inLength -= 2;
145
146	    if (0 > (maxLength -= count + 1))
147		return 0;
148
149	    while (count-- >= 0)
150		*out++ = *(char *) in;
151
152	    in++;
153	}
154    }
155
156    return out - outStart;
157}
158
159} // namespace
160
161
162RleCompressor::RleCompressor (const Header &hdr, size_t maxScanLineSize):
163    Compressor (hdr),
164    _maxScanLineSize (maxScanLineSize),
165    _tmpBuffer (0),
166    _outBuffer (0)
167{
168    _tmpBuffer = new char [maxScanLineSize];
169    _outBuffer = new char [uiMult (maxScanLineSize, size_t (3)) / 2];
170}
171
172
173RleCompressor::~RleCompressor ()
174{
175    delete [] _tmpBuffer;
176    delete [] _outBuffer;
177}
178
179
180int
181RleCompressor::numScanLines () const
182{
183    //
184    // This compressor compresses individual scan lines.
185    //
186
187    return 1;
188}
189
190
191int
192RleCompressor::compress (const char *inPtr,
193			 int inSize,
194			 int minY,
195			 const char *&outPtr)
196{
197    //
198    // Special case ­- empty input buffer
199    //
200
201    if (inSize == 0)
202    {
203	outPtr = _outBuffer;
204	return 0;
205    }
206
207    //
208    // Reorder the pixel data.
209    //
210
211    {
212	char *t1 = _tmpBuffer;
213	char *t2 = _tmpBuffer + (inSize + 1) / 2;
214	const char *stop = inPtr + inSize;
215
216	while (true)
217	{
218	    if (inPtr < stop)
219		*(t1++) = *(inPtr++);
220	    else
221		break;
222
223	    if (inPtr < stop)
224		*(t2++) = *(inPtr++);
225	    else
226		break;
227	}
228    }
229
230    //
231    // Predictor.
232    //
233
234    {
235	unsigned char *t = (unsigned char *) _tmpBuffer + 1;
236	unsigned char *stop = (unsigned char *) _tmpBuffer + inSize;
237	int p = t[-1];
238
239	while (t < stop)
240	{
241	    int d = int (t[0]) - p + (128 + 256);
242	    p = t[0];
243	    t[0] = d;
244	    ++t;
245	}
246    }
247
248    //
249    // Run-length encode the data.
250    //
251
252    outPtr = _outBuffer;
253    return rleCompress (inSize, _tmpBuffer, (signed char *) _outBuffer);
254}
255
256
257int
258RleCompressor::uncompress (const char *inPtr,
259			   int inSize,
260			   int minY,
261			   const char *&outPtr)
262{
263    //
264    // Special case ­- empty input buffer
265    //
266
267    if (inSize == 0)
268    {
269	outPtr = _outBuffer;
270	return 0;
271    }
272
273    //
274    // Decode the run-length encoded data
275    //
276
277    int outSize;
278
279    if (0 == (outSize = rleUncompress (inSize, _maxScanLineSize,
280				       (const signed char *) inPtr,
281				       _tmpBuffer)))
282    {
283	throw Iex::InputExc ("Data decoding (rle) failed.");
284    }
285
286    //
287    // Predictor.
288    //
289
290    {
291	unsigned char *t = (unsigned char *) _tmpBuffer + 1;
292	unsigned char *stop = (unsigned char *) _tmpBuffer + outSize;
293
294	while (t < stop)
295	{
296	    int d = int (t[-1]) + int (t[0]) - 128;
297	    t[0] = d;
298	    ++t;
299	}
300    }
301
302    //
303    // Reorder the pixel data.
304    //
305
306    {
307	const char *t1 = _tmpBuffer;
308	const char *t2 = _tmpBuffer + (outSize + 1) / 2;
309	char *s = _outBuffer;
310	char *stop = s + outSize;
311
312	while (true)
313	{
314	    if (s < stop)
315		*(s++) = *(t1++);
316	    else
317		break;
318
319	    if (s < stop)
320		*(s++) = *(t2++);
321	    else
322		break;
323	}
324    }
325
326    outPtr = _outBuffer;
327    return outSize;
328}
329
330
331} // namespace Imf