I want to crop the image based on specific area, below example how to crop image so it bees only the things (pixel, data...) inside blue line, and delete things (pixel, data...) outside the box?
Below code is what I tried, after canvas draw new image, not correct area what I want, do I miss something, how to fix it ?
Any suggestion will be appreciated. Please don't provide plugin as an answer, and css crop is not what I'm looking for.
UPDATE
/
I update the fiddle and below code, the image naturalWidth is different with css width, so I need to convert the crop x,y,width,height (sx,sy,sw,sh) to fit the natural image size and crop the image.
the result it seems work to crop the correct area but image is not correct scale .. I don't get why
var crop = function() {
var transformMediaBlock = $('.mediaBlock');
var transformCropInner = $('.transformCropInner');
var transformCropLimit = $('.transformCropLimit');
var canvasContainer = $('.canvasContainer')
var canvasWidth = $(transformCropLimit).width();
var canvasHeight = $(transformCropLimit).height();
var canvas = $('<canvas/>',{'class':''}).width(canvasWidth).height(canvasHeight);
canvas = canvas.appendTo($(canvasContainer));
var ctx = canvas[0].getContext('2d');
var limitLeft = transformCropLimit.offset().left;
var limitTop = transformCropLimit.offset().top;
var limitRight = limitLeft + transformCropLimit.width();
var limitBottom = limitTop + transformCropLimit.height();
console.log('limitLeft:'+limitLeft)
console.log('limitRight:'+limitRight)
var imageLeft = transformMediaBlock.find('img').offset().left;
var imageTop = transformMediaBlock.find('img').offset().top;
var imageRight = imageLeft + transformMediaBlock.find('img').width();
var imageBottom = imageTop + transformMediaBlock.find('img').height();
console.log('imageLeft:'+imageLeft)
console.log('imageRight:'+imageRight)
if (limitLeft <= imageLeft) {
var sx = 0;
} else {
var sx = limitLeft - imageLeft;
}
console.log('sx:'+sx)
if (limitTop <= imageTop) {
var sy = 0;
} else {
var sy = limitTop - imageTop;
}
console.log('sy:'+sy)
if (limitLeft <= imageLeft) {
var l = imageLeft;
} else {
var l = limitLeft;
}
if (limitRight <= imageRight) {
var r = limitRight;
} else {
var r = imageRight;
}
var sw = r - l;
console.log('sw:'+sw)
if (limitTop <= imageTop) {
var t = imageTop;
} else {
var t = limitTop;
}
if (limitBottom <= imageBottom) {
var b = limitBottom;
} else {
var b = imageBottom;
}
var sh = b - t;
console.log('sh:'+sh);
var dx = 0;
var dy = 0;
var dw = sw;
var dh = sh;
console.log('naturalWidth:'+transformMediaBlock.find('img')[0].naturalWidth);
console.log('naturalHeight:'+transformMediaBlock.find('img')[0].naturalHeight);
console.log('cssWidth:'+transformMediaBlock.find('img').width());
console.log('cssHeight:'+transformMediaBlock.find('img').height());
var ratio = (transformMediaBlock.find('img')[0].naturalWidth / transformMediaBlock.find('img').width());
console.log('ratio:'+ratio);
sx = sx*ratio;
sy = sy*ratio;
sw = sw*ratio;
sh = sh*ratio;
console.log('sx*ratio:'+sx)
console.log('sy*ratio:'+sy)
console.log('sw*ratio:'+sw)
console.log('sh*ratio:'+sh)
ctx.drawImage(transformMediaBlock.find('img')[0],
sx, sy, sw, sh,
dx, dy, dw, dh
);
};
$('#container').on('click', '.action.crop', function (e) {
var transformMediaBlock = $('.mediaBlock');
transformMediaBlock.find('img').on('load', function() {
crop();
}).each(function() {
if(thisplete) $(this).load();
});
});
.mediaBlock {
position: relative;
display: block;
overflow: hidden;
}
.mediaBlock img {
max-width: 100%;
}
.transformCropLimit {
position: relative;
top: 20px;
left: 20px;
width: 200px;
height: 200px;
border: 1px solid blue;
}
.transformCropInner {
width: 300px;
cursor: pointer;
position: relative;
top: 10px;
left: 10px;
}
<script src=".1.1/jquery.min.js"></script>
<div id="container">
<div class="content main">
<div class="transformCropLimit">
<div class="transformCropInner">
<div class="mediaBlock">
<img src=".jpg">
</div>
</div>
</div>
<div class="action crop">Crop</div>
</div>
<div class="canvasContainer"></div>
</div>
I want to crop the image based on specific area, below example how to crop image so it bees only the things (pixel, data...) inside blue line, and delete things (pixel, data...) outside the box?
Below code is what I tried, after canvas draw new image, not correct area what I want, do I miss something, how to fix it ?
Any suggestion will be appreciated. Please don't provide plugin as an answer, and css crop is not what I'm looking for.
UPDATE
https://jsfiddle/xqpdtq76/
I update the fiddle and below code, the image naturalWidth is different with css width, so I need to convert the crop x,y,width,height (sx,sy,sw,sh) to fit the natural image size and crop the image.
the result it seems work to crop the correct area but image is not correct scale .. I don't get why
var crop = function() {
var transformMediaBlock = $('.mediaBlock');
var transformCropInner = $('.transformCropInner');
var transformCropLimit = $('.transformCropLimit');
var canvasContainer = $('.canvasContainer')
var canvasWidth = $(transformCropLimit).width();
var canvasHeight = $(transformCropLimit).height();
var canvas = $('<canvas/>',{'class':''}).width(canvasWidth).height(canvasHeight);
canvas = canvas.appendTo($(canvasContainer));
var ctx = canvas[0].getContext('2d');
var limitLeft = transformCropLimit.offset().left;
var limitTop = transformCropLimit.offset().top;
var limitRight = limitLeft + transformCropLimit.width();
var limitBottom = limitTop + transformCropLimit.height();
console.log('limitLeft:'+limitLeft)
console.log('limitRight:'+limitRight)
var imageLeft = transformMediaBlock.find('img').offset().left;
var imageTop = transformMediaBlock.find('img').offset().top;
var imageRight = imageLeft + transformMediaBlock.find('img').width();
var imageBottom = imageTop + transformMediaBlock.find('img').height();
console.log('imageLeft:'+imageLeft)
console.log('imageRight:'+imageRight)
if (limitLeft <= imageLeft) {
var sx = 0;
} else {
var sx = limitLeft - imageLeft;
}
console.log('sx:'+sx)
if (limitTop <= imageTop) {
var sy = 0;
} else {
var sy = limitTop - imageTop;
}
console.log('sy:'+sy)
if (limitLeft <= imageLeft) {
var l = imageLeft;
} else {
var l = limitLeft;
}
if (limitRight <= imageRight) {
var r = limitRight;
} else {
var r = imageRight;
}
var sw = r - l;
console.log('sw:'+sw)
if (limitTop <= imageTop) {
var t = imageTop;
} else {
var t = limitTop;
}
if (limitBottom <= imageBottom) {
var b = limitBottom;
} else {
var b = imageBottom;
}
var sh = b - t;
console.log('sh:'+sh);
var dx = 0;
var dy = 0;
var dw = sw;
var dh = sh;
console.log('naturalWidth:'+transformMediaBlock.find('img')[0].naturalWidth);
console.log('naturalHeight:'+transformMediaBlock.find('img')[0].naturalHeight);
console.log('cssWidth:'+transformMediaBlock.find('img').width());
console.log('cssHeight:'+transformMediaBlock.find('img').height());
var ratio = (transformMediaBlock.find('img')[0].naturalWidth / transformMediaBlock.find('img').width());
console.log('ratio:'+ratio);
sx = sx*ratio;
sy = sy*ratio;
sw = sw*ratio;
sh = sh*ratio;
console.log('sx*ratio:'+sx)
console.log('sy*ratio:'+sy)
console.log('sw*ratio:'+sw)
console.log('sh*ratio:'+sh)
ctx.drawImage(transformMediaBlock.find('img')[0],
sx, sy, sw, sh,
dx, dy, dw, dh
);
};
$('#container').on('click', '.action.crop', function (e) {
var transformMediaBlock = $('.mediaBlock');
transformMediaBlock.find('img').on('load', function() {
crop();
}).each(function() {
if(this.plete) $(this).load();
});
});
.mediaBlock {
position: relative;
display: block;
overflow: hidden;
}
.mediaBlock img {
max-width: 100%;
}
.transformCropLimit {
position: relative;
top: 20px;
left: 20px;
width: 200px;
height: 200px;
border: 1px solid blue;
}
.transformCropInner {
width: 300px;
cursor: pointer;
position: relative;
top: 10px;
left: 10px;
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="container">
<div class="content main">
<div class="transformCropLimit">
<div class="transformCropInner">
<div class="mediaBlock">
<img src="http://i.imgur./EdQs9jA.jpg">
</div>
</div>
</div>
<div class="action crop">Crop</div>
</div>
<div class="canvasContainer"></div>
</div>
Share
Improve this question
edited Oct 11, 2016 at 16:21
user1775888
asked Oct 11, 2016 at 0:33
user1775888user1775888
3,31314 gold badges49 silver badges67 bronze badges
8
- Have you tried it with an image that's 300px wide? It looks in your fiddle like you're using a much larger image that is being resized via css – winterfruit Commented Oct 11, 2016 at 4:39
- Testing using this placehold.it image, it seems to be working, but your canvas is outputting the wrong size – winterfruit Commented Oct 11, 2016 at 4:44
- thanks for reply , I figure out it seems crop area base the original image size, not css style. so I think I have to convert the sw sh to fit original image size – user1775888 Commented Oct 11, 2016 at 4:55
- I can't get how to covert sx sy... tried to find a way drawimage scale same size as css, then crop it – user1775888 Commented Oct 11, 2016 at 5:06
- I'm not 100% sure of this, but I think that pulling an image from imgur and cropping it in canvas won't allow you to extract the data because of CORS restrictions. I know this is true for video, and I assume the canvas is tainted by an outside source as well if it is an image... – somethinghere Commented Oct 11, 2016 at 12:07
1 Answer
Reset to default 7To crop image
Create a canvas the size of the crop area, then draw the image on that canvas. For example if you have a 500 by 400 image and you want to crop it to the top left 100,100, and bottom right 200,200
var crop = {
top : 100,
left : 100,
right : 200,
bottom : 200,
}
Create a canvas the correct width and height
var canvas = document.createElement("canvas");
canvas.width = crop.right - crop.left;
canvas.height = crop.bottom - crop.top;
Then draw the image onto that canvas so that the top left 100,100 is at the canvas origin 0,0
var ctx = canvas.getContext("2d"); // so we can draw
ctx.drawImage(image, -crop.left, -crop.top);
And that is how you create a cropped image (Note canvas is a HTMLImageElement)
If you have scaled images.
var w = image.width;
var h = image.height;
and you draw it on a canvas at a scale
var myScale = 0.5; // half scale
and you want to crop it via the scaled canvas coordinates
var crop = { // the canvas coordinate system
top : 100,
left : 100,
right : 200,
bottom : 200,
}
Your image scaled is in the canvas coordinate system with top left at (0,0) and its width and height are w * scale
, h * scale
To crop it just scale the image when you draw it.
Create the canvas.
var canvas = document.createElement("canvas");
canvas.width = crop.right - crop.left;
canvas.height = crop.bottom - crop.top;
draw the image scaled and offset in the image coordinates
var ctx = canvas.getContext("2d"); // so we can draw
ctx.scale(scale,scale);
ctx.drawImage(image, -crop.left / scale, -crop.top / scale); // convert offset to
// image coordinate system