2

I am trying to show previews of uploaded images in a canvas. The preview should be a square version of image.

What I have:

var img = new Image;
img.src = imageSrc;
var c = document.getElementById('file-preview-' + data.response.id);
var ctx = c.getContext("2d");
img.onload = function() {
    ctx.drawImage(img, 0, 0);
};

And the preview:

enter image description here

So how can I draw on the canvas a 150x150 square with maintained ratio cropped version of the image?

For example for this image:

enter image description here

I should get:

enter image description here

  • And your question is...? – Marc B Jun 16 '16 at 20:25
  • I updated the question. – Sebastian Corneliu Vîrlan Jun 16 '16 at 20:28
  • 2
    Possible duplicate of [Scaling an image to fit on canvas](http://stackoverflow.com/questions/23104582/scaling-an-image-to-fit-on-canvas) – A.Sharma Jun 16 '16 at 20:29
  • 1
    That example does not provide me the possibility to create a square maintained ratio cropped. – Sebastian Corneliu Vîrlan Jun 16 '16 at 20:36
  • You should update your question with this requirement. You didn't specify that. Also, include the code that you've tried so far that isn't working. – ManoDestra Jun 16 '16 at 20:41
  • @ManoDestra the OP *did* specify that and someone else edited it out - check the edit history – CupawnTae Jun 16 '16 at 20:42
  • I updated again. Sorry. – Sebastian Corneliu Vîrlan Jun 16 '16 at 20:42
  • Like this? https://stackoverflow.com/questions/21961839/simulation-background-size-cover-in-canvas/21961894#21961894 (1:1 demo: http://jsfiddle.net/epistemex/5fcta2ex/) –  Jun 16 '16 at 20:43
  • Yes. Thank you a lot. – Sebastian Corneliu Vîrlan Jun 16 '16 at 20:45
  • @IonVasile it's still not completely clear from your example. Do you just want to crop to 150x150? Do you want to shrink the image so that the smaller dimension is resized to 150, the aspect ratio is maintained and the excess from the larger dimension is cropped? Your example doesn't appear to crop from the top left - which part of the image do you want to maintain, etc. – CupawnTae Jun 16 '16 at 20:45
  • @CupawnTae It appears to be cropped on the central square (based on the minimum of width or height). In other words, lose the left and right parts of the source image to yield a square. I've added an answer that uses this cropping and resizes to fit the canvas. And it yields exactly the result that the OP has provided above. – ManoDestra Jun 16 '16 at 21:20
  • @ManoDestra it would be better if the question specified it explicitly in words rather than leaving it to guesswork based on the images. Also, the first "preview" image looks more like it's top-left of something, and isn't scaled at all, where the second example is scaled, so even the images are inconsistent. – CupawnTae Jun 16 '16 at 21:50
  • @CupawnTae Doesn't seem like the OP cares too much about which, but I agree, it would be better if it were explicitly a left based cropped resized square or a centrally based cropped resized square (I'll update my answer to accommodate both). – ManoDestra Jun 17 '16 at 13:10
  • How should I react in case I chose @K3N answer from up comments? Should I select one of the answers below? – Sebastian Corneliu Vîrlan Jun 17 '16 at 14:23

2 Answers2

3

Here's a method that yields precisely the result you desire, cropped, resized and centered (with commented out lines that yield a left based cropping instead)...

    var ctx;
    function init(event) {
     ctx = document.getElementById('canvas').getContext('2d');
        // Your preview is actually 120x120,
        // but I've stuck with the textual description of
        // your requirements here.
     ctx.canvas.width = 150;
     ctx.canvas.height = 150;
     loadBackground('https://i.stack.imgur.com/PCKEo.png');
    }
    
    function loadBackground(path) {
     var img = new Image();
     img.onload = drawBackground;
     img.src = path;
    }

    function drawBackground(event) {
     var img = event.target;
     var imgSize = Math.min(img.width, img.height);
        // The following two lines yield a central based cropping.
        // They can both be amended to be 0, if you wish it to be
        // a left based cropped image.
     var left = (img.width - imgSize) / 2;
     var top = (img.height - imgSize) / 2;
        //var left = 0; // If you wish left based cropping instead.
        //var top = 0; // If you wish left based cropping instead.
     ctx.drawImage(event.target, left, top, imgSize, imgSize, 0, 0, ctx.canvas.width, ctx.canvas.height);
    }
    
    window.addEventListener('load', init, false);
<canvas id="canvas"></canvas>
ManoDestra
  • 6,325
  • 6
  • 26
  • 50
1

Based on information from this question: SO Question

I was able to modify what was done to create a square cropped image in canvas:

var img = new Image;
img.src = "http://cdn.bmwblog.com/wp-content/uploads/2016/02/M-Performance-Parts-BMW-M2-3.jpg"; //Or whatever image source you have
var c= document.getElementById('file-preview');
var ctx=c.getContext("2d");

img.onload = function(){
      ctx.drawImage(img, img.width/2, img.height/2, img.width, img.height, 0, 0, img.width, img.height);
};

You just have to modify the arguments you are passing to the drawImage function as well as add some more.

You can see a fiddle here: https://jsfiddle.net/4d93pkoa/3/

Remember that the first two parameters specify the image's top left coordinates within the canvas element.

Remember to set the width and height of the canvas element in HTML to a square shape.

Community
  • 1
  • 1
A.Sharma
  • 2,771
  • 1
  • 11
  • 24
  • 3
    "set the width and height of the canvas element in css" - do you mean in the HTML? Sizing a canvas element via CSS without setting the height and width of the HTML element usually leads to confusing results – CupawnTae Jun 16 '16 at 20:48
  • 1
    (if you have a canvas with its `height` and `width` HTML attributes in a different ratio to its `height` and `width` CSS properties, it won't have a 1:1 aspect ratio and so a square drawn on the canvas won't be square onscreen) – CupawnTae Jun 16 '16 at 20:53