/src/freeimage-svn/FreeImage/trunk/Source/OpenEXR/IlmImf/ImfWav.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | // 16-bit Haar Wavelet encoding and decoding |
40 | | // |
41 | | // The source code in this file is derived from the encoding |
42 | | // and decoding routines written by Christian Rouet for his |
43 | | // PIZ image file format. |
44 | | // |
45 | | //----------------------------------------------------------------------------- |
46 | | |
47 | | |
48 | | #include <ImfWav.h> |
49 | | #include "ImfNamespace.h" |
50 | | |
51 | | OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER |
52 | | namespace { |
53 | | |
54 | | |
55 | | // |
56 | | // Wavelet basis functions without modulo arithmetic; they produce |
57 | | // the best compression ratios when the wavelet-transformed data are |
58 | | // Huffman-encoded, but the wavelet transform works only for 14-bit |
59 | | // data (untransformed data values must be less than (1 << 14)). |
60 | | // |
61 | | |
62 | | inline void |
63 | | wenc14 (unsigned short a, unsigned short b, |
64 | | unsigned short &l, unsigned short &h) |
65 | 0 | { |
66 | 0 | short as = a; |
67 | 0 | short bs = b; |
68 | |
|
69 | 0 | short ms = (as + bs) >> 1; |
70 | 0 | short ds = as - bs; |
71 | |
|
72 | 0 | l = ms; |
73 | 0 | h = ds; |
74 | 0 | } |
75 | | |
76 | | |
77 | | inline void |
78 | | wdec14 (unsigned short l, unsigned short h, |
79 | | unsigned short &a, unsigned short &b) |
80 | 0 | { |
81 | 0 | short ls = l; |
82 | 0 | short hs = h; |
83 | |
|
84 | 0 | int hi = hs; |
85 | 0 | int ai = ls + (hi & 1) + (hi >> 1); |
86 | |
|
87 | 0 | short as = ai; |
88 | 0 | short bs = ai - hi; |
89 | |
|
90 | 0 | a = as; |
91 | 0 | b = bs; |
92 | 0 | } |
93 | | |
94 | | |
95 | | // |
96 | | // Wavelet basis functions with modulo arithmetic; they work with full |
97 | | // 16-bit data, but Huffman-encoding the wavelet-transformed data doesn't |
98 | | // compress the data quite as well. |
99 | | // |
100 | | |
101 | | const int NBITS = 16; |
102 | | const int A_OFFSET = 1 << (NBITS - 1); |
103 | | const int M_OFFSET = 1 << (NBITS - 1); |
104 | | const int MOD_MASK = (1 << NBITS) - 1; |
105 | | |
106 | | |
107 | | inline void |
108 | | wenc16 (unsigned short a, unsigned short b, |
109 | | unsigned short &l, unsigned short &h) |
110 | 0 | { |
111 | 0 | int ao = (a + A_OFFSET) & MOD_MASK; |
112 | 0 | int m = ((ao + b) >> 1); |
113 | 0 | int d = ao - b; |
114 | |
|
115 | 0 | if (d < 0) |
116 | 0 | m = (m + M_OFFSET) & MOD_MASK; |
117 | |
|
118 | 0 | d &= MOD_MASK; |
119 | |
|
120 | 0 | l = m; |
121 | 0 | h = d; |
122 | 0 | } |
123 | | |
124 | | |
125 | | inline void |
126 | | wdec16 (unsigned short l, unsigned short h, |
127 | | unsigned short &a, unsigned short &b) |
128 | 0 | { |
129 | 0 | int m = l; |
130 | 0 | int d = h; |
131 | 0 | int bb = (m - (d >> 1)) & MOD_MASK; |
132 | 0 | int aa = (d + bb - A_OFFSET) & MOD_MASK; |
133 | 0 | b = bb; |
134 | 0 | a = aa; |
135 | 0 | } |
136 | | |
137 | | } // namespace |
138 | | |
139 | | |
140 | | // |
141 | | // 2D Wavelet encoding: |
142 | | // |
143 | | |
144 | | void |
145 | | wav2Encode |
146 | | (unsigned short* in, // io: values are transformed in place |
147 | | int nx, // i : x size |
148 | | int ox, // i : x offset |
149 | | int ny, // i : y size |
150 | | int oy, // i : y offset |
151 | | unsigned short mx) // i : maximum in[x][y] value |
152 | 0 | { |
153 | 0 | bool w14 = (mx < (1 << 14)); |
154 | 0 | int n = (nx > ny)? ny: nx; |
155 | 0 | int p = 1; // == 1 << level |
156 | 0 | int p2 = 2; // == 1 << (level+1) |
157 | | |
158 | | // |
159 | | // Hierachical loop on smaller dimension n |
160 | | // |
161 | |
|
162 | 0 | while (p2 <= n) |
163 | 0 | { |
164 | 0 | unsigned short *py = in; |
165 | 0 | unsigned short *ey = in + oy * (ny - p2); |
166 | 0 | int oy1 = oy * p; |
167 | 0 | int oy2 = oy * p2; |
168 | 0 | int ox1 = ox * p; |
169 | 0 | int ox2 = ox * p2; |
170 | 0 | unsigned short i00,i01,i10,i11; |
171 | | |
172 | | // |
173 | | // Y loop |
174 | | // |
175 | |
|
176 | 0 | for (; py <= ey; py += oy2) |
177 | 0 | { |
178 | 0 | unsigned short *px = py; |
179 | 0 | unsigned short *ex = py + ox * (nx - p2); |
180 | | |
181 | | // |
182 | | // X loop |
183 | | // |
184 | |
|
185 | 0 | for (; px <= ex; px += ox2) |
186 | 0 | { |
187 | 0 | unsigned short *p01 = px + ox1; |
188 | 0 | unsigned short *p10 = px + oy1; |
189 | 0 | unsigned short *p11 = p10 + ox1; |
190 | | |
191 | | // |
192 | | // 2D wavelet encoding |
193 | | // |
194 | |
|
195 | 0 | if (w14) |
196 | 0 | { |
197 | 0 | wenc14 (*px, *p01, i00, i01); |
198 | 0 | wenc14 (*p10, *p11, i10, i11); |
199 | 0 | wenc14 (i00, i10, *px, *p10); |
200 | 0 | wenc14 (i01, i11, *p01, *p11); |
201 | 0 | } |
202 | 0 | else |
203 | 0 | { |
204 | 0 | wenc16 (*px, *p01, i00, i01); |
205 | 0 | wenc16 (*p10, *p11, i10, i11); |
206 | 0 | wenc16 (i00, i10, *px, *p10); |
207 | 0 | wenc16 (i01, i11, *p01, *p11); |
208 | 0 | } |
209 | 0 | } |
210 | | |
211 | | // |
212 | | // Encode (1D) odd column (still in Y loop) |
213 | | // |
214 | |
|
215 | 0 | if (nx & p) |
216 | 0 | { |
217 | 0 | unsigned short *p10 = px + oy1; |
218 | |
|
219 | 0 | if (w14) |
220 | 0 | wenc14 (*px, *p10, i00, *p10); |
221 | 0 | else |
222 | 0 | wenc16 (*px, *p10, i00, *p10); |
223 | |
|
224 | 0 | *px= i00; |
225 | 0 | } |
226 | 0 | } |
227 | | |
228 | | // |
229 | | // Encode (1D) odd line (must loop in X) |
230 | | // |
231 | |
|
232 | 0 | if (ny & p) |
233 | 0 | { |
234 | 0 | unsigned short *px = py; |
235 | 0 | unsigned short *ex = py + ox * (nx - p2); |
236 | |
|
237 | 0 | for (; px <= ex; px += ox2) |
238 | 0 | { |
239 | 0 | unsigned short *p01 = px + ox1; |
240 | |
|
241 | 0 | if (w14) |
242 | 0 | wenc14 (*px, *p01, i00, *p01); |
243 | 0 | else |
244 | 0 | wenc16 (*px, *p01, i00, *p01); |
245 | |
|
246 | 0 | *px= i00; |
247 | 0 | } |
248 | 0 | } |
249 | | |
250 | | // |
251 | | // Next level |
252 | | // |
253 | |
|
254 | 0 | p = p2; |
255 | 0 | p2 <<= 1; |
256 | 0 | } |
257 | 0 | } |
258 | | |
259 | | |
260 | | // |
261 | | // 2D Wavelet decoding: |
262 | | // |
263 | | |
264 | | void |
265 | | wav2Decode |
266 | | (unsigned short* in, // io: values are transformed in place |
267 | | int nx, // i : x size |
268 | | int ox, // i : x offset |
269 | | int ny, // i : y size |
270 | | int oy, // i : y offset |
271 | | unsigned short mx) // i : maximum in[x][y] value |
272 | 0 | { |
273 | 0 | bool w14 = (mx < (1 << 14)); |
274 | 0 | int n = (nx > ny)? ny: nx; |
275 | 0 | int p = 1; |
276 | 0 | int p2; |
277 | | |
278 | | // |
279 | | // Search max level |
280 | | // |
281 | |
|
282 | 0 | while (p <= n) |
283 | 0 | p <<= 1; |
284 | |
|
285 | 0 | p >>= 1; |
286 | 0 | p2 = p; |
287 | 0 | p >>= 1; |
288 | | |
289 | | // |
290 | | // Hierarchical loop on smaller dimension n |
291 | | // |
292 | |
|
293 | 0 | while (p >= 1) |
294 | 0 | { |
295 | 0 | unsigned short *py = in; |
296 | 0 | unsigned short *ey = in + oy * (ny - p2); |
297 | 0 | int oy1 = oy * p; |
298 | 0 | int oy2 = oy * p2; |
299 | 0 | int ox1 = ox * p; |
300 | 0 | int ox2 = ox * p2; |
301 | 0 | unsigned short i00,i01,i10,i11; |
302 | | |
303 | | // |
304 | | // Y loop |
305 | | // |
306 | |
|
307 | 0 | for (; py <= ey; py += oy2) |
308 | 0 | { |
309 | 0 | unsigned short *px = py; |
310 | 0 | unsigned short *ex = py + ox * (nx - p2); |
311 | | |
312 | | // |
313 | | // X loop |
314 | | // |
315 | |
|
316 | 0 | for (; px <= ex; px += ox2) |
317 | 0 | { |
318 | 0 | unsigned short *p01 = px + ox1; |
319 | 0 | unsigned short *p10 = px + oy1; |
320 | 0 | unsigned short *p11 = p10 + ox1; |
321 | | |
322 | | // |
323 | | // 2D wavelet decoding |
324 | | // |
325 | |
|
326 | 0 | if (w14) |
327 | 0 | { |
328 | 0 | wdec14 (*px, *p10, i00, i10); |
329 | 0 | wdec14 (*p01, *p11, i01, i11); |
330 | 0 | wdec14 (i00, i01, *px, *p01); |
331 | 0 | wdec14 (i10, i11, *p10, *p11); |
332 | 0 | } |
333 | 0 | else |
334 | 0 | { |
335 | 0 | wdec16 (*px, *p10, i00, i10); |
336 | 0 | wdec16 (*p01, *p11, i01, i11); |
337 | 0 | wdec16 (i00, i01, *px, *p01); |
338 | 0 | wdec16 (i10, i11, *p10, *p11); |
339 | 0 | } |
340 | 0 | } |
341 | | |
342 | | // |
343 | | // Decode (1D) odd column (still in Y loop) |
344 | | // |
345 | |
|
346 | 0 | if (nx & p) |
347 | 0 | { |
348 | 0 | unsigned short *p10 = px + oy1; |
349 | |
|
350 | 0 | if (w14) |
351 | 0 | wdec14 (*px, *p10, i00, *p10); |
352 | 0 | else |
353 | 0 | wdec16 (*px, *p10, i00, *p10); |
354 | |
|
355 | 0 | *px= i00; |
356 | 0 | } |
357 | 0 | } |
358 | | |
359 | | // |
360 | | // Decode (1D) odd line (must loop in X) |
361 | | // |
362 | |
|
363 | 0 | if (ny & p) |
364 | 0 | { |
365 | 0 | unsigned short *px = py; |
366 | 0 | unsigned short *ex = py + ox * (nx - p2); |
367 | |
|
368 | 0 | for (; px <= ex; px += ox2) |
369 | 0 | { |
370 | 0 | unsigned short *p01 = px + ox1; |
371 | |
|
372 | 0 | if (w14) |
373 | 0 | wdec14 (*px, *p01, i00, *p01); |
374 | 0 | else |
375 | 0 | wdec16 (*px, *p01, i00, *p01); |
376 | |
|
377 | 0 | *px= i00; |
378 | 0 | } |
379 | 0 | } |
380 | | |
381 | | // |
382 | | // Next level |
383 | | // |
384 | |
|
385 | 0 | p2 = p; |
386 | 0 | p >>= 1; |
387 | 0 | } |
388 | 0 | } |
389 | | |
390 | | |
391 | | OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT |