Statistics
| Branch: | Revision:

root / ui / vnc-enc-zywrle.h @ d4970b07

History | View | Annotate | Download (25.3 kB)

1
/********************************************************************
2
 *                                                                  *
3
 * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE.         *
4
 *                                                                  *
5
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
6
 * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE.                *
7
 * PLEASE READ THESE TERMS BEFORE DISTRIBUTING.                     *
8
 *                                                                  *
9
 * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006         *
10
 * BY Hitachi Systems & Services, Ltd.                              *
11
 * (Noriaki Yamazaki, Research & Developement Center)               *
12
 *                                                                  *
13
 *                                                                  *
14
 ********************************************************************
15
Redistribution and use in source and binary forms, with or without
16
modification, are permitted provided that the following conditions
17
are met:
18

19
- Redistributions of source code must retain the above copyright
20
notice, this list of conditions and the following disclaimer.
21

22
- Redistributions in binary form must reproduce the above copyright
23
notice, this list of conditions and the following disclaimer in the
24
documentation and/or other materials provided with the distribution.
25

26
- Neither the name of the Hitachi Systems & Services, Ltd. nor
27
the names of its contributors may be used to endorse or promote
28
products derived from this software without specific prior written
29
permission.
30

31
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34
A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION
35
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
36
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
37
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
38
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
41
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42
 ********************************************************************/
