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 "ImfRle.h"
46 #include "Iex.h"
47 #include "ImfNamespace.h"
48 
49 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
50 
RleCompressor(const Header & hdr,size_t maxScanLineSize)51 RleCompressor::RleCompressor (const Header &hdr, size_t maxScanLineSize):
52     Compressor (hdr),
53     _maxScanLineSize (maxScanLineSize),
54     _tmpBuffer (0),
55     _outBuffer (0)
56 {
57     _tmpBuffer = new char [maxScanLineSize];
58     _outBuffer = new char [uiMult (maxScanLineSize, size_t (3)) / 2];
59 }
60 
61 
~RleCompressor()62 RleCompressor::~RleCompressor ()
63 {
64     delete [] _tmpBuffer;
65     delete [] _outBuffer;
66 }
67 
68 
69 int
numScanLines() const70 RleCompressor::numScanLines () const
71 {
72     //
73     // This compressor compresses individual scan lines.
74     //
75 
76     return 1;
77 }
78 
79 
80 int
compress(const char * inPtr,int inSize,int minY,const char * & outPtr)81 RleCompressor::compress (const char *inPtr,
82 			 int inSize,
83 			 int minY,
84 			 const char *&outPtr)
85 {
86     //
87     // Special case �- empty input buffer
88     //
89 
90     if (inSize == 0)
91     {
92 	outPtr = _outBuffer;
93 	return 0;
94     }
95 
96     //
97     // Reorder the pixel data.
98     //
99 
100     {
101 	char *t1 = _tmpBuffer;
102 	char *t2 = _tmpBuffer + (inSize + 1) / 2;
103 	const char *stop = inPtr + inSize;
104 
105 	while (true)
106 	{
107 	    if (inPtr < stop)
108 		*(t1++) = *(inPtr++);
109 	    else
110 		break;
111 
112 	    if (inPtr < stop)
113 		*(t2++) = *(inPtr++);
114 	    else
115 		break;
116 	}
117     }
118 
119     //
120     // Predictor.
121     //
122 
123     {
124 	unsigned char *t = (unsigned char *) _tmpBuffer + 1;
125 	unsigned char *stop = (unsigned char *) _tmpBuffer + inSize;
126 	int p = t[-1];
127 
128 	while (t < stop)
129 	{
130 	    int d = int (t[0]) - p + (128 + 256);
131 	    p = t[0];
132 	    t[0] = d;
133 	    ++t;
134 	}
135     }
136 
137     //
138     // Run-length encode the data.
139     //
140 
141     outPtr = _outBuffer;
142     return rleCompress (inSize, _tmpBuffer, (signed char *) _outBuffer);
143 }
144 
145 
146 int
uncompress(const char * inPtr,int inSize,int minY,const char * & outPtr)147 RleCompressor::uncompress (const char *inPtr,
148 			   int inSize,
149 			   int minY,
150 			   const char *&outPtr)
151 {
152     //
153     // Special case �- empty input buffer
154     //
155 
156     if (inSize == 0)
157     {
158 	outPtr = _outBuffer;
159 	return 0;
160     }
161 
162     //
163     // Decode the run-length encoded data
164     //
165 
166     int outSize;
167 
168     if (0 == (outSize = rleUncompress (inSize, _maxScanLineSize,
169 				       (const signed char *) inPtr,
170 				       _tmpBuffer)))
171     {
172 	throw IEX_NAMESPACE::InputExc ("Data decoding (rle) failed.");
173     }
174 
175     //
176     // Predictor.
177     //
178 
179     {
180 	unsigned char *t = (unsigned char *) _tmpBuffer + 1;
181 	unsigned char *stop = (unsigned char *) _tmpBuffer + outSize;
182 
183 	while (t < stop)
184 	{
185 	    int d = int (t[-1]) + int (t[0]) - 128;
186 	    t[0] = d;
187 	    ++t;
188 	}
189     }
190 
191     //
192     // Reorder the pixel data.
193     //
194 
195     {
196 	const char *t1 = _tmpBuffer;
197 	const char *t2 = _tmpBuffer + (outSize + 1) / 2;
198 	char *s = _outBuffer;
199 	char *stop = s + outSize;
200 
201 	while (true)
202 	{
203 	    if (s < stop)
204 		*(s++) = *(t1++);
205 	    else
206 		break;
207 
208 	    if (s < stop)
209 		*(s++) = *(t2++);
210 	    else
211 		break;
212 	}
213     }
214 
215     outPtr = _outBuffer;
216     return outSize;
217 }
218 
219 
220 OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
221