root / ui / vnc-enc-zywrle.h @ 7fee199c
History | View | Annotate | Download (25.3 kB)
1 |
/********************************************************************
|
---|---|
2 |
* *
|
3 |
* THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE. *
|
4 |
* *
|
5 |
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
6 |
* GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE. *
|
7 |
* PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
8 |
* *
|
9 |
* THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006 *
|
10 |
* BY Hitachi Systems & Services, Ltd. *
|
11 |
* (Noriaki Yamazaki, Research & Developement Center) *
|
12 |
* *
|
13 |
* *
|
14 |
********************************************************************
|
15 |
Redistribution and use in source and binary forms, with or without
|
16 |
modification, are permitted provided that the following conditions
|
17 |
are met:
|
18 |
|
19 |
- Redistributions of source code must retain the above copyright
|
20 |
notice, this list of conditions and the following disclaimer.
|
21 |
|
22 |
- Redistributions in binary form must reproduce the above copyright
|
23 |
notice, this list of conditions and the following disclaimer in the
|
24 |
documentation and/or other materials provided with the distribution.
|
25 |
|
26 |
- Neither the name of the Hitachi Systems & Services, Ltd. nor
|
27 |
the names of its contributors may be used to endorse or promote
|
28 |
products derived from this software without specific prior written
|
29 |
permission.
|
30 |
|
31 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
32 |
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
33 |
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
34 |
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
35 |
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
36 |
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
37 |
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
38 |
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
39 |
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
40 |
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
41 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
42 |
********************************************************************/
|
43 |
|
44 |
#ifndef VNC_ENCODING_ZYWRLE_H
|
45 |
#define VNC_ENCODING_ZYWRLE_H
|
46 |
|
47 |
/* Tables for Coefficients filtering. */
|
48 |
#ifndef ZYWRLE_QUANTIZE
|
49 |
/* Type A:lower bit omitting of EZW style. */
|
50 |
static const unsigned int zywrle_param[3][3]={ |
51 |
{0x0000F000, 0x00000000, 0x00000000}, |
52 |
{0x0000C000, 0x00F0F0F0, 0x00000000}, |
53 |
{0x0000C000, 0x00C0C0C0, 0x00F0F0F0}, |
54 |
/* {0x0000FF00, 0x00000000, 0x00000000},
|
55 |
{0x0000FF00, 0x00FFFFFF, 0x00000000},
|
56 |
{0x0000FF00, 0x00FFFFFF, 0x00FFFFFF}, */
|
57 |
}; |
58 |
#else
|
59 |
/* Type B:Non liner quantization filter. */
|
60 |
static const int8_t zywrle_conv[4][256]={ |
61 |
{ /* bi=5, bo=5 r=0.0:PSNR=24.849 */
|
62 |
0, 0, 0, 0, 0, 0, 0, 0, |
63 |
0, 0, 0, 0, 0, 0, 0, 0, |
64 |
0, 0, 0, 0, 0, 0, 0, 0, |
65 |
0, 0, 0, 0, 0, 0, 0, 0, |
66 |
0, 0, 0, 0, 0, 0, 0, 0, |
67 |
0, 0, 0, 0, 0, 0, 0, 0, |
68 |
0, 0, 0, 0, 0, 0, 0, 0, |
69 |
0, 0, 0, 0, 0, 0, 0, 0, |
70 |
0, 0, 0, 0, 0, 0, 0, 0, |
71 |
0, 0, 0, 0, 0, 0, 0, 0, |
72 |
0, 0, 0, 0, 0, 0, 0, 0, |
73 |
0, 0, 0, 0, 0, 0, 0, 0, |
74 |
0, 0, 0, 0, 0, 0, 0, 0, |
75 |
0, 0, 0, 0, 0, 0, 0, 0, |
76 |
0, 0, 0, 0, 0, 0, 0, 0, |
77 |
0, 0, 0, 0, 0, 0, 0, 0, |
78 |
0, 0, 0, 0, 0, 0, 0, 0, |
79 |
0, 0, 0, 0, 0, 0, 0, 0, |
80 |
0, 0, 0, 0, 0, 0, 0, 0, |
81 |
0, 0, 0, 0, 0, 0, 0, 0, |
82 |
0, 0, 0, 0, 0, 0, 0, 0, |
83 |
0, 0, 0, 0, 0, 0, 0, 0, |
84 |
0, 0, 0, 0, 0, 0, 0, 0, |
85 |
0, 0, 0, 0, 0, 0, 0, 0, |
86 |
0, 0, 0, 0, 0, 0, 0, 0, |
87 |
0, 0, 0, 0, 0, 0, 0, 0, |
88 |
0, 0, 0, 0, 0, 0, 0, 0, |
89 |
0, 0, 0, 0, 0, 0, 0, 0, |
90 |
0, 0, 0, 0, 0, 0, 0, 0, |
91 |
0, 0, 0, 0, 0, 0, 0, 0, |
92 |
0, 0, 0, 0, 0, 0, 0, 0, |
93 |
0, 0, 0, 0, 0, 0, 0, 0, |
94 |
}, |
95 |
{ /* bi=5, bo=5 r=2.0:PSNR=74.031 */
|
96 |
0, 0, 0, 0, 0, 0, 0, 0, |
97 |
0, 0, 0, 0, 0, 0, 0, 0, |
98 |
0, 0, 0, 0, 0, 0, 0, 32, |
99 |
32, 32, 32, 32, 32, 32, 32, 32, |
100 |
32, 32, 32, 32, 32, 32, 32, 32, |
101 |
48, 48, 48, 48, 48, 48, 48, 48, |
102 |
48, 48, 48, 56, 56, 56, 56, 56, |
103 |
56, 56, 56, 56, 64, 64, 64, 64, |
104 |
64, 64, 64, 64, 72, 72, 72, 72, |
105 |
72, 72, 72, 72, 80, 80, 80, 80, |
106 |
80, 80, 88, 88, 88, 88, 88, 88, |
107 |
88, 88, 88, 88, 88, 88, 96, 96, |
108 |
96, 96, 96, 104, 104, 104, 104, 104, |
109 |
104, 104, 104, 104, 104, 112, 112, 112, |
110 |
112, 112, 112, 112, 112, 112, 120, 120, |
111 |
120, 120, 120, 120, 120, 120, 120, 120, |
112 |
0, -120, -120, -120, -120, -120, -120, -120, |
113 |
-120, -120, -120, -112, -112, -112, -112, -112, |
114 |
-112, -112, -112, -112, -104, -104, -104, -104, |
115 |
-104, -104, -104, -104, -104, -104, -96, -96, |
116 |
-96, -96, -96, -88, -88, -88, -88, -88, |
117 |
-88, -88, -88, -88, -88, -88, -88, -80, |
118 |
-80, -80, -80, -80, -80, -72, -72, -72, |
119 |
-72, -72, -72, -72, -72, -64, -64, -64, |
120 |
-64, -64, -64, -64, -64, -56, -56, -56, |
121 |
-56, -56, -56, -56, -56, -56, -48, -48, |
122 |
-48, -48, -48, -48, -48, -48, -48, -48, |
123 |
-48, -32, -32, -32, -32, -32, -32, -32, |
124 |
-32, -32, -32, -32, -32, -32, -32, -32, |
125 |
-32, -32, 0, 0, 0, 0, 0, 0, |
126 |
0, 0, 0, 0, 0, 0, 0, 0, |
127 |
0, 0, 0, 0, 0, 0, 0, 0, |
128 |
}, |
129 |
{ /* bi=5, bo=4 r=2.0:PSNR=64.441 */
|
130 |
0, 0, 0, 0, 0, 0, 0, 0, |
131 |
0, 0, 0, 0, 0, 0, 0, 0, |
132 |
0, 0, 0, 0, 0, 0, 0, 0, |
133 |
0, 0, 0, 0, 0, 0, 0, 0, |
134 |
48, 48, 48, 48, 48, 48, 48, 48, |
135 |
48, 48, 48, 48, 48, 48, 48, 48, |
136 |
48, 48, 48, 48, 48, 48, 48, 48, |
137 |
64, 64, 64, 64, 64, 64, 64, 64, |
138 |
64, 64, 64, 64, 64, 64, 64, 64, |
139 |
80, 80, 80, 80, 80, 80, 80, 80, |
140 |
80, 80, 80, 80, 80, 88, 88, 88, |
141 |
88, 88, 88, 88, 88, 88, 88, 88, |
142 |
104, 104, 104, 104, 104, 104, 104, 104, |
143 |
104, 104, 104, 112, 112, 112, 112, 112, |
144 |
112, 112, 112, 112, 120, 120, 120, 120, |
145 |
120, 120, 120, 120, 120, 120, 120, 120, |
146 |
0, -120, -120, -120, -120, -120, -120, -120, |
147 |
-120, -120, -120, -120, -120, -112, -112, -112, |
148 |
-112, -112, -112, -112, -112, -112, -104, -104, |
149 |
-104, -104, -104, -104, -104, -104, -104, -104, |
150 |
-104, -88, -88, -88, -88, -88, -88, -88, |
151 |
-88, -88, -88, -88, -80, -80, -80, -80, |
152 |
-80, -80, -80, -80, -80, -80, -80, -80, |
153 |
-80, -64, -64, -64, -64, -64, -64, -64, |
154 |
-64, -64, -64, -64, -64, -64, -64, -64, |
155 |
-64, -48, -48, -48, -48, -48, -48, -48, |
156 |
-48, -48, -48, -48, -48, -48, -48, -48, |
157 |
-48, -48, -48, -48, -48, -48, -48, -48, |
158 |
-48, 0, 0, 0, 0, 0, 0, 0, |
159 |
0, 0, 0, 0, 0, 0, 0, 0, |
160 |
0, 0, 0, 0, 0, 0, 0, 0, |
161 |
0, 0, 0, 0, 0, 0, 0, 0, |
162 |
}, |
163 |
{ /* bi=5, bo=2 r=2.0:PSNR=43.175 */
|
164 |
0, 0, 0, 0, 0, 0, 0, 0, |
165 |
0, 0, 0, 0, 0, 0, 0, 0, |
166 |
0, 0, 0, 0, 0, 0, 0, 0, |
167 |
0, 0, 0, 0, 0, 0, 0, 0, |
168 |
0, 0, 0, 0, 0, 0, 0, 0, |
169 |
0, 0, 0, 0, 0, 0, 0, 0, |
170 |
0, 0, 0, 0, 0, 0, 0, 0, |
171 |
0, 0, 0, 0, 0, 0, 0, 0, |
172 |
88, 88, 88, 88, 88, 88, 88, 88, |
173 |
88, 88, 88, 88, 88, 88, 88, 88, |
174 |
88, 88, 88, 88, 88, 88, 88, 88, |
175 |
88, 88, 88, 88, 88, 88, 88, 88, |
176 |
88, 88, 88, 88, 88, 88, 88, 88, |
177 |
88, 88, 88, 88, 88, 88, 88, 88, |
178 |
88, 88, 88, 88, 88, 88, 88, 88, |
179 |
88, 88, 88, 88, 88, 88, 88, 88, |
180 |
0, -88, -88, -88, -88, -88, -88, -88, |
181 |
-88, -88, -88, -88, -88, -88, -88, -88, |
182 |
-88, -88, -88, -88, -88, -88, -88, -88, |
183 |
-88, -88, -88, -88, -88, -88, -88, -88, |
184 |
-88, -88, -88, -88, -88, -88, -88, -88, |
185 |
-88, -88, -88, -88, -88, -88, -88, -88, |
186 |
-88, -88, -88, -88, -88, -88, -88, -88, |
187 |
-88, -88, -88, -88, -88, -88, -88, -88, |
188 |
-88, 0, 0, 0, 0, 0, 0, 0, |
189 |
0, 0, 0, 0, 0, 0, 0, 0, |
190 |
0, 0, 0, 0, 0, 0, 0, 0, |
191 |
0, 0, 0, 0, 0, 0, 0, 0, |
192 |
0, 0, 0, 0, 0, 0, 0, 0, |
193 |
0, 0, 0, 0, 0, 0, 0, 0, |
194 |
0, 0, 0, 0, 0, 0, 0, 0, |
195 |
0, 0, 0, 0, 0, 0, 0, 0, |
196 |
} |
197 |
}; |
198 |
|
199 |
static const int8_t *zywrle_param[3][3][3]={ |
200 |
{{zywrle_conv[0], zywrle_conv[2], zywrle_conv[0]}, |
201 |
{zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]}, |
202 |
{zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]}}, |
203 |
{{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]}, |
204 |
{zywrle_conv[1], zywrle_conv[1], zywrle_conv[1]}, |
205 |
{zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]}}, |
206 |
{{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]}, |
207 |
{zywrle_conv[2], zywrle_conv[2], zywrle_conv[2]}, |
208 |
{zywrle_conv[1], zywrle_conv[1], zywrle_conv[1]}}, |
209 |
}; |
210 |
#endif
|
211 |
|
212 |
/* Load/Save pixel stuffs. */
|
213 |
#define ZYWRLE_YMASK15 0xFFFFFFF8 |
214 |
#define ZYWRLE_UVMASK15 0xFFFFFFF8 |
215 |
#define ZYWRLE_LOAD_PIXEL15(src, r, g, b) \
|
216 |
do { \
|
217 |
r = (((uint8_t*)src)[S_1]<< 1)& 0xF8; \ |
218 |
g = (((uint8_t*)src)[S_1]<< 6) | (((uint8_t*)src)[S_0]>> 2); \ |
219 |
g &= 0xF8; \
|
220 |
b = (((uint8_t*)src)[S_0]<< 3)& 0xF8; \ |
221 |
} while (0) |
222 |
|
223 |
#define ZYWRLE_SAVE_PIXEL15(dst, r, g, b) \
|
224 |
do { \
|
225 |
r &= 0xF8; \
|
226 |
g &= 0xF8; \
|
227 |
b &= 0xF8; \
|
228 |
((uint8_t*)dst)[S_1] = (uint8_t)((r >> 1)|(g >> 6)); \ |
229 |
((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 2))& 0xFF); \ |
230 |
} while (0) |
231 |
|
232 |
#define ZYWRLE_YMASK16 0xFFFFFFFC |
233 |
#define ZYWRLE_UVMASK16 0xFFFFFFF8 |
234 |
#define ZYWRLE_LOAD_PIXEL16(src, r, g, b) \
|
235 |
do { \
|
236 |
r = ((uint8_t*)src)[S_1] & 0xF8; \
|
237 |
g = (((uint8_t*)src)[S_1]<< 5) | (((uint8_t*)src)[S_0] >> 3); \ |
238 |
g &= 0xFC; \
|
239 |
b = (((uint8_t*)src)[S_0]<< 3) & 0xF8; \ |
240 |
} while (0) |
241 |
|
242 |
#define ZYWRLE_SAVE_PIXEL16(dst, r, g,b) \
|
243 |
do { \
|
244 |
r &= 0xF8; \
|
245 |
g &= 0xFC; \
|
246 |
b &= 0xF8; \
|
247 |
((uint8_t*)dst)[S_1] = (uint8_t)(r | (g >> 5)); \
|
248 |
((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 3)) & 0xFF); \ |
249 |
} while (0) |
250 |
|
251 |
#define ZYWRLE_YMASK32 0xFFFFFFFF |
252 |
#define ZYWRLE_UVMASK32 0xFFFFFFFF |
253 |
#define ZYWRLE_LOAD_PIXEL32(src, r, g, b) \
|
254 |
do { \
|
255 |
r = ((uint8_t*)src)[L_2]; \ |
256 |
g = ((uint8_t*)src)[L_1]; \ |
257 |
b = ((uint8_t*)src)[L_0]; \ |
258 |
} while (0) |
259 |
#define ZYWRLE_SAVE_PIXEL32(dst, r, g, b) \
|
260 |
do { \
|
261 |
((uint8_t*)dst)[L_2] = (uint8_t)r; \ |
262 |
((uint8_t*)dst)[L_1] = (uint8_t)g; \ |
263 |
((uint8_t*)dst)[L_0] = (uint8_t)b; \ |
264 |
} while (0) |
265 |
|
266 |
static inline void harr(int8_t *px0, int8_t *px1) |
267 |
{ |
268 |
/* Piecewise-Linear Harr(PLHarr) */
|
269 |
int x0 = (int)*px0, x1 = (int)*px1; |
270 |
int orgx0 = x0, orgx1 = x1;
|
271 |
|
272 |
if ((x0 ^ x1) & 0x80) { |
273 |
/* differ sign */
|
274 |
x1 += x0; |
275 |
if (((x1 ^ orgx1) & 0x80) == 0) { |
276 |
/* |x1| > |x0| */
|
277 |
x0 -= x1; /* H = -B */
|
278 |
} |
279 |
} else {
|
280 |
/* same sign */
|
281 |
x0 -= x1; |
282 |
if (((x0 ^ orgx0) & 0x80) == 0) { |
283 |
/* |x0| > |x1| */
|
284 |
x1 += x0; /* L = A */
|
285 |
} |
286 |
} |
287 |
*px0 = (int8_t)x1; |
288 |
*px1 = (int8_t)x0; |
289 |
} |
290 |
|
291 |
/*
|
292 |
1D-Wavelet transform.
|
293 |
|
294 |
In coefficients array, the famous 'pyramid' decomposition is well used.
|
295 |
|
296 |
1D Model:
|
297 |
|L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
|
298 |
|L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
|
299 |
|
300 |
But this method needs line buffer because H/L is different position from X0/X1.
|
301 |
So, I used 'interleave' decomposition instead of it.
|
302 |
|
303 |
1D Model:
|
304 |
|L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
|
305 |
|L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
|
306 |
|
307 |
In this method, H/L and X0/X1 is always same position.
|
308 |
This lead us to more speed and less memory.
|
309 |
Of cause, the result of both method is quite same
|
310 |
because it's only difference that coefficient position.
|
311 |
*/
|
312 |
static inline void wavelet_level(int *data, int size, int l, int skip_pixel) |
313 |
{ |
314 |
int s, ofs;
|
315 |
int8_t *px0; |
316 |
int8_t *end; |
317 |
|
318 |
px0 = (int8_t*)data; |
319 |
s = (8 << l) * skip_pixel;
|
320 |
end = px0 + (size >> (l + 1)) * s;
|
321 |
s -= 2;
|
322 |
ofs = (4 << l) * skip_pixel;
|
323 |
|
324 |
while (px0 < end) {
|
325 |
harr(px0, px0 + ofs); |
326 |
px0++; |
327 |
harr(px0, px0 + ofs); |
328 |
px0++; |
329 |
harr(px0, px0 + ofs); |
330 |
px0 += s; |
331 |
} |
332 |
} |
333 |
|
334 |
#ifndef ZYWRLE_QUANTIZE
|
335 |
/* Type A:lower bit omitting of EZW style. */
|
336 |
static inline void filter_wavelet_square(int *buf, int width, int height, |
337 |
int level, int l) |
338 |
{ |
339 |
int r, s;
|
340 |
int x, y;
|
341 |
int *h;
|
342 |
const unsigned int *m; |
343 |
|
344 |
m = &(zywrle_param[level - 1][l]);
|
345 |
s = 2 << l;
|
346 |
|
347 |
for (r = 1; r < 4; r++) { |
348 |
h = buf; |
349 |
if (r & 0x01) { |
350 |
h += s >> 1;
|
351 |
} |
352 |
if (r & 0x02) { |
353 |
h += (s >> 1) * width;
|
354 |
} |
355 |
for (y = 0; y < height / s; y++) { |
356 |
for (x = 0; x < width / s; x++) { |
357 |
/*
|
358 |
these are same following code.
|
359 |
h[x] = h[x] / (~m[x]+1) * (~m[x]+1);
|
360 |
( round h[x] with m[x] bit )
|
361 |
'&' operator isn't 'round' but is 'floor'.
|
362 |
So, we must offset when h[x] is negative.
|
363 |
*/
|
364 |
if (((int8_t*)h)[0] & 0x80) { |
365 |
((int8_t*)h)[0] += ~((int8_t*)m)[0]; |
366 |
} |
367 |
if (((int8_t*)h)[1] & 0x80) { |
368 |
((int8_t*)h)[1] += ~((int8_t*)m)[1]; |
369 |
} |
370 |
if (((int8_t*)h)[2] & 0x80) { |
371 |
((int8_t*)h)[2] += ~((int8_t*)m)[2]; |
372 |
} |
373 |
*h &= *m; |
374 |
h += s; |
375 |
} |
376 |
h += (s-1)*width;
|
377 |
} |
378 |
} |
379 |
} |
380 |
#else
|
381 |
/*
|
382 |
Type B:Non liner quantization filter.
|
383 |
|
384 |
Coefficients have Gaussian curve and smaller value which is
|
385 |
large part of coefficients isn't more important than larger value.
|
386 |
So, I use filter of Non liner quantize/dequantize table.
|
387 |
In general, Non liner quantize formula is explained as following.
|
388 |
|
389 |
y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo)
|
390 |
x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi)
|
391 |
( r:power coefficient bi:effective MSB in input bo:effective MSB in output )
|
392 |
|
393 |
r < 1.0 : Smaller value is more important than larger value.
|
394 |
r > 1.0 : Larger value is more important than smaller value.
|
395 |
r = 1.0 : Liner quantization which is same with EZW style.
|
396 |
|
397 |
r = 0.75 is famous non liner quantization used in MP3 audio codec.
|
398 |
In contrast to audio data, larger value is important in wavelet coefficients.
|
399 |
So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ).
|
400 |
|
401 |
As compared with EZW style liner quantization, this filter tended to be
|
402 |
more sharp edge and be more compression rate but be more blocking noise and be
|
403 |
less quality. Especially, the surface of graphic objects has distinguishable
|
404 |
noise in middle quality mode.
|
405 |
|
406 |
We need only quantized-dequantized(filtered) value rather than quantized value
|
407 |
itself because all values are packed or palette-lized in later ZRLE section.
|
408 |
This lead us not to need to modify client decoder when we change
|
409 |
the filtering procedure in future.
|
410 |
Client only decodes coefficients given by encoder.
|
411 |
*/
|
412 |
static inline void filter_wavelet_square(int *buf, int width, int height, |
413 |
int level, int l) |
414 |
{ |
415 |
int r, s;
|
416 |
int x, y;
|
417 |
int *h;
|
418 |
const int8_t **m;
|
419 |
|
420 |
m = zywrle_param[level - 1][l];
|
421 |
s = 2 << l;
|
422 |
|
423 |
for (r = 1; r < 4; r++) { |
424 |
h = buf; |
425 |
if (r & 0x01) { |
426 |
h += s >> 1;
|
427 |
} |
428 |
if (r & 0x02) { |
429 |
h += (s >> 1) * width;
|
430 |
} |
431 |
for (y = 0; y < height / s; y++) { |
432 |
for (x = 0; x < width / s; x++) { |
433 |
((int8_t*)h)[0] = m[0][((uint8_t*)h)[0]]; |
434 |
((int8_t*)h)[1] = m[1][((uint8_t*)h)[1]]; |
435 |
((int8_t*)h)[2] = m[2][((uint8_t*)h)[2]]; |
436 |
h += s; |
437 |
} |
438 |
h += (s - 1) * width;
|
439 |
} |
440 |
} |
441 |
} |
442 |
#endif
|
443 |
|
444 |
static inline void wavelet(int *buf, int width, int height, int level) |
445 |
{ |
446 |
int l, s;
|
447 |
int *top;
|
448 |
int *end;
|
449 |
|
450 |
for (l = 0; l < level; l++) { |
451 |
top = buf; |
452 |
end = buf + height * width; |
453 |
s = width << l; |
454 |
while (top < end) {
|
455 |
wavelet_level(top, width, l, 1);
|
456 |
top += s; |
457 |
} |
458 |
top = buf; |
459 |
end = buf + width; |
460 |
s = 1<<l;
|
461 |
while (top < end) {
|
462 |
wavelet_level(top, height, l, width); |
463 |
top += s; |
464 |
} |
465 |
filter_wavelet_square(buf, width, height, level, l); |
466 |
} |
467 |
} |
468 |
|
469 |
|
470 |
/* Load/Save coefficients stuffs.
|
471 |
Coefficients manages as 24 bits little-endian pixel. */
|
472 |
#define ZYWRLE_LOAD_COEFF(src, r, g, b) \
|
473 |
do { \
|
474 |
r = ((int8_t*)src)[2]; \
|
475 |
g = ((int8_t*)src)[1]; \
|
476 |
b = ((int8_t*)src)[0]; \
|
477 |
} while (0) |
478 |
|
479 |
#define ZYWRLE_SAVE_COEFF(dst, r, g, b) \
|
480 |
do { \
|
481 |
((int8_t*)dst)[2] = (int8_t)r; \
|
482 |
((int8_t*)dst)[1] = (int8_t)g; \
|
483 |
((int8_t*)dst)[0] = (int8_t)b; \
|
484 |
} while (0) |
485 |
|
486 |
/*
|
487 |
RGB <=> YUV conversion stuffs.
|
488 |
YUV coversion is explained as following formula in strict meaning:
|
489 |
Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255)
|
490 |
U = -0.169R - 0.331G + 0.500B (-128<=U<=127)
|
491 |
V = 0.500R - 0.419G - 0.081B (-128<=V<=127)
|
492 |
|
493 |
I use simple conversion RCT(reversible color transform) which is described
|
494 |
in JPEG-2000 specification.
|
495 |
Y = (R + 2G + B)/4 ( 0<=Y<=255)
|
496 |
U = B-G (-256<=U<=255)
|
497 |
V = R-G (-256<=V<=255)
|
498 |
*/
|
499 |
|
500 |
/* RCT is N-bit RGB to N-bit Y and N+1-bit UV.
|
501 |
For make Same N-bit, UV is lossy.
|
502 |
More exact PLHarr, we reduce to odd range(-127<=x<=127). */
|
503 |
#define ZYWRLE_RGBYUV_(r, g, b, y, u, v, ymask, uvmask) \
|
504 |
do { \
|
505 |
y = (r + (g << 1) + b) >> 2; \ |
506 |
u = b - g; \ |
507 |
v = r - g; \ |
508 |
y -= 128; \
|
509 |
u >>= 1; \
|
510 |
v >>= 1; \
|
511 |
y &= ymask; \ |
512 |
u &= uvmask; \ |
513 |
v &= uvmask; \ |
514 |
if (y == -128) { \ |
515 |
y += (0xFFFFFFFF - ymask + 1); \ |
516 |
} \ |
517 |
if (u == -128) { \ |
518 |
u += (0xFFFFFFFF - uvmask + 1); \ |
519 |
} \ |
520 |
if (v == -128) { \ |
521 |
v += (0xFFFFFFFF - uvmask + 1); \ |
522 |
} \ |
523 |
} while (0) |
524 |
|
525 |
|
526 |
/*
|
527 |
coefficient packing/unpacking stuffs.
|
528 |
Wavelet transform makes 4 sub coefficient image from 1 original image.
|
529 |
|
530 |
model with pyramid decomposition:
|
531 |
+------+------+
|
532 |
| | |
|
533 |
| L | Hx |
|
534 |
| | |
|
535 |
+------+------+
|
536 |
| | |
|
537 |
| H | Hxy |
|
538 |
| | |
|
539 |
+------+------+
|
540 |
|
541 |
So, we must transfer each sub images individually in strict meaning.
|
542 |
But at least ZRLE meaning, following one decompositon image is same as
|
543 |
avobe individual sub image. I use this format.
|
544 |
(Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L)
|
545 |
for simplified procedure for any wavelet level.)
|
546 |
|
547 |
+------+------+
|
548 |
| L |
|
549 |
+------+------+
|
550 |
| Hx |
|
551 |
+------+------+
|
552 |
| Hy |
|
553 |
+------+------+
|
554 |
| Hxy |
|
555 |
+------+------+
|
556 |
*/
|
557 |
#define ZYWRLE_INC_PTR(data) \
|
558 |
do { \
|
559 |
data++; \ |
560 |
if( data - p >= (w + uw) ) { \
|
561 |
data += scanline-(w + uw); \ |
562 |
p = data; \ |
563 |
} \ |
564 |
} while (0) |
565 |
|
566 |
#define ZYWRLE_TRANSFER_COEFF(buf, data, t, w, h, scanline, level, TRANS) \
|
567 |
do { \
|
568 |
ph = buf; \ |
569 |
s = 2 << level; \
|
570 |
if (t & 0x01) { \ |
571 |
ph += s >> 1; \
|
572 |
} \ |
573 |
if (t & 0x02) { \ |
574 |
ph += (s >> 1) * w; \
|
575 |
} \ |
576 |
end = ph + h * w; \ |
577 |
while (ph < end) { \
|
578 |
line = ph + w; \ |
579 |
while (ph < line) { \
|
580 |
TRANS \ |
581 |
ZYWRLE_INC_PTR(data); \ |
582 |
ph += s; \ |
583 |
} \ |
584 |
ph += (s - 1) * w; \
|
585 |
} \ |
586 |
} while (0) |
587 |
|
588 |
#define ZYWRLE_PACK_COEFF(buf, data, t, width, height, scanline, level) \
|
589 |
ZYWRLE_TRANSFER_COEFF(buf, data, t, width, height, scanline, level, \ |
590 |
ZYWRLE_LOAD_COEFF(ph, r, g, b); \ |
591 |
ZYWRLE_SAVE_PIXEL(data, r, g, b);) |
592 |
|
593 |
#define ZYWRLE_UNPACK_COEFF(buf, data, t, width, height, scanline, level) \
|
594 |
ZYWRLE_TRANSFER_COEFF(buf, data, t, width, height, scanline, level, \ |
595 |
ZYWRLE_LOAD_PIXEL(data, r, g, b); \ |
596 |
ZYWRLE_SAVE_COEFF(ph, r, g, b);) |
597 |
|
598 |
#define ZYWRLE_SAVE_UNALIGN(data, TRANS) \
|
599 |
do { \
|
600 |
top = buf + w * h; \ |
601 |
end = buf + (w + uw) * (h + uh); \ |
602 |
while (top < end) { \
|
603 |
TRANS \ |
604 |
ZYWRLE_INC_PTR(data); \ |
605 |
top++; \ |
606 |
} \ |
607 |
} while (0) |
608 |
|
609 |
#define ZYWRLE_LOAD_UNALIGN(data,TRANS) \
|
610 |
do { \
|
611 |
top = buf + w * h; \ |
612 |
if (uw) { \
|
613 |
p = data + w; \ |
614 |
end = (int*)(p + h * scanline); \
|
615 |
while (p < (ZRLE_PIXEL*)end) { \
|
616 |
line = (int*)(p + uw); \
|
617 |
while (p < (ZRLE_PIXEL*)line) { \
|
618 |
TRANS \ |
619 |
p++; \ |
620 |
top++; \ |
621 |
} \ |
622 |
p += scanline - uw; \ |
623 |
} \ |
624 |
} \ |
625 |
if (uh) { \
|
626 |
p = data + h * scanline; \ |
627 |
end = (int*)(p + uh * scanline); \
|
628 |
while (p < (ZRLE_PIXEL*)end) { \
|
629 |
line = (int*)(p + w); \
|
630 |
while (p < (ZRLE_PIXEL*)line) { \
|
631 |
TRANS \ |
632 |
p++; \ |
633 |
top++; \ |
634 |
} \ |
635 |
p += scanline - w; \ |
636 |
} \ |
637 |
} \ |
638 |
if (uw && uh) { \
|
639 |
p= data + w + h * scanline; \ |
640 |
end = (int*)(p + uh * scanline); \
|
641 |
while (p < (ZRLE_PIXEL*)end) { \
|
642 |
line = (int*)(p + uw); \
|
643 |
while (p < (ZRLE_PIXEL*)line) { \
|
644 |
TRANS \ |
645 |
p++; \ |
646 |
top++; \ |
647 |
} \ |
648 |
p += scanline-uw; \ |
649 |
} \ |
650 |
} \ |
651 |
} while (0) |
652 |
|
653 |
static inline void zywrle_calc_size(int *w, int *h, int level) |
654 |
{ |
655 |
*w &= ~((1 << level) - 1); |
656 |
*h &= ~((1 << level) - 1); |
657 |
} |
658 |
|
659 |
#endif
|