#### Howdy, Stranger!

We are about to switch to a new forum software. Until then we have removed the registration on this forum.

# pixels() conceptual questions :|

edited September 2016

I had some quick conceptual questions regarding pixels() which I'm having trouble grasping.

So basically I want to get the r, g and b values of my current mouse position. Now, I want this sketch to work irrespective of the window size (which happens to be 600x900 at the moment) - so I'm resizing using the resize function. Do i need to use loc = x + y*width differently now? And a little confused how to translate that to my current mouse position as well. Haven't really used PImage till now in Processing even though I've been using P5 for generative art for a while now. Some nice links would also be welcome, while the snippets in the reference give some ideas it's not really conceptually enlightening for bigger projects.

Tagged:

• If you have a PImage object of width W and height H then it's colour data is stored in a one dimensional integer array of size W*H and the index of the array element corresponding to the position x, y is calculated from idx = x + y * W

If you resize the image to width W1 and height H1 then the array length will be changed to W1*H1 and the formula becomes idx = x + y *W1

Since PImage is an offscreen buffer then your talking about the mouse position does not make a lot of sense. You need to clarify what you mean.

• Think that helps me a little, but not completely. Here's what I'm hoping to achieve, in plain text.

1. Load an image into PImage.
2. Check if the width and height and if they're bigger than my sketch dimensions then resize them to fit, while maintaining the original image ratio. (this is not a problem - but placing the image dead centre once resized is an issue, I think imageMode(CENTER) will help me here.
3. Load the image as the background.
4. If I mouse over the sketch with the image visible, get the value of r, g and b at the current mouse position (and not of the background/other sketch elements). I might be later wanting to get averaged out values around an area of the mouse pointer but that comes in later.

The convolution filter example helps me out a little, but as I said, conceptually I can't grasp how to achieve this in a processing sketch.

• edited September 2016

@GoToLoop, no that doesn't entirely work as I want to keep the canvas (sketch?) size constant.

@quark + @GoToLoop let me post my updated code once I write it. Pretty sure it's not going to work so then you can help me out :)

Much appreciated!

• So you have a sketch of size `width` and `height`. You also have a PImage that you have resized to fit the display while maintaining the aspect ratio. Assume that the of size this image `w` and `h`.

then because it fits the display either one or both of these statements must be true-

``````width == w
height == h
``````

Since the image is centred in the display we can calculate the top-left corner (`tlX` and `tlY`) of the image with these statements

``````tlX = (width - w) / 2;
tlY = (height - h) / 2;
``````

We can calculate the mouse position relative to the top-left corner of the image

``````posX = mouseX - tlX;
posY = mouseY - tlY;
``````

Since the image may not fill the whole screen we need to test posX and posY

``````if(posX >= 0 && posX < w && posY >= 0 && posY < h){
// inside image so calculate index to pixel array
int idx = posX + posY * w;
}
``````
• @quark seems right at first glance! I'll be testing over tonight and tomorrow, please give me some time to get back to you! Thanks!

• edited September 2016

@quark, okay so here I am at the moment. 2 problems, basically,

1. Can't seem to proportionally scale the image if the width and height are different (marked in comments). Math seems to beat me here, cannot come up with a function to change h or w accordingly.

2. And once I run it, the value of idx doesn't seem to change, or change slowly/not in sync with my mouse movement. What am I doing wrong here?

``````PImage image;

int w = 600;
int h = 600;

int t1X = (width - w)/2;
int t1Y = (height - h)/2;

void setup() {
size(600, 900);
background(0);
frameRate(12);
}

void draw() {
background(0);

//Checking image dimensions
if (image.width>image.height) {
//Need to reset h here somehow relative to w?
}
if (image.height>image.width) {
image.resize(0, h);
//Need to reset w here somehow relative to h?
} else {
image.resize(w, h);
}

image(image, (width-w)/2, (height-h)/2);

//Mouse
int posX = mouseX - t1X;
int posY = mouseY - t1Y;

//Calculating the index pixel
if (posX >= 0 && posX < w && posY >= 0 && posY < h) {
// inside image so calculate index to pixel array
int idx = posX + posY * w;
//Printing value of idx to check
println(idx);
}
}
``````
• These lines

``````int t1X = (width - w)/2;
int t1Y = (height - h)/2;
``````

Should be done a bit different. The values of width and height are defined by size within your setup function call. Consider defining those values after the call to setup:

``````int t1X;
int t1Y;

void setup() {
size(600, 900);
t1X = (width - w)/2;
t1Y = (height - h)/2;
background(0);
frameRate(12);
}
``````

This does not answer your question, but more of keeping sane code.

Related to your question, you should try screenX and screenY:

https://processing.org/reference/screenX_.html

I hope this helps,

Kf

• First of all you should not be loading images inside the draw() method because this is executed 60 times a second.

The solution to getting the new image size is to
1) calculate the scale factor needed to just fill the display horizontally
2) calculate the scale factor needed to just fill the display vertically
3) use the smaller of the 2 scale factors calculated.

It doesn't matter whether the image is smaller or larger that the display as this algorithm works with both.

The sketch below demonstrates how to do this. It also gets the pixel colour under the mouse and uses it for the background colour. Change line 1 with your filename.

``````String imgFname = "cartoon-fish-6.jpg";
PImage image;
// These realte to the size and position of the resized image.
int tlX, tlY;
int w, h;
// Is the mouse over the image on the screen.
boolean isOverImage = false;
int pixelColour;

void setup() {
size(800, 480);
cursor(CROSS);
pixelColour = color(0);

resizeImageToFitDisplay(imgFname);
}

// Get and resize the image so that it just fits the display without
// affecting its aspect ratio.
void resizeImageToFitDisplay(String fname) {
println("Image original size = ", image.width, image.height);
float imgW = image.width, imgH = image.height;
float scale = min(width/imgW, height/imgH);
image.resize(round(scale * imgW), round(scale * imgH));
// Get resized image data : width, height and
// top-left corner position
w = image.width;
h = image.height;
tlX = (width - w)/2;
tlY = (height - h)/2;
println("Image new size = ", w, h);
}

void draw() {
background(pixelColour);
// Displaying image as large as possible to fit display
image(image, tlX, tlY);
// If over image show position with a circle
if (isOverImage) {
strokeWeight(3);
stroke(0);
noFill();
ellipse(mouseX, mouseY, 11, 11);
noCursor();
} else {
cursor(CROSS);
}
}

void mouseMoved() {
// Get mouse position relative to top-left corner of image
int posX = mouseX - tlX;
int posY = mouseY - tlY;
//Calculate the index pixel and change the background colour to match.
if (posX >= 0 && posX < w && posY >= 0 && posY < h) {
// inside image so calculate index to pixel array
int idx = posX + posY * w;
//Printing value of idx to check