We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › fast blur, how
Page Index Toggle Pages: 1
fast blur, how? (Read 4158 times)
fast blur, how?
Aug 17th, 2009, 5:33am
 
good morning dear Processing community, i'm looking for some way to use blur in real time, and have stumbled on this example:

Code:
incubator.quasimondo.com/processing/superfast_blur.php 



Looks nice enough and fast, i've tried to modify it so it runs in Processing 1.05, but it doesn't:

Quote:
// Super Fast Blur v1.1
// by Mario Klingemann
//
// Tip: Multiple invovations of this filter with a small 
// radius will approximate a gaussian blur quite well.
//
PImage a;
PImage b;

void setup()
{

  a=loadImage("dog.jpg");
  size(a.width, a.height);
  b=new PImage(a.width, a.height);
  fill(255);
  noStroke();
  

}

void draw()
{
  System.arraycopy(a.pixels,0,b.pixels,0,a.pixels.length);
  fastblur(b,mouseY/8);
  image(b, 0, 0);
}

void fastblur(PImage img,int radius){

  if (radius<1){
    return;
  }
  int w=img.width;
  int h=img.height;
  int wm=w-1;
  int hm=h-1;
  int wh=w*h;
  int div=radius+radius+1;
  int r[]=new int[wh];
  int g[]=new int[wh];
  int b[]=new int[wh];
  int rsum,gsum,bsum,x,y,i,p,p1,p2,yp,yi,yw;
  int vmin[] = new int[max(w,h)];
  int vmax[] = new int[max(w,h)];
  int[] pix=img.pixels;
  int dv[]=new int[256*div];
  for (i=0;i<256*div;i++){
     dv[i]=(i/div);
  }
  
  yw=yi=0;
 
  for (y=0;y<h;y++){
    rsum=gsum=bsum=0;
    for(i=-radius;i<=radius;i++){
      p=pix[yi+min(wm,max(i,0))];
      rsum+=(p & 0xff0000)>>16;
      gsum+=(p & 0x00ff00)>>8;
      bsum+= p & 0x0000ff;
   }
    for (x=0;x<w;x++){
    
      r[yi]=dv[rsum];
      g[yi]=dv[gsum];
      b[yi]=dv[bsum];

      if(y==0){
        vmin[x]=min(x+radius+1,wm);
        vmax[x]=max(x-radius,0);
       } 
       p1=pix[yw+vmin[x]];
       p2=pix[yw+vmax[x]];

      rsum+=((p1 & 0xff0000)-(p2 & 0xff0000))>>16;
      gsum+=((p1 & 0x00ff00)-(p2 & 0x00ff00))>>8;
      bsum+= (p1 & 0x0000ff)-(p2 & 0x0000ff);
      yi++;
    }
    yw+=w;
  }
  
  for (x=0;x<w;x++){
    rsum=gsum=bsum=0;
    yp=-radius*w;
    for(i=-radius;i<=radius;i++){
      yi=max(0,yp)+x;
      rsum+=r[yi];
      gsum+=g[yi];
      bsum+=b[yi];
      yp+=w;
    }
    yi=x;
    for (y=0;y<h;y++){
      pix[yi]=0xff000000 | (dv[rsum]<<16) | (dv[gsum]<<8) | dv[bsum];
      if(x==0){
        vmin[y]=min(y+radius+1,hm)*w;
        vmax[y]=max(y-radius,0)*w;
      } 
      p1=x+vmin[y];
      p2=x+vmax[y];

      rsum+=r[p1]-r[p2];
      gsum+=g[p1]-g[p2];
      bsum+=b[p1]-b[p2];

      yi+=w;
    }
  }

}



Something with that System.arraycopy line? Sorry i'm a bit noobish.

So once this works, if i want to use the blur just like filter(BLUR), i'd go about pixels[] etc., right?

Also, do you think it's possible to use a blur function like this as a method for some class? i.e. isolate the pixels one object draws, and blur only these, without affecting anything else on the screen. I suppose this to be a bit more complicated, with transparent blurry borders et al...

