mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
391 lines
7.9 KiB
391 lines
7.9 KiB
/////////////////////////////////////////////////////////////////////////// |
|
// |
|
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas |
|
// Digital Ltd. LLC |
|
// |
|
// All rights reserved. |
|
// |
|
// Redistribution and use in source and binary forms, with or without |
|
// modification, are permitted provided that the following conditions are |
|
// met: |
|
// * Redistributions of source code must retain the above copyright |
|
// notice, this list of conditions and the following disclaimer. |
|
// * Redistributions in binary form must reproduce the above |
|
// copyright notice, this list of conditions and the following disclaimer |
|
// in the documentation and/or other materials provided with the |
|
// distribution. |
|
// * Neither the name of Industrial Light & Magic nor the names of |
|
// its contributors may be used to endorse or promote products derived |
|
// from this software without specific prior written permission. |
|
// |
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
// |
|
/////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
// 16-bit Haar Wavelet encoding and decoding |
|
// |
|
// The source code in this file is derived from the encoding |
|
// and decoding routines written by Christian Rouet for his |
|
// PIZ image file format. |
|
// |
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
#include <ImfWav.h> |
|
#include "ImfNamespace.h" |
|
|
|
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER |
|
namespace { |
|
|
|
|
|
// |
|
// Wavelet basis functions without modulo arithmetic; they produce |
|
// the best compression ratios when the wavelet-transformed data are |
|
// Huffman-encoded, but the wavelet transform works only for 14-bit |
|
// data (untransformed data values must be less than (1 << 14)). |
|
// |
|
|
|
inline void |
|
wenc14 (unsigned short a, unsigned short b, |
|
unsigned short &l, unsigned short &h) |
|
{ |
|
short as = a; |
|
short bs = b; |
|
|
|
short ms = (as + bs) >> 1; |
|
short ds = as - bs; |
|
|
|
l = ms; |
|
h = ds; |
|
} |
|
|
|
|
|
inline void |
|
wdec14 (unsigned short l, unsigned short h, |
|
unsigned short &a, unsigned short &b) |
|
{ |
|
short ls = l; |
|
short hs = h; |
|
|
|
int hi = hs; |
|
int ai = ls + (hi & 1) + (hi >> 1); |
|
|
|
short as = ai; |
|
short bs = ai - hi; |
|
|
|
a = as; |
|
b = bs; |
|
} |
|
|
|
|
|
// |
|
// Wavelet basis functions with modulo arithmetic; they work with full |
|
// 16-bit data, but Huffman-encoding the wavelet-transformed data doesn't |
|
// compress the data quite as well. |
|
// |
|
|
|
const int NBITS = 16; |
|
const int A_OFFSET = 1 << (NBITS - 1); |
|
const int M_OFFSET = 1 << (NBITS - 1); |
|
const int MOD_MASK = (1 << NBITS) - 1; |
|
|
|
|
|
inline void |
|
wenc16 (unsigned short a, unsigned short b, |
|
unsigned short &l, unsigned short &h) |
|
{ |
|
int ao = (a + A_OFFSET) & MOD_MASK; |
|
int m = ((ao + b) >> 1); |
|
int d = ao - b; |
|
|
|
if (d < 0) |
|
m = (m + M_OFFSET) & MOD_MASK; |
|
|
|
d &= MOD_MASK; |
|
|
|
l = m; |
|
h = d; |
|
} |
|
|
|
|
|
inline void |
|
wdec16 (unsigned short l, unsigned short h, |
|
unsigned short &a, unsigned short &b) |
|
{ |
|
int m = l; |
|
int d = h; |
|
int bb = (m - (d >> 1)) & MOD_MASK; |
|
int aa = (d + bb - A_OFFSET) & MOD_MASK; |
|
b = bb; |
|
a = aa; |
|
} |
|
|
|
} // namespace |
|
|
|
|
|
// |
|
// 2D Wavelet encoding: |
|
// |
|
|
|
void |
|
wav2Encode |
|
(unsigned short* in, // io: values are transformed in place |
|
int nx, // i : x size |
|
int ox, // i : x offset |
|
int ny, // i : y size |
|
int oy, // i : y offset |
|
unsigned short mx) // i : maximum in[x][y] value |
|
{ |
|
bool w14 = (mx < (1 << 14)); |
|
int n = (nx > ny)? ny: nx; |
|
int p = 1; // == 1 << level |
|
int p2 = 2; // == 1 << (level+1) |
|
|
|
// |
|
// Hierachical loop on smaller dimension n |
|
// |
|
|
|
while (p2 <= n) |
|
{ |
|
unsigned short *py = in; |
|
unsigned short *ey = in + oy * (ny - p2); |
|
int oy1 = oy * p; |
|
int oy2 = oy * p2; |
|
int ox1 = ox * p; |
|
int ox2 = ox * p2; |
|
unsigned short i00,i01,i10,i11; |
|
|
|
// |
|
// Y loop |
|
// |
|
|
|
for (; py <= ey; py += oy2) |
|
{ |
|
unsigned short *px = py; |
|
unsigned short *ex = py + ox * (nx - p2); |
|
|
|
// |
|
// X loop |
|
// |
|
|
|
for (; px <= ex; px += ox2) |
|
{ |
|
unsigned short *p01 = px + ox1; |
|
unsigned short *p10 = px + oy1; |
|
unsigned short *p11 = p10 + ox1; |
|
|
|
// |
|
// 2D wavelet encoding |
|
// |
|
|
|
if (w14) |
|
{ |
|
wenc14 (*px, *p01, i00, i01); |
|
wenc14 (*p10, *p11, i10, i11); |
|
wenc14 (i00, i10, *px, *p10); |
|
wenc14 (i01, i11, *p01, *p11); |
|
} |
|
else |
|
{ |
|
wenc16 (*px, *p01, i00, i01); |
|
wenc16 (*p10, *p11, i10, i11); |
|
wenc16 (i00, i10, *px, *p10); |
|
wenc16 (i01, i11, *p01, *p11); |
|
} |
|
} |
|
|
|
// |
|
// Encode (1D) odd column (still in Y loop) |
|
// |
|
|
|
if (nx & p) |
|
{ |
|
unsigned short *p10 = px + oy1; |
|
|
|
if (w14) |
|
wenc14 (*px, *p10, i00, *p10); |
|
else |
|
wenc16 (*px, *p10, i00, *p10); |
|
|
|
*px= i00; |
|
} |
|
} |
|
|
|
// |
|
// Encode (1D) odd line (must loop in X) |
|
// |
|
|
|
if (ny & p) |
|
{ |
|
unsigned short *px = py; |
|
unsigned short *ex = py + ox * (nx - p2); |
|
|
|
for (; px <= ex; px += ox2) |
|
{ |
|
unsigned short *p01 = px + ox1; |
|
|
|
if (w14) |
|
wenc14 (*px, *p01, i00, *p01); |
|
else |
|
wenc16 (*px, *p01, i00, *p01); |
|
|
|
*px= i00; |
|
} |
|
} |
|
|
|
// |
|
// Next level |
|
// |
|
|
|
p = p2; |
|
p2 <<= 1; |
|
} |
|
} |
|
|
|
|
|
// |
|
// 2D Wavelet decoding: |
|
// |
|
|
|
void |
|
wav2Decode |
|
(unsigned short* in, // io: values are transformed in place |
|
int nx, // i : x size |
|
int ox, // i : x offset |
|
int ny, // i : y size |
|
int oy, // i : y offset |
|
unsigned short mx) // i : maximum in[x][y] value |
|
{ |
|
bool w14 = (mx < (1 << 14)); |
|
int n = (nx > ny)? ny: nx; |
|
int p = 1; |
|
int p2; |
|
|
|
// |
|
// Search max level |
|
// |
|
|
|
while (p <= n) |
|
p <<= 1; |
|
|
|
p >>= 1; |
|
p2 = p; |
|
p >>= 1; |
|
|
|
// |
|
// Hierarchical loop on smaller dimension n |
|
// |
|
|
|
while (p >= 1) |
|
{ |
|
unsigned short *py = in; |
|
unsigned short *ey = in + oy * (ny - p2); |
|
int oy1 = oy * p; |
|
int oy2 = oy * p2; |
|
int ox1 = ox * p; |
|
int ox2 = ox * p2; |
|
unsigned short i00,i01,i10,i11; |
|
|
|
// |
|
// Y loop |
|
// |
|
|
|
for (; py <= ey; py += oy2) |
|
{ |
|
unsigned short *px = py; |
|
unsigned short *ex = py + ox * (nx - p2); |
|
|
|
// |
|
// X loop |
|
// |
|
|
|
for (; px <= ex; px += ox2) |
|
{ |
|
unsigned short *p01 = px + ox1; |
|
unsigned short *p10 = px + oy1; |
|
unsigned short *p11 = p10 + ox1; |
|
|
|
// |
|
// 2D wavelet decoding |
|
// |
|
|
|
if (w14) |
|
{ |
|
wdec14 (*px, *p10, i00, i10); |
|
wdec14 (*p01, *p11, i01, i11); |
|
wdec14 (i00, i01, *px, *p01); |
|
wdec14 (i10, i11, *p10, *p11); |
|
} |
|
else |
|
{ |
|
wdec16 (*px, *p10, i00, i10); |
|
wdec16 (*p01, *p11, i01, i11); |
|
wdec16 (i00, i01, *px, *p01); |
|
wdec16 (i10, i11, *p10, *p11); |
|
} |
|
} |
|
|
|
// |
|
// Decode (1D) odd column (still in Y loop) |
|
// |
|
|
|
if (nx & p) |
|
{ |
|
unsigned short *p10 = px + oy1; |
|
|
|
if (w14) |
|
wdec14 (*px, *p10, i00, *p10); |
|
else |
|
wdec16 (*px, *p10, i00, *p10); |
|
|
|
*px= i00; |
|
} |
|
} |
|
|
|
// |
|
// Decode (1D) odd line (must loop in X) |
|
// |
|
|
|
if (ny & p) |
|
{ |
|
unsigned short *px = py; |
|
unsigned short *ex = py + ox * (nx - p2); |
|
|
|
for (; px <= ex; px += ox2) |
|
{ |
|
unsigned short *p01 = px + ox1; |
|
|
|
if (w14) |
|
wdec14 (*px, *p01, i00, *p01); |
|
else |
|
wdec16 (*px, *p01, i00, *p01); |
|
|
|
*px= i00; |
|
} |
|
} |
|
|
|
// |
|
// Next level |
|
// |
|
|
|
p2 = p; |
|
p >>= 1; |
|
} |
|
} |
|
|
|
|
|
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT
|
|
|