43

    
44
#ifndef VNC_ENCODING_ZYWRLE_H
45
#define VNC_ENCODING_ZYWRLE_H
46

    
47
/* Tables for Coefficients filtering. */
48
#ifndef ZYWRLE_QUANTIZE
49
/* Type A:lower bit omitting of EZW style. */
50
static const unsigned int zywrle_param[3][3]={
51
        {0x0000F000, 0x00000000, 0x00000000},
52
        {0x0000C000, 0x00F0F0F0, 0x00000000},
53
        {0x0000C000, 0x00C0C0C0, 0x00F0F0F0},
54
/*        {0x0000FF00, 0x00000000, 0x00000000},
55
        {0x0000FF00, 0x00FFFFFF, 0x00000000},
56
        {0x0000FF00, 0x00FFFFFF, 0x00FFFFFF}, */
57
};
58
#else
59
/* Type B:Non liner quantization filter. */
60
static const int8_t zywrle_conv[4][256]={
61
{        /* bi=5, bo=5 r=0.0:PSNR=24.849 */
62
        0, 0, 0, 0, 0, 0, 0, 0,
63
        0, 0, 0, 0, 0, 0, 0, 0,
64
        0, 0, 0, 0, 0, 0, 0, 0,
65
        0, 0, 0, 0, 0, 0, 0, 0,
66
        0, 0, 0, 0, 0, 0, 0, 0,
67
        0, 0, 0, 0, 0, 0, 0, 0,
68
        0, 0, 0, 0, 0, 0, 0, 0,
69
        0, 0, 0, 0, 0, 0, 0, 0,
70
        0, 0, 0, 0, 0, 0, 0, 0,
71
        0, 0, 0, 0, 0, 0, 0, 0,
72
        0, 0, 0, 0, 0, 0, 0, 0,
73
        0, 0, 0, 0, 0, 0, 0, 0,
74
        0, 0, 0, 0, 0, 0, 0, 0,
75
        0, 0, 0, 0, 0, 0, 0, 0,
76
        0, 0, 0, 0, 0, 0, 0, 0,
77
        0, 0, 0, 0, 0, 0, 0, 0,
78
        0, 0, 0, 0, 0, 0, 0, 0,
79
        0, 0, 0, 0, 0, 0, 0, 0,
80
        0, 0, 0, 0, 0, 0, 0, 0,
81
        0, 0, 0, 0, 0, 0, 0, 0,
82
        0, 0, 0, 0, 0, 0, 0, 0,
83
        0, 0, 0, 0, 0, 0, 0, 0,
84
        0, 0, 0, 0, 0, 0, 0, 0,
85
        0, 0, 0, 0, 0, 0, 0, 0,
86
        0, 0, 0, 0, 0, 0, 0, 0,
87
        0, 0, 0, 0, 0, 0, 0, 0,
88
        0, 0, 0, 0, 0, 0, 0, 0,
89
        0, 0, 0, 0, 0, 0, 0, 0,
90
        0, 0, 0, 0, 0, 0, 0, 0,
91
        0, 0, 0, 0, 0, 0, 0, 0,
92
        0, 0, 0, 0, 0, 0, 0, 0,
93
        0, 0, 0, 0, 0, 0, 0, 0,
94
},
95
{        /* bi=5, bo=5 r=2.0:PSNR=74.031 */
96
        0, 0, 0, 0, 0, 0, 0, 0,
97
        0, 0, 0, 0, 0, 0, 0, 0,
98
        0, 0, 0, 0, 0, 0, 0, 32,
99
        32, 32, 32, 32, 32, 32, 32, 32,
100
        32, 32, 32, 32, 32, 32, 32, 32,
101
        48, 48, 48, 48, 48, 48, 48, 48,
102
        48, 48, 48, 56, 56, 56, 56, 56,
103
        56, 56, 56, 56, 64, 64, 64, 64,
104
        64, 64, 64, 64, 72, 72, 72, 72,
105
        72, 72, 72, 72, 80, 80, 80, 80,
106
        80, 80, 88, 88, 88, 88, 88, 88,
107
        88, 88, 88, 88, 88, 88, 96, 96,
108
        96, 96, 96, 104, 104, 104, 104, 104,
109
        104, 104, 104, 104, 104, 112, 112, 112,
110
        112, 112, 112, 112, 112, 112, 120, 120,
111
        120, 120, 120, 120, 120, 120, 120, 120,
112
        0, -120, -120, -120, -120, -120, -120, -120,
113
        -120, -120, -120, -112, -112, -112, -112, -112,
114
        -112, -112, -112, -112, -104, -104, -104, -104,
115
        -104, -104, -104, -104, -104, -104, -96, -96,
116
        -96, -96, -96, -88, -88, -88, -88, -88,
117
        -88, -88, -88, -88, -88, -88, -88, -80,
118
        -80, -80, -80, -80, -80, -72, -72, -72,
119
        -72, -72, -72, -72, -72, -64, -64, -64,
120
        -64, -64, -64, -64, -64, -56, -56, -56,
121
        -56, -56, -56, -56, -56, -56, -48, -48,
122
        -48, -48, -48, -48, -48, -48, -48, -48,
123
        -48, -32, -32, -32, -32, -32, -32, -32,
124
        -32, -32, -32, -32, -32, -32, -32, -32,
125
        -32, -32, 0, 0, 0, 0, 0, 0,
126
        0, 0, 0, 0, 0, 0, 0, 0,
127
        0, 0, 0, 0, 0, 0, 0, 0,
128
},
129
{        /* bi=5, bo=4 r=2.0:PSNR=64.441 */
130
        0, 0, 0, 0, 0, 0, 0, 0,
131
        0, 0, 0, 0, 0, 0, 0, 0,
132
        0, 0, 0, 0, 0, 0, 0, 0,
133
        0, 0, 0, 0, 0, 0, 0, 0,
134
        48, 48, 48, 48, 48, 48, 48, 48,
135
        48, 48, 48, 48, 48, 48, 48, 48,
136
        48, 48, 48, 48, 48, 48, 48, 48,
137
        64, 64, 64, 64, 64, 64, 64, 64,
138
        64, 64, 64, 64, 64, 64, 64, 64,
139
        80, 80, 80, 80, 80, 80, 80, 80,
140
        80, 80, 80, 80, 80, 88, 88, 88,
141
        88, 88, 88, 88, 88, 88, 88, 88,
142
        104, 104, 104, 104, 104, 104, 104, 104,
143
        104, 104, 104, 112, 112, 112, 112, 112,
144
        112, 112, 112, 112, 120, 120, 120, 120,
145
        120, 120, 120, 120, 120, 120, 120, 120,
146
        0, -120, -120, -120, -120, -120, -120, -120,
147
        -120, -120, -120, -120, -120, -112, -112, -112,
148
        -112, -112, -112, -112, -112, -112, -104, -104,
149
        -104, -104, -104, -104, -104, -104, -104, -104,
150
        -104, -88, -88, -88, -88, -88, -88, -88,
151
        -88, -88, -88, -88, -80, -80, -80, -80,
152
        -80, -80, -80, -80, -80, -80, -80, -80,
153
        -80, -64, -64, -64, -64, -64, -64, -64,
154
        -64, -64, -64, -64, -64, -64, -64, -64,
155
        -64, -48, -48, -48, -48, -48, -48, -48,
156
        -48, -48, -48, -48, -48, -48, -48, -48,
157
        -48, -48, -48, -48, -48, -48, -48, -48,
158
        -48, 0, 0, 0, 0, 0, 0, 0,
159
        0, 0, 0, 0, 0, 0, 0, 0,
160
        0, 0, 0, 0, 0, 0, 0, 0,
161
        0, 0, 0, 0, 0, 0, 0, 0,
162
},
163
{        /* bi=5, bo=2 r=2.0:PSNR=43.175 */
164
        0, 0, 0, 0, 0, 0, 0, 0,
165
        0, 0, 0, 0, 0, 0, 0, 0,
166
        0, 0, 0, 0, 0, 0, 0, 0,
167
        0, 0, 0, 0, 0, 0, 0, 0,
168
        0, 0, 0, 0, 0, 0, 0, 0,
169
        0, 0, 0, 0, 0, 0, 0, 0,
170
        0, 0, 0, 0, 0, 0, 0, 0,
171
        0, 0, 0, 0, 0, 0, 0, 0,
172
        88, 88, 88, 88, 88, 88, 88, 88,
173
        88, 88, 88, 88, 88, 88, 88, 88,
174
        88, 88, 88, 88, 88, 88, 88, 88,
175
        88, 88, 88, 88, 88, 88, 88, 88,
176
        88, 88, 88, 88, 88, 88, 88, 88,
177
        88, 88, 88, 88, 88, 88, 88, 88,
178
        88, 88, 88, 88, 88, 88, 88, 88,
179
        88, 88, 88, 88, 88, 88, 88, 88,
180
        0, -88, -88, -88, -88, -88, -88, -88,
181
        -88, -88, -88, -88, -88, -88, -88, -88,
182
        -88, -88, -88, -88, -88, -88, -88, -88,
183
        -88, -88, -88, -88, -88, -88, -88, -88,
184
        -88, -88, -88, -88, -88, -88, -88, -88,
185
        -88, -88, -88, -88, -88, -88, -88, -88,
186
        -88, -88, -88, -88, -88, -88, -88, -88,
187
        -88, -88, -88, -88, -88, -88, -88, -88,
188
        -88, 0, 0, 0, 0, 0, 0, 0,
189
        0, 0, 0, 0, 0, 0, 0, 0,
190
        0, 0, 0, 0, 0, 0, 0, 0,
191
        0, 0, 0, 0, 0, 0, 0, 0,
192
        0, 0, 0, 0, 0, 0, 0, 0,
193
        0, 0, 0, 0, 0, 0, 0, 0,
194
        0, 0, 0, 0, 0, 0, 0, 0,
195
        0, 0, 0, 0, 0, 0, 0, 0,
196
}
197
};
198

    
199
static const int8_t *zywrle_param[3][3][3]={
200
        {{zywrle_conv[0], zywrle_conv[2], zywrle_conv[0]},
201
         {zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]},
202
         {zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]}},
