Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to use JCrop to crop an area larger than the actual image?

From what I can tell, JCrop will not let me set things up so the user can crop outside the actual image and include surrounding whitespace. Is there a way to do that?

To help explain what I mean, say we are restricting our crop to a 16:9 ratio. That works fine for an image with a naturally wide subject:

enter image description here

But sometimes the source image that a user wants to use does not comfortably accommodate the desired ratio:

enter image description here

Instead, we'd like to allow them to include space outside the image by making the crop area larger than the image itself:

enter image description here

I've been messing around with JCrop and looking through the manual and Google for a while and it doesn't look like this is possible (without modifying JCrop). Am I wrong? If so, how do you do it?

FWIW, the actual images in this case will be product/organization logo images, which come in a large variety of aspect ratios, and almost always the images available to people have almost no whitespace around the text/imagery. Which means any fixed aspect ratio crop restricted to the bounds of the image will almost certainly chop off either the top+bottom or left+right sides of the image.

like image 572
jwl Avatar asked Apr 24 '13 23:04

jwl


3 Answers

My solution was to create a temporary canvas with square dimensions equal to the largest side of the image. I made the canvas background white and added the image in the center. Then I created a new image and used the canvas as the image source. Then I used that image with jcrop. It's slower, but it works!

Here's an example:

img.onload = function(){ 
    // get the largest side of the image
    // and set the x and y coordinates for where the image will go in the canvas
    if( img.width > img.height ){
        var largestDim = img.width;
        var x = 0;
        var y = (img.width-img.height)/2;
    }
    else{
        var largestDim = img.height;
        var y = 0;
        var x = (img.height-img.width)/2;
    }
    // create a temporary canvas element and set its height and width to largestDim
    canvastemp = document.createElement("canvas");
    canvastemp.width = canvastemp.height = largestDim;
    var ctx = canvastemp.getContext('2d');
    // set the canvas background to white
    ctx.fillStyle="#FFFFFF";
    ctx.fillRect(0, 0, canvastemp.width, canvastemp.height);
    // center the image in the canvas
    ctx.drawImage(img, x, y, img.width, img.height);
    // create a new image and use the canvas as its source
    var squaredImg = document.createElement("img");
    squaredImg.src = canvastemp.toDataURL();
    // add jcrop once the image loads
    squaredImg.onload = function(){
        addJcrop(squaredImg);   
    }
};

function addJcrop(img){
   // your jcrop code
}

This way users can choose to include the entire image in the crop if they wish.

like image 163
Chris Avatar answered Nov 20 '22 12:11

Chris


consider using something like php imagick to convert the photo to photo + transparent big background and then put that to JCrop I dont think its possible other way

like image 45
Jacek Pietal Avatar answered Nov 20 '22 12:11

Jacek Pietal


You could fool the jCrop script. Instead of showing image.jpg, you do something like not_a_real_image.php?imagename=image.jpg. Then give the php file a header of the image, and a width and height, and align the actual image in the center of that.

All you have to do is remember the amount of canvas you've added to correct it later on.

like image 2
Martijn Avatar answered Nov 20 '22 10:11

Martijn