Search code examples
javascriptfilepond

How to convert any image to webp?


Any way to convert any image to webp with filepond?

This is my code:

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

Cannot assign to read only property 'name' of object '#'


Solution

  • You can't "just" change the name and the type of the file and be done with it.

    1. The file name and type are read-only, you'll have to create a new file based on the old one and then you can assign a new name and type.
    const myRenamedFile = new File([myOriginalFile], 'my-new-name');
    

    More on renaming files

    1. Changing the type property doesn't change the actual file data. Rename a .jpeg to .png and the file data (the bits) will still be a JPEG compressed image.

    To transform the data you need to read the original file and then transform it to the WEBP format. You can do so with the .toBlob() method available on the canvas element.

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

    Obviously creating a WEBP image doesn't work on browsers that don't support WEBP like Safari 13.x, IE11, and Edge 17. Support on Firefox is available since the start of 2019 and Chrome has supported WEBP for ages.

    If you need to support those browsers you could use a separate JavaScript library to do the image encoding. For example webpjs.