How can I crop an area of an image using JavaScript? - javascript

How can I crop an area of an image using JavaScript? As I have read, I must use a canvas to project the image on it.
With the following code I am cutting an area of an image, but the size of the cut area is not the indicated one.
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
// draw cropped image
var sourceX = 0;
var sourceY = 0;
var sourceWidth = 500;
var sourceHeight = 150;
var destWidth = sourceWidth;
var destHeight = sourceHeight;
var destX = canvas.width / 2 - destWidth / 2;
var destY = canvas.height / 2 - destHeight / 2;
context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
<canvas id="myCanvas" style="border:1px solid red"></canvas>
I am trying to represent in this image what I want to do.
my main problem is that the canvas does not adapt to the size of the cropped image and the final height (sourceHeight ) and width (sourceWidth ) They are not the ones I specified
How can i fix it?

The problem
Your source "width" is the same width as the image.
The solution
When using ctx.drawImage with 9 arguments, think of it like a cut and paste.
You want to "cut" the outline in red, and "paste" it to your new - centered - location.
You want to "cut" all the way up to the half way point of the source. So you need to select all the way up to the half way point of the image.
I also suggest maybe changing the variable name from "source" to "crop" (cropX, cropWidth, etc) to better reflect its purpose, as it is not really the width of the "source" anymore.
If you want the image to fill the entire canvas, "paste" it with the canvas' width and height at (0,0)
context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, canvas.width, canvas.height);
The code
...
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
// crop from 0,0, to 250,150
var cropX = 0;
var cropY = 0;
var cropWidth = 250;
var cropHeight = 150;
//resize our canvas to match the size of the cropped area
canvas.style.width = cropWidth;
canvas.style.height = cropHeight;
//fill canvas with cropped image
context.drawImage(imageObj, cropX, cropY, cropWidth, cropHeight, 0, 0, canvas.width, canvas.height);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
...

You'll need to tell the canvas the size of the image you're trying to display to ensure the canvas has the desiredWith size;
However, the size of your example image is 438 × 300, which makes it hard to crop to 500px.
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.src = 'https://placehold.it/700x700';
imageObj.onload = function() {
const desiredWidth = 500;
const desiredHeight = 150;
canvas.width = desiredWidth;
canvas.height = desiredHeight;
context.drawImage(imageObj, 0, 0, desiredWidth, desiredHeight, 0, 0, desiredWidth, desiredHeight);
console.log(canvas.width, canvas.height);
};
<canvas id="myCanvas" style="border:1px solid red"></canvas>

Related

drawing a cropped version of an image onto a canvas

I have the following html file which draws an image on the canvas.
<canvas id="canvas"width="800"height="800"></canvas>
<script>
var canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')
let img = new Image()
img.src = 'https://clipartspub.com/images/circle-clipart-blue-1.jpg'
img.onload = function(){
ctx.drawImage(img,300,300,300,300)
}
</script>
It works fine, however I would like to instead draw a cropped version of this image, for example, the bottom right quarter of the image. Is this possible?
You have to use the below implementation of drawImage to achieve that
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
Check the docs here
var canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let img = new Image();
img.src = "https://clipartspub.com/images/circle-clipart-blue-1.jpg";
img.onload = function () {
const width = img.width;
const height = img.height;
ctx.drawImage(
img, // Source image
width / 2, // Start at this x of image
height / 2, // Start at this y of image
width / 2, // Till this width of image
height / 2, // Till this height of image
0, // Start at this x of canvas
0, // Start at this y of image
300, // Till this width of canvas
300 // // Till this height of canvas
);
};
<canvas id="canvas"width="800"height="800"></canvas>
You can also use canvas.width and canvas.height in the canvas values used above for a better scaled result.

JavaScript - Take Center of Image

