2 * Discrete wavelet transform
3 * Copyright (c) 2007 Kamil Nowosad
4 * Copyright (c) 2013 Nicolas Bertrand <nicoinattendu@gmail.com>
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * Discrete wavelet transform
28 #include "libavutil/avassert.h"
29 #include "libavutil/common.h"
30 #include "libavutil/mem.h"
31 #include "jpeg2000dwt.h"
34 /* Defines for 9/7 DWT lifting parameters.
35 * Parameters are in float. */
36 #define F_LFTG_ALPHA 1.586134342059924f
37 #define F_LFTG_BETA 0.052980118572961f
38 #define F_LFTG_GAMMA 0.882911075530934f
39 #define F_LFTG_DELTA 0.443506852043971f
41 /* Lifting parameters in integer format.
42 * Computed as param = (float param) * (1 << 16) */
43 #define I_LFTG_ALPHA 103949
44 #define I_LFTG_BETA 3472
45 #define I_LFTG_GAMMA 57862
46 #define I_LFTG_DELTA 29066
47 #define I_LFTG_K 80621
48 #define I_LFTG_X 53274
50 static inline void extend53(int *p, int i0, int i1)
52 p[i0 - 1] = p[i0 + 1];
54 p[i0 - 2] = p[i0 + 2];
55 p[i1 + 1] = p[i1 - 3];
58 static inline void extend97_float(float *p, int i0, int i1)
62 for (i = 1; i <= 4; i++) {
63 p[i0 - i] = p[i0 + i];
64 p[i1 + i - 1] = p[i1 - i - 1];
68 static inline void extend97_int(int32_t *p, int i0, int i1)
72 for (i = 1; i <= 4; i++) {
73 p[i0 - i] = p[i0 + i];
74 p[i1 + i - 1] = p[i1 - i - 1];
78 static void sd_1d53(int *p, int i0, int i1)
90 for (i = (i0+1)/2 - 1; i < (i1+1)/2; i++)
91 p[2*i+1] -= (p[2*i] + p[2*i+2]) >> 1;
92 for (i = (i0+1)/2; i < (i1+1)/2; i++)
93 p[2*i] += (p[2*i-1] + p[2*i+1] + 2) >> 2;
96 static void dwt_encode53(DWTContext *s, int *t)
99 w = s->linelen[s->ndeclevels-1][0];
100 int *line = s->i_linebuf;
103 for (lev = s->ndeclevels-1; lev >= 0; lev--){
104 int lh = s->linelen[lev][0],
105 lv = s->linelen[lev][1],
113 for (lp = 0; lp < lh; lp++) {
116 for (i = 0; i < lv; i++)
119 sd_1d53(line, mv, mv + lv);
121 // copy back and deinterleave
122 for (i = mv; i < lv; i+=2, j++)
124 for (i = 1-mv; i < lv; i+=2, j++)
130 for (lp = 0; lp < lv; lp++){
133 for (i = 0; i < lh; i++)
136 sd_1d53(line, mh, mh + lh);
138 // copy back and deinterleave
139 for (i = mh; i < lh; i+=2, j++)
141 for (i = 1-mh; i < lh; i+=2, j++)
146 static void sd_1d97_float(float *p, int i0, int i1)
152 p[1] *= F_LFTG_X * 2;
158 extend97_float(p, i0, i1);
161 for (i = i0/2 - 2; i < i1/2 + 1; i++)
162 p[2*i+1] -= 1.586134 * (p[2*i] + p[2*i+2]);
163 for (i = i0/2 - 1; i < i1/2 + 1; i++)
164 p[2*i] -= 0.052980 * (p[2*i-1] + p[2*i+1]);
165 for (i = i0/2 - 1; i < i1/2; i++)
166 p[2*i+1] += 0.882911 * (p[2*i] + p[2*i+2]);
167 for (i = i0/2; i < i1/2; i++)
168 p[2*i] += 0.443506 * (p[2*i-1] + p[2*i+1]);
171 static void dwt_encode97_float(DWTContext *s, float *t)
174 w = s->linelen[s->ndeclevels-1][0];
175 float *line = s->f_linebuf;
178 for (lev = s->ndeclevels-1; lev >= 0; lev--){
179 int lh = s->linelen[lev][0],
180 lv = s->linelen[lev][1],
188 for (lp = 0; lp < lv; lp++){
191 for (i = 0; i < lh; i++)
194 sd_1d97_float(line, mh, mh + lh);
196 // copy back and deinterleave
197 for (i = mh; i < lh; i+=2, j++)
198 t[w*lp + j] = F_LFTG_X * l[i];
199 for (i = 1-mh; i < lh; i+=2, j++)
205 for (lp = 0; lp < lh; lp++) {
208 for (i = 0; i < lv; i++)
211 sd_1d97_float(line, mv, mv + lv);
213 // copy back and deinterleave
214 for (i = mv; i < lv; i+=2, j++)
215 t[w*j + lp] = F_LFTG_X * l[i];
216 for (i = 1-mv; i < lv; i+=2, j++)
222 static void sd_1d97_int(int *p, int i0, int i1)
228 p[1] = (p[1] * I_LFTG_X + (1<<14)) >> 15;
230 p[0] = (p[0] * I_LFTG_K + (1<<15)) >> 16;
234 extend97_int(p, i0, i1);
237 for (i = i0/2 - 2; i < i1/2 + 1; i++)
238 p[2 * i + 1] -= (I_LFTG_ALPHA * (p[2 * i] + p[2 * i + 2]) + (1 << 15)) >> 16;
239 for (i = i0/2 - 1; i < i1/2 + 1; i++)
240 p[2 * i] -= (I_LFTG_BETA * (p[2 * i - 1] + p[2 * i + 1]) + (1 << 15)) >> 16;
241 for (i = i0/2 - 1; i < i1/2; i++)
242 p[2 * i + 1] += (I_LFTG_GAMMA * (p[2 * i] + p[2 * i + 2]) + (1 << 15)) >> 16;
243 for (i = i0/2; i < i1/2; i++)
244 p[2 * i] += (I_LFTG_DELTA * (p[2 * i - 1] + p[2 * i + 1]) + (1 << 15)) >> 16;
247 static void dwt_encode97_int(DWTContext *s, int *t)
250 w = s->linelen[s->ndeclevels-1][0];
251 int *line = s->i_linebuf;
254 for (lev = s->ndeclevels-1; lev >= 0; lev--){
255 int lh = s->linelen[lev][0],
256 lv = s->linelen[lev][1],
264 for (lp = 0; lp < lh; lp++) {
267 for (i = 0; i < lv; i++)
270 sd_1d97_int(line, mv, mv + lv);
272 // copy back and deinterleave
273 for (i = mv; i < lv; i+=2, j++)
274 t[w*j + lp] = ((l[i] * I_LFTG_X) + (1 << 15)) >> 16;
275 for (i = 1-mv; i < lv; i+=2, j++)
281 for (lp = 0; lp < lv; lp++){
284 for (i = 0; i < lh; i++)
287 sd_1d97_int(line, mh, mh + lh);
289 // copy back and deinterleave
290 for (i = mh; i < lh; i+=2, j++)
291 t[w*lp + j] = ((l[i] * I_LFTG_X) + (1 << 15)) >> 16;
292 for (i = 1-mh; i < lh; i+=2, j++)
299 static void sr_1d53(int *p, int i0, int i1)
311 for (i = i0 / 2; i < i1 / 2 + 1; i++)
312 p[2 * i] -= (p[2 * i - 1] + p[2 * i + 1] + 2) >> 2;
313 for (i = i0 / 2; i < i1 / 2; i++)
314 p[2 * i + 1] += (p[2 * i] + p[2 * i + 2]) >> 1;
317 static void dwt_decode53(DWTContext *s, int *t)
320 int w = s->linelen[s->ndeclevels - 1][0];
321 int32_t *line = s->i_linebuf;
324 for (lev = 0; lev < s->ndeclevels; lev++) {
325 int lh = s->linelen[lev][0],
326 lv = s->linelen[lev][1],
334 for (lp = 0; lp < lv; lp++) {
336 // copy with interleaving
337 for (i = mh; i < lh; i += 2, j++)
338 l[i] = t[w * lp + j];
339 for (i = 1 - mh; i < lh; i += 2, j++)
340 l[i] = t[w * lp + j];
342 sr_1d53(line, mh, mh + lh);
344 for (i = 0; i < lh; i++)
345 t[w * lp + i] = l[i];
350 for (lp = 0; lp < lh; lp++) {
352 // copy with interleaving
353 for (i = mv; i < lv; i += 2, j++)
354 l[i] = t[w * j + lp];
355 for (i = 1 - mv; i < lv; i += 2, j++)
356 l[i] = t[w * j + lp];
358 sr_1d53(line, mv, mv + lv);
360 for (i = 0; i < lv; i++)
361 t[w * i + lp] = l[i];
366 static void sr_1d97_float(float *p, int i0, int i1)
378 extend97_float(p, i0, i1);
380 for (i = i0 / 2 - 1; i < i1 / 2 + 2; i++)
381 p[2 * i] -= F_LFTG_DELTA * (p[2 * i - 1] + p[2 * i + 1]);
383 for (i = i0 / 2 - 1; i < i1 / 2 + 1; i++)
384 p[2 * i + 1] -= F_LFTG_GAMMA * (p[2 * i] + p[2 * i + 2]);
386 for (i = i0 / 2; i < i1 / 2 + 1; i++)
387 p[2 * i] += F_LFTG_BETA * (p[2 * i - 1] + p[2 * i + 1]);
389 for (i = i0 / 2; i < i1 / 2; i++)
390 p[2 * i + 1] += F_LFTG_ALPHA * (p[2 * i] + p[2 * i + 2]);
393 static void dwt_decode97_float(DWTContext *s, float *t)
396 int w = s->linelen[s->ndeclevels - 1][0];
397 float *line = s->f_linebuf;
399 /* position at index O of line range [0-5,w+5] cf. extend function */
402 for (lev = 0; lev < s->ndeclevels; lev++) {
403 int lh = s->linelen[lev][0],
404 lv = s->linelen[lev][1],
411 for (lp = 0; lp < lv; lp++) {
413 // copy with interleaving
414 for (i = mh; i < lh; i += 2, j++)
415 l[i] = data[w * lp + j] * F_LFTG_K;
416 for (i = 1 - mh; i < lh; i += 2, j++)
417 l[i] = data[w * lp + j];
419 sr_1d97_float(line, mh, mh + lh);
421 for (i = 0; i < lh; i++)
422 data[w * lp + i] = l[i];
427 for (lp = 0; lp < lh; lp++) {
429 // copy with interleaving
430 for (i = mv; i < lv; i += 2, j++)
431 l[i] = data[w * j + lp] * F_LFTG_K;
432 for (i = 1 - mv; i < lv; i += 2, j++)
433 l[i] = data[w * j + lp];
435 sr_1d97_float(line, mv, mv + lv);
437 for (i = 0; i < lv; i++)
438 data[w * i + lp] = l[i];
443 static void sr_1d97_int(int32_t *p, int i0, int i1)
449 p[1] = (p[1] * I_LFTG_K + (1<<16)) >> 17;
451 p[0] = (p[0] * I_LFTG_X + (1<<15)) >> 16;
455 extend97_int(p, i0, i1);
457 for (i = i0 / 2 - 1; i < i1 / 2 + 2; i++)
458 p[2 * i] -= (I_LFTG_DELTA * (p[2 * i - 1] + p[2 * i + 1]) + (1 << 15)) >> 16;
460 for (i = i0 / 2 - 1; i < i1 / 2 + 1; i++)
461 p[2 * i + 1] -= (I_LFTG_GAMMA * (p[2 * i] + p[2 * i + 2]) + (1 << 15)) >> 16;
463 for (i = i0 / 2; i < i1 / 2 + 1; i++)
464 p[2 * i] += (I_LFTG_BETA * (p[2 * i - 1] + p[2 * i + 1]) + (1 << 15)) >> 16;
466 for (i = i0 / 2; i < i1 / 2; i++)
467 p[2 * i + 1] += (I_LFTG_ALPHA * (p[2 * i] + p[2 * i + 2]) + (1 << 15)) >> 16;
470 static void dwt_decode97_int(DWTContext *s, int32_t *t)
473 int w = s->linelen[s->ndeclevels - 1][0];
474 int32_t *line = s->i_linebuf;
476 /* position at index O of line range [0-5,w+5] cf. extend function */
479 for (lev = 0; lev < s->ndeclevels; lev++) {
480 int lh = s->linelen[lev][0],
481 lv = s->linelen[lev][1],
488 for (lp = 0; lp < lv; lp++) {
490 // rescale with interleaving
491 for (i = mh; i < lh; i += 2, j++)
492 l[i] = ((data[w * lp + j] * I_LFTG_K) + (1 << 15)) >> 16;
493 for (i = 1 - mh; i < lh; i += 2, j++)
494 l[i] = data[w * lp + j];
496 sr_1d97_int(line, mh, mh + lh);
498 for (i = 0; i < lh; i++)
499 data[w * lp + i] = l[i];
504 for (lp = 0; lp < lh; lp++) {
506 // rescale with interleaving
507 for (i = mv; i < lv; i += 2, j++)
508 l[i] = ((data[w * j + lp] * I_LFTG_K) + (1 << 15)) >> 16;
509 for (i = 1 - mv; i < lv; i += 2, j++)
510 l[i] = data[w * j + lp];
512 sr_1d97_int(line, mv, mv + lv);
514 for (i = 0; i < lv; i++)
515 data[w * i + lp] = l[i];
520 int ff_jpeg2000_dwt_init(DWTContext *s, uint16_t border[2][2],
521 int decomp_levels, int type)
523 int i, j, lev = decomp_levels, maxlen,
526 s->ndeclevels = decomp_levels;
529 for (i = 0; i < 2; i++)
530 for (j = 0; j < 2; j++)
531 b[i][j] = border[i][j];
533 maxlen = FFMAX(b[0][1] - b[0][0],
536 for (i = 0; i < 2; i++) {
537 s->linelen[lev][i] = b[i][1] - b[i][0];
538 s->mod[lev][i] = b[i][0] & 1;
539 for (j = 0; j < 2; j++)
540 b[i][j] = (b[i][j] + 1) >> 1;
544 s->f_linebuf = av_malloc_array((maxlen + 12), sizeof(*s->f_linebuf));
546 return AVERROR(ENOMEM);
549 s->i_linebuf = av_malloc_array((maxlen + 12), sizeof(*s->i_linebuf));
551 return AVERROR(ENOMEM);
554 s->i_linebuf = av_malloc_array((maxlen + 6), sizeof(*s->i_linebuf));
556 return AVERROR(ENOMEM);
564 int ff_dwt_encode(DWTContext *s, void *t)
568 dwt_encode97_float(s, t); break;
570 dwt_encode97_int(s, t); break;
572 dwt_encode53(s, t); break;
579 int ff_dwt_decode(DWTContext *s, void *t)
583 dwt_decode97_float(s, t);
586 dwt_decode97_int(s, t);
597 void ff_dwt_destroy(DWTContext *s)
599 av_freep(&s->f_linebuf);
600 av_freep(&s->i_linebuf);
605 #include "libavutil/lfg.h"
609 static int test_dwt(int *array, int *ref, uint16_t border[2][2], int decomp_levels, int type, int max_diff) {
611 DWTContext s1={{{0}}}, *s= &s1;
614 ret = ff_jpeg2000_dwt_init(s, border, decomp_levels, type);
616 fprintf(stderr, "ff_jpeg2000_dwt_init failed\n");
619 ret = ff_dwt_encode(s, array);
621 fprintf(stderr, "ff_dwt_encode failed\n");
624 ret = ff_dwt_decode(s, array);
626 fprintf(stderr, "ff_dwt_encode failed\n");
629 for (j = 0; j<MAX_W * MAX_W; j++) {
630 if (FFABS(array[j] - ref[j]) > max_diff) {
631 fprintf(stderr, "missmatch at %d (%d != %d) decomp:%d border %d %d %d %d\n",
632 j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]);
635 err2 += (array[j] - ref[j]) * (array[j] - ref[j]);
640 printf("%s, decomp:%2d border %3d %3d %3d %3d milli-err2:%9"PRId64"\n",
641 type == FF_DWT53 ? "5/3i" : "9/7i",
642 decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1],
643 1000*err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0])));
648 static int test_dwtf(float *array, float *ref, uint16_t border[2][2], int decomp_levels, float max_diff) {
650 DWTContext s1={{{0}}}, *s= &s1;
653 ret = ff_jpeg2000_dwt_init(s, border, decomp_levels, FF_DWT97);
655 fprintf(stderr, "ff_jpeg2000_dwt_init failed\n");
658 ret = ff_dwt_encode(s, array);
660 fprintf(stderr, "ff_dwt_encode failed\n");
663 ret = ff_dwt_decode(s, array);
665 fprintf(stderr, "ff_dwt_encode failed\n");
668 for (j = 0; j<MAX_W * MAX_W; j++) {
669 if (FFABS(array[j] - ref[j]) > max_diff) {
670 fprintf(stderr, "missmatch at %d (%f != %f) decomp:%d border %d %d %d %d\n",
671 j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]);
674 err2 += (array[j] - ref[j]) * (array[j] - ref[j]);
679 printf("9/7f, decomp:%2d border %3d %3d %3d %3d err2:%20.4f\n",
680 decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1],
681 err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0])));
687 int array[MAX_W * MAX_W];
688 int ref [MAX_W * MAX_W];
689 float arrayf[MAX_W * MAX_W];
690 float reff [MAX_W * MAX_W];
693 uint16_t border[2][2];
694 int ret, decomp_levels;
696 av_lfg_init(&prng, 1);
698 for (i = 0; i<MAX_W * MAX_W; i++)
699 arrayf[i] = reff[i] = array[i] = ref[i] = av_lfg_get(&prng) % 2048;
701 for (i = 0; i < 100; i++) {
703 border[j>>1][j&1] = av_lfg_get(&prng) % MAX_W;
704 if (border[0][0] >= border[0][1] || border[1][0] >= border[1][1])
706 decomp_levels = av_lfg_get(&prng) % FF_DWT_MAX_DECLVLS;
708 ret = test_dwt(array, ref, border, decomp_levels, FF_DWT53, 0);
711 ret = test_dwt(array, ref, border, decomp_levels, FF_DWT97_INT, FFMIN(7+5*decomp_levels, 15+3*decomp_levels));
714 ret = test_dwtf(arrayf, reff, border, decomp_levels, 1.0);