|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.