I got an image, it could be of every size but I need to take the center area of 86x86. Also I've to do that in javascript when a new image is loaded, replacing the old one.
At the end of the code I need to have my 's src updated with the new image.
function loadedImage(elem,gCount){
var crop = { //just messing with numbers
top : 10,
left : 10,
right : 20,
bottom : 20,
};
var file = elem.files[0]; //I take the loaded image
var img = document.getElementsByName('imag')[gCount]; //I take the interessed <img>
var canvas = document.createElement("canvas"); //create canvas
canvas.width = crop.right - crop.left; //set dimensions
canvas.height = crop.bottom - crop.top;
var ctx = canvas.getContext("2d"); // so we can draw
var image = new Image();
image.setAttribute('crossOrigin', 'anonymous');
image.width = img.width;
image.height = img.height;
image.src = window.URL.createObjectURL(file);
ctx.drawImage(image, -crop.left, -crop.top);
image.src = canvas.toDataURL("image/png");
img.src = image.src;
}
No image is shown
Use a load event listener to wait for your image to load. Once it's ready, you can then start drawing.
To draw the center part of your image, the source x-coordinate should be half the width of your image, minus half the width of the crop. (The source y-coordinate can be calculated in a similar way.)
var input = document.getElementsByName('input')[0];
input.addEventListener('change', function (e) {
var file = e.target.files[0];
drawCroppedImage(file, 86, 86);
});
function drawCroppedImage(file, w, h) {
var canvas = document.getElementById('canvas');
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');
var image = new Image();
image.addEventListener('load', function (e) {
var sx = (image.width / 2) - (w / 2), // Source X
sy = (image.height / 2) - (h / 2), // Source Y
dx = 0, // Destination X
dy = 0; // Destination Y
ctx.drawImage(image, sx, sy, w, h, dx, dy, w, h);
});
image.src = URL.createObjectURL(file);
}
<input type="file" name="input">
<br><br>
<canvas id="canvas" width="86" height="86"></canvas>

image doesn't cover the full area of the canvas

I want to stretch the image to the size of the canvas. But the image takes its original size instead of taking the canvas size.Any help is appreciated.
var canvas = document.createElement("canvas");
canvas.setAttribute("width", "100px");
canvas.setAttribute("height", "180px");
//alert(canvas.height);
myImg.width = canvas.width;
myImg.height = canvas.height;
var ctx44 = canvas.getContext("2d");
ctx44.drawImage(myImg, 0, 0, canvas.width, canvas.height,0,0,canvas.width,canvas.height);
// image gets displayed in its original size instead of taking the size of the canvas
The 2nd ~ 4th parameters of drawImage represent the source rectangle. That is, a rectangle from where your image will be cropped, before being applied to the destination, resized by the rectangle defined in the following rectangle.
Here is a simple demo:
var img = new Image();
img.onload = e => {
const source = document.getElementById('source');
const destination = document.getElementById('destination');
const imgWIDTH = source.width = destination.width = 300;
const imgHEIGHT = source.height = destination.height = 300;
const src_x = source.getContext('2d');
const dest_x = destination.getContext('2d');
src_x.drawImage(img, 0, 0, imgWIDTH, imgHEIGHT); // simple copy to source canvas
const source_rect = {
x: 20,
y: 20,
w: 150,
h: 150
};
const dest_rect = {
x: 0,
y: 0,
w: 300,
h: 300
};
destination.getContext('2d')
.drawImage(source,
source_rect.x,
source_rect.y,
source_rect.w,
source_rect.h,
dest_rect.x,
dest_rect.y,
dest_rect.w,
dest_rect.h
);
// show the source rectangle on the 'source' canvas
src_x.strokeRect(
source_rect.x,
source_rect.y,
source_rect.w,
source_rect.h,
);
};
img.src = "https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"
<canvas id="source"></canvas>
<canvas id="destination"></canvas>
So in your case, if your original image is smaller than the 100x180px of your canvas, you are defining the source rectangle to be outside of the source image, this will then result in no apparent changes from the original image.
What you probably wanted was
ctx44.drawImage(myImg, 0, 0, myImg.naturalWidth, myImg.naturalHeight,0,0,canvas.width,canvas.height);
which is the same as the 5 param version
ctx44.drawImage(myImg,0,0,canvas.width,canvas.height);
var myImg = new Image();
myImg.onload = function(e) {
var canvas = document.createElement("canvas");
canvas.width = 100;
canvas.height = 180;
var ctx44 = canvas.getContext("2d");
ctx44.drawImage(myImg, 0,0,canvas.width,canvas.height);
document.body.appendChild(myImg);
document.body.appendChild(canvas);
};
myImg.src = "https://i.stack.imgur.com/LbM0l.jpg?s=32&g=1"

canvas shadow with globalCompositeOperation[ destination-out ]

