3

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();
            }
        }
    }
}

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
kaktus
  • 169
  • 1
  • 1
  • 11

2 Answers2

1

add a "background(0);" before "image(pg,0,0);" in your drawing method, that way you reset the background every time, if you don't do that the program will keep drawing every frame images on top of each other's, which will make the low opacity pixel gain opacity slowly every frame until reaching 100%

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

Edit: After testing your code I noticed there was a problem with the way you were creating those circles, making it super slow to run (every frame you go through that double for loop to draw one circle ) and also gave that weird black edges problem, so here is what I did:

First I used your variable pg and drew one circle on it on the startup, Then I declared another PGraphics 'pg_all', where I drew one pg every call of the mousedrag method, I tested it on multiple backgrounds it seems like working fine, here is the final code, let me know if you didn't understand a part or want to do it differently:

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

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

  pg_all = createGraphics(800, 800, JAVA2D);
  pg_all.beginDraw();
  pg_all.endDraw();

  pg = createGraphics(800, 800, JAVA2D);
  pg.beginDraw();
  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(20+x,20+y,color(255,255,255, alpha));
        pg.set(20-x,20+y,color(255,255,255, alpha));
        pg.set(20+x,20-y,color(255,255,255, alpha));
        pg.set(20-x,20-y,color(255,255,255, alpha));
        pg.endDraw();
      }
    }
  }
  pg.endDraw();
}

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

void mouseDragged(){
  X = mouseX;
  Y = mouseY;

  pg_all.beginDraw();
  pg_all.image(pg,X-rad,Y-rad);
  pg_all.endDraw();
}
  • Thank you! Unfortunately, this helps only partially because what should be transparent simply becomes black. I edited my answer with an example. Do you have any idea how to get around this? – kaktus Oct 03 '19 at 10:41
  • @YOUSFIMohamedWalid The `pg.beginDraw()` and `pg.endDraw()` statement in the inner loop are superfluous and probably slow down the generation of the `PGraphics`. For `pg` a size of 40x40 is sufficient. – Rabbid76 Oct 03 '19 at 20:40
1

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);
    }
}
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • thats what did on my solution, or did I miss something? – YOUSFI Mohamed Walid Oct 03 '19 at 20:21
  • @YOUSFIMohamedWalid I didn't read your answer. I only read the comment which mentioned that it doesn't work as expected. – Rabbid76 Oct 03 '19 at 20:37
  • Thank you, it works so smoothly compared to what I had attempted! Is it possible to get the color of the pixel where the mouse was pressed by ´c = pg.get(cptX,cptY);´ in the DrawPen function? I briefly tried and it didn't work but that might be because I have not quite understood how the scopes of variables work and there might be something wrong here. – kaktus Oct 04 '19 at 17:53
  • @kaktus Do you want to get the color of a point in the final image (`pg`)? e.g get the color of the pixel where the mouse is on in `mouseDragged`: - `void mouseDragged() { color c = pg.get(mouseX, mouseY); println(c); ... }` – Rabbid76 Oct 04 '19 at 18:01
  • Exactly, I would like to get the color from the mouse position the moment it is clicked. But when add the line of code which your proposed, it still paints black only although I drew a white letter on ```pg``` in the setup. – kaktus Oct 04 '19 at 23:16
  • * ... and tried to get the color from the white part to draw on the black part. – kaktus Oct 05 '19 at 06:14
  • 1
    Thank you! I feel like your answer at the same Time serves as an introduction to Programming for me! – kaktus Oct 05 '19 at 11:09