How to warp an image

hi i try to warp an image use following code but not works. need a help thank you

PImage img; // Declare a variable to hold the image
int widthTop = 102; // Example parameters
int heightTop = 80;
int widthBottom = 20;
int heightBottom = 214;

void setup() {
  size(1155, 870); // Set the size of the canvas
  img = loadImage("target.png"); // Load the image
}

void draw() {
  background(255); // Clear the background
  
  // Draw the original image
  image(img, 0, 0);
  
  // Define the corners of the original image
  float[] srcX = {0, width, width, 0}; // Top-left, top-right, bottom-right, bottom-left
  float[] srcY = {0, 0, height, height};
  
  // Define the corners of the warped shape
  float[] dstX = {widthTop, width - widthTop, width - widthBottom, widthBottom}; // Top-left, top-right, bottom-right, bottom-left
  float[] dstY = {heightTop, heightTop, height - heightBottom, height - heightBottom};
  
  // Apply the warp and get the result image
  PImage warpedImage = warpImage(img, srcX, srcY, dstX, dstY);
  
  // Display the warped image
  image(warpedImage, width, 0);
}

// Function to warp the image
PImage warpImage(PImage img, float[] srcX, float[] srcY, float[] dstX, float[] dstY) {
  PGraphics pg = createGraphics(img.width, img.height);
  pg.beginDraw();
  pg.texture(img);
  
  pg.beginShape();
  for (int i = 0; i < srcX.length; i++) {
    pg.vertex(dstX[i], dstY[i], srcX[i], srcY[i]); // Map texture coordinates to vertices
  }
  pg.endShape(CLOSE);
  
  pg.endDraw();
  
  // Get the result image from PGraphics
  PImage resultImage = pg.get();
  
  return resultImage;
}
1 Like

Hello @doni ,

See reference:
texture() / Reference / Processing.org

Example using the code from reference in a PGraphic:

size(800, 400, P2D);
noStroke();
PImage img = loadImage("http://learningprocessing.com/code/assets/sunflower.jpg");

textureMode(NORMAL); 
beginShape();
texture(img);
vertex(40, 80, 0, 0);
vertex(320, 20, 1, 0);
vertex(380, 360, 1, 1);
vertex(160, 380, 0, 1);
endShape();

PGraphics pg = createGraphics(400, 400, P2D);
pg.beginDraw();

pg.beginShape();
pg.textureMode(NORMAL);
pg.texture(img); 
pg.vertex(40, 80, 0, 0);
pg.vertex(320, 20, 1, 0);
pg.vertex(380, 360, 1, 1);
pg.vertex(160, 380, 0, 1);
pg.endShape(CLOSE);

pg.endDraw();

image(pg, 400, 0);

Try some test code first with working vertices and then use loops and variables later.

:)

this is not good

you want

image(warpedImage, 0, 0);
or
image(warpedImage, width/2, 0);

  • Maybe, texture needs P2D as render, so set this for size and createGraphics commands please
  • this line pg.texture(img); was in the wrong place

The texture() function must be called between beginShape() and endShape() and before any calls to vertex(). This function only works with the P2D and P3D renderers.

Chrisir


Your code


// warp an image

PImage img; // Declare a variable to hold the image

int widthTop = 102; // Example parameters
int heightTop = 80;
int widthBottom = 20;
int heightBottom = 214;

int a = 0;

//------------------------------------------------------------------

void setup() {
  size(1155, 870, P2D); // Set the size of the canvas
  img = loadImage("target.png"); // Load the src image
  img.resize(0, 800);
}

void draw() {
  background(255); // Clear the background

  // Draw the original image
  image(img, 0, 0);

  // Define the corners of the original image
  float[] srcX = {0, width, width, 0}; // Top-left, top-right, bottom-right, bottom-left
  float[] srcY = {0, 0, height, height};

  // Define the corners of the warped shape
  float[] dstX = {widthTop, width - widthTop, width - widthBottom, widthBottom}; // Top-left, top-right, bottom-right, bottom-left
  float[] dstY = {heightTop, heightTop+a, height - heightBottom, height - heightBottom};

  a++;

  // Apply the warp and get the result image
  PImage warpedImage = warpImage(img, srcX, srcY, dstX, dstY);

  // Display the warped image
  image(warpedImage, 0, 0);

  //noLoop();
}

//------------------------------------------------------------------

// Function to warp the image
PImage warpImage(PImage img, float[] srcX, float[] srcY, float[] dstX, float[] dstY) {

  // set with P2D
  PGraphics pg = createGraphics(img.width, img.height, P2D);

  pg.beginDraw();

  pg.beginShape();
  pg.texture(img);
  for (int i = 0; i < srcX.length; i++) {
    pg.vertex(dstX[i], dstY[i], srcX[i], srcY[i]); // Map texture coordinates to vertices
  }
  pg.endShape(CLOSE);

  pg.endDraw();

  // Get the result image from PGraphics
  PImage resultImage = pg.get();

  return resultImage;
}