thanks
Re: fast blur, how?
Reply #1 - Aug 17th, 2009, 6:31am
 
PImage reference says: "do not use new PImage()"...
You can use the get() method of PImage to get a valid copy.
Example:
Code:
void setup()
{
 a=loadImage("dog.jpg");
 size(a.width, a.height);
}

void draw()
{
 b = a.get();
 fastblur(b, mouseY/8);
 image(b, 0, 0);
}

And yes, you can blur any PImage this way. So you can make your class draw in a PImage, blur it, then draw the result on the sketch.
Re: fast blur, how?
Reply #2 - Aug 17th, 2009, 6:48am
 
okay thanks, it draws the copied image.

edit: wait, that works. thanks a lot!
the createGraphics() tip was nice too.

edit 2: now, does anyone understand how this blur function actually works? i'd like to make it work with the alpha channel too, but errr...
i've tried to add in the math for alpha, but non-surprisingly something is terribly wrong:

Quote:
PGraphics graphed;
PImage img;

void setup() {
     size(400, 300);
     smooth();

    // draw the circle to be blurred to buffer
    
     graphed = createGraphics(80, 80, JAVA2D);
     graphed.beginDraw();
     graphed.noFill();
     graphed.smooth();
     graphed.strokeWeight(3);
     graphed.ellipseMode(CORNER);
     graphed.ellipse(3, 3, 73, 73);
     graphed.endDraw();
     img = graphed.get();
}

void draw() {
     background(255);
     noStroke();
     fill(180);
     rect(30, 20, 300, 200);

    // apply blur to the off-screen buffer then draw to screen
    
     fastBlur(img, 3);
     image(img, mouseX, mouseY);
}

void fastBlur(PImage img,int radius){

     if (radius<1){
           return;
     }
     int w=img.width;
     int h=img.height;
     int wm=w-1;
     int hm=h-1;
     int wh=w*h;
     int div=radius+radius+1;
     int a[]=new int[wh]; // i've added this
     int r[]=new int[wh];
     int g[]=new int[wh];
     int b[]=new int[wh];
     int asum,rsum,gsum,bsum,x,y,i,p,p1,p2,yp,yi,yw; // and the asum here
     int vmin[] = new int[max(w,h)];
     int vmax[] = new int[max(w,h)];
     int[] pix=img.pixels;
     int dv[]=new int[256*div];
     for (i=0;i<256*div;i++){
           dv[i]=(i/div);
     }

     yw=yi=0;

     for (y=0;y<h;y++){
           asum=rsum=gsum=bsum=0; // asum
           for(i=-radius;i<=radius;i++){
                 p=pix[yi+min(wm,max(i,0))];
                 asum+=(p & 0xff000000)>>24; // is this correct? Cheesy
                 rsum+=(p & 0xff0000)>>16;
                 gsum+=(p & 0x00ff00)>>8;
                 bsum+= p & 0x0000ff;
           }
           for (x=0;x<w;x++){
                 a[yi]=dv[asum]; // crashes with this...  Sad
                 r[yi]=dv[rsum];
                 g[yi]=dv[gsum];
                 b[yi]=dv[bsum];

                 if(y==0){
                       vmin[x]=min(x+radius+1,wm);
                       vmax[x]=max(x-radius,0);
                 } 
                 p1=pix[yw+vmin[x]];
                 p2=pix[yw+vmax[x]];
                 
                 asum+=((p1 & 0xff000000)-(p2 & 0xff000000))>>24; // asum
                 rsum+=((p1 & 0xff0000)-(p2 & 0xff0000))>>16;
                 gsum+=((p1 & 0x00ff00)-(p2 & 0x00ff00))>>8;
                 bsum+= (p1 & 0x0000ff)-(p2 & 0x0000ff);
                 yi++;
           }
           yw+=w;
     }

     for (x=0;x<w;x++){
           asum=rsum=gsum=bsum=0;
           yp=-radius*w;
           for(i=-radius;i<=radius;i++){
                 yi=max(0,yp)+x;
                 asum+=r[yi]; // asum
                 rsum+=r[yi];
                 gsum+=g[yi];
                 bsum+=b[yi];
                 yp+=w;
           }
           yi=x;
           for (y=0;y<h;y++){
                 pix[yi]=0xff000000 | (dv[asum]<<24) | (dv[rsum]<<16) | (dv[gsum]<<8) | dv[bsum]; // and asum
                 if(x==0){
                       vmin[y]=min(y+radius+1,hm)*w;
                       vmax[y]=max(y-radius,0)*w;
                 } 
                 p1=x+vmin[y];
                 p2=x+vmax[y];
                 
                 asum+=a[p1]-a[p2]; // asum
                 rsum+=r[p1]-r[p2];
                 gsum+=g[p1]-g[p2];
                 bsum+=b[p1]-b[p2];

                 yi+=w;
           }
     }
}