203
        {{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]},
204
         {zywrle_conv[1], zywrle_conv[1], zywrle_conv[1]},
205
         {zywrle_conv[0], zywrle_conv[0], zywrle_conv[0]}},
206
        {{zywrle_conv[0], zywrle_conv[3], zywrle_conv[0]},
207
         {zywrle_conv[2], zywrle_conv[2], zywrle_conv[2]},
208
         {zywrle_conv[1], zywrle_conv[1], zywrle_conv[1]}},
209
};
210
#endif
211

    
212
/*   Load/Save pixel stuffs. */
213
#define ZYWRLE_YMASK15  0xFFFFFFF8
214
#define ZYWRLE_UVMASK15 0xFFFFFFF8
215
#define ZYWRLE_LOAD_PIXEL15(src, r, g, b)                               \
216
    do {                                                                \
217
        r = (((uint8_t*)src)[S_1]<< 1)& 0xF8;                           \
218
        g = (((uint8_t*)src)[S_1]<< 6) | (((uint8_t*)src)[S_0]>> 2);    \
219
        g &= 0xF8;                                                      \
220
        b =  (((uint8_t*)src)[S_0]<< 3)& 0xF8;                          \
221
    } while (0)
222

    
223
#define ZYWRLE_SAVE_PIXEL15(dst, r, g, b)                               \
224
    do {                                                                \
225
        r &= 0xF8;                                                      \
226
        g &= 0xF8;                                                      \
227
        b &= 0xF8;                                                      \
228
        ((uint8_t*)dst)[S_1] = (uint8_t)((r >> 1)|(g >> 6));            \
229
        ((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 2))& 0xFF);    \
