Search code examples
javaprocessingopacityblurbrush

Blurred edges keep regaining 100% opacity (Processing)


I am trying to create a round brush with blurred edges in Processing through the following code. The circle shape is drawn pixel by pixel because in the actual version, I try to draw with pixels taken from the PGraphic pg.

PFont font;
PGraphics pg;
int X;
int Y;
int rad = 20;

void setup (){
    size(800, 800, P2D);
    background(0);
    noStroke();

    pg = createGraphics(800, 800, JAVA2D);
    pg.beginDraw();
    pg.fill(255);
    pg.noStroke();
    pg.textFont(font);
    pg.textSize(400);
    pg.pushMatrix();
    pg.translate(width/2, height/2-140);
    pg.textAlign(CENTER, CENTER);
    pg.text("b", 0 , 0);
    pg.popMatrix();
    pg.endDraw();
}

void draw () {
    image(pg,0,0);
}

void mousePressed(){
    X = mouseX;
    Y = mouseY;
}

void mouseDragged(){

    for (int x=0; x<rad; x++) {
        for (int y=0; y<rad; y++) {
        float distance = sqrt(pow(x,2)+pow(y,2));
        float alpha = 255-map(distance,0,rad,0,255);

            if (sqrt(pow(x,2)+pow(y,2)) < rad){
                pg.beginDraw();
                pg.set(mouseX+x,mouseY+y,color(255,255,255, alpha));
                pg.set(mouseX-x,mouseY+y,color(255,255,255, alpha));
                pg.set(mouseX+x,mouseY-y,color(255,255,255, alpha));
                pg.set(mouseX-x,mouseY-y,color(255,255,255, alpha));
                pg.endDraw();
            }
        }
    }
}


Solution

  • Create a function which draw a single dot to a PGraphics object:

    void DrawPen(PGraphics pg, int cptX, int cptY, int r) {
        pg.beginDraw();
        for (int x = 0; x < r; ++x) {
            for (int y = 0; y < r; ++y) {
              float distance = sqrt(x*x + y*y);
              float alpha = 255-map(distance,0,r,0,255);
              if (distance < r) {
                  pg.set(cptX+x,cptY+y,color(255,255,255, alpha));
                  pg.set(cptX-x,cptY+y,color(255,255,255, alpha));
                  pg.set(cptX+x,cptY-y,color(255,255,255, alpha));
                  pg.set(cptX-x,cptY-y,color(255,255,255, alpha));
              }
            }
        }
        pg.endDraw();
    }
    

    Draw a dot to a separate PGraphics object in setup

    PGraphics pg;
    PGraphics pg_pen;
    int rad = 20;
    
    void setup (){
        size(800, 800, P2D);
    
        pg = createGraphics(800, 800, JAVA2D);
        pg.beginDraw();
        // [...]
        pg.endDraw();
    
        pg_pen = createGraphics(2*rad, 2*rad, JAVA2D);
        DrawPen(pg_pen, rad, rad, rad);
    }
    

    When the mouse is dragged then blend the pg_pen to the common PGraphics object (pg) at the current mouse position:

    void mouseDragged(){
        pg.beginDraw();
        pg.image(pg_pen, mouseX-rad, mouseY-rad);
        pg.endDraw();
    }
    

    For the seek of completeness the draw function:

    void draw () {
        background(0); 
        image(pg,0,0);
    }
    


    [...] and tried to get the color from the white part to draw on the black part.

    Add a color parameter to the DrawPen function and clear the pen PGraphics before drawing to it:

    void DrawPen(PGraphics pg, int cptX, int cptY, int r, color c) {
        pg.beginDraw();
        pg.clear();
        for (int x = 0; x < r; ++x) {
            for (int y = 0; y < r; ++y) {
              float distance = sqrt(x*x + y*y);
              float alpha = 255-map(distance,0,r,0,255);
              if (distance < r) {
                  color pc = color(red(c),green(c),blue(c), alpha);
                  pg.set(cptX+x,cptY+y,pc);
                  pg.set(cptX-x,cptY+y,pc);
                  pg.set(cptX+x,cptY-y,pc);
                  pg.set(cptX-x,cptY-y,pc);
              }
            }
        }
        pg.endDraw();
    }
    

    Get the color in the mouse pressed event call back and change the color of the pen:

    void mousePressed() {
        color c = pg.get(mouseX, mouseY);
        println(c);
    
        DrawPen(pg_pen, rad, rad, rad, c);
    }
    

    Note, the color is get from the pg object and not from the screen. If you want to get the color from the screen then it has to be (without .pg):

    color c = get(mouseX, mouseY);
    

    Further the color is changed any time when any mouse is pressed (pressed not dragged). Possibly you want to change the color when the right mouse button is pressed and paint when the left mouse button is pressed:

    void mousePressed() {
        if (mouseButton == RIGHT) {
            color c = pg.get(mouseX, mouseY);
            println(c);
            DrawPen(pg_pen, rad, rad, rad, c);
        }
    }