I have an image at a resolution of 512x512
pixels and I need to map a point in this image, selected through a mouse's click, to a point in the same image but at a resolution of 1024x1024
.
I think that the problem is easy but I'm missing something. I tried calculating the mapping with a classical mathematical proportion like:
xp = x*1024/512
But it obviously doubles the value of x
without actually making a map/conversion.
How should I make this mapping?
EDIT
As suggested in the comments, the core of the question is:
How can I make a projection of a point in a 512x512
image to a 1024x1024
image?
CodePudding user response:
Your math checks out: if one image is 512x512 and the other is 1024x1024 the scale factor is 2 (multiplying x, y coordinates by 2 should do the trick.
Alternatively you can use map()
, but in this trivial case it might be more simpler to just use the scale factor directly if you also need to maintain the mapped x,y values as integers.
Here's a basic sketch to demonstrate your mapping (and if you hold the mouse pressed it will use map()
instead, though the results are the same and you'll notice no difference):
PImage img512, img1024;
void setup(){
size(1536, 1024);
strokeWeight(2);
img512 = makeTestImage(512, 512);
img1024 = makeTestImage(1024, 1024);
}
void draw(){
background(0);
image(img512, 0, 0);
image(img1024, 512, 0);
int x = mouseX;
int y = mouseY;
if((x >= 0 && x < 512) &&
(y >= 0 && y < 512)){
// for debugging pruposes compare with map() when mousePressed
int xp, yp;
if(mousePressed){
xp = (int)map(x, 0, 512, 0, 1024);
yp = (int)map(y, 0, 512, 0, 1024);
}else{
xp = x * 1024 / 512;
yp = y * 1024 / 512;
}
drawCrosshair(x, y, color(0), String.format("original [%d,%d]", x, y));
// for visualisation purposes offset x ( since we're drawing the 1024 image at 512, 0 )
drawCrosshair(xp 512, yp, color(255), String.format("mapped [%d,%d]", xp, yp));
}
}
void drawCrosshair(float x, float y, color c, String label){
stroke(c);
// h
line(0, y, width, y);
// v
line(x, 0, x, height);
text(label, x - 100, y);
}
PImage makeTestImage(int w, int h){
pushStyle();
colorMode(HSB, 255, 255, 255);
PImage out = createImage(w, h, RGB);
out.loadPixels();
for(int i = 0 ; i < out.pixels.length; i ){
out.pixels[i] = color(i % 255, 128, 128);
}
out.updatePixels();
popStyle();
return out;
}
Note that the mapped coordinate is displayed coorectly, but it's rendered with an offset of 512 pixels given the second PImage
is rendered to the right of the first.
Here's a modified version that accesses pixels[]
to copy a single pixel from one image to another:
PImage img512, img1024;
void setup(){
size(1536, 1024);
strokeWeight(2);
img512 = makeTestImage(512, 512);
img1024 = makeTestImage(1024, 1024);
}
void draw(){
background(0);
image(img512, 0, 0);
image(img1024, 512, 0);
int x = mouseX;
int y = mouseY;
if((x >= 0 && x < 512) &&
(y >= 0 && y < 512)){
// for debugging pruposes compare with map() when mousePressed
int xp, yp;
if(mousePressed){
xp = (int)map(x, 0, 512, 0, 1024);
yp = (int)map(y, 0, 512, 0, 1024);
// test 1D pixel index
copyPixel(img512, img1024, x, y);
}else{
xp = x * 1024 / 512;
yp = y * 1024 / 512;
}
drawCrosshair(x, y, color(0), String.format("original [%d,%d]", x, y));
// for visualisation purposes offset x ( since we're drawing the 1024 image at 512, 0 )
drawCrosshair(xp 512, yp, color(255), String.format("mapped [%d,%d]", xp, yp));
}
}
void copyPixel(PImage from, PImage to, int xsrc, int ysrc){
xsrc = constrain(xsrc, 0, from.width);
ysrc = constrain(ysrc, 0, from.height);
from.loadPixels();
to.loadPixels();
int fromIndex = xsrc (ysrc * from.width);
float scaleFactor = (float)to.width / from.width;
int xdst = (int)(xsrc * scaleFactor);
int ydst = (int)(ysrc * scaleFactor);
int toIndex = xdst (ydst * to.width);
to.pixels[toIndex] = from.pixels[fromIndex];
to.updatePixels();
}
void drawCrosshair(float x, float y, color c, String label){
stroke(c);
// h
line(0, y, width, y);
// v
line(x, 0, x, height);
text(label, x - 100, y);
}
PImage makeTestImage(int w, int h){
pushStyle();
colorMode(HSB, 255, 255, 255);
PImage out = createImage(w, h, RGB);
out.loadPixels();
for(int i = 0 ; i < out.pixels.length; i ){
out.pixels[i] = color(i % 255, 128, 128);
}
out.updatePixels();
popStyle();
return out;
}
As you drag you'll notice colours around the white crosshair change.
The above is more to demonstrate mapping from 2D x,y indices to an 1D pixels[]
index.
(If you simply want to swap a single pixel using PImage's get()
and set()
functions would be simpler.)
Alternatively you can call resize()
on one image to match the dimensions of the other and have 1:1 mapping between pixels.