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 & Development 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_ENC_ZYWRLE_H 45 #define VNC_ENC_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 leads 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 660