230
    } while (0)
231

    
232
#define ZYWRLE_YMASK16  0xFFFFFFFC
233
#define ZYWRLE_UVMASK16 0xFFFFFFF8
234
#define ZYWRLE_LOAD_PIXEL16(src, r, g, b)                               \
235
    do {                                                                \
236
        r = ((uint8_t*)src)[S_1] & 0xF8;                                \
237
        g = (((uint8_t*)src)[S_1]<< 5) | (((uint8_t*)src)[S_0] >> 3);   \
238
        g &= 0xFC;                                                      \
239
        b = (((uint8_t*)src)[S_0]<< 3) & 0xF8;                          \
240
    } while (0)
241

    
242
#define ZYWRLE_SAVE_PIXEL16(dst, r, g,b)                                \
243
    do {                                                                \
244
        r &= 0xF8;                                                      \
245
        g &= 0xFC;                                                      \
246
        b &= 0xF8;                                                      \
247
        ((uint8_t*)dst)[S_1] = (uint8_t)(r | (g >> 5));                 \
248
        ((uint8_t*)dst)[S_0] = (uint8_t)(((b >> 3)|(g << 3)) & 0xFF);   \
249
    } while (0)
250

    
251
#define ZYWRLE_YMASK32  0xFFFFFFFF
252
#define ZYWRLE_UVMASK32 0xFFFFFFFF
253
#define ZYWRLE_LOAD_PIXEL32(src, r, g, b)     \
254
    do {                                      \
255
        r = ((uint8_t*)src)[L_2];             \
256
        g = ((uint8_t*)src)[L_1];             \
257
        b = ((uint8_t*)src)[L_0];             \
258
    } while (0)
259
#define ZYWRLE_SAVE_PIXEL32(dst, r, g, b)             \
260
    do {                                              \
261
        ((uint8_t*)dst)[L_2] = (uint8_t)r;            \
262
        ((uint8_t*)dst)[L_1] = (uint8_t)g;            \
263
        ((uint8_t*)dst)[L_0] = (uint8_t)b;            \
264
    } while (0)
265

    
266
static inline void harr(int8_t *px0, int8_t *px1)
267
{
268
    /* Piecewise-Linear Harr(PLHarr) */
269
    int x0 = (int)*px0, x1 = (int)*px1;
270
    int orgx0 = x0, orgx1 = x1;
271

    
272
    if ((x0 ^ x1) & 0x80) {
273
        /* differ sign */
274
        x1 += x0;
275
        if (((x1 ^ orgx1) & 0x80) == 0) {
276
            /* |x1| > |x0| */
277
            x0 -= x1;        /* H = -B */
278
        }
279
    } else {
280
        /* same sign */
281
        x0 -= x1;
282
        if (((x0 ^ orgx0) & 0x80) == 0) {
283
            /* |x0| > |x1| */
284
            x1 += x0;        /* L = A */
285
        }
286
    }
287
    *px0 = (int8_t)x1;
288
    *px1 = (int8_t)x0;
289
}
290

    
291
/*
292
 1D-Wavelet transform.
293

294
 In coefficients array, the famous 'pyramid' decomposition is well used.
295

296
 1D Model:
297
   |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0
298
   |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1
299

300
 But this method needs line buffer because H/L is different position from X0/X1.
301
 So, I used 'interleave' decomposition instead of it.
302

303
 1D Model:
304
   |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0
305
   |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1
306

307
 In this method, H/L and X0/X1 is always same position.
308
 This lead us to more speed and less memory.
309
 Of cause, the result of both method is quite same
310
 because it's only difference that coefficient position.
311
*/
312
static inline void wavelet_level(int *data, int size, int l, int skip_pixel)
313
{
314
    int s, ofs;
315
    int8_t *px0;
316
    int8_t *end;
317

    
318
    px0 = (int8_t*)data;
319
    s = (8 << l) * skip_pixel;
320
    end = px0 + (size >> (l + 1)) * s;
321
    s -= 2;
322
    ofs = (4 << l) * skip_pixel;
323

    
324
    while (px0 < end) {
325
        harr(px0, px0 + ofs);
326
        px0++;
327
        harr(px0, px0 + ofs);
328
        px0++;
329
        harr(px0, px0 + ofs);
330
        px0 += s;
331
    }
332
}
333

    
334
#ifndef ZYWRLE_QUANTIZE
335
/* Type A:lower bit omitting of EZW style. */
336
static inline void filter_wavelet_square(int *buf, int width, int height,
337
                                         int level, int l)
