processing / processing/p5.js

[Bug]: p5.Image.prototype.copy and blend do not scale destination coordinates for high pixel density

Open Beginner friendly
#9,169 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
24k
Forks
3.8k
Avg merge
3d 16h
Merged PRs (30d)
25

Description

Most appropriate component

Image (p5.Image, image, etc.)

Describe the bug

When calling copy() or blend() on a p5.Image instance that has pixelDensity > 1 (e.g., Retina / high-DPI displays), the destination coordinates (dx, dy, dw, dh) are not scaled by the destination image's pixel density.

In p5.Image.prototype._copyHelper (lines 920-960), the source coordinates are scaled by s = srcImage.canvas.width / srcImage.width, but the destination parameters are passed directly as raw logical values to dstImage.drawingContext.drawImage().

Because dstImage.drawingContext operates directly on the physical canvas of dstImage without an automated DPI transformation matrix, drawImage() draws into only [dx, dy, dw, dh] physical canvas pixels instead of [d*dx, d*dy, d*dw, d*dh].

For pixelDensity(2), this results in the copied image covering only 1/4th of the intended area in the top-left corner, leaving the remaining 75% of the intended target area completely untouched (transparent / blank). Because p5.Image.prototype.blend() delegates to copy(), it suffers from the identical issue.

Steps to reproduce
let src = createImage(50, 50);
src.loadPixels();
for (let i = 0; i < src.pixels.length; i += 4) {
  src.pixels[i] = 255;     // Red
  src.pixels[i + 3] = 255; // Alpha
}
src.updatePixels();

let dst = createImage(100, 100);
dst.pixelDensity(2); // canvas backing store is 200x200
dst.copy(src, 0, 0, 50, 50, 0, 0, 50, 50);

// Sample a point in the bottom-right quadrant of the logical image
let col = dst.get(35, 35);
console.log(col); // [0, 0, 0, 0] instead of [255, 0, 0, 255]
Expected behavior

The destination coordinates should be scaled by d = dstImage.canvas.width / dstImage.width so that copy() and blend() properly fill the intended logical region on high-DPI images.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in p5.Image.prototype._copyHelper around lines 920-960 and reproduce the issue with the provided high-DPI copy() example. Check the destination values passed to dstImage.drawingContext.drawImage(), then verify both copy() and blend() cover the intended logical region when pixelDensity(2) is used.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
computer-graphics
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.