Since iPhone 8, a new image format has been around. HEIC files are unfortunately not supported by many frontend tools. While some solutions have been found, here’s how we solved it using a backend trick.
Prerequisites: pyheif, PIL
This post has an image featured from https://www.macworld.co.uk/feature/iphone/what-is-heic-3660408/. Use this link to find out more about HEIC/HEIF files if you want to learn more.
In frontend
Setup your frontend tool to fall back to a base64 img src. If the image uploaded is supported natively, use the base64 encoding provided by the frontend tool. Otherwise, make a backend call to convert the .HEIC file to jpg:
function convert_heic_to_jpeg(image_data, imageId, fallback) {
if (image_data.type != "image/heic") {
$(imageId).attr('src', fallback);
return;
}
var fd = new FormData();
var files = image_data;
fd.append('file', files);
$.ajax({
url: '/ajax/convert-heic-to-jpeg/', # whatever your backend URL for conversion is
type: 'post',
data: fd,
contentType: false,
processData: false,
success: function(data) {
$(imageId).attr('src', data['result']);
return data;
}
});
}
In backend
Configure your URL in routes.py. Write a function that converts the HEIC to JPG, encodes the JPG data to base64 and return it as a JsonResponse.
import pyheif
import io
from PIL import Image
@csrf_exempt
@login_required
def convert_heic_to_jpeg(request):
heic_img = pyheif.read(request.FILES['file'])
pil_image = Image.frombytes(
mode=heic_img.mode, size=heic_img.size, data=heic_img.data
)
output = io.BytesIO()
pil_image.save(output, format="jpeg")
output.seek(0)
return JsonResponse({
'result': "data:image/jpeg;base64," + base64.b64encode(
output.getvalue()
).decode(),
}, status=200)