338
{
339
    int r, s;
340
    int x, y;
341
    int *h;
342
    const unsigned int *m;
343

    
344
    m = &(zywrle_param[level - 1][l]);
345
    s = 2 << l;
346

    
347
    for (r = 1; r < 4; r++) {
348
        h = buf;
349
        if (r & 0x01) {
350
            h += s >> 1;
351
        }
352
        if (r & 0x02) {
353
            h += (s >> 1) * width;
354
        }
355
        for (y = 0; y < height / s; y++) {
356
            for (x = 0; x < width / s; x++) {
357
                /*
358
                  these are same following code.
359
                  h[x] = h[x] / (~m[x]+1) * (~m[x]+1);
360
                  ( round h[x] with m[x] bit )
361
                  '&' operator isn't 'round' but is 'floor'.
362
                  So, we must offset when h[x] is negative.
363
                */
364
                if (((int8_t*)h)[0] & 0x80) {
365
                    ((int8_t*)h)[0] += ~((int8_t*)m)[0];
366
                }
367
                if (((int8_t*)h)[1] & 0x80) {
368
                    ((int8_t*)h)[1] += ~((int8_t*)m)[1];
369
                }
370
                if (((int8_t*)h)[2] & 0x80) {
371
                    ((int8_t*)h)[2] += ~((int8_t*)m)[2];
372
                }
373
                *h &= *m;
374
                h += s;
375
            }
376
            h += (s-1)*width;
377
        }
378
    }
379
}
380
#else
381
/*
382
 Type B:Non liner quantization filter.
383

384
 Coefficients have Gaussian curve and smaller value which is
385
 large part of coefficients isn't more important than larger value.
386
 So, I use filter of Non liner quantize/dequantize table.
387
 In general, Non liner quantize formula is explained as following.
388

389
    y=f(x)   = sign(x)*round( ((abs(x)/(2^7))^ r   )* 2^(bo-1) )*2^(8-bo)
390
    x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi)
391
 ( r:power coefficient  bi:effective MSB in input  bo:effective MSB in output )
392

393
   r < 1.0 : Smaller value is more important than larger value.
394
   r > 1.0 : Larger value is more important than smaller value.
395
   r = 1.0 : Liner quantization which is same with EZW style.
396

397
 r = 0.75 is famous non liner quantization used in MP3 audio codec.
398
 In contrast to audio data, larger value is important in wavelet coefficients.
399
 So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ).
400

401
 As compared with EZW style liner quantization, this filter tended to be
402
 more sharp edge and be more compression rate but be more blocking noise and be
403
 less quality. Especially, the surface of graphic objects has distinguishable
404
 noise in middle quality mode.
405

406
 We need only quantized-dequantized(filtered) value rather than quantized value
407
 itself because all values are packed or palette-lized in later ZRLE section.
408
 This lead us not to need to modify client decoder when we change
409
 the filtering procedure in future.
410
 Client only decodes coefficients given by encoder.
411
*/
412
static inline void filter_wavelet_square(int *buf, int width, int height,
413
                                         int level, int l)
414
{
415
    int r, s;
416
    int x, y;
417
    int *h;
418
    const int8_t **m;
419

    
420
    m = zywrle_param[level - 1][l];
421
    s = 2 << l;
422

    
423
    for (r = 1; r < 4; r++) {
424
        h = buf;
425
        if (r & 0x01) {
426
            h += s >> 1;
427
        }
428
        if (r & 0x02) {
429
            h += (s >> 1) * width;
430
        }
431
        for (y = 0; y < height / s; y++) {
432
            for (x = 0; x < width / s; x++) {
433
                ((int8_t*)h)[0] = m[0][((uint8_t*)h)[0]];
434
                ((int8_t*)h)[1] = m[1][((uint8_t*)h)[1]];
435
                ((int8_t*)h)[2] = m[2][((uint8_t*)h)[2]];
436
                h += s;
437
            }
438
            h += (s - 1) * width;
439
        }
440
    }
441
}
442
#endif
443

    
444
static inline void wavelet(int *buf, int width, int height, int level)
445
{
446
        int l, s;
447
        int *top;
448
        int *end;
449

    
450
        for (l = 0; l < level; l++) {
451
                top = buf;
452
                end = buf + height * width;
453
                s = width << l;
454
                while (top < end) {
455
                        wavelet_level(top, width, l, 1);
456
                        top += s;
457
                }
458
                top = buf;
459
                end = buf + width;
460
                s = 1<<l;
461
                while (top < end) {
462
                        wavelet_level(top, height, l, width);
463
                        top += s;
464
                }
465
                filter_wavelet_square(buf, width, height, level, l);
466
        }
467
}
468

    
469

    
470
/* Load/Save coefficients stuffs.
471
 Coefficients manages as 24 bits little-endian pixel. */
