HTML5 - resize image and keep EXIF in resized image

后端 未结 4 616
一生所求
一生所求 2020-12-16 01:31

How can I resize an image (using an HTML5 canvas element) and keep the EXIF information from the original image? I can extract EXIF info from from original imag

相关标签:
4条回答
  • 2020-12-16 01:48

    It looks my code is used in 'ExifRestorer.js'...

    I've try resizing image by canvas. And I felt that resized image is bad quality. If you felt so, too, try my code. My code resizes JPEG by bilinear interpolation. Of course it doesn't lose exif.

    https://github.com/hMatoba/JavaScript-MinifyJpegAsync

    function post(data) {
        var req = new XMLHttpRequest();
        req.open("POST", "/jpeg", false);
        req.setRequestHeader('Content-Type', 'image/jpeg');
        req.send(data.buffer);
    }
    
    function handleFileSelect(evt) {
        var files = evt.target.files;
    
        for (var i = 0, f; f = files[i]; i++){
            var reader = new FileReader();
            reader.onloadend = function(e){
                MinifyJpegAsync.minify(e.target.result, 1280, post);
            };
        reader.readAsDataURL(f);
        }
    }
    
    document.getElementById('files').addEventListener('change', handleFileSelect, false);
    
    0 讨论(0)
  • 2020-12-16 01:59

    Canvas generates images with 20 bytes header (before jpeg data segments start). You can slice head with exif segments from original file and replace first 20 bytes in resized one.

    0 讨论(0)
  • 2020-12-16 01:59

    You can use copyExif.js.

    This module is more efficient than Martin's solution and uses only Blob and ArrayBuffer without Base64 encoder/decoder.

    Besides, there is no need to use exif.js if you only want to keep EXIF. Just copy the entire APP1 marker from the original JPEG to the destination canvas blob and it would just work. It is also how copyExif.js does.

    Usage

    demo: https://codepen.io/tonytonyjan/project/editor/XEkOkv

    <input type="file" id="file" accept="image/jpeg" />
    
    import copyExif from "./copyExif.js";
    
    document.getElementById("file").onchange = async ({ target: { files } }) => {
      const file = files[0],
        canvas = document.createElement("canvas"),
        ctx = canvas.getContext("2d");
    
      ctx.drawImage(await blobToImage(file), 0, 0, canvas.width, canvas.height);
      canvas.toBlob(
        async blob =>
          document.body.appendChild(await blobToImage(await copyExif(file, blob))),
        "image/jpeg"
      );
    };
    
    const blobToImage = blob => {
      return new Promise(resolve => {
        const reader = new FileReader(),
          image = new Image();
        image.onload = () => resolve(image);
        reader.onload = ({ target: { result: dataURL } }) => (image.src = dataURL);
        reader.readAsDataURL(blob);
      });
    };
    
    0 讨论(0)
  • 2020-12-16 02:02

    Working solution: ExifRestorer.js

    Usage with HTML5 image resize:

    function dataURItoBlob(dataURI) 
    {
        var binary = atob(dataURI.split(',')[1]);
        var array = [];
        for(var i = 0; i < binary.length; i++) {
            array.push(binary.charCodeAt(i));
        }
        return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
    }
    

    And main code, taken as part of HTML5 resizer from this page: https://github.com/josefrichter/resize/blob/master/public/preprocess.js (but slightly modified)

    var reader = new FileReader();
    
    //reader.readAsArrayBuffer(file); //load data ... old version
    reader.readAsDataURL(file);       //load data ... new version
    reader.onload = function (event) {
    // blob stuff
    //var blob = new Blob([event.target.result]); // create blob... old version
    var blob = dataURItoBlob(event.target.result); // create blob...new version
    window.URL = window.URL || window.webkitURL;
    var blobURL = window.URL.createObjectURL(blob); // and get it's URL
    
    // helper Image object
    var image = new Image();
    image.src = blobURL;
    
    image.onload = function() {
    
       // have to wait till it's loaded
       var resized = ResizeImage(image); // send it to canvas
    
       resized = ExifRestorer.restore(event.target.result, resized);  //<= EXIF  
    
       var newinput = document.createElement("input");
       newinput.type = 'hidden';
       newinput.name = 'html5_images[]';
       newinput.value = resized; // put result from canvas into new hidden input
       form.appendChild(newinput);
     };
    };
    
    0 讨论(0)
提交回复
热议问题