Crop the image using JavaScript

66,531

Solution 1

Here is a function to get the image as you are uploading using the choose file button

function readURL() {
    const myimg = document.getElementById("myimg");
    const input = document.getElementById("myfile");
    if(input.files && input.files[0]) {
        const reader = new FileReader();
        reader.onload = e => {
            console.log("changed");
            myimg.src = e.target.result;
        };
        reader.readAsDataURL(input.files[0]);
    }
}
document.querySelector('#myfile').addEventListener('change', () => {
    readURL();
});

And the HTML will be

<img src="" id="myimg"><br>
<input type="file" id="myfile">

Here is a working fiddle

If you add a file the preview image will be updated. You actually get a data url here. Use the data url to the load the image to the canvas then crop it. calling drawimg(e.target.result)

function drawimg(idata) {
    const img = new Image();
    img.onload = () => {
        ctx.drawImage(img, 33, 71, 104, 124, 21, 20, 87, 104);
    };
    img.src = idata;
}

See working Fiddle: here

Solution 2

I'm a bit late to the party on this one, but I was facing a very similar issue myself yesterday, but instead using NodeJS.

My solution in the end was to break down the image into its RGBA values and check each row and column of the image to find where the image itself actually starts in comparison to the BG.

In my case, I'm working with images that are around 1500px*500px, with my solution taking around 150-250ms per image to read in the file, break down its pixels, calculate the cropping positions and to write the cropped file back to disk.

Since I couldn't find any nice libraries online to handle this, I've made my own and published it to NPM in case anyone else comes across the same issue and needs some help! :-)

https://www.npmjs.com/package/developyn-autocrop

Solution 3

Here is how I implemented it in my case:

  onSelectFile(event) {
    if (event.target.files && event.target.files[0]) {
      var reader = new FileReader();

      reader.readAsDataURL(event.target.files[0]); // read file as data url

      reader.onload = (event) => { // called once readAsDataURL is completed
       console.log(event);
        this.url = event.target.result;
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        const image = new Image();
        image.src = this.url;

        ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);

      }

The working stackblitz demo is here : https://stackblitz.com/edit/angular-file-upload-preview-qrrgx5

Hope it helps and this is what you want.

Share:
66,531
Maniraj Murugan
Author by

Maniraj Murugan

Proud | 27 | Farmer | Cricketer Born and brought up from evergreen town Karur, Tamilnadu, India. Civil Engineer by graduation and Software Engineer by Profession .. If my answers helped you, feel free to buy a coffee for me You can contact me via email in [email protected] ..

Updated on July 17, 2022

Comments

  • Maniraj Murugan
    Maniraj Murugan almost 2 years

    In my Angular 6 application I am making a file upload option and in preview the uploaded file needs to be displayed with auto cropping and auto resizing.

    I have tried the following,

    HTML:

    <canvas id="canvas"></canvas>
    <div style="display:none;">
      <img id="source" [src]="url" width="300" height="227">
    </div>
    <input type='file' (change)="onSelectFile($event)">
    

    File select functtion:

      onSelectFile(event) {
        if (event.target.files && event.target.files[0]) {
          var reader = new FileReader();
    
          reader.readAsDataURL(event.target.files[0]); // read file as data url
    
          reader.onload = (event) => { // called once readAsDataURL is completed
            this.url = event.target.result;
          }
    
          const canvas : any =  document.getElementById('canvas');
          const ctx = canvas.getContext('2d');
          const image = document.getElementById('source');
    
          ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
        }
      }
    

    In the above I have tried the following with the reference of link https://jsfiddle.net/8jwq3cs7/

          const canvas : any =  document.getElementById('canvas');
          const ctx = canvas.getContext('2d');
          const image = document.getElementById('source');
    
          ctx.drawImage(image, 33, 71, 104, 124, 21, 20, 87, 104);
    

    Before using the canvas the original image looks like this: https://mdn.mozillademos.org/files/5397/rhino.jpg

    Whereas after using canvas it's like this: https://jsfiddle.net/8jwq3cs7/

    But if I choose the image from choose file then I am unable to see the image after choosing...

    Working example: https://stackblitz.com/edit/angular-file-upload-preview-uwpf8f

    Even the solution with pure JavaScript alone would also be appreciable if not in the Angular way...

    The requirement is, if I choose a file then the same file needs to be cropped and fit the size automatically in preview...

    Kindly help me to achieve the result without jQuery or any library...

  • Geon George
    Geon George over 5 years
    I just used jquery so I could do the .change() function easily. There isn't much jquery involved in this. Just read before you downvote
  • Maniraj Murugan
    Maniraj Murugan over 5 years
    Hello dear it is angular application, here we won't use jquery at any case even it may small or big.. It is strictly restricted to use jquery.. If i need jquery then i wouldn't post this question..
  • Geon George
    Geon George over 5 years
    @undefined now I have edited the answer. You haven't even read the answer properly before you went to downvote. The code was and is still working. I used jquery only on the part to identify file change event. Now it's entirely vanilla js
  • Maniraj Murugan
    Maniraj Murugan over 5 years
    I think you haven't got my question well.. I am in the need of croping of uploaded image.. Read it carefully..
  • Sikshya Maharjan
    Sikshya Maharjan over 5 years
    Your closing sentence - "Use the data url to the load image to canvas then crop it" - is the question that the OP seems to be asking; can you expand upon that to show how that might be accomplished? Also please remember to explain your answers in order that people can learn from you.
  • Geon George
    Geon George over 5 years
    @undefined Here is the full working version: jsfiddle.net/geongeorgek/8jwq3cs7/14
  • Geon George
    Geon George over 5 years
    @undefined Oops a change was not saved. Here you go: jsfiddle.net/geongeorgek/rp0bym1a
  • Geon George
    Geon George over 5 years
    So you want the user to select the face region or auto detect faces? either way you framed the question wrong or I'm sorry for misreading it
  • Maniraj Murugan
    Maniraj Murugan over 5 years
    My requirement needs to be like, if i upload my picture that has 500px in height and 500px in width then i need to resize it with displaying the face alone with auto crop and auto resize.I hope you got it that i am uploading image for profile picture then it automatically crop the face area alone and displaying it.. I am expecting auto crop of face area alone in the profile image we upload..
  • Vaibhav Vishal
    Vaibhav Vishal almost 5 years
    Providing code is good but some explanation too of why your code works and what mistakes the person asking the question was making will help people understand your answer. from review
  • Gufran Hasan
    Gufran Hasan almost 5 years
    Please add some expalinations.
  • Neurotransmitter
    Neurotransmitter almost 4 years
    Error: Oops. Something is broken.