HTML5 Pre-resize images before uploading

前端 未结 10 2371
野的像风
野的像风 2020-11-22 15:53

Here\'s a noodle scratcher.

Bearing in mind we have HTML5 local storage and xhr v2 and what not. I was wondering if anyone could find a work

相关标签:
10条回答
  • 2020-11-22 16:11

    The accepted answer works great, but the resize logic ignores the case in which the image is larger than the maximum in only one of the axes (for example, height > maxHeight but width <= maxWidth).

    I think the following code takes care of all cases in a more straight-forward and functional way (ignore the typescript type annotations if using plain javascript):

    private scaleDownSize(width: number, height: number, maxWidth: number, maxHeight: number): {width: number, height: number} {
        if (width <= maxWidth && height <= maxHeight)
          return { width, height };
        else if (width / maxWidth > height / maxHeight)
          return { width: maxWidth, height: height * maxWidth / width};
        else
          return { width: width * maxHeight / height, height: maxHeight };
      }
    
    0 讨论(0)
  • 2020-11-22 16:14

    Typescript

    async resizeImg(file: Blob): Promise<Blob> {
        let img = document.createElement("img");
        img.src = await new Promise<any>(resolve => {
            let reader = new FileReader();
            reader.onload = (e: any) => resolve(e.target.result);
            reader.readAsDataURL(file);
        });
        await new Promise(resolve => img.onload = resolve)
        let canvas = document.createElement("canvas");
        let ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0);
        let MAX_WIDTH = 1000;
        let MAX_HEIGHT = 1000;
        let width = img.naturalWidth;
        let height = img.naturalHeight;
        if (width > height) {
            if (width > MAX_WIDTH) {
                height *= MAX_WIDTH / width;
                width = MAX_WIDTH;
            }
        } else {
            if (height > MAX_HEIGHT) {
                width *= MAX_HEIGHT / height;
                height = MAX_HEIGHT;
            }
        }
        canvas.width = width;
        canvas.height = height;
        ctx = canvas.getContext("2d");
        ctx.drawImage(img, 0, 0, width, height);
        let result = await new Promise<Blob>(resolve => { canvas.toBlob(resolve, 'image/jpeg', 0.95); });
        return result;
    }
    
    0 讨论(0)
  • 2020-11-22 16:15

    Resizing images in a canvas element is generally bad idea since it uses the cheapest box interpolation. The resulting image noticeable degrades in quality. I'd recommend using http://nodeca.github.io/pica/demo/ which can perform Lanczos transformation instead. The demo page above shows difference between canvas and Lanczos approaches.

    It also uses web workers for resizing images in parallel. There is also WEBGL implementation.

    There are some online image resizers that use pica for doing the job, like https://myimageresizer.com

    0 讨论(0)
  • 2020-11-22 16:16

    Modification to the answer by Justin that works for me:

    1. Added img.onload
    2. Expand the POST request with a real example
    
    function handleFiles()
    {
        var dataurl = null;
        var filesToUpload = document.getElementById('photo').files;
        var file = filesToUpload[0];
    
        // Create an image
        var img = document.createElement("img");
        // Create a file reader
        var reader = new FileReader();
        // Set the image once loaded into file reader
        reader.onload = function(e)
        {
            img.src = e.target.result;
    
            img.onload = function () {
                var canvas = document.createElement("canvas");
                var ctx = canvas.getContext("2d");
                ctx.drawImage(img, 0, 0);
    
                var MAX_WIDTH = 800;
                var MAX_HEIGHT = 600;
                var width = img.width;
                var height = img.height;
    
                if (width > height) {
                  if (width > MAX_WIDTH) {
                    height *= MAX_WIDTH / width;
                    width = MAX_WIDTH;
                  }
                } else {
                  if (height > MAX_HEIGHT) {
                    width *= MAX_HEIGHT / height;
                    height = MAX_HEIGHT;
                  }
                }
                canvas.width = width;
                canvas.height = height;
                var ctx = canvas.getContext("2d");
                ctx.drawImage(img, 0, 0, width, height);
    
                dataurl = canvas.toDataURL("image/jpeg");
    
                // Post the data
                var fd = new FormData();
                fd.append("name", "some_filename.jpg");
                fd.append("image", dataurl);
                fd.append("info", "lah_de_dah");
                $.ajax({
                    url: '/ajax_photo',
                    data: fd,
                    cache: false,
                    contentType: false,
                    processData: false,
                    type: 'POST',
                    success: function(data){
                        $('#form_photo')[0].reset();
                        location.reload();
                    }
                });
            } // img.onload
        }
        // Load files into file reader
        reader.readAsDataURL(file);
    }
    
    0 讨论(0)
  • 2020-11-22 16:17

    Yes, use the File API, then you can process the images with the canvas element.

    This Mozilla Hacks blog post walks you through most of the process. For reference here's the assembled source code from the blog post:

    // from an input element
    var filesToUpload = input.files;
    var file = filesToUpload[0];
    
    var img = document.createElement("img");
    var reader = new FileReader();  
    reader.onload = function(e) {img.src = e.target.result}
    reader.readAsDataURL(file);
    
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);
    
    var MAX_WIDTH = 800;
    var MAX_HEIGHT = 600;
    var width = img.width;
    var height = img.height;
    
    if (width > height) {
      if (width > MAX_WIDTH) {
        height *= MAX_WIDTH / width;
        width = MAX_WIDTH;
      }
    } else {
      if (height > MAX_HEIGHT) {
        width *= MAX_HEIGHT / height;
        height = MAX_HEIGHT;
      }
    }
    canvas.width = width;
    canvas.height = height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0, width, height);
    
    var dataurl = canvas.toDataURL("image/png");
    
    //Post dataurl to the server with AJAX
    
    0 讨论(0)
  • 2020-11-22 16:20

    Correction to above:

    <img src="" id="image">
    <input id="input" type="file" onchange="handleFiles()">
    <script>
    
    function handleFiles()
    {
        var filesToUpload = document.getElementById('input').files;
        var file = filesToUpload[0];
    
        // Create an image
        var img = document.createElement("img");
        // Create a file reader
        var reader = new FileReader();
        // Set the image once loaded into file reader
        reader.onload = function(e)
        {
            img.src = e.target.result;
    
            var canvas = document.createElement("canvas");
            //var canvas = $("<canvas>", {"id":"testing"})[0];
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0);
    
            var MAX_WIDTH = 400;
            var MAX_HEIGHT = 300;
            var width = img.width;
            var height = img.height;
    
            if (width > height) {
              if (width > MAX_WIDTH) {
                height *= MAX_WIDTH / width;
                width = MAX_WIDTH;
              }
            } else {
              if (height > MAX_HEIGHT) {
                width *= MAX_HEIGHT / height;
                height = MAX_HEIGHT;
              }
            }
            canvas.width = width;
            canvas.height = height;
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0, width, height);
    
            var dataurl = canvas.toDataURL("image/png");
            document.getElementById('image').src = dataurl;     
        }
        // Load files into file reader
        reader.readAsDataURL(file);
    
    
        // Post the data
        /*
        var fd = new FormData();
        fd.append("name", "some_filename.jpg");
        fd.append("image", dataurl);
        fd.append("info", "lah_de_dah");
        */
    }</script>
    
    0 讨论(0)
提交回复
热议问题