2 /********************************************************************
4 * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE. *
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. *
10 * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006 *
11 * BY Hitachi Systems & Services, Ltd. *
12 * (Noriaki Yamazaki, Research & Developement Center) * *
14 ********************************************************************
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions
19 - Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
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.
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
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 ********************************************************************/
45 V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline
46 (Thanks Johannes Schindelin, author of LibVNC
48 V0.01 : 2007/02/06 : Initial release
51 /* #define ZYWRLE_ENCODE */
52 /* #define ZYWRLE_DECODE */
53 #define ZYWRLE_QUANTIZE
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.
60 Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993).
64 /* Template Macro stuffs. */
66 #undef ZYWRLE_SYNTHESIZE
67 #define ZYWRLE_ANALYZE __RFB_CONCAT3E(zywrleAnalyze,BPP,END_FIX)
68 #define ZYWRLE_SYNTHESIZE __RFB_CONCAT3E(zywrleSynthesize,BPP,END_FIX)
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)
77 /* Packing/Unpacking pixel stuffs.
78 Endian conversion stuffs. */
84 #if ZYWRLE_ENDIAN == ENDIAN_BIG
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; \
106 #define ZYWRLE_SAVE_PIXEL15(pDst,R,G,B) { \
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); \
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; \
120 #define ZYWRLE_SAVE_PIXEL16(pDst,R,G,B) { \
124 ((unsigned char*)pDst)[S_1] = (unsigned char)( R |(G>>5) ); \
125 ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<3))& 0xFF); \
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]; \
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; \
144 #define InlineX __inline
146 #define InlineX inline
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}, */
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,
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,
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,
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,
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]}},
309 static InlineX void Harr(signed char* pX0, signed char* pX1)
311 /* Piecewise-Linear Harr(PLHarr) */
312 int X0 = (int)*pX0, X1 = (int)*pX1;
313 int orgX0 = X0, orgX1 = X1;
314 if ((X0 ^ X1) & 0x80) {
317 if (((X1^orgX1)&0x80)==0) {
319 X0 -= X1; /* H = -B */
324 if (((X0 ^ orgX0) & 0x80) == 0) {
326 X1 += X0; /* L = A */
329 *pX0 = (signed char)X1;
330 *pX1 = (signed char)X0;
333 1D-Wavelet transform.
335 In coefficients array, the famous 'pyramid' decomposition is well used.
338 |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
339 |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
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.
345 |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
346 |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
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.
353 static InlineX void WaveletLevel(int* data, int size, int l, int SkipPixel)
359 pX0 = (signed char*)data;
360 s = (8<<l)*SkipPixel;
361 end = pX0+(size>>(l+1))*s;
363 ofs = (4<<l)*SkipPixel;
373 #define InvWaveletLevel(d,s,l,pix) WaveletLevel(d,s,l,pix)
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)
383 const unsigned int* pM;
385 pM = &(zywrleParam[level-1][l]);
387 for (r = 1; r < 4; r++) {
393 for (y = 0; y < height / s; y++) {
394 for (x = 0; x < width / s; x++) {
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.
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];
417 Type B:Non liner quantization filter.
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.
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 )
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.
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) ).
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.
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.
446 static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l)
451 const signed char** pM;
453 pM = zywrleParam[level-1][l];
455 for (r = 1; r < 4; r++) {
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]];
474 static InlineX void Wavelet(int* pBuf, int width, int height, int level)
480 for (l = 0; l < level; l++) {
482 pEnd = pBuf+height*width;
484 while (pTop < pEnd) {
485 WaveletLevel(pTop, width, l, 1);
491 while (pTop < pEnd) {
492 WaveletLevel(pTop, height,l, width);
495 FilterWaveletSquare(pBuf, width, height, level, l);
500 static InlineX void InvWavelet(int* pBuf, int width, int height, int level)
506 for (l = level - 1; l >= 0; l--) {
510 while (pTop < pEnd) {
511 InvWaveletLevel(pTop, height,l, width);
515 pEnd = pBuf+height*width;
517 while (pTop < pEnd) {
518 InvWaveletLevel(pTop, width, l, 1);
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]; \
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; \
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)
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)
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; \
566 Y += (0xFFFFFFFF-ymask+1); \
568 U += (0xFFFFFFFF-uvmask+1); \
570 V += (0xFFFFFFFF-uvmask+1); \
572 #define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \
585 coefficient packing/unpacking stuffs.
586 Wavelet transform makes 4 sub coefficient image from 1 original image.
588 model with pyramid decomposition:
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.)
615 #define INC_PTR(data) \
617 if( data-pData >= (w+uw) ){ \
618 data += scanline-(w+uw); \
622 #define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,w,h,scanline,level,TRANS) \
630 while (pH < pEnd) { \
632 while (pH < pLine) { \
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);)
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);)
646 #define ZYWRLE_SAVE_UNALIGN(data,TRANS) \
648 pEnd = pBuf + (w+uw)*(h+uh); \
649 while (pTop < pEnd) { \
655 #define ZYWRLE_LOAD_UNALIGN(data,TRANS) \
659 pEnd = (int*)(pData+ h*scanline); \
660 while (pData < (PIXEL_T*)pEnd) { \
661 pLine = (int*)(pData + uw); \
662 while (pData < (PIXEL_T*)pLine) { \
667 pData += scanline-uw; \
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) { \
680 pData += scanline-w; \
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) { \
693 pData += scanline-uw; \
697 static InlineX void zywrleCalcSize(int* pW, int* pH, int level)
699 *pW &= ~((1<<level)-1);
700 *pH &= ~((1<<level)-1);
703 #endif /* ZYWRLE_ONCE */
707 static InlineX void ZYWRLE_RGBYUV(int* pBuf, PIXEL_T* data, int width, int height, int scanline)
713 pEnd = pBuf+height*width;
714 while (pBuf < pEnd) {
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);
723 data += scanline-width;
728 static InlineX void ZYWRLE_YUVRGB(int* pBuf, PIXEL_T* data, int width, int height, int scanline) {
733 pEnd = pBuf+height*width;
734 while (pBuf < pEnd) {
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);
743 data += scanline-width;
749 PIXEL_T* ZYWRLE_ANALYZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf) {
761 zywrleCalcSize(&w, &h, level);
762 if (w == 0 || h == 0)
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);
779 ZYWRLE_SAVE_UNALIGN(dst,*dst=*(PIXEL_T*)pTop;)
784 PIXEL_T* ZYWRLE_SYNTHESIZE(PIXEL_T* dst, PIXEL_T* src, int w, int h, int scanline, int level, int* pBuf)
797 zywrleCalcSize(&w, &h, level);
798 if (w == 0 || h == 0)
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);
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;)
823 #undef ZYWRLE_LOAD_PIXEL
824 #undef ZYWRLE_SAVE_PIXEL