catdad-experiments / heic-convert

🤳 convert heic/heif images to jpeg and png
252 stars 26 forks source link

TypeError: input buffer is not a HEIC image when passing image from base64 buffer #27

Closed bhr closed 1 year ago

bhr commented 1 year ago

Been trying to use heic-convert with an image that is passed as base64 string. Always getting TypeError: input buffer is not a HEIC image.

imagemagick: ~/Downloads/IMG_7316.HEIC HEIC 3024x4032 3024x4032+0+0 8-bit sRGB 2.32526MiB 0.020u 0:00.008

file command: ~/Downloads/IMG_7316.HEIC: ISO Media, HEIF Image HEVC Main or Main Still Picture Profile

This online base64 decoder also identifies the image as HEIC.

Code

const inputBuffer = Buffer.from(heicBase64String, 'base64');
const outputBuffer: Buffer = await convert({
  buffer: inputBuffer,
  format: 'JPEG', // output format
  quality: 0.85, // the jpeg compression quality, between 0 and 1
});

base64-string.txt IMG_7316.HEIC.zip

catdad commented 1 year ago

If you are using the contents of that text file, you are not providing a base64 string but rather a data URI that is base64 encoded. It is subtle, but there is a difference.

image

A data URI contains the scheme (data:), followed by encoding information, then followed by the actual base64 encoded data. The parts of the data URI are not part of the image file itself. Node's Buffer should error, but doesn't... I guess they decide to drop all non-base64 encoded data from the string, but nevertheless, the resulting buffer contains garbage that isn't part of the actual HEIC file (i.e. dataimage/heicbase64 that appears before the data).

To convert a data URI to a buffer, you could use a library such as data-uri-to-buffer or even do it manually.

bhr commented 1 year ago

@catdad Thanks for looking into this! Figured it out too after converting the original buffer back to base64 that it was garbage. Will convert it manually and should be all good then!