[xiph-commits] r15578 - trunk/gimp-montypak
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Sat Dec 13 02:35:03 PST 2008
Author: xiphmont
Date: 2008-12-13 02:35:02 -0800 (Sat, 13 Dec 2008)
New Revision: 15578
Modified:
trunk/gimp-montypak/denoise.c
trunk/gimp-montypak/wavelet.c
Log:
Keep the denoise dialog UI alive while processing occurs.
Modified: trunk/gimp-montypak/denoise.c
===================================================================
--- trunk/gimp-montypak/denoise.c 2008-12-13 05:57:50 UTC (rev 15577)
+++ trunk/gimp-montypak/denoise.c 2008-12-13 10:35:02 UTC (rev 15578)
@@ -27,6 +27,7 @@
#include <string.h>
#include <stdlib.h>
+#include <gtk/gtk.h>
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
@@ -52,9 +53,9 @@
static void denoise (GimpDrawable *drawable);
static gboolean denoise_dialog (GimpDrawable *drawable);
-static void denoise_work(int w, int h, int bpp, guchar *buffer, int progress);
+static int denoise_work(int w, int h, int bpp, guchar *buffer, int progress, int(*interrupt)(void));
-static void preview_update (GimpPreview *preview);
+static void preview_update (GtkWidget *preview, GtkWidget *dialog);
/*
* Globals...
@@ -89,7 +90,13 @@
static GtkWidget *preview;
static GtkObject *madj[4];
+static guchar *preview_cache_buffer=NULL;
+static int preview_cache_x;
+static int preview_cache_y;
+static int preview_cache_w;
+static int preview_cache_h;
+
MAIN ()
#include "wavelet.c"
@@ -282,7 +289,7 @@
/***************************************/
buffer = g_new (guchar, w * h * bpp);
gimp_pixel_rgn_get_rect (&src_rgn, buffer, x1, y1, w, h);
- denoise_work(w,h,bpp,buffer,1);
+ denoise_work(w,h,bpp,buffer,1,NULL);
gimp_pixel_rgn_set_rect (&dst_rgn, buffer, x1, y1, w, h);
/**************************************/
@@ -322,7 +329,20 @@
gimp_preview_invalidate (GIMP_PREVIEW (preview));
}
+static void dump_cache(GtkWidget *widget, gpointer dummy){
+ if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))){
+ if(preview_cache_buffer)
+ g_free(preview_cache_buffer);
+ preview_cache_buffer=NULL;
+ }
+}
+static void decache_on_toggle(GtkWidget *widget, gpointer dummy){
+ g_signal_connect (widget, "toggled",
+ G_CALLBACK (dump_cache),
+ NULL);
+}
+
static gboolean denoise_dialog (GimpDrawable *drawable)
{
GtkWidget *dialog;
@@ -361,7 +381,9 @@
g_signal_connect (preview, "invalidated",
G_CALLBACK (preview_update),
- NULL);
+ dialog);
+ gtk_container_foreach(GTK_CONTAINER(gimp_preview_get_controls(GIMP_PREVIEW(preview))),
+ decache_on_toggle,NULL);
/* Main filter strength adjust */
table = gtk_table_new (1, 3, FALSE);
@@ -477,42 +499,101 @@
gtk_widget_destroy (dialog);
+ if(preview_cache_buffer)
+ g_free(preview_cache_buffer);
+
return run;
}
-static void preview_update (GimpPreview *preview)
-{
+static int denoise_active_interruptable;
+static int denoise_active_interrupt;
+
+static int check_recompute(){
+ while(gtk_events_pending())
+ gtk_main_iteration ();
+ return denoise_active_interrupt;
+}
+
+static int set_busy(GtkWidget *preview, GtkWidget *dialog){
+ GdkDisplay *display = gtk_widget_get_display (dialog);
+ GdkCursor *cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
+ gdk_window_set_cursor(preview->window, cursor);
+ gdk_window_set_cursor(gimp_preview_get_area(GIMP_PREVIEW(preview))->window, cursor);
+ gdk_window_set_cursor(dialog->window, cursor);
+ gdk_cursor_unref(cursor);
+}
+
+static void preview_update (GtkWidget *preview, GtkWidget *dialog){
+
GimpDrawable *drawable;
GimpPixelRgn rgn; /* previw region */
gint x1, y1;
gint w,h;
- guchar *buffer;
+ guchar *buffer=NULL;
gint bpp; /* Bytes-per-pixel in image */
-
- gimp_preview_get_position (preview, &x1, &y1);
- gimp_preview_get_size (preview, &w, &h);
+ /* because we allow async event processing, a stray expose of the
+ GimpPreviewArea will cause it reload the original unfiltered
+ data, which is annoying when doing small parameter tweaks. Make
+ sure the previous run's data is blitted in if it can be */
drawable = gimp_drawable_preview_get_drawable (GIMP_DRAWABLE_PREVIEW (preview));
bpp = gimp_drawable_bpp (drawable->drawable_id);
- buffer = g_new (guchar, w * h * bpp);
- gimp_pixel_rgn_init (&rgn, drawable,
- x1, y1, w, h,
- FALSE, FALSE);
- gimp_pixel_rgn_get_rect (&rgn, buffer, x1, y1, w, h);
- denoise_work(w,h,bpp,buffer,0);
- gimp_preview_draw_buffer (preview, buffer, w*bpp);
- gimp_drawable_flush (drawable);
+ gimp_preview_get_position (GIMP_PREVIEW(preview), &x1, &y1);
+ gimp_preview_get_size (GIMP_PREVIEW(preview), &w, &h);
- g_free (buffer);
+ if(preview_cache_buffer &&
+ x1 == preview_cache_x &&
+ y1 == preview_cache_y &&
+ w == preview_cache_w &&
+ h == preview_cache_h){
+
+ gimp_preview_draw_buffer (GIMP_PREVIEW(preview), preview_cache_buffer, w*bpp);
+ }else{
+ g_free(preview_cache_buffer);
+ preview_cache_buffer=NULL;
+ }
+
+ denoise_active_interrupt=1;
+ if(denoise_active_interruptable) return;
+ denoise_active_interruptable = 1;
+
+ while(denoise_active_interrupt){
+ denoise_active_interrupt=0;
+
+ set_busy(preview,dialog);
+
+ gimp_preview_get_position (GIMP_PREVIEW(preview), &x1, &y1);
+ gimp_preview_get_size (GIMP_PREVIEW(preview), &w, &h);
+ gimp_pixel_rgn_init (&rgn, drawable,
+ x1, y1, w, h,
+ FALSE, FALSE);
+ if(buffer) g_free (buffer);
+ buffer = g_new (guchar, w * h * bpp);
+ gimp_pixel_rgn_get_rect (&rgn, buffer, x1, y1, w, h);
+ if(!denoise_work(w,h,bpp,buffer,0,check_recompute)){
+ gimp_preview_draw_buffer (GIMP_PREVIEW(preview), buffer, w*bpp);
+ gimp_drawable_flush (drawable);
+ }
+ }
+
+ if(preview_cache_buffer)
+ g_free(preview_cache_buffer);
+ preview_cache_buffer = buffer;
+ preview_cache_x = x1;
+ preview_cache_y = y1;
+ preview_cache_w = w;
+ preview_cache_h = h;
+
+ denoise_active_interruptable = 0;
}
-static void denoise_work(int width, int height, int planes, guchar *buffer, int pr){
+static int denoise_work(int width, int height, int planes, guchar *buffer, int pr, int(*check)(void)){
int i;
double T[16];
for(i=0;i<16;i++)
- T[i]=denoise_params.filter*.2;
-
+ T[i]=denoise_params.filter*.2;
+
if(denoise_params.multiscale){
T[0]*=(denoise_params.f1+100)*.01;
T[1]*=(denoise_params.f2+100)*.01;
@@ -520,8 +601,8 @@
for(i=3;i<16;i++)
T[i]*=(denoise_params.f4+100)*.01;
}
+
+ return wavelet_filter(width, height, planes, buffer, pr, T, denoise_params.soft, check);
- wavelet_filter(width, height, planes, buffer, pr, T, denoise_params.soft);
-
}
Modified: trunk/gimp-montypak/wavelet.c
===================================================================
--- trunk/gimp-montypak/wavelet.c 2008-12-13 05:57:50 UTC (rev 15577)
+++ trunk/gimp-montypak/wavelet.c 2008-12-13 10:35:02 UTC (rev 15578)
@@ -464,70 +464,75 @@
return ret;
}
-static void free_m2D(m2D c){
- if(c.x) free(c.x);
+static void free_m2D(m2D *c){
+ if(c->x) free(c->x);
+ c->x = NULL;
}
-static void complex_threshold(m2D set[4], double T, int soft, int pt, int *pc){
- int i;
+static void complex_threshold(m2D set[4], double T, int soft, int pt, int *pc, int(*check)(void)){
+ int i,j;
int N = set[0].rows*set[0].cols;
if(T>.01){
double TT = T*T;
if(soft){
- for(i=0;i<N;i++){
- double v00 = (set[0].x[i] + set[3].x[i]) * .7071067812;
- double v11 = (set[0].x[i] - set[3].x[i]) * .7071067812;
- double v01 = (set[1].x[i] + set[2].x[i]) * .7071067812;
- double v10 = (set[1].x[i] - set[2].x[i]) * .7071067812;
-
- if(v00*v00 + v10*v10 < TT){
- v00 = 0.;
- v10 = 0.;
- }else{
- double y = sqrt(v00*v00 + v10*v10);
- double scale = y/(y+T);
- v00 *= scale;
- v10 *= scale;
+ for(i=0;i<N;){
+ for(j=0;j<set[0].cols;i++,j++){
+ double v00 = (set[0].x[i] + set[3].x[i]) * .7071067812;
+ double v11 = (set[0].x[i] - set[3].x[i]) * .7071067812;
+ double v01 = (set[1].x[i] + set[2].x[i]) * .7071067812;
+ double v10 = (set[1].x[i] - set[2].x[i]) * .7071067812;
+
+ if(v00*v00 + v10*v10 < TT){
+ v00 = 0.;
+ v10 = 0.;
+ }else{
+ double y = sqrt(v00*v00 + v10*v10);
+ double scale = y/(y+T);
+ v00 *= scale;
+ v10 *= scale;
+ }
+ if(v01*v01 + v11*v11 < TT){
+ v01 = 0.;
+ v11 = 0.;
+ }else{
+ double y = sqrt(v01*v01 + v11*v11);
+ double scale = y/(y+T);
+ v01 *= scale;
+ v11 *= scale;
+ }
+
+ set[0].x[i] = (v00 + v11) * .7071067812;
+ set[3].x[i] = (v00 - v11) * .7071067812;
+ set[1].x[i] = (v01 + v10) * .7071067812;
+ set[2].x[i] = (v01 - v10) * .7071067812;
}
- if(v01*v01 + v11*v11 < TT){
- v01 = 0.;
- v11 = 0.;
- }else{
- double y = sqrt(v01*v01 + v11*v11);
- double scale = y/(y+T);
- v01 *= scale;
- v11 *= scale;
- }
-
- set[0].x[i] = (v00 + v11) * .7071067812;
- set[3].x[i] = (v00 - v11) * .7071067812;
- set[1].x[i] = (v01 + v10) * .7071067812;
- set[2].x[i] = (v01 - v10) * .7071067812;
-
+ if(check && check())return;
}
}else{
- for(i=0;i<N;i++){
- double v00 = (set[0].x[i] + set[3].x[i]) * .7071067812;
- double v11 = (set[0].x[i] - set[3].x[i]) * .7071067812;
- double v01 = (set[1].x[i] + set[2].x[i]) * .7071067812;
- double v10 = (set[1].x[i] - set[2].x[i]) * .7071067812;
-
- if(v00*v00 + v10*v10 < TT){
- v00 = 0.;
- v10 = 0.;
+ for(i=0;i<N;){
+ for(j=0;j<set[0].cols;i++,j++){
+ double v00 = (set[0].x[i] + set[3].x[i]) * .7071067812;
+ double v11 = (set[0].x[i] - set[3].x[i]) * .7071067812;
+ double v01 = (set[1].x[i] + set[2].x[i]) * .7071067812;
+ double v10 = (set[1].x[i] - set[2].x[i]) * .7071067812;
+
+ if(v00*v00 + v10*v10 < TT){
+ v00 = 0.;
+ v10 = 0.;
+ }
+ if(v01*v01 + v11*v11 < TT){
+ v01 = 0.;
+ v11 = 0.;
+ }
+
+ set[0].x[i] = (v00 + v11) * .7071067812;
+ set[3].x[i] = (v00 - v11) * .7071067812;
+ set[1].x[i] = (v01 + v10) * .7071067812;
+ set[2].x[i] = (v01 - v10) * .7071067812;
}
- if(v01*v01 + v11*v11 < TT){
- v01 = 0.;
- v11 = 0.;
- }
-
- set[0].x[i] = (v00 + v11) * .7071067812;
- set[3].x[i] = (v00 - v11) * .7071067812;
- set[1].x[i] = (v01 + v10) * .7071067812;
- set[2].x[i] = (v01 - v10) * .7071067812;
-
+ if(check && check())return;
}
}
}
@@ -537,7 +542,7 @@
/* assume the input is padded, return output that's padded for next stage */
/* FSZ*2-2 padding, +1 additional padding if vector odd */
-static m2D convolve_padded(m2D x, double *f, int pt, int *pc){
+static m2D convolve_padded(const m2D x, double *f, int pt, int *pc, int(*check)(void)){
int i,M = x.rows;
int j,in_N = x.cols;
int k;
@@ -545,6 +550,7 @@
int out_N = (comp_N+1)/2*2+FSZ*2-2;
m2D y=alloc_m2D(M,out_N);
+ if(check && check())return y;
for(i=0;i<M;i++){
double *xrow = x.x+i*in_N;
@@ -556,6 +562,7 @@
xrow+=2;
yrow[j]=a;
}
+ if(check && check())return y;
/* extend output padding */
for(j=0;j<FSZ-1;j++){
@@ -564,12 +571,15 @@
}
for(j=FSZ-1+comp_N;j<out_N;j++)
yrow[j] = yrow[j-1];
+
+ if(check && check())return y;
+
}
if(pt)gimp_progress_update((gdouble)((*pc)++)/pt);
return y;
}
-static m2D convolve_transpose_padded(m2D x, double *f, int pt, int *pc){
+static m2D convolve_transpose_padded(const m2D x, double *f, int pt, int *pc, int(*check)(void)){
int i,M = x.rows;
int j,in_N = x.cols;
int k;
@@ -577,6 +587,7 @@
int out_N = (comp_N+1)/2*2+FSZ*2-2;
m2D y=alloc_m2D(out_N,M);
+ if(check && check())return y;
for(i=0;i<M;i++){
double *xrow = x.x+i*in_N;
@@ -588,6 +599,7 @@
xrow+=2;
ycol[j*M]=a;
}
+ if(check && check())return y;
/* extend output padding */
for(j=0;j<FSZ-1;j++){
@@ -596,6 +608,9 @@
}
for(j=FSZ-1+comp_N;j<out_N;j++)
ycol[j*M] = ycol[(j-1)*M];
+
+ if(check && check())return y;
+
}
if(pt)gimp_progress_update((gdouble)((*pc)++)/pt);
return y;
@@ -606,8 +621,7 @@
/* y will often be smaller than a full x expansion due to preceeding
rounds of padding out to even values; this padding is also
discarded */
-
-static m2D deconvolve_padded(m2D y, m2D x, double *f, int pt, int *pc){
+static void deconvolve_padded(m2D y, m2D x, double *f, int pt, int *pc, int(*check)(void)){
int i;
int j,in_N = x.cols;
int k;
@@ -629,10 +643,10 @@
yrow[j+1]+=a;
xrow++;
}
+ if(check && check()) return;
}
+
if(pt)gimp_progress_update((gdouble)((*pc)++)/pt);
- free_m2D(x);
- return y;
}
/* discards the padding added by the matching convolution */
@@ -640,8 +654,7 @@
/* y will often be smaller than a full x expansion due to preceeding
rounds of padding out to even values; this padding is also
discarded */
-
-static m2D deconvolve_transpose_padded(m2D y, m2D x, double *f, int pt, int *pc){
+static void deconvolve_transpose_padded(m2D y, m2D x, double *f, int pt, int *pc, int(*check)(void)){
int i;
int j,in_N = x.cols;
int k;
@@ -662,122 +675,190 @@
ycol[(j+1)*out_N]+=a;
xrow++;
}
+ if(check && check()) return;
}
-
- free_m2D(x);
+
if(pt)gimp_progress_update((gdouble)((*pc)++)/pt);
- return y;
}
+/* consumes and replaces lo if free_input set, otherwise overwrites */
static void forward_threshold(m2D lo[4], m2D y[4],
double af[2][3][FSZ], double sf[2][3][FSZ],
double T, int soft,
- int free_input, int pt, int *pc){
- m2D x[4];
- m2D temp[4];
- m2D tempw[4];
- m2D temp2[4];
+ int free_input, int pt, int *pc,
+ int(*check)(void)){
+ m2D x[4] = {{NULL,0,0},{NULL,0,0},{NULL,0,0},{NULL,0,0}};
+ m2D temp[4] = {{NULL,0,0},{NULL,0,0},{NULL,0,0},{NULL,0,0}};
+ m2D tempw[4] = {{NULL,0,0},{NULL,0,0},{NULL,0,0},{NULL,0,0}};
+ m2D temp2[4] = {{NULL,0,0},{NULL,0,0},{NULL,0,0},{NULL,0,0}};
int r,c,i;
-
+
for(i=0;i<4;i++){
x[i] = lo[i];
- temp[i] = convolve_transpose_padded(x[i], af[i>>1][2], pt, pc);
- tempw[i] = convolve_padded(temp[i], af[i&1][2], pt, pc); /* w 7 */
+ lo[i] = (m2D){NULL,0,0};
}
+ for(i=0;i<4;i++){
+ temp[i] = convolve_transpose_padded(x[i], af[i>>1][2], pt, pc, check);
+ if(check && check())goto cleanup;
+ tempw[i] = convolve_padded(temp[i], af[i&1][2], pt, pc, check); /* w 7 */
+ if(check && check())goto cleanup;
+ }
+
r = tempw[0].rows;
c = tempw[0].cols;
- complex_threshold(tempw, T, soft, pt, pc);
+ complex_threshold(tempw, T, soft, pt, pc, check);
+ if(check && check())goto cleanup;
for(i=0;i<4;i++){
temp2[i]=alloc_m2D(c*2 - FSZ*3 + 2, r);
y[i] = alloc_m2D(temp2[i].rows, temp2[i].cols*2 - FSZ*3 + 2);
- deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][2], pt, pc);
- tempw[i] = convolve_padded(temp[i], af[i&1][1], pt, pc); /* w6 */
+ if(check && check())goto cleanup;
+ deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][2], pt, pc, check);
+ if(check && check())goto cleanup;
+ tempw[i] = convolve_padded(temp[i], af[i&1][1], pt, pc, check); /* w6 */
+ if(check && check())goto cleanup;
}
- complex_threshold(tempw, T, soft, pt, pc);
+ complex_threshold(tempw, T, soft, pt, pc, check);
+ if(check && check())goto cleanup;
for(i=0;i<4;i++){
- deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][1], pt, pc);
- tempw[i] = convolve_padded(temp[i], af[i&1][0], pt, pc); /* w5 */
- free_m2D(temp[i]);
+ deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][1], pt, pc, check);
+ if(check && check())goto cleanup;
+ tempw[i] = convolve_padded(temp[i], af[i&1][0], pt, pc, check); /* w5 */
+ if(check && check())goto cleanup;
+ free_m2D(temp+i);
}
- complex_threshold(tempw, T, soft, pt, pc);
+ complex_threshold(tempw, T, soft, pt, pc, check);
+ if(check && check())goto cleanup;
for(i=0;i<4;i++){
- deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][0], pt, pc);
- deconvolve_padded(y[i],temp2[i],sf[i>>1][2], pt, pc);
- temp[i] = convolve_transpose_padded(x[i], af[i>>1][1], pt, pc);
+ deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][0], pt, pc, check);
+ if(check && check())goto cleanup;
+ deconvolve_padded(y[i],temp2[i],sf[i>>1][2], pt, pc, check);
+ if(check && check())goto cleanup;
+ temp[i] = convolve_transpose_padded(x[i], af[i>>1][1], pt, pc, check);
+ if(check && check())goto cleanup;
temp2[i] = alloc_m2D(c*2 - FSZ*3 + 2, r);
- tempw[i] = convolve_padded(temp[i], af[i&1][2], pt, pc); /* w4 */
+ if(check && check())goto cleanup;
+ tempw[i] = convolve_padded(temp[i], af[i&1][2], pt, pc, check); /* w4 */
+ if(check && check())goto cleanup;
}
- complex_threshold(tempw, T, soft, pt, pc);
+ complex_threshold(tempw, T, soft, pt, pc, check);
+ if(check && check())goto cleanup;
for(i=0;i<4;i++){
- deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][2], pt, pc);
- tempw[i] = convolve_padded(temp[i], af[i&1][1], pt, pc); /* w3 */
+ deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][2], pt, pc, check);
+ if(check && check())goto cleanup;
+ tempw[i] = convolve_padded(temp[i], af[i&1][1], pt, pc, check); /* w3 */
+ if(check && check())goto cleanup;
}
- complex_threshold(tempw, T, soft, pt, pc);
+ complex_threshold(tempw, T, soft, pt, pc, check);
+ if(check && check())goto cleanup;
for(i=0;i<4;i++){
- deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][1], pt, pc);
- tempw[i] = convolve_padded(temp[i], af[i&1][0], pt, pc); /* w2 */
- free_m2D(temp[i]);
+ deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][1], pt, pc, check);
+ if(check && check())goto cleanup;
+ tempw[i] = convolve_padded(temp[i], af[i&1][0], pt, pc, check); /* w2 */
+ if(check && check())goto cleanup;
+ free_m2D(temp+i);
}
- complex_threshold(tempw, T, soft, pt, pc);
+ complex_threshold(tempw, T, soft, pt, pc, check);
+ if(check && check())goto cleanup;
for(i=0;i<4;i++){
- deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][0], pt, pc);
- deconvolve_padded(y[i],temp2[i],sf[i>>1][1], pt, pc);
- temp[i] = convolve_transpose_padded(x[i], af[i>>1][0], pt, pc);
- if(free_input) free_m2D(x[i]);
+ deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][0], pt, pc, check);
+ if(check && check())goto cleanup;
+ deconvolve_padded(y[i],temp2[i],sf[i>>1][1], pt, pc, check);
+ if(check && check())goto cleanup;
+ temp[i] = convolve_transpose_padded(x[i], af[i>>1][0], pt, pc, check);
+ if(check && check())goto cleanup;
+ if(free_input) free_m2D(x+i);
temp2[i] = alloc_m2D(c*2 - FSZ*3 + 2, r);
- tempw[i] = convolve_padded(temp[i], af[i&1][2], pt, pc); /* w1 */
+ if(check && check())goto cleanup;
+ tempw[i] = convolve_padded(temp[i], af[i&1][2], pt, pc, check); /* w1 */
+ if(check && check())goto cleanup;
}
- complex_threshold(tempw, T, soft, pt, pc);
+ complex_threshold(tempw, T, soft, pt, pc, check);
+ if(check && check())goto cleanup;
for(i=0;i<4;i++){
- deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][2], pt, pc);
- tempw[i] = convolve_padded(temp[i], af[i&1][1], pt, pc); /* w0 */
+ deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][2], pt, pc, check);
+ if(check && check())goto cleanup;
+ tempw[i] = convolve_padded(temp[i], af[i&1][1], pt, pc, check); /* w0 */
+ if(check && check())goto cleanup;
}
- complex_threshold(tempw, T, soft, pt, pc);
+ complex_threshold(tempw, T, soft, pt, pc, check);
+ if(check && check())goto cleanup;
for(i=0;i<4;i++){
- deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][1], pt, pc);
- deconvolve_padded(y[i],temp2[i],sf[i>>1][0], pt, pc);
- lo[i] = convolve_padded(temp[i], af[i&1][0], pt, pc); /* lo */
- free_m2D(temp[i]);
+ deconvolve_transpose_padded(temp2[i],tempw[i],sf[i&1][1], pt, pc, check);
+ if(check && check())goto cleanup;
+ deconvolve_padded(y[i],temp2[i],sf[i>>1][0], pt, pc, check);
+ if(check && check())goto cleanup;
+ lo[i] = convolve_padded(temp[i], af[i&1][0], pt, pc, check); /* lo */
+ if(check && check())goto cleanup;
+ free_m2D(temp+i);
+ if(check && check())goto cleanup;
}
+ return;
+ cleanup:
+ for(i=0;i<4;i++){
+ if(free_input)free_m2D(x+i);
+ free_m2D(temp+i);
+ free_m2D(tempw+i);
+ free_m2D(temp2+i);
+ }
}
-static void finish_backward(m2D lo[4], m2D y[4], double sf[2][3][FSZ], int pt, int *pc){
+/* consumes/replaces lo */
+static void finish_backward(m2D lo[4], m2D y[4], double sf[2][3][FSZ], int pt, int *pc, int(*check)(void)){
int r=lo[0].rows,c=lo[0].cols,i;
- m2D temp;
+ m2D temp = {NULL,0,0};
for(i=0;i<4;i++){
temp=alloc_m2D(c*2 - FSZ*3 + 2, r);
- deconvolve_transpose_padded(temp,lo[i],sf[i&1][0], pt, pc);
- deconvolve_padded(y[i],temp,sf[i>>1][0], pt, pc);
+ deconvolve_transpose_padded(temp,lo[i],sf[i&1][0], pt, pc, check);
+ free_m2D(lo+i);
+ if(check && check()){
+ free_m2D(&temp);
+ return;
+ }
+ deconvolve_padded(y[i],temp,sf[i>>1][0], pt, pc, check);
+ free_m2D(&temp);
lo[i]=y[i];
+ y[i]=(m2D){NULL,0,0};
+ if(check && check()) return;
}
}
-static m2D transform_threshold(m2D x, int J, double T[16], int soft, int pt, int *pc){
+static m2D transform_threshold(m2D x, int J, double T[16], int soft, int pt, int *pc, int (*check)(void)){
int i,j;
m2D partial_y[J][4];
m2D lo[4];
+ for(j=0;j<J;j++)
+ for(i=0;i<4;i++)
+ partial_y[j][i]=(m2D){NULL,0,0};
+
lo[0] = lo[1] = lo[2] = lo[3] = x;
- forward_threshold(lo, partial_y[0], analysis_fs, synthesis_fs, T[0], soft, 0, pt, pc);
+ forward_threshold(lo, partial_y[0], analysis_fs, synthesis_fs, T[0], soft, 0, pt, pc, check);
+ if(check && check()) goto cleanup3;
- for(j=1;j<J;j++)
- forward_threshold(lo, partial_y[j], analysis, synthesis, T[j], soft, 1, pt, pc);
+ for(j=1;j<J;j++){
+ forward_threshold(lo, partial_y[j], analysis, synthesis, T[j], soft, 1, pt, pc, check);
+ if(check && check()) goto cleanup3;
+ }
- for(j=J-1;j;j--)
- finish_backward(lo, partial_y[j], synthesis, pt, pc);
- finish_backward(lo, partial_y[0], synthesis_fs, pt, pc);
+ for(j=J-1;j;j--){
+ finish_backward(lo, partial_y[j], synthesis, pt, pc, check);
+ if(check && check()) goto cleanup3;
+ }
+ finish_backward(lo, partial_y[0], synthesis_fs, pt, pc, check);
+ if(check && check()) goto cleanup3;
+
{
int end = lo[0].rows*lo[0].cols;
double *y = lo[0].x;
@@ -788,19 +869,28 @@
for(j=0;j<end;j++)
y[j]+=p1[j]+p2[j]+p3[j];
- free_m2D(lo[1]);
- free_m2D(lo[2]);
- free_m2D(lo[3]);
+ if(check && check()) goto cleanup3;
}
+ cleanup3:
+
+ for(j=0;j<J;j++)
+ for(i=0;i<4;i++)
+ free_m2D(&partial_y[j][i]);
+
+ free_m2D(lo+1);
+ free_m2D(lo+2);
+ free_m2D(lo+3);
return lo[0];
}
-static void wavelet_filter(int width, int height, int planes, guchar *buffer, int pr, double T[16],int soft){
+static int wavelet_filter(int width, int height, int planes, guchar *buffer, int pr, double T[16],int soft,
+ int (*check)(void)){
int J=4;
int i,j,p;
- m2D xc,yc;
+ m2D xc={NULL,0,0};
+ m2D yc={NULL,0,0};
int pc=0;
int pt;
@@ -822,6 +912,7 @@
xc = alloc_m2D((height+1)/2*2+FSZ*2-2,
(width+1)/2*2+FSZ*2-2),yc;
+ if(check && check())goto abort;
/* loop through planes */
for(p=0;p<planes;p++){
@@ -860,8 +951,10 @@
row[j]=pre[j];
}
- yc=transform_threshold(xc,J,T,soft,pt,&pc);
-
+ if(check && check())goto abort;
+ yc=transform_threshold(xc,J,T,soft,pt,&pc,check);
+ if(check && check())goto abort;
+
/* pull filtered values back out of padded matrix */
ptr = buffer+p;
for(i=0;i<height;i++){
@@ -874,10 +967,14 @@
}
}
- free_m2D(yc);
+ if(check && check())goto abort;
+ free_m2D(&yc);
+ if(check && check())goto abort;
}
- free_m2D(xc);
-
+ abort:
+ free_m2D(&yc);
+ free_m2D(&xc);
+ return check();
}
More information about the commits
mailing list