-1

I'm trying to crop image to selected red rectangle in canvas, but i'm stuck. Do you have any idea?

I have data about coords rectangle and vertex, and i can calculate it to pixels.

let arr = [
  [2333748.391245694, 6846480.395930305],
  [2343351.375319867, 6838186.909684428],
  [2339754.200562619, 6834021.75996551],
  [2330151.216488446, 6842315.246211386],
  [2333748.391245694, 6846480.395930305]
]

let xmax = 2343351.375319867
let xmin = 2330151.216488446
let ymax = 6846480.395930305
let ymin = 6834021.75996551

const mapWidth = xmax - xmin
const mapHeight = ymax - ymin

let h = 600;
let w = 637.0370370370371;

let A = [((arr[0][0] - xmin) * w) / mapWidth, 0]
let B = [w, ((ymax - arr[1][1]) * w) / mapHeight]
let C = [((xmax - arr[0][0]) * w) / mapWidth, h]
let D = [0, ((arr[1][1] - ymin) * w) / mapHeight]

var canvas = document.getElementById('image');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = () => {
  context.drawImage(imageObj, ...A, ...B, ...C, ...D);
  context.beginPath();
  context.lineWidth = "6";
  context.strokeStyle = "blue";
  context.rect(...A, 5, 5);
  context.rect(...B, 5, 5);
  context.rect(...C, 5, 5);
  context.rect(...D, 5, 5);
  context.stroke();
};
imageObj.src = './test.png';

test image

doğukan
  • 23,073
  • 13
  • 57
  • 69
tyskocz
  • 133
  • 1
  • 8

2 Answers2

1

You can use clip-path, as in this example:

img {
  width: 100px;
  height: 100px;
}

.clipped {
  clip-path: polygon(30px 0, 0 30px, 70px 100px, 100px 70px);
}
1: <img src="https://picsum.photos/id/0/100/100">
2: <img src="https://picsum.photos/id/0/100/100" class="clipped">

Or with an example more like your code:

var canvas = document.getElementById('image');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = () => {
  context.drawImage(imageObj, 0, 0, 100, 100);
};
imageObj.src = 'https://picsum.photos/id/0/100/100';
.clipped {
  clip-path: polygon(30px 0, 0 30px, 70px 100px, 100px 70px);
}
<canvas id="image" class="clipped"></canvas>
Peter B
  • 22,460
  • 5
  • 32
  • 69
1

You have a few options:

  • Rotate the base image so that the clip rect is aligned horizontally and vertically. Then use ctx.rect to define the clip region.

  • Use CSS clipping per @peter-b's answer

  • Clip as a polygonal path

The third option is probably easiest, but it maybe depends on what you intend to do with the image once cropped. i.e. Do you intend to rotate it?

Here is working snippet using your image and similar code:

const originalImg = new Image()
originalImg.onload = () => {

  const srcCanvas = document.getElementById('srcCanvas')
  const srcCtx = srcCanvas.getContext('2d')

  // Calculate rect coordinates.
  // These are hardcoded approximations for this snippet:
  let srcA = [172, 0]
  let srcB = [originalImg.width, originalImg.height / 4 * 3 - 50]
  let srcC = [465, originalImg.height]
  let srcD = [0, originalImg.height / 3]

  srcCtx.moveTo(...srcA)
  srcCtx.beginPath()
  srcCtx.lineTo(...srcB)
  srcCtx.lineTo(...srcC)
  srcCtx.lineTo(...srcD)
  srcCtx.lineTo(...srcA)
  srcCtx.closePath()

  srcCtx.clip()

  srcCtx.drawImage(originalImg, 0, 0)
};
originalImg.src = 'https://i.stack.imgur.com/15BPX.png'
<div style="margin-bottom:5rem">

  <h4>Clipped</h4>
  <canvas id="srcCanvas" width="637" height="600" />

</div>
kaliatech
  • 17,579
  • 5
  • 72
  • 84