Donaldcwl / browser-image-compression

Image compression in web browser
MIT License
1.3k stars 160 forks source link

Add support for .heic #79

Open hempels opened 4 years ago

hempels commented 4 years ago

Would be awesome if support could be added for converting HEIC image files to JPG as Mac has dug in pretty aggressively on using this format.

MentalGear commented 1 year ago

Wondering if this allowed, e.g. has apple open sourced the format ?

sideshot commented 2 months ago

I was able to get heic support doing the following... Code was used in my sveltekit project.

    import imageCompression from 'browser-image-compression';
    import heic2any from 'heic2any';

    let imageUploaded = false;
    let uploadedImage = null;
    let optimizedImageURL = '';

    async function handleImageUpload(event) {
        let file = event.target.files[0];
        if (file) {
            console.log('File selected:', file);
            imageUploaded = true;

            const options = {
                maxSizeMB: 1,
                maxWidthOrHeight: 1024,
                useWebWorker: true,
                maxResolution: 72
            };

            try {
                if (file.name.endsWith('.HEIC') || file.name.endsWith('.HEIF')) {
                    console.log('Converting HEIC/HEIF to JPEG...');
                    file = await heic2any({ blob: file, toType: 'image/jpeg' });
                    console.log('Conversion completed:', file);
                }

                if (!file.type.startsWith('image/')) {
                    throw new Error('The file given is not an image');
                }

                console.log('Starting image compression...');
                const compressedFile = await imageCompression(file, options);
                console.log('Image compression completed:', compressedFile);

                uploadedImage = compressedFile;
                optimizedImageURL = URL.createObjectURL(compressedFile);
                console.log('Image ready for submission:', uploadedImage);
            } catch (error) {
                console.error('Image compression failed:', error);
            }
        }
    }
filoxo commented 2 weeks ago

I tried using the above syntax with a Remix (server-rendered React) project but encountered the following error:

[vite] Error when evaluating SSR module /src/util/optimizeImage.ts: failed to import "heic2any"
|- ReferenceError: window is not defined

I instead switched to dynamic import to solve the issue.

/** src/util/optimizeImage.ts **/
import imageCompression from "browser-image-compression"

export const optimizeImage = async (file: File): Promise<File> => {
  if (!file.type.startsWith("image/"))
    throw new Error("The file given is not an image")

  try {
    console.log(`originalFile size ${file.size / 1024 / 1024} MB`)

    let fileJpeg = file

    if (
      file.name.endsWith(".HEIC") ||
      file.name.endsWith(".heic") ||
      file.name.endsWith(".HEIF") ||
      file.name.endsWith(".heif")
    ) {
      console.log("Converting HEIC/HEIF to JPEG...")
      fileJpeg = (await import("heic2any").then((mod) => {
        return mod.default({
          blob: file,
          toType: "image/jpeg",
        })
      })) as File
      console.log("Conversion completed")
    }

    const compressedFile = await imageCompression(fileJpeg, {
      maxSizeMB: 1,
      maxWidthOrHeight: 2200,
      useWebWorker: true,
      fileType: "image/jpeg",
    })

    console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`) // smaller than maxSizeMB

    return compressedFile
  } catch (err) {
    console.error("Error resizing file:", err)
    return file
  }
}