..Hi there, After a long gap,i again got the opportunity to work with JavaScript and canvas.
here i am trying to draw, transparent image using canvas [ globalCompositeOperation ] helps me alot,
i got success on draw image[img1] and removed a overlapped part of image[ img2 ].
search alot but failed : Wanna try to drop shadow on output of canvas,look like below,
Please check out and give me your valuable suggestion OR solution.
$('.bg').one("load", function() {
var canvas = document.getElementById('canva'),
context = canvas.getContext('2d'),
img1 = $('.bg')[0],
img2 = $('.bgover')[0];
context.drawImage(img1, 0, 0);
context.globalCompositeOperation = 'destination-out';
context.beginPath();
context.drawImage(img2, 10, 10);
context.closePath();
//drop shadow -> Doesn't work
context.shadowBlur = 5;
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowColor = "black";
});
body {
background: #E7FF00
}
.bg {
background: url() center;
width: 300px;
height: 300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<img class='bg' src="http://www.qdtricks.org/wp-content/uploads/2015/02/hd-wallpapers-for-mobile.jpg" style='display:none'>
<img class='bgover' src="http://spotremoval.coit.com/sites/spotremoval.coit.com/files/styles/stain_sidebar/public/Feces%20Stain%20Removal%20-%20SPOT%20REMOVAL%20GUIDE.png?itok=j6f96IHQ" style='display:none'>
<canvas id="canva" width="400" height="400" style="position:absolute;left:0;top:0"></canvas>
Inner shadow with destination-out & source-atop
This is my solution. Load the image then create a copy with a 2D context so it can be drawn to. Then create a second image a little bigger to accommodate the shadow, offsets, and blur. Make it an inverted mask with comp destination-out. Set the original image's shadow settings. Then draw the mask image on top with comp source-atop
Now the image has the shadow and can be draw where you want it.
The function innerShadow(image,col,offX,offY,blur) does the work. Code is commented so enjoy :)
/** CanvasCtx.js begin **/
var canvas = document.getElementById("canV");
var ctx = canvas.getContext("2d");
/** CanvasCtx.js end **/
// copies an image adding the 2d context
function copyImage(img){
var image = document.createElement("canvas");
image.width = img.width;
image.height = img.height;
image.ctx = image.getContext("2d");
image.ctx.drawImage(img,0,0);
return image;
}
// creates a blank image with 2d context
var createImage = function(w,h){
var image = document.createElement("canvas");
image.width = w;
image.height =h;
image.ctx = image.getContext("2d");
return image;
}
// load an image from URL. Create a editable copy and then
// call the function ready
var loadImage = function(url,ready){
function onload(){
this.removeEventListener("load",onload);
image = copyImage(this);
ready(image);
}
var image = new Image();
image.src = url;
image.addEventListener("load",onload);
}
function innerShadow(image,shadowCol,offX,offY,blur){
var mx, my, img1;
// create a mask image, with pixel alpha the invers of original
// Needs to be bigger so that the shadow is consistant at edges
img1 = createImage(image.width+Math.abs(offX)+blur,image.height+Math.abs(offY)+blur);
// set the shadow colur to requiered but only for alising the edge
img1.ctx.fillStyle = shadowCol;
img1.ctx.fillRect(0,0,img1.width,img1.height); // fill the mask
img1.ctx.globalCompositeOperation = "destination-out"; // remove dest pixels
mx = img1.width/2- image.width/2; // recalculate offsets
my = img1.height/2- image.height/2;
// draw it 3 times to remove the slight alpha edge bleading
img1.ctx.drawImage(image,mx,my); // cut out the images shape from mask
img1.ctx.drawImage(image,mx,my); // cut out the images shape from mask
img1.ctx.drawImage(image,mx,my); // cut out the images shape from mask
// set up shadow settings
image.ctx.shadowColor = shadowCol;
image.ctx.shadowOffsetX = offX;
image.ctx.shadowOffsetY = offY;
image.ctx.shadowBlur = blur;
// draw the mask with the shadow on original image
image.ctx.globalCompositeOperation = "source-atop"; // only visible pixels
image.ctx.drawImage(img1,-mx,-my); // draw the shadow
}
// clear the canvas
ctx.clearRect(0,0,canvas.width,canvas.height)
// load and add shadow.
var imageWithInnerShadow;
var shadowOffX = 10;
var shadowOffY = 10;
var shadowBlur = 10;
var shadowCol = "Black";
// load the image
loadImage("http://i.stack.imgur.com/Jafta.png",function(img){
// add the shadow
innerShadow(img,shadowCol,shadowOffX,shadowOffY,shadowBlur);
ctx.drawImage(img,20,20); // show that it worked
imageWithInnerShadow = img; // hold the image for use
})
.canC { width:500px; height:500px;}
<canvas class="canC" id="canV" width=500 height=500></canvas>
Here's a dropShadow function that has the desired effect.
$('.bg').one("load", function() {
var canvas = document.getElementById('canva'),
context = canvas.getContext('2d'),
img1 = $('.bg')[0],
img2 = $('.bgover')[0];
context.drawImage(img1, 0, 0);
context.save();
context.globalCompositeOperation = 'destination-out';
context.drawImage(img2, 10, 10);
context.restore();
dropShadow(canvas, "red", 5, 2, 2);
});
// This function draws the image to left of canvas
// leaving only the shadow then draws the shadow in the
// empty space.
function dropShadow(can, color, blur, offsetX, offsetY) {
var s_can = document.createElement('canvas');
var s_ctx = s_can.getContext('2d');
var ctx = can.getContext('2d');
var w = can.width;
var h = can.height;
s_can.width = w;
s_can.height = h;
s_ctx.shadowBlur = blur;
s_ctx.shadowColor = color;
s_ctx.shadowOffsetX = w;
s_ctx.shadowOffsetY = 0;
s_ctx.drawImage(can, 0, 0, w, h,-w,0,w,h);
ctx.save();
ctx.globalCompositeOperation = 'destination-over';
ctx.drawImage(s_can, offsetX, offsetY);
ctx.restore();
}
body {
background: #E7FF00
}
.bg {
background: url() center;
width: 300px;
height: 300px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<img class='bg' src="http://www.qdtricks.org/wp-content/uploads/2015/02/hd-wallpapers-for-mobile.jpg" style='display:none'>
<img class='bgover' src="http://spotremoval.coit.com/sites/spotremoval.coit.com/files/styles/stain_sidebar/public/Feces%20Stain%20Removal%20-%20SPOT%20REMOVAL%20GUIDE.png?itok=j6f96IHQ" style='display:none'>
<canvas id="canva" width="400" height="400" style="position:absolute;left:0;top:0"></canvas>

Create Canvas element with image and append to parent

I need to create Canvas element with image and need to append to parent for this i have done this
<html>
<head>
<script>
window.onload = function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext("2d");
canvas.id = "canvas_id";
canvas.setAttribute("class" ,"canvas");
canvas.height = "400";
canvas.width = "800";
var image = new Image();
image.src = "http://localhost/tile.png";
image.onload = function(){
context.drawImage(image, canvas.width, canvas.height);
}
document.body.appendChild(canvas);
}
</script>
</head>
<body>
</body>
</html>
it give blank canvas
can somebody guide me ?
You are using drawImage() the wrong way. Instead of drawing the image at (0,0) you are drawing it just outside the canvas area as width and height is where position normally goes.
The valid signatures are:
context.drawImage(image, dx, dy)
context.drawImage(image, dx, dy, dw, dh)
context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
Where dx and dy are delta position (relative to origin, normally (0,0) when untranslated). Without width and height specified drawImage() will by default use the image's natural width and height.
The second version allows to override the default size, and the third will allow you to draw from one region to another.
Source
Corrected example:
window.onload = function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext("2d");
canvas.id = "canvas_id";
canvas.className = "canvas"; // should be className
canvas.height = 400; // should be numbers
canvas.width = 800;
var image = new Image();
image.onload = function() {
// or set canvas size = image, here: (this = currently loaded image)
// canvas.width = this.width;
// canvas.height = this.height;
context.drawImage(this, 0, 0); // draw at (0,0), size = image size
// or, if you want to fill the canvas independent on image size:
// context.drawImage(this, 0, 0, canvas.width, canvas.height);
}
// set src last (recommend to use relative paths where possible)
image.src = "http://lorempixel.com/output/fashion-q-c-800-400-7.jpg";
document.body.appendChild(canvas);
}
That being said, if you only need the image appended there is no need to go via canvas. Just add the image to DOM directly (I assume this is not you want, but just in case..):
var image = new Image();
image.src = "tile.png";
document.body.appendChild(image);
This is my take on it... You need to indicate the coordinates where you want to start drawing (i.e. 0, 0) and - optionally - you can specify how big (wide, height) the canvas is to be.
In my case, I make the canvas to be as big as the image (instead of an arbitrary 400x800) you may need to update that your suit your requirements.
I added some css to show how big the canvas is in relation to the image. You can update/remove that as well depending on your needs.
UPDATED
It uses an hidden image as the source.
I hope this will work for you.
window.onload = function() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext("2d");
canvas.id = 'canvas_id';
canvas.setAttribute("class", "canvas");
var image = new Image();
image.src = 'http://placekitten.com/g/200/300';
canvas.width = image.width;
canvas.height = image.height;
ctx.drawImage(image, 0, 0, image.width, image.height);
document.body.appendChild(canvas);
}
.canvas {
border: solid red 1px;
}
<html>
<body>
</body>
</html>

Categories