so there has to be some misunderstanding on my behalf of the bitwise operations i guess...
Re: fast blur, how?
Reply #3 - Aug 20th, 2009, 10:01am
 
hm is there nobody who could point me in the right direction?
this blur algorithm does the job really well, and the boxy look gives it a nice touch:
Code:
dl.getdropbox.com/u/1358257/blurrr/new/applet/index.html 



so yeah it's all well except for the alpha channel, it's not in the original blur algorithm.
who can make that grey smiley happy again?
Re: fast blur, how?
Reply #4 - Aug 20th, 2009, 11:07pm
 
No time to test right now, but I would look at the line:
asum+=((p1 & 0xff000000)-(p2 & 0xff000000))>>24; // asum
where you might have an integer overflow. Try to convert it to:
asum+=((p1 & 0xff000000)>>24)-((p2 & 0xff000000)>>24);
for example.
Might not be the culprit...
Re: fast blur, how?
Reply #5 - Aug 21st, 2009, 3:09pm
 
the crash was caused by the asum going into negative values... thanks anyway!

now that it doesn't crash anymore, i could kind of locate the problem (maybe).
in this line the pixels get their argb-values assigned: Code:
pix[yi]=0xff000000 | (dv[asum]<<24) | (dv[rsum]<<16) | (dv[gsum]<<8) | dv[bsum]; 



now no matter what i put before the "<<24", the resulting 8 bits are always just 1's:

Code:
11111111010001010100010101000101
11111111010001100100011001000110
11111111010001100100011001000110
11111111010001100100011001000110
11111111010001100100011001000110


*scratches head*

edit: Code:
pix[yi] = (dv[asum]<<24) | (dv[rsum]<<16) | (dv[gsum]<<8) | dv[bsum]; 



heh, that works.  Roll Eyes

so the last hurdle:
the alpha values still do not do what they should...
for one, the asum thing will turn negative, so something has to be wrong with the math for alpha. i can't see what it is though, as i just tried to mimic exactly what the operations for r, g and b channels do...
Re: fast blur, how?
Reply #6 - Aug 22nd, 2009, 3:23am
 
Beware of sign propagation on >>!
You can use the unsigned right shift operator ">>>" or mask after shifting:
Instead of:
asum+=(p & 0xff000000)>>24;
do:
asum+=(p & 0xff000000)>>>24;
or:
asum+=(p>>24) & 0xff;
Re: fast blur, how?
Reply #7 - Nov 4th, 2009, 3:51am
 
Hei, could you put the final code here? i was trying it but allways get an "out of bound exception: 1792" at this line:

a[yi]=dv[asum]; // crashes with this...  

thx
Re: fast blur, how?
Reply #8 - Nov 4th, 2009, 4:55am
 
Perhaps you should try and apply the proposed fixes?
Re: fast blur, how?
Reply #9 - Nov 4th, 2009, 6:21am
 
well i tried this, still i get the error
Re: fast blur, how?
Reply #10 - Nov 4th, 2009, 8:32am
 
Well, yes, there was still a typo: asum+=r[yi]; (using r instead of a).
Here is the working version:
Code:
PGraphics graphed;
int IMAGE_SIZE = 80;
int BLUR_RADIUS = 7;

