HTML5 - изменение размера изображения и сохранение EXIF в измененном размере
Как изменить размер изображения (используя элемент HTML5 canvas
) и сохранить информацию EXIF с исходного изображения? Я могу извлечь EXIF-информацию из исходного изображения, но я не знаю, как ее скопировать в измененное изображение.
Вот как я получаю данные с измененными размерами для отправки на серверный код:
canvas.toDataURL("image/jpeg", 0.7);
Для получения EXIF я использую библиотеку exif.js.
Ответы
Ответ 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 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 URL
// helper Image object
var image = new Image();
image.src = blobURL;
image.onload = function() {
// have to wait till it 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);
};
};
Ответ 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
Canvas генерирует изображения с заголовком 20 байтов (перед началом сегмента jpeg). Вы можете нарезать голову сегментами exif из исходного файла и заменить первые 20 байтов в измененном размере.
Ответ 4
Вы можете использовать copyExif.js.
Этот модуль более эффективен, чем решение Martin, и использует только Blob и ArrayBuffer без кодера/декодера Base64.
Кроме того, нет необходимости использовать exif.js, если вы хотите сохранить только EXIF. Просто скопируйте весь маркер APP1 из исходного JPEG в конечный объект canvas, и он будет работать. Это также как 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);
});
};