1 Like

This is displaying it outside of sketch window.

Did you see this error? The console provides important information.
See references for texture() and example I provided.

Is this in the correct place in your code?
See references for texture().

Do you mean width or img.width?
Be sure to use the correct one.

I get this exploring some of the points from above:

Using this:

  float[] dstX = {200, 200, 0,   0}; //Starting at (200,0) and going clock-wise
  float[] dstY = {0,   200, 200, 0};

I get this:

println() and text() are useful for plotting points; I used this to see order of points in array to test code.

Example:

  for (int i = 0; i < srcX.length; i++) 
    {
    textSize(24);
    text(str(i) + ", " + str(srcX[i]) + ", " + str(srcY[i]), srcX[i], srcY[i]);
    }

Keep at it!

:)

hi all. to clear my question
i have source img
Screenshot 2024-05-07 063445-1

and want to warp the area within red dots
Screenshot 2024-05-07 063445-2

and displaying the warped image next to original source

1 Like

When you look at my code you can easily achieve this

2 Likes

Hello @doni ,

I split the image in half and warped it:

size(700, 500, P2D);
noStroke();
PImage img = loadImage("http://learningprocessing.com/code/assets/sunflower.jpg");

textureMode(NORMAL); 
beginShape();
texture(img);
vertex(0, 0, 0, 0);
vertex(320, 0, 1, 0);
vertex(320, 320, 1, 1);
vertex(0, 320, 0, 1);
endShape();

PGraphics pg = createGraphics(400, 400, P2D);
pg.beginDraw();

pg.beginShape();
pg.textureMode(NORMAL);
PImage tex = img.get(0, 0, img.width/2, img.height);
pg.texture(tex); 
pg.vertex(0, 0, 0, 0);
pg.vertex(160, 0+30, 1, 0);      //+30
pg.vertex(160, 320+80, 1, 1);    //+80
pg.vertex(0, 320, 0, 1); 
pg.endShape(CLOSE);

pg.beginShape();
pg.textureMode(NORMAL);
tex = img.get(img.width/2, 0, img.width/2, img.height);
pg.texture(tex); 
pg.vertex(160, 0+30, 0, 0);   //+30
pg.vertex(320, 0, 1, 0);
pg.vertex(320, 320, 1, 1); 
pg.vertex(160, 320+80, 0, 1); //+80
pg.endShape(CLOSE);

pg.endDraw();

image(pg, 350, 0);

You can split the image into a grid and can move each node for more control.

You may have to do some masking later to only show the warped grids.

:)

1 Like

Hello @doni ,

You can do this with shapes directly:

s = createShape();
 
  s.beginShape(TRIANGLE_FAN); 
  int mx = mouseX;
  int my = mouseY;
  
  s.texture(img);
  s.vertex(mx, my, 100, 100);
  s.vertex(50, 50, 50, 50);
  s.vertex(150, 50, 150, 50);
  s.vertex(150, 150, 150, 150);
  s.vertex(50, 150, 50, 150);
  s.vertex(50, 50, 50, 50);
 
  s.endShape(CLOSE);

image

Edit it for whatever shape you want:

image

:)

1 Like

hi all. i come up with following code inspire from @Chrisir, where manually set values of srcPoint

PImage img; // Declare a variable to hold the image
PVector[] srcPoints = new PVector[4]; // Source points
PVector[] dstPoints = new PVector[4]; // Destination points

void setup() {
  size(800, 600,P2D); // Set the size of the canvas
  img = loadImage("target.png"); // Load the image
  
  // Define source points (corners of the original image)
  srcPoints[0] = new PVector(200, 600); //original point we want to warp
  srcPoints[1] = new PVector(img.width- 100, 450);
  srcPoints[2] = new PVector(img.width, img.height- 200);
  srcPoints[3] = new PVector(100, img.height-20);
  //[102, 80, 20, 214] 
  // Define destination points (warped corners)
  dstPoints[0] = new PVector(0, 0);
  dstPoints[1] = new PVector(width, 0);
  dstPoints[2] = new PVector(width, height);
  dstPoints[3] = new PVector(0, height);
}

void draw() {
  background(255); // Clear the background
  
  // Apply perspective transformation and draw the image
  warpImage(img, srcPoints, dstPoints);
}

void warpImage(PImage img, PVector[] srcPoints, PVector[] dstPoints) {
  beginShape();
  texture(img); // Use the image as texture
  
  for (int i = 0; i < srcPoints.length; i++) {
    vertex(dstPoints[i].x, dstPoints[i].y, srcPoints[i].x, srcPoints[i].y); // Map texture coordinates to vertices
  }
  
  endShape(CLOSE);
}

this code i used to track line. its ok when the curve towards right but need inversion pragrammatically when the curve line goes to left side

1 Like