12

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

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

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

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

4

4 回答 4

21

工作解决方案: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 resizer 的一部分,来自此页面: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);
 };
};
于 2013-08-18T10:15:55.363 回答
1

看起来我的代码在'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);
于 2015-02-19T02:35:19.477 回答
1

您可以使用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);
  });
};
于 2019-09-23T07:36:04.143 回答
0

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

于 2014-09-21T01:56:44.020 回答