void setup() {
size(400, 300);
smooth();

// draw the circle to be blurred to buffer

graphed = createGraphics(IMAGE_SIZE, IMAGE_SIZE, JAVA2D);
graphed.beginDraw();
graphed.noFill();
graphed.smooth();
graphed.strokeWeight(BLUR_RADIUS / 2);
graphed.ellipseMode(CORNER);
graphed.ellipse(BLUR_RADIUS, BLUR_RADIUS, IMAGE_SIZE - BLUR_RADIUS * 2, IMAGE_SIZE - BLUR_RADIUS * 2);
graphed.endDraw();
}

void draw() {
background(255);
noStroke();
fill(180);
rect(30, 20, 300, 200);

// apply blur to the off-screen buffer then draw to screen

fastBlur(graphed, 5);
image(graphed, mouseX, mouseY);
}

void fastBlur(PImage img, int radius){
if (radius<1){
return;
}
int w=img.width;
int h=img.height;
int wm=w-1;
int hm=h-1;
int wh=w*h;
int div=radius+radius+1;
int a[]=new int[wh]; // i've added this
int r[]=new int[wh];
int g[]=new int[wh];
int b[]=new int[wh];
int asum,rsum,gsum,bsum,x,y,i,p,p1,p2,yp,yi,yw; // and the asum here
int vmin[] = new int[max(w,h)];
int vmax[] = new int[max(w,h)];
int[] pix=img.pixels;
int dv[]=new int[256*div];
for (i=0;i<256*div;i++){
dv[i]=(i/div);
}

yw=yi=0;

for (y=0;y<h;y++){
asum=rsum=gsum=bsum=0; // asum
for(i=-radius;i<=radius;i++){
p=pix[yi+min(wm,max(i,0))];
asum+=(p>>24) & 0xff;
rsum+=(p & 0xff0000)>>16;
gsum+=(p & 0x00ff00)>>8;
bsum+= p & 0x0000ff;
}
for (x=0;x<w;x++){
a[yi]=dv[asum];
r[yi]=dv[rsum];
g[yi]=dv[gsum];
b[yi]=dv[bsum];

if(y==0){
vmin[x]=min(x+radius+1,wm);
vmax[x]=max(x-radius,0);
}
p1=pix[yw+vmin[x]];
p2=pix[yw+vmax[x]];

asum+=((p1>>24) & 0xff)-((p2>>24) & 0xff); // asum
rsum+=((p1 & 0xff0000)-(p2 & 0xff0000))>>16;
gsum+=((p1 & 0x00ff00)-(p2 & 0x00ff00))>>8;
bsum+= (p1 & 0x0000ff)-(p2 & 0x0000ff);
yi++;
}
yw+=w;
}

for (x=0;x<w;x++){
asum=rsum=gsum=bsum=0;
yp=-radius*w;
for(i=-radius;i<=radius;i++){
yi=max(0,yp)+x;
asum+=a[yi]; // asum
rsum+=r[yi];
gsum+=g[yi];
bsum+=b[yi];
yp+=w;
}
yi=x;
for (y=0;y<h;y++){
pix[yi] = (dv[asum]<<24) | (dv[rsum]<<16) | (dv[gsum]<<8) | dv[bsum];
if(x==0){
vmin[y]=min(y+radius+1,hm)*w;
vmax[y]=max(y-radius,0)*w;
}
p1=x+vmin[y];
p2=x+vmax[y];

asum+=a[p1]-a[p2]; // asum
rsum+=r[p1]-r[p2];
gsum+=g[p1]-g[p2];
bsum+=b[p1]-b[p2];

yi+=w;
}
}
}
Re: fast blur, how?
Reply #11 - Nov 9th, 2009, 1:32am
 
If you are willing to use OpenGL, have a look at the GLGraphics library (can't post a link, I don't have 5 posts yet). On their website they have an example blur if you look around a bit.
Page Index Toggle Pages: 1