Weichzeichnen (Blur)


Objekte weichzeichnen zu können ist, ein Muss, will man ansprechende Graphiken erstellen. Die Processing eigene weichzeichen-Funktion blur() hat einen entscheidenden Nachteil. Sie ist sehr langsam. Will man Objekte in einer Animation (in Echtzeit) weichzeichnen ist sie somit obsolet.

Mario Klingemann hat einen sehr schnellen Weichzeichen-Algorithmus geschrieben, welcher wiederum von PhiLho erweitert wurde, so dass er nun auch mit dem Alpha Kanal umgehen kann. Damit hat man die Möglichkeit auch mit transparentem Hintergrund zu arbeiten.

// ==================================================
// fastblur, reworked by PhiLho from the Processing Forum
// by Mario Klingemann http://incubator.quasimondo.com/processing/superfast_blur.php
// ==================================================
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;
}
}
}

Wie setzt man den Algorithmus ein?

Wie wir der ersten Zeile entnehmen können, verlangt die Funktion beim Aufruf ein PImage und einen Integer als Parameter. Wir können nun also ein *.jpg laden und dieses, bevor wir es am Bildschirm ausgeben, mit dem Algorithmus weichzeichnen.

Beispiel FotoBlur:   starte Applet

PImage img;

void setup() {
img=loadImage("blume.JPG");
size(img.width, img.height);
}

void draw() {
img=loadImage("blume.JPG");
fastBlur(img,mouseX/5);
image(img, 0, 0);
}

Wollen wir aber von Processing gezeichnete Objekte weichzeichen, müssen wir diese in einen sog. FrameBuffer zeichnen. Siehe hochauflösende Bilder ausgeben.

Beispiel  Bluring selbst gezeichneter Objekte: Starte Applet

Hier wird ein Graphik-Objekt (ellipse()) in einen Offscreen Buffer gezeichnet und dieser dann mit fastBlur() weichgezeichnet.


/*---------------------------------------------------------
By Thomas Koberger
https://lernprocessing.wordpress.com/
---------------------------------------------------------*/

PImage img;
PGraphics pg;

void setup() {
img=loadImage("blume.JPG");
size(img.width, img.height);
}

void draw() {
image(img, 0, 0);
pg= createGraphics(width, height, P2D);
pg.beginDraw();
pg.noFill();
pg.strokeWeight(8);
pg.stroke(50, 100, 250);
pg.ellipse(width/2, height/2, 200, 200);
pg.loadPixels();
fastBlur(pg,mouseX/10);
pg.endDraw();
image(pg, 0, 0);
}

Beispiel Agenten weichzeichnen: starte Applet

Hier werden Agenten in kleine FrameBuffer gerendert, weichgezeichnet und dann angezeigt. Außerdem wird das ganze Bild, jeweils weichgezeichnet und im nächsten Frame als Hintergrund verwendet.

SourceCode siehe Applet!

Advertisements

2 Kommentare

  1. Pingback: Processing – Über dieses Weblog « processing – tutorial

  2. Errors in Proccessing 2.0 b7

    to make the examples run:
    // put P2D or P3D in the setup – size() function

    Example 2, blur the PGraphics doesn’t work. There’s maybe an error in the PGraphics transparency.

    In the Agents example
    add „pg.loadPixels();“ in the Agent class before fastBlur(pg, 2);
    it runs very slowly and there’s a the same transparency problem as in example 2.

    Is there any hint to activate alpha blending to the PGraphics?

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: