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

4

14

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.

Moncrief answered 24/4, 2013 at 23:48 Comment(5)
You cannot even crop like this in Gimp, so I think that this is not an oversight by JCrop. <edit>not</edit>Xuthus
@Mr.Polywhirl well, in PhotoShop & Gimp the way you'd do this is to increase the canvas size. Maybe I should reword my question to include that concept... hmm. But good luck googling "javascript image crop canvas" or anything like that, you'll only get HTML5 canvas hits!Moncrief
@jlarson did you ever figure this out?? I'm having the same issue and needs - user logos are all different shapes, but our software requires a square crop. Clients are complaining about it, but I can't seem to figure out any way to change jCrop's functionality.Fumed
@JeremyMiller - no I did not. IIRC I ended up changing the UI to get around this deficiencyMoncrief
boo. I was hoping that I wouldn't have to do that.Fumed
C
5

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.

Cyclometer answered 1/8, 2014 at 8:53 Comment(0)
T
3

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

Telic answered 1/7, 2014 at 12:3 Comment(3)
Yes, thats the way I would do it too. I think image magick can help.Countersign
I'm looking to do something like this, but unfortunately I'm using .net, so no PHP for me. Would there be something similar for .net?Fumed
I dont know net but you could try something like https://mcmap.net/q/216676/-merging-two-images-in-c-netTelic
C
2

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.

Commeasure answered 4/11, 2013 at 8:41 Comment(0)
W
0

I made a function using Imagick:

function resizeImage($imgSrc, $width, $height, $createBg, $output, $show) {

    $img = new Imagick($imgSrc);

    if ($img->getImageWidth() / $img->getImageHeight() < $width / $height) {
        $img->thumbnailImage(0, $height);
    } else {
        $img->thumbnailImage($width, 0);
    }

    $canvas = new Imagick();
    $canvas->newImage($width, $height, 'white', 'jpg');

    /* Creates a background image (good for vertical images in horizontal canvas or vice-versa) */
    if ($createBg) {

        $imgBg = new Imagick($imgSrc);

        if ($imgBg->getImageWidth() / $imgBg->getImageHeight() < $width / $height) {
            $imgBg->thumbnailImage($width, 0);
        } else {
            $imgBg->thumbnailImage(0, $height);
        }

        $imgBg->blurImage(0, 80);

        $geometryBg = $imgBg->getImageGeometry();
        $xBg = ( $width - $geometryBg['width'] ) / 2;
        $yBg = ( $height - $geometryBg['height'] ) / 2;

        $canvas->compositeImage( $imgBg, imagick::COMPOSITE_OVER, $xBg, $yBg );
    }

    /* Center image */
    $geometry = $img->getImageGeometry();
    $x = ( $width - $geometry['width'] ) / 2;
    $y = ( $height - $geometry['height'] ) / 2;

    $canvas->compositeImage( $img, imagick::COMPOSITE_OVER, $x, $y );

    /* Save image  */
    if ($output) {
        $canvas->writeImage($output);
    }

    /* Show the image */
    if ($show) {
        header( 'Content-Type: image/jpg' );
        echo $canvas;
    }

}

The comment's explain it all, enjoy!

Womera answered 22/6, 2015 at 22:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.