summaryrefslogtreecommitdiffstats
path: root/ext/tarkin/wavelet_xform.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/tarkin/wavelet_xform.c')
-rw-r--r--ext/tarkin/wavelet_xform.c391
1 files changed, 391 insertions, 0 deletions
diff --git a/ext/tarkin/wavelet_xform.c b/ext/tarkin/wavelet_xform.c
new file mode 100644
index 00000000..768446a2
--- /dev/null
+++ b/ext/tarkin/wavelet_xform.c
@@ -0,0 +1,391 @@
+#include "mem.h"
+#include <assert.h>
+#include "wavelet.h"
+
+
+
+static
+void fwd_analyze_1 (const TYPE *x, TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ for (i=0; i<k; i++)
+ d[i] = x[(2*i+1)*stride] - x[2*i*stride];
+}
+
+
+static
+void fwd_synthesize_1 (const TYPE *x, TYPE *s, const TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ for (i=0; i<k; i++)
+ s[i*stride] = x[2*i*stride] + d[i] / 2;
+ if (n & 1)
+ s[k*stride] = x[2*k*stride] + d[k-1] / 2;
+}
+
+
+static
+void inv_analyze_1 (TYPE *x, const TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ for (i=0; i<k; i++)
+ x[(2*i+1)*stride] = d[i] + x[2*i*stride];
+}
+
+
+static
+void inv_synthesize_1 (TYPE *x, const TYPE *s, const TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ for (i=0; i<k; i++)
+ x[2*i*stride] = s[i] - d[i] / 2;
+ if (n & 1)
+ x[2*k*stride] = s[k] - d[k-1] / 2;
+}
+
+
+
+static
+void fwd_analyze_2 (const TYPE *x, TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ if (n & 1) {
+ for (i=0; i<k; i++)
+ d[i] = x[(2*i+1)*stride] - (x[2*i*stride] + x[(2*i+2)*stride]) / 2;
+ } else {
+ for (i=0; i<k-1; i++)
+ d[i] = x[(2*i+1)*stride] - (x[2*i*stride] + x[(2*i+2)*stride]) / 2;
+ d[k-1] = x[(n-1)*stride] - x[(n-2)*stride];
+ }
+}
+
+
+
+static
+void fwd_synthesize_2 (const TYPE *x, TYPE *s, const TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ s[0] = x[0] + d[1] / 2;
+ for (i=1; i<k; i++)
+ s[i*stride] = x[2*i*stride] + (d[i-1] + d[i]) / 4;
+ if (n & 1)
+ s[k*stride] = x[2*k*stride] + d[k-1] / 2;
+}
+
+
+static inline
+void inv_analyze_2 (TYPE *x, const TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ if (n & 1) {
+ for (i=0; i<k; i++)
+ x[(2*i+1)*stride] = d[i] + (x[2*i*stride] + x[(2*i+2)*stride]) / 2;
+ } else {
+ for (i=0; i<k-1; i++)
+ x[(2*i+1)*stride] = d[i] + (x[2*i*stride] + x[(2*i+2)*stride]) / 2;
+ x[(n-1)*stride] = d[k-1] + x[(n-2)*stride];
+ }
+}
+
+
+static inline
+void inv_synthesize_2 (TYPE *x, const TYPE *s, const TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ x[0] = s[0] - d[1] / 2;
+ for (i=1; i<k; i++)
+ x[2*i*stride] = s[i] - (d[i-1] + d[i]) / 4;
+ if (n & 1)
+ x[2*k*stride] = s[k] - d[k-1] / 2;
+}
+
+
+
+static
+void fwd_analyze_4 (const TYPE *x, TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ d[0] = x[stride] - (x[0] + x[2*stride]) / 2;
+
+ if (n & 1) {
+ for (i=1; i<k-1; i++)
+ d[i] = x[(2*i+1)*stride]
+ - ((uint32_t) 9 * (x[2*i*stride] + x[(2*i+2)*stride])
+ - (x[(2*i-2)*stride] + x[(2*i+4)*stride])) / 16;
+ if (k > 1)
+ d[k-1] = x[(2*k-1)*stride] - (x[(2*k-2)*stride] + x[2*k*stride]) / 2;
+ } else {
+ for (i=1; i<k-2; i++)
+ d[i] = x[(2*i+1)*stride]
+ - ((uint32_t) 9 * (x[2*i*stride] + x[(2*i+2)*stride])
+ - (x[(2*i-2)*stride] + x[(2*i+4)*stride])) / 16;
+ if (k > 2)
+ d[k-2] = x[(2*k-3)*stride] - (x[(2*k-4)*stride]
+ + x[(2*k-2)*stride]) / 2;
+ if (k > 1)
+ d[k-1] = x[(n-1)*stride] - x[(n-2)*stride];
+ }
+}
+
+
+static
+void fwd_synthesize_4 (const TYPE *x, TYPE *s, const TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ s[0] = x[0] + d[1] / 2;
+ if (k > 1)
+ s[stride] = x[2*stride] + (d[0] + d[1]) / 4;
+ for (i=2; i<k-1; i++)
+ s[i*stride] = x[2*i*stride]
+ + ((uint32_t) 9 * (d[i-1] + d[i]) - (d[i-2] + d[i+1])) / 32;
+ if (k > 2)
+ s[(k-1)*stride] = x[(2*k-2)*stride] + (d[k-2] + d[k-1]) / 4;
+ if (n & 1)
+ s[k*stride] = x[2*k*stride] + d[k-1] / 2;
+}
+
+
+static
+void inv_analyze_4 (TYPE *x, const TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ x[stride] = d[0] + (x[0] + x[2*stride]) / 2;
+
+ if (n & 1) {
+ for (i=1; i<k-1; i++)
+ x[(2*i+1)*stride] = d[i]
+ + ((uint32_t) 9 * (x[2*i*stride] + x[(2*i+2)*stride])
+ - (x[(2*i-2)*stride] + x[(2*i+4)*stride])) / 16;
+ if (k > 1)
+ x[(2*k-1)*stride] = d[k-1] + (x[(2*k-2)*stride] + x[2*k*stride]) / 2;
+ } else {
+ for (i=1; i<k-2; i++)
+ x[(2*i+1)*stride] = d[i]
+ + (9 * (x[2*i*stride] + x[(2*i+2)*stride])
+ - (x[(2*i-2)*stride] + x[(2*i+4)*stride])) / 16;
+ if (k > 2)
+ x[(2*k-3)*stride] = d[k-2] + (x[(2*k-4)*stride]
+ + x[(2*k-2)*stride]) / 2;
+ if (k > 1)
+ x[(n-1)*stride] = d[k-1] + x[(n-2)*stride];
+ }
+}
+
+
+static
+void inv_synthesize_4 (TYPE *x, const TYPE *s, const TYPE *d, int stride, int n)
+{
+ int i, k=n/2;
+
+ x[0] = s[0] - d[1] / 2;
+ if (k > 1)
+ x[2*stride] = s[1] - (d[0] + d[1]) / 4;
+ for (i=2; i<k-1; i++)
+ x[2*i*stride] = s[i] - ((uint32_t) 9 * (d[i-1] + d[i])
+ - (d[i-2] + d[i+1])) / 32;
+ if (k > 2)
+ x[(2*k-2)*stride] = s[k-1] - (d[k-2] + d[k-1]) / 4;
+ if (n & 1)
+ x[2*k*stride] = s[k] - d[k-1] / 2;
+}
+
+
+static inline
+void copyback_d (TYPE *x, const TYPE *d, int stride, int n)
+{
+ int i, j, k=n/2;
+
+ for (i=n-k, j=0; i<n; i++, j++)
+ x [i*stride] = d[j];
+}
+
+
+static inline
+void copy_s_d (const TYPE *x, TYPE *s_d, int stride, int n)
+{
+ int i;
+
+ for (i=0; i<n; i++)
+ s_d[i] = x [i*stride];
+}
+
+
+
+typedef
+void (*FwdSFnc) (const TYPE *x, TYPE *s, const TYPE *d, int stride, int n);
+
+typedef
+void (*FwdAFnc) (const TYPE *x, TYPE *d, int stride, int n);
+
+typedef
+void (*InvSFnc) (TYPE *x, const TYPE *s, const TYPE *d, int stride, int n);
+
+typedef
+void (*InvAFnc) (TYPE *x, const TYPE *d, int stride, int n);
+
+
+
+static FwdSFnc fwd_synthesize [] = { NULL, fwd_synthesize_1, fwd_synthesize_2,
+ NULL, fwd_synthesize_4 };
+
+static FwdAFnc fwd_analyze [] = { NULL, fwd_analyze_1, fwd_analyze_2,
+ NULL, fwd_analyze_4 };
+
+static InvSFnc inv_synthesize [] = { NULL, inv_synthesize_1, inv_synthesize_2,
+ NULL, inv_synthesize_4 };
+
+static InvAFnc inv_analyze [] = { NULL, inv_analyze_1, inv_analyze_2,
+ NULL, inv_analyze_4 };
+
+
+
+static inline
+void fwd_xform (TYPE *scratchbuf, TYPE *data, int stride, int n,
+ int a_moments, int s_moments)
+{
+ TYPE *x = data;
+ TYPE *d = scratchbuf;
+ TYPE *s = data;
+
+ assert (a_moments == 1 || a_moments == 2 || a_moments == 4);
+ assert (s_moments == 1 || s_moments == 2 || s_moments == 4);
+
+ /* XXX FIXME: Ugly hack to work around */
+ /* the short-row bug in high */
+ /* order xform functions */
+ if (n < 9)
+ a_moments = s_moments = 2;
+ if (n < 5)
+ a_moments = s_moments = 1;
+
+ fwd_analyze [a_moments] (x, d, stride, n);
+ fwd_synthesize [s_moments] (x, s, d, stride, n);
+ copyback_d (x, d, stride, n);
+}
+
+
+static inline
+void inv_xform (TYPE *scratchbuf, TYPE *data, int stride, int n,
+ int a_moments, int s_moments)
+{
+ int k=n/2;
+ TYPE *x = data;
+ TYPE *s = scratchbuf;
+ TYPE *d = scratchbuf + n - k;
+
+ assert (a_moments == 1 || a_moments == 2 || a_moments == 4);
+ assert (s_moments == 1 || s_moments == 2 || s_moments == 4);
+
+ /* XXX FIXME: Ugly hack to work around */
+ /* the short-row bug in high */
+ /* order xform functions */
+ if (n < 9)
+ a_moments = s_moments = 2;
+ if (n < 5)
+ a_moments = s_moments = 1;
+
+ copy_s_d (data, scratchbuf, stride, n);
+ inv_synthesize [s_moments] (x, s, d, stride, n);
+ inv_analyze [a_moments] (x, d, stride, n);
+}
+
+
+
+void wavelet_3d_buf_fwd_xform (Wavelet3DBuf* buf, int a_moments, int s_moments)
+{
+ int level;
+
+ for (level=buf->scales-1; level>0; level--) {
+ uint32_t w = buf->w[level];
+ uint32_t h = buf->h[level];
+ uint32_t f = buf->f[level];
+
+ if (w > 1) {
+ int row, frame;
+ for (frame=0; frame<f; frame++) {
+ for (row=0; row<h; row++) {
+ TYPE *data = buf->data + (frame * buf->height + row) * buf->width;
+ fwd_xform (buf->scratchbuf, data, 1, w, a_moments, s_moments);
+ }
+ }
+ }
+
+ if (h > 1) {
+ int col, frame;
+ for (frame=0; frame<f; frame++) {
+ for (col=0; col<w; col++) {
+ TYPE *data = buf->data + frame * buf->width * buf->height + col;
+ fwd_xform (buf->scratchbuf, data, buf->width, h,
+ a_moments, s_moments);
+ }
+ }
+ }
+
+ if (f > 1) {
+ int i, j;
+ for (j=0; j<h; j++) {
+ for (i=0; i<w; i++) {
+ TYPE *data = buf->data + j*buf->width + i;
+ fwd_xform (buf->scratchbuf, data, buf->width * buf->height, f,
+ a_moments, s_moments);
+ }
+ }
+ }
+ }
+}
+
+
+void wavelet_3d_buf_inv_xform (Wavelet3DBuf* buf, int a_moments, int s_moments)
+{
+ int level;
+
+ for (level=1; level<buf->scales; level++) {
+ uint32_t w = buf->w[level];
+ uint32_t h = buf->h[level];
+ uint32_t f = buf->f[level];
+
+ if (f > 1) {
+ int i, j;
+ for (j=0; j<h; j++) {
+ for (i=0; i<w; i++) {
+ TYPE *data = buf->data + j*buf->width + i;
+ inv_xform (buf->scratchbuf, data, buf->width * buf->height, f,
+ a_moments, s_moments);
+ }
+ }
+ }
+
+ if (h > 1) {
+ int col, frame;
+ for (frame=0; frame<f; frame++) {
+ for (col=0; col<w; col++) {
+ TYPE *data = buf->data + frame * buf->width * buf->height + col;
+ inv_xform (buf->scratchbuf, data, buf->width, h,
+ a_moments, s_moments);
+ }
+ }
+ }
+
+ if (w > 1) {
+ int row, frame;
+ for (frame=0; frame<f; frame++) {
+ for (row=0; row<h; row++) {
+ TYPE *data = buf->data + (frame * buf->height + row) * buf->width;
+ inv_xform (buf->scratchbuf, data, 1, w, a_moments, s_moments);
+ }
+ }
+ }
+ }
+}
+