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