472
#define ZYWRLE_LOAD_COEFF(src, r, g, b)         \
473
    do {                                        \
474
        r = ((int8_t*)src)[2];                  \
475
        g = ((int8_t*)src)[1];                  \
476
        b = ((int8_t*)src)[0];                  \
477
    } while (0)
478

    
479
#define ZYWRLE_SAVE_COEFF(dst, r, g, b)       \
480
    do {                                      \
481
        ((int8_t*)dst)[2] = (int8_t)r;        \
482
        ((int8_t*)dst)[1] = (int8_t)g;        \
483
        ((int8_t*)dst)[0] = (int8_t)b;        \
484
    } while (0)
485

    
486
/*
487
  RGB <=> YUV conversion stuffs.
488
  YUV coversion is explained as following formula in strict meaning:
489
  Y =  0.299R + 0.587G + 0.114B (   0<=Y<=255)
490
  U = -0.169R - 0.331G + 0.500B (-128<=U<=127)
491
  V =  0.500R - 0.419G - 0.081B (-128<=V<=127)
492

493
  I use simple conversion RCT(reversible color transform) which is described
494
  in JPEG-2000 specification.
495
  Y = (R + 2G + B)/4 (   0<=Y<=255)
496
  U = B-G (-256<=U<=255)
497
  V = R-G (-256<=V<=255)
498
*/
499

    
500
/* RCT is N-bit RGB to N-bit Y and N+1-bit UV.
501
   For make Same N-bit, UV is lossy.
502
   More exact PLHarr, we reduce to odd range(-127<=x<=127). */
503
#define ZYWRLE_RGBYUV_(r, g, b, y, u, v, ymask, uvmask)          \
504
    do {                                                         \
505
        y = (r + (g << 1) + b) >> 2;                             \
506
        u =  b - g;                                              \
507
        v =  r - g;                                              \
508
        y -= 128;                                                \
509
        u >>= 1;                                                 \
510
        v >>= 1;                                                 \
511
        y &= ymask;                                              \
512
        u &= uvmask;                                             \
513
        v &= uvmask;                                             \
514
        if (y == -128) {                                         \
515
            y += (0xFFFFFFFF - ymask + 1);                       \
516
        }                                                        \
517
        if (u == -128) {                                         \
518
            u += (0xFFFFFFFF - uvmask + 1);                      \
519
        }                                                        \
520
        if (v == -128) {                                         \
521
            v += (0xFFFFFFFF - uvmask + 1);                      \
522
        }                                                        \
523
    } while (0)
524

    
525

    
526
/*
527
 coefficient packing/unpacking stuffs.
528
 Wavelet transform makes 4 sub coefficient image from 1 original image.
529

530
 model with pyramid decomposition:
531
   +------+------+
532
   |      |      |
533
   |  L   |  Hx  |
534
   |      |      |
535
   +------+------+
536
   |      |      |
537
   |  H   |  Hxy |
538
   |      |      |
539
   +------+------+
540

541
 So, we must transfer each sub images individually in strict meaning.
542
 But at least ZRLE meaning, following one decompositon image is same as
543
 avobe individual sub image. I use this format.
544
 (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L)
545
  for simplified procedure for any wavelet level.)
546

547
   +------+------+
548
   |      L      |
549
   +------+------+
550
   |      Hx     |
551
   +------+------+
552
   |      Hy     |
553
   +------+------+
554
   |      Hxy    |
555
   +------+------+
556
*/
557
#define ZYWRLE_INC_PTR(data)                         \
558
    do {                                             \
559
        data++;                                      \
560
        if( data - p >= (w + uw) ) {                 \
561
            data += scanline-(w + uw);               \
562
            p = data;                                \
563
        }                                            \
564
    } while (0)
