[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