Is the pixels offset calculation correct in the p5.js reference?

Hi hi, I’m using the webcam on a high dpi tablet, showing the webcam image and overlaying a few rectangles matching the webcam pixel color below.

I based my code on the reference:

// From https://p5js.org/reference/#/p5/get
let x, y, d; // set these to the coordinates
let off = (y * width + x) * d * 4;
let components = [
  pixels[off],
  pixels[off + 1],
  pixels[off + 2],
  pixels[off + 3]
];
print(components);

but the rectangle colors seem to be sampling a scaled webcam image. With this change

let off = (y * width * d + x) * d * 4;

it works fine. So I wonder where is the bug: somewhere else in my code? Or should the reference be corrected? ps. I haven’t used high dpi before and my code includes two blur shaders and two Graphics, so the issue may be elsewhere.

You’re correct, that sample has a bug.

In order to find the position of a virtual “pixel” (which is really a 2x2 square of pixels on a high DPI screen) you need to find the offset in the following ways for each pixel:

+--+--+
|TL|TR|
+--+--+
|BL|BR|
+--+--+

First off, to find the offset for the two pixels on the top row, you need to multiply y times the density (since for each virtual row there are actually two rows of pixels; this is missing from the example!), then you need to multiply that by the width of each row times the density again (since for each virtual column there are actually two columns of pixels), next you need to add the horizontal offset by adding x * d for the TL pixel and x * d + 1 for the TR pixel, and lastly you need to multiply that entire thing by 4 since there are four bytes per pixel.

If you want to find the values of the bottom row of pixels for each virtual “pixel” on a high DPI display, the math for finding the row offset changes to (y * d + 1) * width * d and the horizontal offset is the same.

Your example code is correctly finding the position of the TL pixel, it’s just arranged differently than my description because you pull the * d term out, whereas in my description it is distributed into the group that adds the vertical and horizontal offsets.

Note: I’ve described all this in terms of a pixel density of 2 but in theory we could have screens with higher pixel densities, so with a pixel density of 3 you would actually have 9 pixels in a 3x3 grid and so on.

3 Likes

Thank you for the thorough explanation :slight_smile: In the end, as I’m only sampling 12 points in the image, I figured out the easiest is to call pixelDensity(1); and then I can remove density from the calculations.

I can still open an issue about the documentation unless someone wants to improve that help page: p5.js/pixels.js at v1.4.0 · processing/p5.js · GitHub

I don’t see any related open issues or pull requests.