Cropping images in the browser BEFORE the upload [closed]

Yes, it can be done.
It is based on the new HTML5 “download” attribute of anchor tags.
The flow should be something like this:

  1. load the image
  2. draw the image into a canvas with the crop boundaries specified
  3. get the image data from the canvas and make it a href attribute for an anchor tag in the DOM
  4. add the download attribute (download="desired-file-name") to that a element
    That’s it. all the user has to do is click your “download link” and the image will be downloaded to his pc.

I’ll come back with a demo when I get the chance.

Here’s the live demo as I promised. It takes the JSFiddle logo and crops 5px of each margin.
The code looks like this:

var img = new Image();
img.onload = function(){
    var cropMarginWidth = 5,
        canvas = $('<canvas/>')
                    .attr({
                         width: img.width - 2 * cropMarginWidth,
                         height: img.height - 2 * cropMarginWidth
                     })
                    .hide()
                    .appendTo('body'),
        ctx = canvas.get(0).getContext('2d'),
        a = $('<a download="cropped-image" title="click to download the image" />'),
        cropCoords = {
            topLeft : {
                x : cropMarginWidth,
                y : cropMarginWidth
            },
            bottomRight :{
                x : img.width - cropMarginWidth,
                y : img.height - cropMarginWidth
            }
        };

    ctx.drawImage(img, cropCoords.topLeft.x, cropCoords.topLeft.y, cropCoords.bottomRight.x, cropCoords.bottomRight.y, 0, 0, img.width, img.height);
    var base64ImageData = canvas.get(0).toDataURL();

    a
        .attr('href', base64ImageData)
        .text('cropped image')
        .appendTo('body');

    a
        .clone()
        .attr('href', img.src)
        .text('original image')
        .attr('download','original-image')
        .appendTo('body');

    canvas.remove();
}
img.src="https://stackoverflow.com/questions/12728188/some-image-src";

Forgot to mention: of course there is a downside :(.
Because of the same-origin policy that is applied to images too, if you want to access an image’s data (through the canvas method toDataUrl).
So you would still need a server-side proxy that would serve your image as if it were hosted on your domain.

Although I can’t provide a live demo for this (for security reasons), here is a PHP sample code that solves the same-origin policy:

file proxy.php:

$imgData = getimagesize($_GET['img']);
header("Content-type: " . $imgData['mime']);
echo file_get_contents($_GET['img']);

This way, instead of loading the external image direct from it’s origin:

img.src="http://example.com/imagefile.png";

You can load it through your proxy:

img.src="https://stackoverflow.com/questions/12728188/proxy.php?img=" + encodeURIComponent('http://example.com/imagefile.png');

And here’s a sample PHP code for saving the image data (base64) into an actual image:

file save-image.php:

$data = preg_replace('/data:image\/(png|jpg|jpeg|gif|bmp);base64/','',$_POST['data']);
$data = base64_decode($data);
$img = imagecreatefromstring($data);

$path="path-to-saved-images/";
// generate random name
$name  = substr(md5(time()),10);
$ext="png";
$imageName = $path.$name.'.'.$ext;

// write the image to disk
imagepng($img,  $imageName);
imagedestroy($img);
// return the image path
echo $imageName;

All you have to do then is post the image data to this file and it will save the image to disc and return you the existing image filename.

Of course all this might feel a bit complicated, but I wanted to show you that what you’re trying to achieve is possible.

Leave a Comment