如何将任何图像转换为WebP格式?

5

如何使用FilePond将任何图像转换为WebP格式?

这是我的代码:

import vueFilePond, { setOptions } from 'vue-filepond'

// ...

setOptions({
  server: {
    process: (field, file) => {
      file.name = String(file.name.substr(0, file.name.lastIndexOf('.'))) + '.webp';
      file.type = 'image/webp';
      // ... upload to firebase storage
    }
  }
})

无法将值分配给只读属性“name”的对象“#”。

https://www.npmjs.com/package/webp-converter - Justinas
https://dev59.com/kKzka4cB1Zd3GeqP7VxC - Justinas
@Justinas 这很有趣,但我想从头开始做,也就是使用Vue作为客户端JavaScript。 - Rimuru Tempest
2个回答

6
您不能仅仅更改文件名和类型就完成了。
1. 文件名和类型是只读的,您需要基于旧文件创建一个新文件,然后才能分配新的名称和类型。
const myRenamedFile = new File([myOriginalFile], 'my-new-name');

关于重命名文件的更多信息

  1. 更改type属性不会更改实际文件数据。将.png重命名为.jpeg,文件数据(bits)仍将是JPEG压缩图像。

要转换数据,您需要读取原始文件,然后将其转换为WEBP格式。您可以使用画布元素上可用的.toBlob()方法来执行此操作。

const image = new Image();
image.onload = () => {

  const canvas = document.createElement('canvas');
  canvas.width = image.naturalWidth;
  canvas.height = image.naturalHeight;
  canvas.getContext('2d').drawImage(image, 0, 0);
  canvas.toBlob((blob) => {
    
    // Now we have a `blob` containing webp data

    // Use the file rename trick to turn it back into a file
    const myImage = new File([blob], 'my-new-name.webp', { type: blob.type });

  }, 'image/webp');

};

image.src = URL.createObjectURL(myFile);

显然,在不支持WEBP的浏览器上,如Safari 13.x、IE11和Edge 17,创建WEBP图像是行不通的。自2019年初起,Firefox已经支持WEBP,而Chrome则支持WEBP已经有很长时间了。

如果您需要支持这些浏览器,可以使用单独的JavaScript库进行图像编码。例如webpjs


目前在Firefox 84中无法正常工作。即使有所谓的webp支持,使用image/webp的toBlob仍会回退到png编码的blob。 - drglove
链接已损坏。现在没有canvas,怎么办? - Yeets

1

是的,您可以使用以下源代码来实现它,不仅可以将图像格式更改为 .webp,还可以转换整个图像。

它提供了将 .jpeg、.png 文件转换为 .webp 格式的选项。

源代码:Image To Webp Converter

let refs = {};
refs.imagePreviews = document.querySelector('#previews');
refs.fileSelector = document.querySelector('input[type=file]');

function addImageBox(container) {
  let imageBox = document.createElement("div");
  let progressBox = document.createElement("progress");
  imageBox.appendChild(progressBox);
  container.appendChild(imageBox);
  
  return imageBox;
}

function processFile(file) {
  if (!file) {
    return;
  }
  console.log(file);

  let imageBox = addImageBox(refs.imagePreviews);

  // Load the data into an image
  new Promise(function (resolve, reject) {
    let rawImage = new Image();

    rawImage.addEventListener("load", function () {
      resolve(rawImage);
    });

    rawImage.src = URL.createObjectURL(file);
  })
  .then(function (rawImage) {
    // Convert image to webp ObjectURL via a canvas blob
    return new Promise(function (resolve, reject) {
      let canvas = document.createElement('canvas');
      let ctx = canvas.getContext("2d");

      canvas.width = rawImage.width;
      canvas.height = rawImage.height;
      ctx.drawImage(rawImage, 0, 0);

      canvas.toBlob(function (blob) {
        resolve(URL.createObjectURL(blob));
      }, "image/webp");
    });
  })
  .then(function (imageURL) {
    // Load image for display on the page
    return new Promise(function (resolve, reject) {
      let scaledImg = new Image();

      scaledImg.addEventListener("load", function () {
        resolve({imageURL, scaledImg});
      });

      scaledImg.setAttribute("src", imageURL);
    });
  })
  .then(function (data) {
    // Inject into the DOM
    let imageLink = document.createElement("a");

    imageLink.setAttribute("href", data.imageURL);
    imageLink.setAttribute('download', `${file.name}.webp`);
    imageLink.appendChild(data.scaledImg);

    imageBox.innerHTML = "";
    imageBox.appendChild(imageLink);
  });
}

function processFiles(files) {
  for (let file of files) {
    processFile(file);
  }
}

function fileSelectorChanged() {
  processFiles(refs.fileSelector.files);
  refs.fileSelector.value = "";
}

refs.fileSelector.addEventListener("change", fileSelectorChanged);

// Set up Drag and Drop
function dragenter(e) {
  e.stopPropagation();
  e.preventDefault();
}

function dragover(e) {
  e.stopPropagation();
  e.preventDefault();
}

function drop(callback, e) {
  e.stopPropagation();
  e.preventDefault();
  callback(e.dataTransfer.files);
}

function setDragDrop(area, callback) {
  area.addEventListener("dragenter", dragenter, false);
  area.addEventListener("dragover", dragover, false);
  area.addEventListener("drop", function (e) { drop(callback, e); }, false);
}
setDragDrop(document.documentElement, processFiles);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接