Full opacity of pixel alpha on image border


#1

I am seeing full opacity on the border of my image when painting pixels … why is this?

My source image has 0 opacity around the edges. If you uncomment lines 21 and 27, and comment out line 52 you will see.

In the provided example you will see when painting, the top and left borders will show up, I set my graphics canvas to cut off the right and bottom edge of the canvas by 13 pixels.

https://editor.p5js.org/slow_izzm/sketches/S1h7b2SCm


#2

The image appears transparent because when you create the graphics, you filled the circle with opacity: pg.fill(col[0], col[1], col[2], col[3]);. When using RGB values fill(); only needs 3 values, and the forth one is to change the opacity.


#3

Thanks, but that’s not my question, what I am asking is why the border of an alpha image is being drawn as if it was opaque where there is no opacity.


#4

Sorry, I misread your question.

I’ve tested it on my laptop, and the image renders with the correct opacity. Try putting

fill(255,0,0);
rect(150,150,100,100);

directly above image(img_paint,0,0); do you see the red rectangle behind the image?


#5

Maybe I’m not being clear … here is a code without hiding the edges. Paint from the middle all the way to the edge of the canvas and you will see what I am talking about.

let img_paint;
let brush = [];
let pg;

function preload() {
	img_paint = loadImage("burner.png");
}

function setup() {
	createCanvas(window.innerWidth - 4, window.innerHeight - 4);
	background(51);
	for (let i = 0; i < 33; i++) {
		let b = new Brush();
		brush.push(b);
	}
	img_paint.resize(img_paint.width>>1, img_paint.height>>1);
	pg = createGraphics(img_paint.width, img_paint.height);
}

function draw() {
	//clear();
	if (mouseIsPressed) {
		for (let i = 0; i < brush.length; i++) {
			brush[i].render();
		}
	}
	//image(img_paint,0,0);
}

class Brush {
	constructor() {
		this.pos = createVector();
	}

	update() {
		let d = dist(mouseX, mouseY, this.pos.x, this.pos.y);
		this.pos.x = mouseX + (random(-13, 13));
		this.pos.y = mouseY + (random(-13, 13));

		return this;
	}

	display() {
		pg.clear();
		pg.noStroke();
		pg.imageMode(CENTER);
		let px = floor(this.pos.x);
		let py = floor(this.pos.y);
		let col = img_paint.get(px, py);
		pg.fill(col[0], col[1], col[2], col[3]);
		pg.ellipse(this.pos.x, this.pos.y, 13, 13);
		image(pg, 0, 0);

		return this;
	}

	render() {
		return this.update().display();
	}
}

Also here is a screenshot of the issue …


As you can see, the edges of the images are acting as if they have some opacity. If you are to uncomment clear(); and image(img_paint,0,0); … you will see my source image has no opacity near the edges.


#6

This issue isn’t the image file.

  1. Where is the brush color coming from? The image pixels.
  2. What happens when you move the mouse off the image? The image pixels aren’t assigning to the brush anymore – the brush turns black.
  3. How much of this black-brush can we see? Half the brush radius – 13 pixels. Hence a ~6 px line when you rub the mouse around past the edges of your images.

There are many ways to deal with this. Here is just one – only draw where you want to.

	display() {
		pg.clear();
		pg.noStroke();
		pg.imageMode(CENTER);
		let px = floor(this.pos.x);
		let py = floor(this.pos.y);
		let brush_radius = 13;
		let img_margin = brush_radius/2 + 1;
		if(px > 0 + img_margin &&
		   px < img_paint.width - img_margin &&
		   py > 0 + img_margin &&
		   py < img_paint.height - img_margin)
		{
			let col = img_paint.get(px, py);
  		pg.fill(col[0], col[1], col[2], col[3]);
	  	pg.ellipse(this.pos.x, this.pos.y,
		           brush_radius, brush_radius);
		}
		image(pg, 0, 0);
		return this;
	}

Another approach would be to change your method of coloring the brush.


#7

Ahh … that makes perfect sense. Thank you for your help!