11

I have a canvas tag:

<canvas width="321" height="240" id="img_source"></canvas>

I want to add a crop functionality, so I made a resizeable div that can identify the borders of cropped image through dragging the corners of the div using the mouse. It looks like the image below:

enter image description here

enter image description here

I'm currently using "toDataURL()" to convert the data from the canvass to an image that can be displayed by an <img> tag. My question is, How will I convert to an image only part of the canvas that was identified by the resizeable div?

4 Answers4

14

Use the method getImageData with the selected rectangle coordinates. For example:

let imageData = ctx.getImageData(65, 60, 100, 100);

Then create a secondary canvas with the desired sizes and use putImageData to set the pixels:

let canvas1 = document.createElement("canvas");
canvas1.width = 100;
canvas1.height = 100;
let ctx1 = canvas1.getContext("2d");
ctx1.rect(0, 0, 100, 100);
ctx1.fillStyle = 'white';
ctx1.fill();
ctx1.putImageData(imageData, 0, 0);

Finally use toDataURL to update the image:

dstImg.src = canvas1.toDataURL("image/png");

See the full sample I've prepared for you in CodePen

Kostas Minaidis
  • 4,681
  • 3
  • 17
  • 25
Alexander Dayan
  • 2,846
  • 1
  • 17
  • 30
  • 1
    Good answer. One improvement, use the clipping version of `drawImage` to draw the clipped section of the original canvas onto canvas1. This avoids the slower `.getImageData` and `.putImageData` commands. Also, if the clipped image(s) are staying on the page (if the clipped images are not being saved to server or user's computer), you can just add your canvas1 to the DOM and it will visually display like an img element. This would be important if the original image source is cross-domain because then both `toDataURL` and `getImageData` would be prevented for security reasons. – markE Feb 16 '15 at 17:13
  • 1
    Thank you for the comment. I'm absolutely agree with you :) Of course using canvas as a DOM element would be better; I've just tried to stick with the question and not confuse PO with too much of additional information. For the same reason I said nothing about CORS because almost sure the image is from the same domain. – Alexander Dayan Feb 16 '15 at 17:57
  • @AlexanderDayan -Thanks for giving me an idea. Anyways do you have any idea hot to get the parameters of getImageData dynamically? In my case, Im using a resizable div to determine the image borders. Thanks in advance. –  Feb 17 '15 at 01:04
  • @AlyssaGono I'm not sure that I understand the last question. Could you please explain more how you want to use it and what result do you want to achieve? – Alexander Dayan Feb 17 '15 at 08:15
9

Create a new canvas at destination size, draw in the cropped image using drawImage() and insert that canvas into the DOM avoiding using img and data-uri:

var ccanvas = document.createElement("canvas"),
    cctx = ccanvas.getContext("2d");

ccanvas.width = w;
ccanvas.height = h;

// draw with crop arguments
cctx.drawImage(image_src,  x, y, w, h,  0, 0, w, h);
//                         ^^^^^^^^^^ source region
//                                      ^^^^^^^^^^ dest. region

// insert cropped image somewhere in the DOM tree:
document.body.appendChild(ccanvas);

window.onload = function() {

  var img = document.getElementById("image_src");

  document.body.appendChild(region2canvas(img, 150, 60, 220, 200));
}

function region2canvas(img, x, y, w, h) {
  var ccanvas = document.createElement("canvas"),
    cctx = ccanvas.getContext("2d");

  ccanvas.width = w;
  ccanvas.height = h;

  // draw with crop arguments
  cctx.drawImage(img, x, y, w, h, 0, 0, w, h);

  return ccanvas;
}
<img src="http://i.imgur.com/kWI4Cmz.png" id="image_src">
2

The key to cropping from one image is that the context's drawImage method allows us to render a cropped section of the source image to the canvas.

context.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);

img - Source image object
sx - Source x
sy - Source y
sw - Source width
sh - Source height
dx - Destination x
dy - Destination y
dw - Destination width
dh - Destination height

Anuj Sain
  • 163
  • 3
  • 9
-1

Create a new canvas, and copy the selected portion to that new canvas, and then get the toDataURL() from that new canvas.