add libvncserver
[presencevnc] / libvnc / libvncserver / zywrletemplate.c
1
2 /********************************************************************
3  *                                                                  *
4  * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE.         *
5  *                                                                  *
6  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
7  * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE.                *
8  * PLEASE READ THESE TERMS BEFORE DISTRIBUTING.                     *
9  *                                                                  *
10  * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006         *
11  * BY Hitachi Systems & Services, Ltd.                              *
12  * (Noriaki Yamazaki, Research & Developement Center)               *                                                                 *
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 /* Change Log:
45      V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline
46                              (Thanks Johannes Schindelin, author of LibVNC
47                                                   Server/Client)
48      V0.01 : 2007/02/06 : Initial release
49 */
50
51 /* #define ZYWRLE_ENCODE */
52 /* #define ZYWRLE_DECODE */
53 #define ZYWRLE_QUANTIZE
54
55 /*
56 [References]
57  PLHarr:
58    Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy, "An Improved N-Bit to N-Bit Reversible Haar-Like Transform," Pacific Graphics 2004, October 2004, pp. 371-380.
59  EZW:
60    Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993).
61 */
62
63
64 /* Template Macro stuffs. */
65 #undef ZYWRLE_ANALYZE
66 #undef ZYWRLE_SYNTHESIZE
67 #define ZYWRLE_ANALYZE __RFB_CONCAT3E(zywrleAnalyze,BPP,END_FIX)
68 #define ZYWRLE_SYNTHESIZE __RFB_CONCAT3E(zywrleSynthesize,BPP,END_FIX)
69
70 #define ZYWRLE_RGBYUV __RFB_CONCAT3E(zywrleRGBYUV,BPP,END_FIX)
71 #define ZYWRLE_YUVRGB __RFB_CONCAT3E(zywrleYUVRGB,BPP,END_FIX)
72 #define ZYWRLE_YMASK __RFB_CONCAT2E(ZYWRLE_YMASK,BPP)
73 #define ZYWRLE_UVMASK __RFB_CONCAT2E(ZYWRLE_UVMASK,BPP)
74 #define ZYWRLE_LOAD_PIXEL __RFB_CONCAT2E(ZYWRLE_LOAD_PIXEL,BPP)
75 #define ZYWRLE_SAVE_PIXEL __RFB_CONCAT2E(ZYWRLE_SAVE_PIXEL,BPP)
76
77 /* Packing/Unpacking pixel stuffs.
78    Endian conversion stuffs. */
79 #undef S_0
80 #undef S_1
81 #undef L_0
82 #undef L_1
83 #undef L_2
84 #if ZYWRLE_ENDIAN == ENDIAN_BIG
85 #  define S_0   1
86 #  define S_1   0
87 #  define L_0   3
88 #  define L_1   2
89 #  define L_2   1
90 #else
91 #  define S_0   0
92 #  define S_1   1
93 #  define L_0   0
94 #  define L_1   1
95 #  define L_2   2
96 #endif
97
98 /*   Load/Save pixel stuffs. */
99 #define ZYWRLE_YMASK15  0xFFFFFFF8
100 #define ZYWRLE_UVMASK15 0xFFFFFFF8
101 #define ZYWRLE_LOAD_PIXEL15(pSrc,R,G,B) { \
102         R =  (((unsigned char*)pSrc)[S_1]<< 1)& 0xF8;   \
103         G = ((((unsigned char*)pSrc)[S_1]<< 6)|(((unsigned char*)pSrc)[S_0]>> 2))& 0xF8;        \
104         B =  (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8;   \
105 }
106 #define ZYWRLE_SAVE_PIXEL15(pDst,R,G,B) { \
107         R &= 0xF8;      \
108         G &= 0xF8;      \
109         B &= 0xF8;      \
110         ((unsigned char*)pDst)[S_1] = (unsigned char)( (R>>1)|(G>>6)       );   \
111         ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<2))& 0xFF);   \
112 }
113 #define ZYWRLE_YMASK16  0xFFFFFFFC
114 #define ZYWRLE_UVMASK16 0xFFFFFFF8
115 #define ZYWRLE_LOAD_PIXEL16(pSrc,R,G,B) { \
116         R =   ((unsigned char*)pSrc)[S_1]     & 0xF8;   \
117         G = ((((unsigned char*)pSrc)[S_1]<< 5)|(((unsigned char*)pSrc)[S_0]>> 3))& 0xFC;        \
118         B =  (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8;   \
119 }
120 #define ZYWRLE_SAVE_PIXEL16(pDst,R,G,B) { \
121         R &= 0xF8;      \
122         G &= 0xFC;      \
123         B &= 0xF8;      \
124         ((unsigned char*)pDst)[S_1] = (unsigned char)(  R    |(G>>5)       );   \
125         ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<3))& 0xFF);   \
126 }
127 #define ZYWRLE_YMASK32  0xFFFFFFFF
128 #define ZYWRLE_UVMASK32 0xFFFFFFFF
129 #define ZYWRLE_LOAD_PIXEL32(pSrc,R,G,B) { \
130         R = ((unsigned char*)pSrc)[L_2];        \
131         G = ((unsigned char*)pSrc)[L_1];        \
132         B = ((unsigned char*)pSrc)[L_0];        \
133 }
134 #define ZYWRLE_SAVE_PIXEL32(pDst,R,G,B) { \
135         ((unsigned char*)pDst)[L_2] = (unsigned char)R; \
136         ((unsigned char*)pDst)[L_1] = (unsigned char)G; \
137         ((unsigned char*)pDst)[L_0] = (unsigned char)B; \
138 }
139
140 #ifndef ZYWRLE_ONCE
141 #define ZYWRLE_ONCE
142
143 #ifdef WIN32
144 #define InlineX __inline
145 #else
146 #define InlineX inline
147 #endif
148
149 #ifdef ZYWRLE_ENCODE
150 /* Tables for Coefficients filtering. */
151 #  ifndef ZYWRLE_QUANTIZE
152 /* Type A:lower bit omitting of EZW style. */
153 const static unsigned int zywrleParam[3][3]={
154         {0x0000F000,0x00000000,0x00000000},
155         {0x0000C000,0x00F0F0F0,0x00000000},
156         {0x0000C000,0x00C0C0C0,0x00F0F0F0},
157 /*      {0x0000FF00,0x00000000,0x00000000},
158         {0x0000FF00,0x00FFFFFF,0x00000000},
159         {0x0000FF00,0x00FFFFFF,0x00FFFFFF}, */
160 };
161 #  else
162 /* Type B:Non liner quantization filter. */
163 static const signed char zywrleConv[4][256]={
164 {       /* bi=5, bo=5 r=0.0:PSNR=24.849 */
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         0, 0, 0, 0, 0, 0, 0, 0,
173         0, 0, 0, 0, 0, 0, 0, 0,
174         0, 0, 0, 0, 0, 0, 0, 0,
175         0, 0, 0, 0, 0, 0, 0, 0,
176         0, 0, 0, 0, 0, 0, 0, 0,
177         0, 0, 0, 0, 0, 0, 0, 0,
178         0, 0, 0, 0, 0, 0, 0, 0,
179         0, 0, 0, 0, 0, 0, 0, 0,
180         0, 0, 0, 0, 0, 0, 0, 0,
181         0, 0, 0, 0, 0, 0, 0, 0,
182         0, 0, 0, 0, 0, 0, 0, 0,
183         0, 0, 0, 0, 0, 0, 0, 0,
184         0, 0, 0, 0, 0, 0, 0, 0,
185         0, 0, 0, 0, 0, 0, 0, 0,
186         0, 0, 0, 0, 0, 0, 0, 0,
187         0, 0, 0, 0, 0, 0, 0, 0,
188         0, 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         0, 0, 0, 0, 0, 0, 0, 0,
197 },
198 {       /* bi=5, bo=5 r=2.0:PSNR=74.031 */
199         0, 0, 0, 0, 0, 0, 0, 0,
200         0, 0, 0, 0, 0, 0, 0, 0,
201         0, 0, 0, 0, 0, 0, 0, 32,
202         32, 32, 32, 32, 32, 32, 32, 32,
203         32, 32, 32, 32, 32, 32, 32, 32,
204         48, 48, 48, 48, 48, 48, 48, 48,
205         48, 48, 48, 56, 56, 56, 56, 56,
206         56, 56, 56, 56, 64, 64, 64, 64,
207         64, 64, 64, 64, 72, 72, 72, 72,
208         72, 72, 72, 72, 80, 80, 80, 80,
209         80, 80, 88, 88, 88, 88, 88, 88,
210         88, 88, 88, 88, 88, 88, 96, 96,
211         96, 96, 96, 104, 104, 104, 104, 104,
212         104, 104, 104, 104, 104, 112, 112, 112,
213         112, 112, 112, 112, 112, 112, 120, 120,
214         120, 120, 120, 120, 120, 120, 120, 120,
215         0, -120, -120, -120, -120, -120, -120, -120,
216         -120, -120, -120, -112, -112, -112, -112, -112,
217         -112, -112, -112, -112, -104, -104, -104, -104,
218         -104, -104, -104, -104, -104, -104, -96, -96,
219         -96, -96, -96, -88, -88, -88, -88, -88,
220         -88, -88, -88, -88, -88, -88, -88, -80,
221         -80, -80, -80, -80, -80, -72, -72, -72,
222         -72, -72, -72, -72, -72, -64, -64, -64,
223         -64, -64, -64, -64, -64, -56, -56, -56,
224         -56, -56, -56, -56, -56, -56, -48, -48,
225         -48, -48, -48, -48, -48, -48, -48, -48,
226         -48, -32, -32, -32, -32, -32, -32, -32,
227         -32, -32, -32, -32, -32, -32, -32, -32,
228         -32, -32, 0, 0, 0, 0, 0, 0,
229         0, 0, 0, 0, 0, 0, 0, 0,
230         0, 0, 0, 0, 0, 0, 0, 0,
231 },
232 {       /* bi=5, bo=4 r=2.0:PSNR=64.441 */
233         0, 0, 0, 0, 0, 0, 0, 0,
234         0, 0, 0, 0, 0, 0, 0, 0,
235         0, 0, 0, 0, 0, 0, 0, 0,
236         0, 0, 0, 0, 0, 0, 0, 0,
237         48, 48, 48, 48, 48, 48, 48, 48,
238         48, 48, 48, 48, 48, 48, 48, 48,
239         48, 48, 48, 48, 48, 48, 48, 48,
240         64, 64, 64, 64, 64, 64, 64, 64,
241         64, 64, 64, 64, 64, 64, 64, 64,
242         80, 80, 80, 80, 80, 80, 80, 80,
243         80, 80, 80, 80, 80, 88, 88, 88,
244         88, 88, 88, 88, 88, 88, 88, 88,
245         104, 104, 104, 104, 104, 104, 104, 104,
246         104, 104, 104, 112, 112, 112, 112, 112,
247         112, 112, 112, 112, 120, 120, 120, 120,
248         120, 120, 120, 120, 120, 120, 120, 120,
249         0, -120, -120, -120, -120, -120, -120, -120,
250         -120, -120, -120, -120, -120, -112, -112, -112,
251         -112, -112, -112, -112, -112, -112, -104, -104,
252         -104, -104, -104, -104, -104, -104, -104, -104,
253         -104, -88, -88, -88, -88, -88, -88, -88,
254         -88, -88, -88, -88, -80, -80, -80, -80,
255         -80, -80, -80, -80, -80, -80, -80, -80,
256         -80, -64, -64, -64, -64, -64, -64, -64,
257         -64, -64, -64, -64, -64, -64, -64, -64,
258         -64, -48, -48, -48, -48, -48, -48, -48,
259         -48, -48, -48, -48, -48, -48, -48, -48,
260         -48, -48, -48, -48, -48, -48, -48, -48,
261         -48, 0, 0, 0, 0, 0, 0, 0,
262         0, 0, 0, 0, 0, 0, 0, 0,
263         0, 0, 0, 0, 0, 0, 0, 0,
264         0, 0, 0, 0, 0, 0, 0, 0,
265 },
266 {       /* bi=5, bo=2 r=2.0:PSNR=43.175 */
267         0, 0, 0, 0, 0, 0, 0, 0,
268         0, 0, 0, 0, 0, 0, 0, 0,
269         0, 0, 0, 0, 0, 0, 0, 0,
270         0, 0, 0, 0, 0, 0, 0, 0,
271         0, 0, 0, 0, 0, 0, 0, 0,
272         0, 0, 0, 0, 0, 0, 0, 0,
273         0, 0, 0, 0, 0, 0, 0, 0,
274         0, 0, 0, 0, 0, 0, 0, 0,
275         88, 88, 88, 88, 88, 88, 88, 88,
276         88, 88, 88, 88, 88, 88, 88, 88,
277         88, 88, 88, 88, 88, 88, 88, 88,
278         88, 88, 88, 88, 88, 88, 88, 88,
279         88, 88, 88, 88, 88, 88, 88, 88,
280         88, 88, 88, 88, 88, 88, 88, 88,
281         88, 88, 88, 88, 88, 88, 88, 88,
282         88, 88, 88, 88, 88, 88, 88, 88,
283         0, -88, -88, -88, -88, -88, -88, -88,
284         -88, -88, -88, -88, -88, -88, -88, -88,
285         -88, -88, -88, -88, -88, -88, -88, -88,
286         -88, -88, -88, -88, -88, -88, -88, -88,
287         -88, -88, -88, -88, -88, -88, -88, -88,
288         -88, -88, -88, -88, -88, -88, -88, -88,
289         -88, -88, -88, -88, -88, -88, -88, -88,
290         -88, -88, -88, -88, -88, -88, -88, -88,
291         -88, 0, 0, 0, 0, 0, 0, 0,
292         0, 0, 0, 0, 0, 0, 0, 0,
293         0, 0, 0, 0, 0, 0, 0, 0,
294         0, 0, 0, 0, 0, 0, 0, 0,
295         0, 0, 0, 0, 0, 0, 0, 0,
296         0, 0, 0, 0, 0, 0, 0, 0,
297         0, 0, 0, 0, 0, 0, 0, 0,
298         0, 0, 0, 0, 0, 0, 0, 0,
299 }
300 };
301 const static signed char* zywrleParam[3][3][3]={
302         {{zywrleConv[0],zywrleConv[2],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}},
303         {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}},
304         {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[2],zywrleConv[2],zywrleConv[2]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]}},
305 };
306 #  endif
307 #endif
308
309 static InlineX void Harr(signed char* pX0, signed char* pX1)
310 {
311         /* Piecewise-Linear Harr(PLHarr) */
312         int X0 = (int)*pX0, X1 = (int)*pX1;
313         int orgX0 = X0, orgX1 = X1;
314         if ((X0 ^ X1) & 0x80) {
315                 /* differ sign */
316                 X1 += X0;
317                 if (((X1^orgX1)&0x80)==0) {
318                         /* |X1| > |X0| */
319                         X0 -= X1;       /* H = -B */
320                 }
321         } else {
322                 /* same sign */
323                 X0 -= X1;
324                 if (((X0 ^ orgX0) & 0x80) == 0) {
325                         /* |X0| > |X1| */
326                         X1 += X0;       /* L = A */
327                 }
328         }
329         *pX0 = (signed char)X1;
330         *pX1 = (signed char)X0;
331 }
332 /*
333  1D-Wavelet transform.
334
335  In coefficients array, the famous 'pyramid' decomposition is well used.
336
337  1D Model:
338    |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
339    |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
340
341  But this method needs line buffer because H/L is different position from X0/X1.
342  So, I used 'interleave' decomposition instead of it.
343
344  1D Model:
345    |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
346    |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
347
348  In this method, H/L and X0/X1 is always same position.
349  This lead us to more speed and less memory.
350  Of cause, the result of both method is quite same
351  because it's only difference that coefficient position.
352 */
353 static InlineX void WaveletLevel(int* data, int size, int l, int SkipPixel)
354 {
355         int s, ofs;
356         signed char* pX0;
357         signed char* end;
358
359         pX0 = (signed char*)data;
360         s = (8<<l)*SkipPixel;
361         end = pX0+(size>>(l+1))*s;
362         s -= 2;
363         ofs = (4<<l)*SkipPixel;
364         while (pX0 < end) {
365                 Harr(pX0, pX0+ofs);
366                 pX0++;
367                 Harr(pX0, pX0+ofs);
368                 pX0++;
369                 Harr(pX0, pX0+ofs);
370                 pX0 += s;
371         }
372 }
373 #define InvWaveletLevel(d,s,l,pix) WaveletLevel(d,s,l,pix)
374
375 #ifdef ZYWRLE_ENCODE
376 #  ifndef ZYWRLE_QUANTIZE
377 /* Type A:lower bit omitting of EZW style. */
378 static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l)
379 {
380         int r, s;
381         int x, y;
382         int* pH;
383         const unsigned int* pM;
384
385         pM = &(zywrleParam[level-1][l]);
386         s = 2<<l;
387         for (r = 1; r < 4; r++) {
388                 pH   = pBuf;
389                 if (r & 0x01)
390                         pH +=  s>>1;
391                 if (r & 0x02)
392                         pH += (s>>1)*width;
393                 for (y = 0; y < height / s; y++) {
394                         for (x = 0; x < width / s; x++) {
395                                 /*
396                                  these are same following code.
397                                      pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1);
398                                      ( round pH[x] with pM[x] bit )
399                                  '&' operator isn't 'round' but is 'floor'.
400                                  So, we must offset when pH[x] is negative.
401                                 */
402                                 if (((signed char*)pH)[0] & 0x80)
403                                         ((signed char*)pH)[0] += ~((signed char*)pM)[0];
404                                 if (((signed char*)pH)[1] & 0x80)
405                                         ((signed char*)pH)[1] += ~((signed char*)pM)[1];
406                                 if (((signed char*)pH)[2] & 0x80)
407                                         ((signed char*)pH)[2] += ~((signed char*)pM)[2];
408                                 *pH &= *pM;
409                                 pH += s;
410                         }
411                         pH += (s-1)*width;
412                 }
413         }
414 }
415 #  else
416 /*
417  Type B:Non liner quantization filter.
418
419  Coefficients have Gaussian curve and smaller value which is
420  large part of coefficients isn't more important than larger value.
421  So, I use filter of Non liner quantize/dequantize table.
422  In general, Non liner quantize formula is explained as following.
423
424     y=f(x)   = sign(x)*round( ((abs(x)/(2^7))^ r   )* 2^(bo-1) )*2^(8-bo)
425     x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi)
426  ( r:power coefficient  bi:effective MSB in input  bo:effective MSB in output )
427
428    r < 1.0 : Smaller value is more important than larger value.
429    r > 1.0 : Larger value is more important than smaller value.
430    r = 1.0 : Liner quantization which is same with EZW style.
431
432  r = 0.75 is famous non liner quantization used in MP3 audio codec.
433  In contrast to audio data, larger value is important in wavelet coefficients.
434  So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ).
435
436  As compared with EZW style liner quantization, this filter tended to be
437  more sharp edge and be more compression rate but be more blocking noise and be less quality.
438  Especially, the surface of graphic objects has distinguishable noise in middle quality mode.
439
440  We need only quantized-dequantized(filtered) value rather than quantized value itself
441  because all values are packed or palette-lized in later ZRLE section.
442  This lead us not to need to modify client decoder when we change
443  the filtering procedure in future.
444  Client only decodes coefficients given by encoder.
445 */
446 static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l)
447 {
448         int r, s;
449         int x, y;
450         int* pH;
451         const signed char** pM;
452
453         pM = zywrleParam[level-1][l];
454         s = 2<<l;
455         for (r = 1; r < 4; r++) {
456                 pH   = pBuf;
457                 if (r & 0x01)
458                         pH +=  s>>1;
459                 if (r & 0x02)
460                         pH += (s>>1)*width;
461                 for (y = 0; y < height / s; y++) {
462                         for (x = 0; x < width / s; x++) {
463                                 ((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]];
464                                 ((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]];
465                                 ((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]];
466                                 pH += s;
467                         }
468                         pH += (s-1)*width;
469                 }
470         }
471 }
472 #  endif
473
474 static InlineX void Wavelet(int* pBuf, int width, int height, int level)
475 {
476         int l, s;
477         int* pTop;
478         int* pEnd;
479
480         for (l = 0; l < level; l++) {
481                 pTop = pBuf;
482                 pEnd = pBuf+height*width;
483                 s = width<<l;
484                 while (pTop < pEnd) {
485                         WaveletLevel(pTop, width, l, 1);
486                         pTop += s;
487                 }
488                 pTop = pBuf;
489                 pEnd = pBuf+width;
490                 s = 1<<l;
491                 while (pTop < pEnd) {
492                         WaveletLevel(pTop, height,l, width);
493                         pTop += s;
494                 }
495                 FilterWaveletSquare(pBuf, width, height, level, l);
496         }
497 }
498 #endif
499 #ifdef ZYWRLE_DECODE
500 static InlineX void InvWavelet(int* pBuf, int width, int height, int level)
501 {
502         int l, s;
503         int* pTop;
504         int* pEnd;
505
506         for (l = level - 1; l >= 0; l--) {
507                 pTop = pBuf;
508                 pEnd = pBuf+width;
509                 s = 1<<l;
510                 while (pTop < pEnd) {
511                         InvWaveletLevel(pTop, height,l, width);
512                         pTop += s;
513                 }
514                 pTop = pBuf;
515                 pEnd = pBuf+height*width;
516                 s = width<<l;
517                 while (pTop < pEnd) {
518                         InvWaveletLevel(pTop, width, l, 1);
519                         pTop += s;
520                 }
521         }
522 }
523 #endif
524
525 /* Load/Save coefficients stuffs.
526  Coefficients manages as 24 bits little-endian pixel. */
527 #define ZYWRLE_LOAD_COEFF(pSrc,R,G,B) { \
528         R = ((signed char*)pSrc)[2];    \
529         G = ((signed char*)pSrc)[1];    \
530         B = ((signed char*)pSrc)[0];    \
531 }
532 #define ZYWRLE_SAVE_COEFF(pDst,R,G,B) { \
533         ((signed char*)pDst)[2] = (signed char)R;       \
534         ((signed char*)pDst)[1] = (signed char)G;       \
535         ((signed char*)pDst)[0] = (signed char)B;       \
536 }
537
538 /*
539  RGB <=> YUV conversion stuffs.
540  YUV coversion is explained as following formula in strict meaning:
541    Y =  0.299R + 0.587G + 0.114B (   0<=Y<=255)
542    U = -0.169R - 0.331G + 0.500B (-128<=U<=127)
543    V =  0.500R - 0.419G - 0.081B (-128<=V<=127)
544
545  I use simple conversion RCT(reversible color transform) which is described
546  in JPEG-2000 specification.
547    Y = (R + 2G + B)/4 (   0<=Y<=255)
548    U = B-G (-256<=U<=255)
549    V = R-G (-256<=V<=255)
550 */
551 #define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x)))
552         /* RCT is N-bit RGB to N-bit Y and N+1-bit UV.
553          For make Same N-bit, UV is lossy.
554          More exact PLHarr, we reduce to odd range(-127<=x<=127). */
555 #define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \
556         Y = (R+(G<<1)+B)>>2;    \
557         U =  B-G;       \
558         V =  R-G;       \
559         Y -= 128;       \
560         U >>= 1;        \
561         V >>= 1;        \
562         Y &= ymask;     \
563         U &= uvmask;    \
564         V &= uvmask;    \
565         if (Y == -128)  \
566                 Y += (0xFFFFFFFF-ymask+1);      \
567         if (U == -128)  \
568                 U += (0xFFFFFFFF-uvmask+1);     \
569         if (V == -128)  \
570                 V += (0xFFFFFFFF-uvmask+1);     \
571 }
572 #define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \
573         Y += 128;       \
574         U <<= 1;        \
575         V <<= 1;        \
576         G = Y-((U+V)>>2);       \
577         B = U+G;        \
578         R = V+G;        \
579         G = ROUND(G);   \
580         B = ROUND(B);   \
581         R = ROUND(R);   \
582 }
583
584 /*
585  coefficient packing/unpacking stuffs.
586  Wavelet transform makes 4 sub coefficient image from 1 original image.
587
588  model with pyramid decomposition:
589    +------+------+
590    |      |      |
591    |  L   |  Hx  |
592    |      |      |
593    +------+------+
594    |      |      |
595    |  H   |  Hxy |
596    |      |      |
597    +------+------+
598
599  So, we must transfer each sub images individually in strict meaning.
600  But at least ZRLE meaning, following one decompositon image is same as
601  avobe individual sub image. I use this format.
602  (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L)
603   for simplified procedure for any wavelet level.)
604
605    +------+------+
606    |      L      |
607    +------+------+
608    |      Hx     |
609    +------+------+
610    |      Hy     |
611    +------+------+
612    |      Hxy    |
613    +------+------+
614 */
615 #define INC_PTR(data) \
616         data++; \
617         if( data-pData >= (w+uw) ){     \
618                 data += scanline-(w+uw);        \
619                 pData = data;   \
620         }
621
622 #define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,w,h,scanline,level,TRANS)     \
623         pH = pBuf;      \
624         s = 2<<level;   \
625         if (r & 0x01)   \
626                 pH +=  s>>1;    \
627         if (r & 0x02)   \
628                 pH += (s>>1)*w; \
629         pEnd = pH+h*w;  \
630         while (pH < pEnd) {     \
631                 pLine = pH+w;   \
632                 while (pH < pLine) {    \
633                         TRANS   \
634                         INC_PTR(data)   \
635                         pH += s;        \
636                 }       \
637                 pH += (s-1)*w;  \
638         }
639
640 #define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,scanline,level)      \
641         ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);)
642
643 #define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,scanline,level)    \
644         ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);)
645
646 #define ZYWRLE_SAVE_UNALIGN(data,TRANS) \
647         pTop = pBuf+w*h;        \
648         pEnd = pBuf + (w+uw)*(h+uh);    \
649         while (pTop < pEnd) {   \
650                 TRANS   \
651                 INC_PTR(data)   \
652                 pTop++; \
653         }
654
655 #define ZYWRLE_LOAD_UNALIGN(data,TRANS) \
656         pTop = pBuf+w*h;        \
657         if (uw) {       \
658                 pData=         data + w;        \
659                 pEnd = (int*)(pData+ h*scanline);       \
660                 while (pData < (PIXEL_T*)pEnd) {        \
661                         pLine = (int*)(pData + uw);     \
662                         while (pData < (PIXEL_T*)pLine) {       \
663                                 TRANS   \
664                                 pData++;        \
665                                 pTop++; \
666                         }       \
667                         pData += scanline-uw;   \
668                 }       \
669         }       \
670         if (uh) {       \
671                 pData=         data +  h*scanline;      \
672                 pEnd = (int*)(pData+ uh*scanline);      \
673                 while (pData < (PIXEL_T*)pEnd) {        \
674                         pLine = (int*)(pData + w);      \
675                         while (pData < (PIXEL_T*)pLine) {       \
676                                 TRANS   \
677                                 pData++;        \
678                                 pTop++; \
679                         }       \
680                         pData += scanline-w;    \
681                 }       \
682         }       \
683         if (uw && uh) { \
684                 pData=         data + w+ h*scanline;    \
685                 pEnd = (int*)(pData+   uh*scanline);    \
686                 while (pData < (PIXEL_T*)pEnd) {        \
687                         pLine = (int*)(pData + uw);     \
688                         while (pData < (PIXEL_T*)pLine) {       \
689                                 TRANS   \
690                                 pData++;        \
691                                 pTop++; \
692                         }       \
693                         pData += scanline-uw;   \
694                 }       \
695         }
696
697 static InlineX void zywrleCalcSize(int* pW, int* pH, int level)
698 {
699         *pW &= ~((1<<level)-1);
700         *pH &= ~((1<<level)-1);
701 }
702
703 #endif /* ZYWRLE_ONCE */
704
705 #ifndef CPIXEL
706 #ifdef ZYWRLE_ENCODE
707 static InlineX void ZYWRLE_RGBYUV(int* pBuf, PIXEL_T* data, int width, int height, int scanline)
708 {
709         int R, G, B;
710         int Y, U, V;
711         int* pLine;
712         int* pEnd;
713         pEnd = pBuf+height*width;
714         while (pBuf < pEnd) {
715                 pLine = pBuf+width;
716                 while (pBuf < pLine) {
717                         ZYWRLE_LOAD_PIXEL(data,R,G,B);
718                         ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ZYWRLE_YMASK,ZYWRLE_UVMASK);
719                         ZYWRLE_SAVE_COEFF(pBuf,V,Y,U);
720                         pBuf++;
721                         data++;
722                 }
723                 data += scanline-width;
724         }
725 }
726 #endif
727 #ifdef ZYWRLE_DECODE
728 static InlineX void ZYWRLE_YUVRGB(int* pBuf, PIXEL_T* data, int width, int height, int scanline) {
729         int R, G, B;
730         int Y, U, V;
731         int* pLine;
732         int* pEnd;
733         pEnd = pBuf+height*width;
734         while (pBuf < pEnd) {
735                 pLine = pBuf+width;
736                 while (pBuf < pLine) {
737                         ZYWRLE_LOAD_COEFF(pBuf,V,Y,U);
738                         ZYWRLE_YUVRGB1(R,G,B,Y,U,V);
739                         ZYWRLE_SAVE_PIXEL(data,R,G,B);
740                         pBuf++;
741                         data++;
742                 }
743                 data += scanline-width;
744         }
745 }
746 #endif
747
748 #ifdef ZYWRLE_ENCODE
749 PIXEL_T* ZYWRLE_ANALYZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf) {
750         int l;
751         int uw = w;
752         int uh = h;
753         int* pTop;
754         int* pEnd;
755         int* pLine;
756         PIXEL_T* pData;
757         int R, G, B;
758         int s;
759         int* pH;
760
761         zywrleCalcSize(&w, &h, level);
762         if (w == 0 || h == 0)
763                 return NULL;
764         uw -= w;
765         uh -= h;
766
767         pData = dst;
768         ZYWRLE_LOAD_UNALIGN(src,*(PIXEL_T*)pTop=*pData;)
769         ZYWRLE_RGBYUV(pBuf, src, w, h, scanline);
770         Wavelet(pBuf, w, h, level);
771         for (l = 0; l < level; l++) {
772                 ZYWRLE_PACK_COEFF(pBuf, dst, 3, w, h, scanline, l);
773                 ZYWRLE_PACK_COEFF(pBuf, dst, 2, w, h, scanline, l);
774                 ZYWRLE_PACK_COEFF(pBuf, dst, 1, w, h, scanline, l);
775                 if (l == level - 1) {
776                         ZYWRLE_PACK_COEFF(pBuf, dst, 0, w, h, scanline, l);
777                 }
778         }
779         ZYWRLE_SAVE_UNALIGN(dst,*dst=*(PIXEL_T*)pTop;)
780         return dst;
781 }
782 #endif
783 #ifdef ZYWRLE_DECODE
784 PIXEL_T* ZYWRLE_SYNTHESIZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf)
785 {
786         int l;
787         int uw = w;
788         int uh = h;
789         int* pTop;
790         int* pEnd;
791         int* pLine;
792         PIXEL_T* pData;
793         int R, G, B;
794         int s;
795         int* pH;
796
797         zywrleCalcSize(&w, &h, level);
798         if (w == 0 || h == 0)
799                 return NULL;
800         uw -= w;
801         uh -= h;
802
803         pData = src;
804         for (l = 0; l < level; l++) {
805                 ZYWRLE_UNPACK_COEFF(pBuf, src, 3, w, h, scanline, l);
806                 ZYWRLE_UNPACK_COEFF(pBuf, src, 2, w, h, scanline, l);
807                 ZYWRLE_UNPACK_COEFF(pBuf, src, 1, w, h, scanline, l);
808                 if (l == level - 1) {
809                         ZYWRLE_UNPACK_COEFF(pBuf, src, 0, w, h, scanline, l);
810                 }
811         }
812         ZYWRLE_SAVE_UNALIGN(src,*(PIXEL_T*)pTop=*src;)
813         InvWavelet(pBuf, w, h, level);
814         ZYWRLE_YUVRGB(pBuf, dst, w, h, scanline);
815         ZYWRLE_LOAD_UNALIGN(dst,*pData=*(PIXEL_T*)pTop;)
816         return src;
817 }
818 #endif
819 #endif  /* CPIXEL */
820
821 #undef ZYWRLE_RGBYUV
822 #undef ZYWRLE_YUVRGB
823 #undef ZYWRLE_LOAD_PIXEL
824 #undef ZYWRLE_SAVE_PIXEL