【问题标题】:HTML5 - resize image and keep EXIF in resized imageHTML5 - 调整图像大小并将 EXIF 保留在调整大小的图像中
【发布时间】:2013-08-20 06:22:00
【问题描述】:

如何调整图像大小(使用 HTML5 canvas 元素)并保留原始图像中的 EXIF 信息?我可以从原始图像中提取 EXIF 信息,但我不知道如何将其复制到调整大小的图像中。

这是我检索调整大小的图像数据以发送到服务器端代码的方式:

canvas.toDataURL("image/jpeg", 0.7);

对于 EXIF 检索,我使用的是 exif.js 库。

【问题讨论】:

    标签: javascript html image-processing exif


    【解决方案1】:

    工作解决方案:ExifRestorer.js

    使用 HTML5 图片调整大小:

    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'});
    }
    

    和主要代码,作为 HTML5 大小调整器的一部分来自此页面:https://github.com/josefrichter/resize/blob/master/public/preprocess.js(但略有修改)

    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);
     };
    };
    

    【讨论】:

    • 您会为您的 ExifRestorer.js 文件创建一个 GitHub 存储库并添加一个许可证以便其他人可以使用它吗?或者您是否会在此处明确说明其他人可以在您的答案中使用该代码的条款?
    • @KennyEvitt 您可以随意使用代码。我尽力创建它,我只是将不同代码的几个部分连接在一起。
    • @MartinPerry - 它与我的代码完美配合 - 我做了一些画布图像处理 - 然后我就可以恢复数据了。但是我想覆盖图像 exif 方向值。一旦我用画布旋转图像 - exif 方向仍然不正确。有什么解决办法吗?
    • 感谢 ExifRestorer.js。可爱的剧本!
    • 为了使 ExifRestorer.js 能够处理不同于 jpeg 的文件类型,需要将库中出现的 'data:image/jpeg;base64,' 替换为 /data:image\/\w+;base64,/
    【解决方案2】:

    看来我的代码在“ExifRestorer.js”中使用...

    我尝试通过画布调整图像大小。而且我觉得调整大小的图像质量很差。如果你也这么觉得,试试我的代码。我的代码通过双线性插值调整 JPEG 的大小。当然不会丢失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);
    

    【讨论】:

      【解决方案3】:

      您可以使用copyExif.js

      这个模块比 Martin 的方案效率更高,只使用了 Blob 和 ArrayBuffer,没有 Base64 编码器/解码器。

      另外,如果你只想保留EXIF,则不需要使用exif.js。只需将整个 APP1 标记从原始 JPEG 复制到目标画布 blob 即可。 copyExif.js 也是如此。

      用法

      演示: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”,你能帮帮我吗?而且我不能使用“ctx.transform”,因为最后我想要“Blob object”。
      【解决方案4】:

      Canvas 生成带有 20 字节标题的图像(在 jpeg 数据段开始之前)。您可以使用原始文件中的 exif 段切片头,并在调整大小的文件中替换前 20 个字节。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-24
        • 1970-01-01
        • 1970-01-01
        • 2013-09-09
        • 1970-01-01
        • 2021-08-26
        • 2011-05-09
        相关资源
        最近更新 更多