565

    
566
#define ZYWRLE_TRANSFER_COEFF(buf, data, t, w, h, scanline, level, TRANS) \
567
    do {                                                                \
568
        ph = buf;                                                       \
569
        s = 2 << level;                                                 \
570
        if (t & 0x01) {                                                 \
571
            ph += s >> 1;                                               \
572
        }                                                               \
573
        if (t & 0x02) {                                                 \
574
            ph += (s >> 1) * w;                                         \
575
        }                                                               \
576
        end = ph + h * w;                                               \
577
        while (ph < end) {                                              \
578
            line = ph + w;                                              \
579
            while (ph < line) {                                         \
580
                TRANS                                                   \
581
                    ZYWRLE_INC_PTR(data);                               \
582
                ph += s;                                                \
583
            }                                                           \
584
            ph += (s - 1) * w;                                          \
585
        }                                                               \
586
    } while (0)
587

    
588
#define ZYWRLE_PACK_COEFF(buf, data, t, width, height, scanline, level)        \
589
    ZYWRLE_TRANSFER_COEFF(buf, data, t, width, height, scanline, level, \
590
                          ZYWRLE_LOAD_COEFF(ph, r, g, b);               \
591
                          ZYWRLE_SAVE_PIXEL(data, r, g, b);)
592

    
593
#define ZYWRLE_UNPACK_COEFF(buf, data, t, width, height, scanline, level) \
594
    ZYWRLE_TRANSFER_COEFF(buf, data, t, width, height, scanline, level, \
595
                          ZYWRLE_LOAD_PIXEL(data, r, g, b);             \
596
                          ZYWRLE_SAVE_COEFF(ph, r, g, b);)
597

    
598
#define ZYWRLE_SAVE_UNALIGN(data, TRANS)                     \
599
    do {                                                     \
600
        top = buf + w * h;                                   \
601
        end = buf + (w + uw) * (h + uh);                     \
602
        while (top < end) {                                  \
603
            TRANS                                            \
604
                ZYWRLE_INC_PTR(data);                        \
605
                top++;                                       \
606
        }                                                    \
607
    } while (0)
608

    
609
#define ZYWRLE_LOAD_UNALIGN(data,TRANS)                                 \
610
    do {                                                                \
611
        top = buf + w * h;                                              \
612
        if (uw) {                                                       \
613
            p = data + w;                                               \
614
            end = (int*)(p + h * scanline);                             \
615
            while (p < (ZRLE_PIXEL*)end) {                              \
616
                line = (int*)(p + uw);                                  \
617
                while (p < (ZRLE_PIXEL*)line) {                         \
618
                    TRANS                                               \
619
                        p++;                                            \
620
                    top++;                                              \
621
                }                                                       \
622
                p += scanline - uw;                                     \
623
            }                                                           \
624
        }                                                               \
625
        if (uh) {                                                       \
626
            p = data + h * scanline;                                    \
627
            end = (int*)(p + uh * scanline);                            \
628
            while (p < (ZRLE_PIXEL*)end) {                              \
629
                line = (int*)(p + w);                                   \
630
                while (p < (ZRLE_PIXEL*)line) {                         \
631
                    TRANS                                               \
632
                        p++;                                            \
633
                    top++;                                              \
634
                }                                                       \
635
                p += scanline - w;                                      \
636
            }                                                           \
637
        }                                                               \
638
        if (uw && uh) {                                                 \
639
            p= data + w + h * scanline;                                 \
640
            end = (int*)(p + uh * scanline);                            \
641
            while (p < (ZRLE_PIXEL*)end) {                              \
642
                line = (int*)(p + uw);                                  \
643
                while (p < (ZRLE_PIXEL*)line) {                         \
644
                    TRANS                                               \
645
                        p++;                                            \
646
                    top++;                                              \
647
                }                                                       \
648
                p += scanline-uw;                                       \
649
            }                                                           \
650
        }                                                               \
651
    } while (0)
652

    
653
static inline void zywrle_calc_size(int *w, int *h, int level)
654
{
655
    *w &= ~((1 << level) - 1);
656
    *h &= ~((1 << level) - 1);
657
}
658

    
659
#endif