alexcorvi / heic2any

Converting HEIF/HEIF image formats to PNG/GIF/JPEG in the browser
https://alexcorvi.github.io/heic2any/
MIT License
585 stars 74 forks source link

ERR_LIBHEIF format not supported #50

Open zyktrcn opened 1 year ago

zyktrcn commented 1 year ago

we use heic2any to change heic to jpeg in Android 13, but get an error: ERR_LIBHEIF format not supported.

in our test, heic image is validate. we have no idea about which type of heic image will get this error.

is there any unsupported heic image with heic2any?

OlehLoda commented 1 year ago

same issue

MarianaKWork commented 11 months ago

Getting the same issue here

rookieDJ commented 11 months ago

same issue

amilich commented 10 months ago

also seeing this

shabbir-hossain-ftdl commented 10 months ago

Is there any solution found to this problem?

ewrfli commented 9 months ago

same issue

sandeep1995 commented 7 months ago

same here

byronwall commented 7 months ago

I struggled with this issue. Turns out I was feeding heic2any garbage data but didn't spot it immediately.

My issue is that I had source image data in a base64 data thing like data:image/heic;base64,blahblahblah. I was doing bad operations to get that data into this library. My context is the browser.

Things to keep an eye on:

If you're in the same spot, actual working code looks like:

import heic2any from "heic2any";

export async function convertHEICToPNG(base64Data: string) {
  const uint8Array = convertBase64ToUInt8Array(base64Data);

  const blob = new Blob([uint8Array], { type: "image/heic" });

  let pngBlob = await heic2any({
    blob: blob,
    toType: "image/png",
  });

  // get single png blob if heic2any returns an array
  if (Array.isArray(pngBlob)) {
    pngBlob = pngBlob[0];
  }

  // return base 64 data
  return extractBase64FromBlob(pngBlob);
}

export function convertBase64ToUInt8Array(base64: string): Uint8Array {
  // this is basically a node buffer
  // can get an array buffer with bytes.buffer
  // remove data:image/jpeg;base64, from base64 string if present
  if (base64.startsWith("data:")) {
    base64 = base64.split(",")[1];
  }

  const binary_string = window.atob(base64);
  const len = binary_string.length;
  const bytes = new Uint8Array(len);
  for (let i = 0; i < len; i++) {
    bytes[i] = binary_string.charCodeAt(i);
  }

  return bytes;
}

export async function extractBase64FromBlob(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onloadend = () => resolve(String(reader.result));
    reader.onerror = reject;

    reader.readAsDataURL(blob);
  });
}

If you want to see "proof that it works", you can visit where I am using this code: https://byroni.us/client-image-ops/

Relevant code pulled from: https://github.com/byronwall/client-image-ops/blob/bb5f2ba1694333c0ff7f532cd8bb6ee9885d00a4/src/utils/heic.ts#L5

Sonupro1997 commented 3 months ago

I struggled with this issue. Turns out I was feeding heic2any garbage data but didn't spot it immediately.

My issue is that I had source image data in a base64 data thing like data:image/heic;base64,blahblahblah. I was doing bad operations to get that data into this library. My context is the browser.

Things to keep an eye on:

  • base64 strings usually have a mime type at the front; you need to remove that
  • base64 data needs to be converted to uint8 array and then make a blob from that
  • you then reverse the process to get a base64 string from the blob created by this library

If you're in the same spot, actual working code looks like:

import heic2any from "heic2any";

export async function convertHEICToPNG(base64Data: string) {
  const uint8Array = convertBase64ToUInt8Array(base64Data);

  const blob = new Blob([uint8Array], { type: "image/heic" });

  let pngBlob = await heic2any({
    blob: blob,
    toType: "image/png",
  });

  // get single png blob if heic2any returns an array
  if (Array.isArray(pngBlob)) {
    pngBlob = pngBlob[0];
  }

  // return base 64 data
  return extractBase64FromBlob(pngBlob);
}

export function convertBase64ToUInt8Array(base64: string): Uint8Array {
  // this is basically a node buffer
  // can get an array buffer with bytes.buffer
  // remove data:image/jpeg;base64, from base64 string if present
  if (base64.startsWith("data:")) {
    base64 = base64.split(",")[1];
  }

  const binary_string = window.atob(base64);
  const len = binary_string.length;
  const bytes = new Uint8Array(len);
  for (let i = 0; i < len; i++) {
    bytes[i] = binary_string.charCodeAt(i);
  }

  return bytes;
}

export async function extractBase64FromBlob(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onloadend = () => resolve(String(reader.result));
    reader.onerror = reject;

    reader.readAsDataURL(blob);
  });
}

If you want to see "proof that it works", you can visit where I am using this code: https://byroni.us/client-image-ops/

Relevant code pulled from: https://github.com/byronwall/client-image-ops/blob/bb5f2ba1694333c0ff7f532cd8bb6ee9885d00a4/src/utils/heic.ts#L5

Didn't work for me. Is there any other solution to convert every heic images to jpeg?

shabbir-hossain-ftdl commented 3 months ago

... Didn't work for me. Is there any other solution to convert every heic images to a jpeg?

I fell into this issue earlier. Please feel free to check my comment above. I found a solution that I want to share...

const setUploadImage = async (variable: any, event: Event) => {
    const input = event.target as HTMLInputElement;
    if (input.files && input.files.length > 0) {
      const file = input.files[0];
      console.log('Selected file:', file);
      ...
      ...
      const heic2any = (await import('heic2any')).default;
      const heicToJpegResponse = await heic2any({
            blob: file,
            toType: 'image/jpeg',
            quality: 1,
      });

      const base64String = await blobToBase64Async(heicToJpegResponse as Blob);
      ...

I needed to convert it to a base64 string but you can take the idea and do what you want with it.

BTW, I used "heic2any": "^0.0.4" version.

caffeinated-dj commented 1 week ago

anyone has a workaround for this?