Skip to content

Commit 6b50b5b

Browse files
authored
Merge pull request #6788 from Papershine/mask-fix
Account for pixel density when masking images
2 parents 54dbffd + a11e2bc commit 6b50b5b

File tree

2 files changed

+70
-12
lines changed

2 files changed

+70
-12
lines changed

src/image/p5.Image.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,7 +1111,8 @@ p5.Image = class {
11111111
*
11121112
* `img.mask()` uses another <a href="#/p5.Image">p5.Image</a> object's
11131113
* alpha channel as the alpha channel for this image. Masks are cumulative
1114-
* and can't be removed once applied.
1114+
* and can't be removed once applied. If the mask has a different
1115+
* pixel density from this image, the mask will be scaled.
11151116
*
11161117
* @method mask
11171118
* @param {p5.Image} srcImage source image.
@@ -1149,21 +1150,22 @@ p5.Image = class {
11491150
}
11501151
const currBlend = this.drawingContext.globalCompositeOperation;
11511152

1152-
let scaleFactor = 1;
1153+
let imgScaleFactor = this._pixelDensity;
1154+
let maskScaleFactor = 1;
11531155
if (p5Image instanceof p5.Renderer) {
1154-
scaleFactor = p5Image._pInst._pixelDensity;
1156+
maskScaleFactor = p5Image._pInst._pixelDensity;
11551157
}
11561158

11571159
const copyArgs = [
11581160
p5Image,
11591161
0,
11601162
0,
1161-
scaleFactor * p5Image.width,
1162-
scaleFactor * p5Image.height,
1163+
maskScaleFactor * p5Image.width,
1164+
maskScaleFactor * p5Image.height,
11631165
0,
11641166
0,
1165-
this.width,
1166-
this.height
1167+
imgScaleFactor * this.width,
1168+
imgScaleFactor * this.height
11671169
];
11681170

11691171
this.drawingContext.globalCompositeOperation = 'destination-in';
@@ -1178,8 +1180,8 @@ p5.Image = class {
11781180
this.gifProperties.frames[i].image = this.drawingContext.getImageData(
11791181
0,
11801182
0,
1181-
this.width,
1182-
this.height
1183+
imgScaleFactor * this.width,
1184+
imgScaleFactor * this.height
11831185
);
11841186
}
11851187
this.drawingContext.putImageData(

test/unit/image/p5.Image.js

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,44 @@ suite('p5.Image', function() {
5151
});
5252

5353
suite('p5.Image.prototype.mask', function() {
54-
test('it should mask the image', function() {
54+
for (const density of [1, 2]) {
55+
test(`it should mask the image at pixel density ${density}`, function() {
56+
let img = myp5.createImage(10, 10);
57+
img.pixelDensity(density);
58+
img.loadPixels();
59+
for (let i = 0; i < img.height; i++) {
60+
for (let j = 0; j < img.width; j++) {
61+
let alpha = i < 5 ? 255 : 0;
62+
img.set(i, j, myp5.color(0, 0, 0, alpha));
63+
}
64+
}
65+
img.updatePixels();
66+
67+
let mask = myp5.createImage(10, 10);
68+
mask.pixelDensity(density);
69+
mask.loadPixels();
70+
for (let i = 0; i < mask.width; i++) {
71+
for (let j = 0; j < mask.height; j++) {
72+
let alpha = j < 5 ? 255 : 0;
73+
mask.set(i, j, myp5.color(0, 0, 0, alpha));
74+
}
75+
}
76+
mask.updatePixels();
77+
78+
img.mask(mask);
79+
img.loadPixels();
80+
for (let i = 0; i < img.width; i++) {
81+
for (let j = 0; j < img.height; j++) {
82+
let alpha = i < 5 && j < 5 ? 255 : 0;
83+
assert.strictEqual(img.get(i, j)[3], alpha);
84+
}
85+
}
86+
});
87+
}
88+
89+
test('it should mask images of different density', function() {
5590
let img = myp5.createImage(10, 10);
91+
img.pixelDensity(1);
5692
img.loadPixels();
5793
for (let i = 0; i < img.height; i++) {
5894
for (let j = 0; j < img.width; j++) {
@@ -62,15 +98,16 @@ suite('p5.Image', function() {
6298
}
6399
img.updatePixels();
64100

65-
let mask = myp5.createImage(10, 10);
101+
let mask = myp5.createImage(20, 20);
66102
mask.loadPixels();
67103
for (let i = 0; i < mask.width; i++) {
68104
for (let j = 0; j < mask.height; j++) {
69-
let alpha = j < 5 ? 255 : 0;
105+
let alpha = j < 10 ? 255 : 0;
70106
mask.set(i, j, myp5.color(0, 0, 0, alpha));
71107
}
72108
}
73109
mask.updatePixels();
110+
mask.pixelDensity(2);
74111

75112
img.mask(mask);
76113
img.loadPixels();
@@ -82,6 +119,25 @@ suite('p5.Image', function() {
82119
}
83120
});
84121

122+
test('it should mask images from createGraphics', function() {
123+
myp5.createCanvas(10,10);
124+
myp5.pixelDensity(2);
125+
let img = myp5.createGraphics(10,10);
126+
img.rect(0,0,10,10);
127+
img.background(0);
128+
let mask = createGraphics(10,10);
129+
mask.rect(0,0,5,5);
130+
let masked = img.get();
131+
masked.mask( mask.get() );
132+
133+
for (let i = 0; i < masked.width; i++) {
134+
for (let j = 0; j < masked.height; j++) {
135+
let alpha = i < 5 && j < 5 ? 255 : 0;
136+
assert.strictEqual(masked.get(i, j)[3], alpha);
137+
}
138+
}
139+
});
140+
85141
test('it should mask the animated gif image', function() {
86142
const imagePath = 'unit/assets/nyan_cat.gif';
87143
return new Promise(function(resolve, reject) {

0 commit comments

Comments
 (0)