Index: gauss.c
===================================================================
RCS file: /cvs/gnome/gimp/plug-ins/common/gauss.c,v
retrieving revision 1.31
diff -r1.31 gauss.c
8c8
<  *
---
>  * 
28d27
< 
36d34
< 
77,83c75,82
< static void      find_constants    (gdouble  n_p[],
<                                     gdouble  n_m[],
<                                     gdouble  d_p[],
<                                     gdouble  d_m[],
<                                     gdouble  bd_p[],
<                                     gdouble  bd_m[],
<                                     gdouble  std_dev);
---
> static void      find_iir_constants    (gdouble  n_p[],
> 					gdouble  n_m[],
> 					gdouble  d_p[],
> 					gdouble  d_m[],
> 					gdouble  bd_p[],
> 					gdouble  bd_m[],
> 					gdouble  std_dev);
> 
90,95c89,108
< static gint *    make_curve        (gdouble    sigma,
<                                     gint      *length);
< static void      run_length_encode (guchar    *src,
<                                     gint      *dest,
<                                     gint       bytes,
<                                     gint       width);
---
> static void  make_rle_curve (gdouble   sigma,
> 			     gint   ** p_curve,
> 			     gint    * p_length,
> 			     gint   ** p_sum,
> 			     gint    * p_total
> 			     )  ;
> 
> static void free_rle_curve (gint    * curve ,
> 			    gint      length ,
> 			    gint    * sum
> 			    ) ;
> 
> static inline int  run_length_encode (const guchar *src,
> 				      gint      *repeat,
> 				      gint      *dest,
> 				      gint       bytes,
> 				      gint       width,
> 				      gint       border,
> 				      gint       pack
> 				      );
280c293
<   gimp_tile_cache_ntiles (2 *
---
>   gimp_tile_cache_ntiles (2*
622a636,729
> /* 
>  * run_length_encode( src, rle, pix, dist, width, border, pack ) ;
>  *
>  * Copy 'width' 8bit pixels from 'src' to 'pix' and extend both sides 
>  * by 'border' pixels so 'pix[]' is filled from '-border' to 'width+border-1'. 
>  *
>  * 'dist' is the distance between the pixels in 'src'.
>  * 
>  * If 'pack' is non-zero, then 'rle' is filled with a run-length encoding of 
>  * the pixels. In plain english, that means that rle[i] gives the number of times
>  * the same pixel is found  pix[i], pix[i+1], ...
>  * A standalone pixel has a rle value of 1.
>  * 
>  * The function returns the number of times 2 identical consecutive pixels 
>  * were found.
>  *
>  * Note: The function must be inlined to insure that all tests on 'pack' are efficiently
>  *       resolved by the compiler (they are in the critical loop). 
>  *       As a consequence, the function should only be called with known constant value
>  *       for 'pack'. 
>  *       In the current implementation, 'pack' is always 1 but it might be more efficient
>  *       to have an 'adaptative' algotirhm that switches to 0 when the run-length 
>  *       is innefficient
>  *      
>  * 
>  */ 
> 
> 
> static inline int
> run_length_encode(const guchar *src,
> 		  gint   *rle,
> 		  gint   *pix,     
> 		  gint    dist,     /* distance between 2 src pixels */
> 		  gint    width,
> 		  gint    border,
> 		  gint    pack
> 		  )
> {
>   gint last  ;
>   gint count = 0 ;
>   gint i = width ; 
> 
>   gint same = 0 ; 
> 
>   src += dist*(width-1) ;
>   if (pack) {  
>     rle += width + border - 1 ;
>   }
>   pix += width + border - 1 ;
> 
>   last  = *src ;
>   count = 0 ;
> 
>   /* the 'end' border */
>   for (i=0;i<border;i++) {
>     count++ ; 
>     *pix--   = last ;
>     if (pack) { 
>       *rle-- = count ;
>     }
>   }
> 
>   /* the real pixels */
>   for (i=0;i<width;i++) {
>     gint c  = *src ; 
>     src    -= dist ;
>     if (pack && c==last) {
>       count++ ; 
>       *pix-- = last ;
>       *rle-- = count ;
>       same++ ; 
>     } else {
>       count   = 1 ; 
>       last    = c ; 
>       *pix--  = last ;
>       if ( pack ) {
> 	*rle-- = count ;
>       }
>     }
>   }
> 
>   /* the start pixels */
>   for (i=0;i<border;i++) {
>     count++ ; 
>     *pix--   = last ;
>     if ( pack ) {
>       *rle-- = count ;
>     }
>   }
>   
>   return same ; 
> }
> 
> 
624,628c731,859
< gauss (GimpDrawable *drawable,
<        gdouble       horz,
<        gdouble       vert,
<        BlurMethod    method,
<        GtkWidget    *preview)
---
> do_encoded_lre( gint *enc , gint *src,  guchar *dest , gint width, gint length , gint dist  , gint *curve,  gint ctotal , gint *csum ) 
> {
>   gint col ; 
>   for (col = 0; col < width; col++)
>     {
>       gint * rpt ;
>       gint * pix ;
>       gint nb ;
>       gint s1 ;
>       gint i ;
>       gint val = 0;
>       gint start = -length ; 
>       
>       rpt = &enc[col+start] ;
>       pix = &src[col+start] ;
>       
>       s1 = csum[start] ;
>       nb = rpt[0];
>       i  = start + nb;
> 
>       while (i <= length)
> 	{           
> 	  int s2 = csum[i] ;
> 	  val   += pix[0] * (s2-s1);
> 	  s1     = s2 ; 
> 	  rpt    = &rpt[nb] ;
> 	  pix    = &pix[nb] ;
> 	  nb     = rpt[0];
> 	  i     += nb;
> 	}
>       
>       val += pix[0] * ( csum[length] - s1 );
>       
>       *dest = val / ctotal;
> 
>       dest += dist ;
>     }
> }
> 
> static void
> do_full_lre( gint *src , guchar *dest , gint width, gint length , gint dist  , gint *curve,  gint ctotal ) 
> {
>   gint col ; 
> 
>   for (col = 0; col < width; col++)
>     {
>       gint * x1 ;
>       gint * x2 ;
>       gint * c = &curve[0] ;
>       gint   i ;
>       gint   val ; 
> 
>       x1 = x2 = &src[col] ;
>       
>       /* The central point is a special case since it should only be processed ONCE */
>       
>       val = x1[0] * c[0] ;
>       
>       c  += 1 ;
>       x1 += 1 ;
>       x2 -= 1 ;
>       i   = length ;
>       
>       /* Processing multiple points in a single iteration should be 
>        * faster but is not strictly required.  
>        * Some precise benchmarking will be needed to figure out
>        * if this is really interesting. 
>        */
>       while (i>=8) 
> 	{
> 	  val += ( x1[0] + x2[-0] ) * c[0] ;
> 	  val += ( x1[1] + x2[-1] ) * c[1] ;
> 	  val += ( x1[2] + x2[-2] ) * c[2] ;
> 	  val += ( x1[3] + x2[-3] ) * c[3] ;
> 	  val += ( x1[4] + x2[-4] ) * c[4] ;
> 	  val += ( x1[5] + x2[-5] ) * c[5] ;
> 	  val += ( x1[6] + x2[-6] ) * c[6] ;
> 	  val += ( x1[7] + x2[-7] ) * c[7] ;
> 	 
> 	  c  += 8 ; 
> 	  x1 += 8 ;
> 	  x2 -= 8 ;
> 	  i  -= 8 ;
> 	}
>       
>       while (i>=4) 
> 	{
> 	  val += ( x1[0] + x2[-0] ) * c[0] ;
> 	  val += ( x1[1] + x2[-1] ) * c[1] ;
> 	  val += ( x1[2] + x2[-2] ) * c[2] ;
> 	  val += ( x1[3] + x2[-3] ) * c[3] ;
> 	  c  += 4 ;
> 	  x1 += 4 ;
> 	  x2 -= 4 ;
> 	  i  -= 4 ;
> 	}
>       
>       /* Only that final loop is strictly required */
>       
>       while (i>=1) 
> 	{
> 	  /* process the pixels at the distance i before and after the 
> 	   * central point. They must have the same coefficient
> 	   */
> 	  val += ( x1[0] + x2[-0] ) * c[0] ;
> 	  c  += 1 ; 
> 	  x1 += 1 ;
> 	  x2 -= 1 ;
> 	  i  -= 1 ;
> 	}
>       
>       *dest = val / ctotal ; 
>       dest += dist ; 
>       
>     }
>   
> }
>  
> static void
> gauss_iir(GimpDrawable *drawable,
> 	  gdouble       horz,
> 	  gdouble       vert,
> 	  BlurMethod    method,
> 	  guchar       *preview_buffer ,
> 	  gint          x1 , 
> 	  gint          y1 , 
> 	  gint          width, 
> 	  gint          height
> 	  )
631d861
<   gint          width, height;
634,637c864,865
<   guchar       *dest, *dp;
<   guchar       *src, *sp, *sp_p, *sp_m;
<   gint         *buf = NULL;
<   gint         *bb;
---
>   guchar       *dest;
>   guchar       *src,  *sp_p, *sp_m;
644d871
<   gint          x1, y1, x2, y2;
652,661c879,880
<   gint          pixels;
<   gint          total = 1;
<   gint          start, end;
<   gint         *curve = NULL;
<   gint         *sum   = NULL;
<   gint          val;
<   gint          length;
<   gint          initial_pp, initial_mm;
<   guchar       *preview_buffer1 = NULL;
<   guchar       *preview_buffer2 = NULL;
---
>   gboolean      direct  ;  
>   gint          progress_step  ;  
663,668d881
<   /*
<    * IIR goes wrong if the blur radius is less than 1, so we silently
<    * switch to RLE in this case.  See bug #315953
<    */
<   if (horz <= 1.0 || vert <= 1.0)
<     method = BLUR_RLE;
670,673c883
<   if (horz <= 0.0 && vert <= 0.0)
<     {
<       if (preview)
<         gimp_preview_draw (GIMP_PREVIEW (preview));
---
>   direct = (preview_buffer == NULL) ;
675c885,901
<       return;
---
>   bytes = drawable->bpp;
>   has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
>  
>   val_p = g_new (gdouble, MAX (width, height) * bytes);
>   val_m = g_new (gdouble, MAX (width, height) * bytes);
>      
>   src =  g_new (guchar, MAX (width, height) * bytes);
>   dest = g_new (guchar, MAX (width, height) * bytes);
> 
>   gimp_pixel_rgn_init (&src_rgn,
>                        drawable, 0, 0, drawable->width, drawable->height,
>                        FALSE, FALSE);
>   if (direct)
>     { 
>       gimp_pixel_rgn_init (&dest_rgn,
>                            drawable, 0, 0, drawable->width, drawable->height,
>                            TRUE, TRUE);
676a903
>   
678c905,911
<   if (preview)
---
>   progress = 0.0;
>   max_progress  = (horz <= 0.0 ) ? 0 : width * height * horz;
>   max_progress += (vert <= 0.0 ) ? 0 : width * height * vert;
> 
>     
>   /*  First the vertical pass  */
>   if (vert > 0.0)
680,681c913,1011
<       gimp_preview_get_position (GIMP_PREVIEW (preview), &x1, &y1);
<       gimp_preview_get_size (GIMP_PREVIEW (preview), &width, &height);
---
>       vert = fabs (vert) + 1.0;
>       std_dev = sqrt (-(vert * vert) / (2 * log (1.0 / 255.0)));
> 
>       /* We do not want too many progress updates because they 
>        * can slow down the processing significantly for very 
>        * large images
>        */
>       progress_step = width / 100  ;
>       if ( progress_step < 5 ) {
> 	progress_step = 5 ; 
>       }
> 
>       /*  derive the constants for calculating the gaussian
>        *  from the std dev
>        */
> 
>       find_iir_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
>         
> 
>       for (col = 0; col < width; col++)
>         {
>           
> 	  memset (val_p, 0, height * bytes * sizeof (gdouble));
> 	  memset (val_m, 0, height * bytes * sizeof (gdouble));
>              
>           gimp_pixel_rgn_get_col (&src_rgn, src, col + x1, y1, height);
> 
>           if (has_alpha)
>             multiply_alpha (src, height, bytes);
>         
> 	  sp_p = src;
> 	  sp_m = src + (height - 1) * bytes;
> 	  vp = val_p;
> 	  vm = val_m + (height - 1) * bytes;
> 
> 	  /*  Set up the first vals  */
> 	  for (i = 0; i < bytes; i++)
> 	    {
> 	      initial_p[i] = sp_p[i];
> 	      initial_m[i] = sp_m[i];
> 	    }
> 
> 	  for (row = 0; row < height; row++)
> 	    {
> 	      gdouble *vpptr, *vmptr;
> 	      terms = (row < 4) ? row : 4;
> 
> 	      for (b = 0; b < bytes; b++)
> 		{
> 		  vpptr = vp + b; vmptr = vm + b;
> 		  for (i = 0; i <= terms; i++)
> 		    {
> 		      *vpptr += n_p[i] * sp_p[(-i * bytes) + b] - d_p[i] * vp[(-i * bytes) + b];
> 		      *vmptr += n_m[i] * sp_m[( i * bytes) + b] - d_m[i] * vm[( i * bytes) + b];
> 		    }
> 		  for (j = i; j <= 4; j++)
> 		    {
> 		      *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
> 		      *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
> 		    }
> 		}
> 
> 	      sp_p += bytes;
> 	      sp_m -= bytes;
> 	      vp += bytes;
> 	      vm -= bytes;
> 	    }
> 
> 	  transfer_pixels (val_p, val_m, dest, bytes, height);
>              
> 
>           if (has_alpha)
>             separate_alpha (dest, height, bytes);
> 
>           if (direct)
> 	    {
>               gimp_pixel_rgn_set_col(&dest_rgn, dest, col + x1, y1, height);
> 
>               progress += height * vert;
>               if ((col % progress_step) == 0)
> 		gimp_progress_update (progress / max_progress) ;
>             }  
>           else
> 	    {
>               for (row = 0 ; row < height ; row++)
>                 memcpy (preview_buffer + (row * width + col) * bytes,
>                         dest + row * bytes,
>                         bytes);
>             }
>         }
> 
>       
> 
>       /*  prepare for the horizontal pass  */
>       gimp_pixel_rgn_init (&src_rgn,
>                            drawable, 
> 			   0, 0, 
> 			   drawable->width, drawable->height,
>                            FALSE, TRUE);
683c1013
<   else
---
>   else if (!direct)
685,688c1015,1018
<       gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
< 
<       width  = (x2 - x1);
<       height = (y2 - y1);
---
>       gimp_pixel_rgn_get_rect (&src_rgn,
>                                preview_buffer, 
> 			       x1, y1, 
> 			       width, height);
691,692c1021,1023
<   if (width < 1 || height < 1)
<     return;
---
>   /*  Now the horizontal pass  */
>   if (horz > 0.0)
>     {
694,695c1025,1131
<   bytes = drawable->bpp;
<   has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
---
>       /* We do not want too many progress updates because they 
>        * can slow down the processing significantly for very 
>        * large images
>        */
>       progress_step = height / 100 ;
>       if ( progress_step < 5 ) {
> 	progress_step = 5 ; 
>       }
> 
>       horz = fabs (horz) + 1.0;
> 
>       if (horz != vert)
>         {
>           std_dev = sqrt (-(horz * horz) / (2 * log (1.0 / 255.0)));
> 
> 	  /*  derive the constants for calculating the gaussian
> 	   *  from the std dev
> 	   */
> 	  find_iir_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
>             
>         }
> 
>       
>       for (row = 0; row < height; row++)
>         {
>         
> 	  memset (val_p, 0, width * bytes * sizeof (gdouble));
> 	  memset (val_m, 0, width * bytes * sizeof (gdouble));
> 
>           if (direct)
> 	    {
>               gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, width);
>             }
> 	  else
> 	    {
>               memcpy (src,
>                       preview_buffer + row * width * bytes,
>                       width * bytes);
>             }
>            
> 
>           if (has_alpha)
>             multiply_alpha (src, width, bytes);
> 
>         
> 	  sp_p = src;
> 	  sp_m = src + (width - 1) * bytes;
> 	  vp = val_p;
> 	  vm = val_m + (width - 1) * bytes;
> 
> 	  /*  Set up the first vals  */
> 	  for (i = 0; i < bytes; i++)
> 	    {
> 	      initial_p[i] = sp_p[i];
> 	      initial_m[i] = sp_m[i];
> 	    }
> 
> 	  for (col = 0; col < width; col++)
> 	    {
> 	      gdouble *vpptr, *vmptr;
> 	      terms = (col < 4) ? col : 4;
> 
> 	      for (b = 0; b < bytes; b++)
> 		{
> 		  vpptr = vp + b; vmptr = vm + b;
> 		  for (i = 0; i <= terms; i++)
> 		    {
> 		      *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
> 			d_p[i] * vp[(-i * bytes) + b];
> 		      *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
> 			d_m[i] * vm[(i * bytes) + b];
> 		    }
> 		  for (j = i; j <= 4; j++)
> 		    {
> 		      *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
> 		      *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
> 		    }
> 		}
> 
> 	      sp_p += bytes;
> 	      sp_m -= bytes;
> 	      vp += bytes;
> 	      vm -= bytes;
> 	    }
> 
> 	  transfer_pixels (val_p, val_m, dest, bytes, width);
> 
>           if (has_alpha)
>             separate_alpha (dest, width, bytes);
> 
>           if (direct)
>             {
> 	      gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, width); 
> 
>               progress += width * horz;
>               if ( ( row % progress_step ) == 0) 
> 		gimp_progress_update (progress / max_progress)  ; 
>             }
> 	  else
> 	    {
>               memcpy (preview_buffer + row * width * bytes,
>                       dest,
>                       width * bytes);
>             }
>             
>         }
>       
697,706d1132
<   switch (method)
<     {
<     case BLUR_IIR:
<       val_p = g_new (gdouble, MAX (width, height) * bytes);
<       val_m = g_new (gdouble, MAX (width, height) * bytes);
<       break;
< 
<     case BLUR_RLE:
<       buf = g_new (gint, MAX (width, height) * 2);
<       break;
709c1135,1178
<   src =  g_new (guchar, MAX (width, height) * bytes);
---
>   /*  free up buffers  */
>  
>   g_free (val_p);
>   g_free (val_m);
> 
>   g_free (src);
>   g_free (dest);
> 
> }
> 
> 
> static void
> gauss_rle(GimpDrawable *drawable,
> 	  gdouble       horz,
> 	  gdouble       vert,
> 	  BlurMethod    method,
> 	  guchar       *preview_buffer ,
> 	  gint          x1,
> 	  gint          y1,
> 	  gint          width, 
> 	  gint          height
> 	  )
> {
>   GimpPixelRgn  src_rgn, dest_rgn;
>   gint          bytes;
>   gboolean      has_alpha;
>   guchar       *dest;
>   guchar       *src ;
>   gint          row, col, b;
>   gdouble       progress, max_progress;
>   gdouble       std_dev;
>   gint          total = 1;
>   gint         *curve = NULL;
>   gint         *sum   = NULL;
>   gint          length;
>   gboolean      direct  ;  
>   gint          progress_step  ;  
> 
>   direct = (preview_buffer == NULL) ;
> 
>   bytes = drawable->bpp;
>   has_alpha = gimp_drawable_has_alpha (drawable->drawable_id);
>    
>   src  = g_new (guchar, MAX (width, height) * bytes);
715,720c1184,1185
<   if (preview)
<     {
<       preview_buffer1 = g_new (guchar, width * height * bytes);
<       preview_buffer2 = g_new (guchar, width * height * bytes);
<     }
<   else
---
> 
>   if (direct)
731c1196
< 
---
>     
734a1200,1202
>       gint   * rle = NULL;
>       gint   * pix = NULL;
> 
738,749c1206,1212
<       switch (method)
<         {
<         case BLUR_IIR:
<           /*  derive the constants for calculating the gaussian
<            *  from the std dev
<            */
<           find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
<           break;
< 
<         case BLUR_RLE:
<           curve = make_curve (std_dev, &length);
<           sum = g_new (gint, 2 * length + 1);
---
>       /* Insure that we do not have too many progress updates for 
>        * images with a lot of rows or columns
>        */
>       progress_step = width / 150  ;
>       if ( progress_step < 5 ) {
> 	progress_step = 5 ; 
>       }
751c1214
<           sum[0] = 0;
---
>       make_rle_curve( std_dev, &curve , &length , &sum , &total );
753,755c1216,1217
<           for (i = 1; i <= length*2; i++)
<             sum[i] = curve[i-length-1] + sum[i-1];
<           sum += length;
---
>       rle = g_new(gint, height+2*length ) ;
>       rle += length ; /* rle[] extends from -length to height+length-1 */
757,759c1219,1220
<           total = sum[length] - sum[-length];
<           break;
<         }
---
>       pix = g_new(gint, height+2*length ) ;
>       pix += length ; /* pix[] extends from -length to height+length-1 */
763,773c1224
<           switch (method)
<             {
<             case BLUR_IIR:
<               memset (val_p, 0, height * bytes * sizeof (gdouble));
<               memset (val_m, 0, height * bytes * sizeof (gdouble));
<               break;
< 
<             case BLUR_RLE:
<               break;
<             }
< 
---
>           
779,868c1230,1240
<           switch (method)
<             {
<             case BLUR_IIR:
<               sp_p = src;
<               sp_m = src + (height - 1) * bytes;
<               vp = val_p;
<               vm = val_m + (height - 1) * bytes;
< 
<               /*  Set up the first vals  */
<               for (i = 0; i < bytes; i++)
<                 {
<                   initial_p[i] = sp_p[i];
<                   initial_m[i] = sp_m[i];
<                 }
< 
<               for (row = 0; row < height; row++)
<                 {
<                   gdouble *vpptr, *vmptr;
<                   terms = (row < 4) ? row : 4;
< 
<                   for (b = 0; b < bytes; b++)
<                     {
<                       vpptr = vp + b; vmptr = vm + b;
<                       for (i = 0; i <= terms; i++)
<                         {
<                           *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
<                             d_p[i] * vp[(-i * bytes) + b];
<                           *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
<                             d_m[i] * vm[(i * bytes) + b];
<                         }
<                       for (j = i; j <= 4; j++)
<                         {
<                           *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
<                           *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
<                         }
<                     }
< 
<                   sp_p += bytes;
<                   sp_m -= bytes;
<                   vp += bytes;
<                   vm -= bytes;
<                 }
< 
<               transfer_pixels (val_p, val_m, dest, bytes, height);
<               break;
< 
<             case BLUR_RLE:
<               sp = src;
<               dp = dest;
< 
<               for (b = 0; b < bytes; b++)
<                 {
<                   initial_pp = sp[b];
<                   initial_mm = sp[(height-1) * bytes + b];
< 
<                   /*  Determine a run-length encoded version of the row  */
<                   run_length_encode (sp + b, buf, bytes, height);
< 
<                   for (row = 0; row < height; row++)
<                     {
<                       start = (row < length) ? -row : -length;
<                       end = (height <= (row + length) ?
<                              (height - row - 1) : length);
< 
<                       val = 0;
<                       i = start;
<                       bb = buf + (row + i) * 2;
< 
<                       if (start != -length)
<                         val += initial_pp * (sum[start] - sum[-length]);
< 
<                       while (i < end)
<                         {
<                           pixels = bb[0];
<                           i += pixels;
<                           if (i > end)
<                             i = end;
<                           val += bb[1] * (sum[i] - sum[start]);
<                           bb += (pixels * 2);
<                           start = i;
<                         }
< 
<                       if (end != length)
<                         val += initial_mm * (sum[length] - sum[end]);
< 
<                       dp[row * bytes + b] = val / total;
<                     }
<                  }
<               break;
<             }
---
> 	  for (b = 0; b < bytes; b++)
> 	    {
> 	      gint same =  run_length_encode(src + b, rle, pix, bytes, height, length , 1 );
> 	      if ( same > (3*height)/4 ) {
> 		/* encoded_rle is only fastest if there are a lot of repeating pixels */  
> 		do_encoded_lre( rle ,pix , dest+b , height , length  , bytes , curve , total , sum )  ; 
> 	      } else {
> 		/* else a full but more simple algorithm is better */  
> 		do_full_lre( pix , dest+b , height , length  , bytes , curve , total )  ; 
> 	      }
> 	    }
871c1243
<             separate_alpha (src, height, bytes);
---
>             separate_alpha (dest, height, bytes);
873,874c1245,1253
<           if (preview)
<             {
---
>           if (direct)
>            {
>               gimp_pixel_rgn_set_col(&dest_rgn, dest, col + x1, y1, height);
>               progress += height * vert;
>               if ((col % progress_step) == 0)
> 		gimp_progress_update (progress / max_progress) ;
>             }
>           else 
> 	    {
876c1255
<                 memcpy (preview_buffer1 + (row * width + col) * bytes,
---
>                 memcpy (preview_buffer + (row * width + col) * bytes,
880,887c1259
<           else
<             {
<               gimp_pixel_rgn_set_col (&dest_rgn, dest, col + x1, y1, height);
< 
<               progress += height * vert;
<               if ((col % 5) == 0)
<                 gimp_progress_update (progress / max_progress);
<             }
---
>             
890c1262,1266
<       /*  prepare for the horizontal pass  */
---
>       
>       g_free (rle - length);
>       g_free (pix - length);
> 
>       /* prepare for the horizontal pass  */
895c1271
<   else if (preview)
---
>   else if (!direct)
898c1274,1277
<                                preview_buffer1, x1, y1, width, height);
---
>                                preview_buffer, 
> 			       x1, y1, 
> 			       width, height
> 			       );
903a1283,1293
>       gint   * rle = NULL;
>       gint   * pix = NULL;
>        
>       /* Insure that we do not have too many progress updates for 
>        * images with a lot of rows or columns
>        */
>       progress_step = height / 150 ;
>       if ( progress_step < 5 ) {
> 	progress_step = 5 ; 
>       }
> 
905a1296
>       /* euse the same curve if possible else recompute a new one */
907a1299
> 	  
908a1301,1304
>          
> 	  if ( curve != NULL ) {
> 	    free_rle_curve( curve , length, sum ) ;
> 	  }
910,937c1306,1307
<           switch (method)
<             {
<             case BLUR_IIR:
<               /*  derive the constants for calculating the gaussian
<                *  from the std dev
<                */
<               find_constants (n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
<               break;
< 
<             case BLUR_RLE:
<               if (vert > 0.0)
<                 {
<                   g_free (sum - length);
<                   g_free (curve - length);
<                 }
< 
<               curve = make_curve (std_dev, &length);
<               sum = g_new (gint, 2 * length + 1);
< 
<               sum[0] = 0;
< 
<               for (i = 1; i <= length*2; i++)
<                 sum[i] = curve[i-length-1] + sum[i-1];
<               sum += length;
< 
<               total = sum[length] - sum[-length];
<               break;
<             }
---
> 	  make_rle_curve(std_dev, &curve , &length , &sum , &total );
>              
939a1310,1316
>       
>       rle = g_new (gint, width+2*length ) ;
>       rle += length ; /* so rle[] extends from -width to width+length-1 */
> 
>       pix = g_new (gint, width+2*length ) ;
>       pix += length ; /* so pix[] extends from -width to width+length-1 */
> 
942c1319,1320
<           switch (method)
---
>           
>           if (direct)
944,950c1322
<             case BLUR_IIR:
<               memset (val_p, 0, width * bytes * sizeof (gdouble));
<               memset (val_m, 0, width * bytes * sizeof (gdouble));
<               break;
< 
<             case BLUR_RLE:
<               break;
---
>               gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, width);
952,954c1324,1325
< 
<           if (preview)
<             {
---
> 	  else 
> 	    {
956c1327
<                       preview_buffer1 + row * width * bytes,
---
>                       preview_buffer + row * width * bytes,
959,962d1329
<           else
<             {
<               gimp_pixel_rgn_get_row (&src_rgn, src, x1, row + y1, width);
<             }
966,1055c1333,1346
< 
<           switch (method)
<             {
<             case BLUR_IIR:
<               sp_p = src;
<               sp_m = src + (width - 1) * bytes;
<               vp = val_p;
<               vm = val_m + (width - 1) * bytes;
< 
<               /*  Set up the first vals  */
<               for (i = 0; i < bytes; i++)
<                 {
<                   initial_p[i] = sp_p[i];
<                   initial_m[i] = sp_m[i];
<                 }
< 
<               for (col = 0; col < width; col++)
<                 {
<                   gdouble *vpptr, *vmptr;
<                   terms = (col < 4) ? col : 4;
< 
<                   for (b = 0; b < bytes; b++)
<                     {
<                       vpptr = vp + b; vmptr = vm + b;
<                       for (i = 0; i <= terms; i++)
<                         {
<                           *vpptr += n_p[i] * sp_p[(-i * bytes) + b] -
<                             d_p[i] * vp[(-i * bytes) + b];
<                           *vmptr += n_m[i] * sp_m[(i * bytes) + b] -
<                             d_m[i] * vm[(i * bytes) + b];
<                         }
<                       for (j = i; j <= 4; j++)
<                         {
<                           *vpptr += (n_p[j] - bd_p[j]) * initial_p[b];
<                           *vmptr += (n_m[j] - bd_m[j]) * initial_m[b];
<                         }
<                     }
< 
<                   sp_p += bytes;
<                   sp_m -= bytes;
<                   vp += bytes;
<                   vm -= bytes;
<                 }
< 
<               transfer_pixels (val_p, val_m, dest, bytes, width);
<               break;
< 
<             case BLUR_RLE:
<               sp = src;
<               dp = dest;
< 
<               for (b = 0; b < bytes; b++)
<                 {
<                   initial_pp = sp[b];
<                   initial_mm = sp[(width-1) * bytes + b];
< 
<                   /*  Determine a run-length encoded version of the row  */
<                   run_length_encode (sp + b, buf, bytes, width);
< 
<                   for (col = 0; col < width; col++)
<                     {
<                       start = (col < length) ? -col : -length;
<                       end = (width <= (col + length)) ? (width - col - 1) : length;
< 
<                       val = 0;
<                       i = start;
<                       bb = buf + (col + i) * 2;
< 
<                       if (start != -length)
<                         val += initial_pp * (sum[start] - sum[-length]);
< 
<                       while (i < end)
<                         {
<                           pixels = bb[0];
<                           i += pixels;
<                           if (i > end)
<                             i = end;
<                           val += bb[1] * (sum[i] - sum[start]);
<                           bb += (pixels * 2);
<                           start = i;
<                         }
< 
<                       if (end != length)
<                         val += initial_mm * (sum[length] - sum[end]);
< 
<                       dp[col * bytes + b] = val / total;
<                     }
<                 }
<               break;
<             }
---
> 		
> 	  for (b = 0; b < bytes; b++)
> 	    {
> 	      gint same = run_length_encode(src + b, rle, pix, bytes, width, length , 1 );
> 
> 	      if ( same > (3*width)/4 ) {
> 		/* encoded_rle is only fastest if there are a lot of repeating pixels */  
> 		do_encoded_lre( rle ,pix , dest+b , width , length  , bytes , curve , total , sum )  ; 
> 	      } else {
> 		/* else a full but more simple algorithm is better */  
> 		do_full_lre( pix , dest+b , width , length  , bytes , curve , total )  ; 
> 	      }
> 	    }
> 		
1060c1351
<           if (preview)
---
>           if (direct)
1062,1064c1353,1357
<               memcpy (preview_buffer2 + row * width * bytes,
<                       dest,
<                       width * bytes);
---
> 	      gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, width); 
> 
>               progress += width * horz;
>               if ( ( row % progress_step ) == 0) 
> 		gimp_progress_update (progress / max_progress)  ; 
1068,1072c1361,1363
<               gimp_pixel_rgn_set_row (&dest_rgn, dest, x1, row + y1, width);
< 
<               progress += width * horz;
<               if ((row % 5) == 0)
<                 gimp_progress_update (progress / max_progress);
---
>               memcpy (preview_buffer + row * width * bytes,
>                       dest,
>                       width * bytes);
1074a1366,1370
>       
>       g_free (rle - length );
>       g_free (pix - length );
> 
> 
1076c1372,1405
<   else if (preview)
---
> 
> 
> 
>   if ( curve != NULL ) {
>     free_rle_curve( curve , length, sum ) ;
>   }
> 
>   g_free (src);
>   g_free (dest);
> 
> }
> 
> 
> 
> static void
> gauss (GimpDrawable *drawable,
>        gdouble       horz,
>        gdouble       vert,
>        BlurMethod    method,
>        GtkWidget    *preview)
> {
> 
>   gint     x1, y1, x2, y2 ;
>   gint     width, height ;
>   guchar * preview_buffer;
> 
>   /*
>    * IIR goes wrong if the blur radius is less than 1, so we silently
>    * switch to RLE in this case.  See bug #315953
>    */
>   if (horz <= 1.0 || vert <= 1.0) 
>     method = BLUR_RLE;
>   
>   if (horz <= 0.0 && vert <= 0.0)
1078c1407,1409
<       memcpy (preview_buffer2, preview_buffer1, width * height * bytes);
---
>       if (preview)
>         gimp_preview_draw (GIMP_PREVIEW (preview));
>       return;
1083,1086c1414,1447
<       gimp_preview_draw_buffer (GIMP_PREVIEW (preview),
<                                 preview_buffer2, width * bytes);
<       g_free (preview_buffer1);
<       g_free (preview_buffer2);
---
>       gimp_preview_get_position (GIMP_PREVIEW (preview), &x1, &y1);
>       gimp_preview_get_size (GIMP_PREVIEW (preview), &width, &height);
> 
>       if (width < 1 || height < 1)
> 	return;
> 
>       preview_buffer = g_new (guchar, width * height * drawable->bpp);
> 
>     }
>   else
>     {
>       gimp_drawable_mask_bounds (drawable->drawable_id, &x1, &y1, &x2, &y2);
> 
>       width  = (x2 - x1);
>       height = (y2 - y1);
> 
>       if (width < 1 || height < 1)
> 	return;
> 
>       preview_buffer = NULL ; 
> 
>     }
> 
>   
>   if (method == BLUR_IIR){
>     gauss_iir(drawable, horz, vert, method, preview_buffer, x1, y1 , width , height ) ; 
>   } else {
>     gauss_rle(drawable, horz, vert, method, preview_buffer, x1, y1 , width , height ) ; 
>   }
>   
>   if (preview)
>     {
>       gimp_preview_draw_buffer (GIMP_PREVIEW (preview),  preview_buffer, width * drawable->bpp);
>       g_free (preview_buffer);
1096,1112c1457
<   /*  free up buffers  */
<   switch (method)
<     {
<     case BLUR_IIR:
<       g_free (val_p);
<       g_free (val_m);
<       break;
< 
<     case BLUR_RLE:
<       if (horz > 0.0 || vert > 0.0)
<         {
<           g_free (sum - length);
<           g_free (curve - length);
<         }
<       g_free (buf);
<       break;
<     }
---
>   
1114,1115d1458
<   g_free (src);
<   g_free (dest);
1117a1461,1463
> 
> 
> 
1133c1479
<       else if(sum < 0) sum = 0;
---
>       else if (sum < 0) sum = 0;
1140,1146c1486,1492
< find_constants (gdouble n_p[],
<                 gdouble n_m[],
<                 gdouble d_p[],
<                 gdouble d_m[],
<                 gdouble bd_p[],
<                 gdouble bd_m[],
<                 gdouble std_dev)
---
> find_iir_constants (gdouble n_p[],
> 		    gdouble n_m[],
> 		    gdouble d_p[],
> 		    gdouble d_m[],
> 		    gdouble bd_p[],
> 		    gdouble bd_m[],
> 		    gdouble std_dev)
1149c1495,1502
<   gdouble constants [8];
---
>   gdouble x0;
>   gdouble x1;
>   gdouble x2;
>   gdouble x3;
>   gdouble x4;
>   gdouble x5;
>   gdouble x6;
>   gdouble x7;
1157,1182c1510,1523
<   constants [0] = -1.783 / std_dev;
<   constants [1] = -1.723 / std_dev;
<   constants [2] = 0.6318 / std_dev;
<   constants [3] = 1.997  / std_dev;
<   constants [4] = 1.6803 / div;
<   constants [5] = 3.735 / div;
<   constants [6] = -0.6803 / div;
<   constants [7] = -0.2598 / div;
< 
<   n_p [0] = constants[4] + constants[6];
<   n_p [1] = exp (constants[1]) *
<     (constants[7] * sin (constants[3]) -
<      (constants[6] + 2 * constants[4]) * cos (constants[3])) +
<        exp (constants[0]) *
<          (constants[5] * sin (constants[2]) -
<           (2 * constants[6] + constants[4]) * cos (constants[2]));
<   n_p [2] = 2 * exp (constants[0] + constants[1]) *
<     ((constants[4] + constants[6]) * cos (constants[3]) * cos (constants[2]) -
<      constants[5] * cos (constants[3]) * sin (constants[2]) -
<      constants[7] * cos (constants[2]) * sin (constants[3])) +
<        constants[6] * exp (2 * constants[0]) +
<          constants[4] * exp (2 * constants[1]);
<   n_p [3] = exp (constants[1] + 2 * constants[0]) *
<     (constants[7] * sin (constants[3]) - constants[6] * cos (constants[3])) +
<       exp (constants[0] + 2 * constants[1]) *
<         (constants[5] * sin (constants[2]) - constants[4] * cos (constants[2]));
---
>   x0 = -1.783 / std_dev;
>   x1 = -1.723 / std_dev;
>   x2 = 0.6318 / std_dev;
>   x3 = 1.997  / std_dev;
>   x4 = 1.6803 / div;
>   x5 = 3.735 / div;
>   x6 = -0.6803 / div;
>   x7 = -0.2598 / div;
> 
>   n_p [0] = x4 + x6;
>   n_p [1] = exp(x1)*(x7*sin(x3)-(x6+2*x4)*cos(x3)) + exp(x0)*(x5*sin(x2) - (2*x6+x4)*cos (x2));
>   n_p [2] = 2*exp(x0+x1) * ((x4+x6)*cos(x3)*cos(x2) - x5*cos(x3)*sin(x2) - x7*cos(x2)*sin(x3)) 
>           + x6*exp(2*x0) + x4*exp(2*x1);
>   n_p [3] = exp(x1+2*x0) * ( x7*sin(x3) - x6*cos(x3)) +  exp(x0+2*x1) * (x5*sin(x2) - x4*cos(x2));
1186,1192c1527,1530
<   d_p [1] = -2 * exp (constants[1]) * cos (constants[3]) -
<     2 * exp (constants[0]) * cos (constants[2]);
<   d_p [2] = 4 * cos (constants[3]) * cos (constants[2]) * exp (constants[0] + constants[1]) +
<     exp (2 * constants[1]) + exp (2 * constants[0]);
<   d_p [3] = -2 * cos (constants[2]) * exp (constants[0] + 2 * constants[1]) -
<     2 * cos (constants[3]) * exp (constants[1] + 2 * constants[0]);
<   d_p [4] = exp (2 * constants[0] + 2 * constants[1]);
---
>   d_p [1] = -2 * exp(x1) * cos(x3) -  2 * exp(x0) * cos (x2);
>   d_p [2] = 4 * cos(x3) * cos(x2) * exp(x0 + x1) +  exp(2 * x1) + exp(2 * x0);
>   d_p [3] = -2 * cos(x2) * exp(x0 + 2*x1) -  2*cos(x3) * exp(x1 + 2*x0);
>   d_p [4] = exp(2*x0 + 2*x1);
1194,1195c1532,1534
<   for (i = 0; i <= 4; i++)
<     d_m [i] = d_p [i];
---
>   for (i = 0; i <= 4; i++) {
>     d_m[i] = d_p[i];
>   }
1198,1199c1537,1539
<   for (i = 1; i <= 4; i++)
<     n_m [i] = n_p[i] - d_p[i] * n_p[0];
---
>   for (i = 1; i <= 4; i++) {
>     n_m[i] = n_p[i] - d_p[i] * n_p[0];
>   }
1228,1229c1568,1582
<  * The equations: g(r) = exp (- r^2 / (2 * sigma^2))
<  *                   r = sqrt (x^2 + y ^2)
---
>  * make_rle_curve( sigma , &curve , &length , &sum , &total ) 
>  *
>  * 
>  * Fill the Gauss curve.
>  *
>  *               g(r) = exp (- r^2 / (2 * sigma^2))
>  *                  r = sqrt (x^2 + y ^2)
>  * 
>  * o length is filled with the length the curve (in both directions)
>  * o curve[-length .. length] is allocated and filled with the (scaled) gauss curve. 
>  * o sum[-length .. length]   is allocated and filled with the 'summed' curve. 
>  * o total is filled with the sum of all elements in the curve (for normalization).
>  *
>  *  
>  *
1232,1234c1585,1592
< static gint *
< make_curve (gdouble  sigma,
<             gint    *length)
---
> 
> static void
> make_rle_curve (gdouble   sigma,
> 		gint   ** p_curve,
> 		gint    * p_length,
> 		gint   ** p_sum,
> 		gint    * p_total
> 		) 
1240a1599,1600
>   gint     length;
>   gint    *sum;
1251,1252c1611,1612
<   *length = n / 2;
<   curve += *length;
---
>   length = n / 2;
>   curve += length; /* 'center' the curve[] */ 
1255c1615
<   for (i = 1; i <= *length; i++)
---
>   for (i = 1; i <= length; i++)
1262c1622,1635
<   return curve;
---
>   sum   = g_new (gint, 2 * length + 1);
> 
>   sum[0] = 0;
>   for (i = 1; i <= length*2; i++) {
>     sum[i] = curve[i-length-1] + sum[i-1];
>   }
> 
>   sum += length; /* 'center' the sum[] */ 
>    
>   *p_total  = sum[length] - sum[-length];
>   *p_curve  = curve ;
>   *p_sum    = sum ;
>   *p_length = length ;
> 
1264a1638,1640
> /*
>  * Free a curve previously allocated with make_rle_curve
>  */
1266,1269c1642,1645
< run_length_encode (guchar *src,
<                    gint   *dest,
<                    gint    bytes,
<                    gint    width)
---
> free_rle_curve (gint    * curve ,
> 		gint      length ,
> 		gint    * sum
> 		) 
1271,1278c1647,1649
<   gint   start;
<   gint   i;
<   gint   j;
<   guchar last;
< 
<   last = *src;
<   src += bytes;
<   start = 0;
---
>    g_free (sum - length);
>    g_free (curve - length);
> }
1280,1293d1650
<   for (i = 1; i < width; i++)
<     {
<       if (*src != last)
<         {
<           for (j = start; j < i; j++)
<             {
<               *dest++ = (i - j);
<               *dest++ = last;
<             }
<           start = i;
<           last = *src;
<         }
<       src += bytes;
<     }
1295,1300d1651
<   for (j = start; j < i; j++)
<     {
<       *dest++ = (i - j);
<       *dest++ = last;
<     }
< }
