Browser-Based HEIC to PDF Conversion: A Simple Guide

Browser-Based HEIC to PDF Conversion: A Simple Guide

Quick steps to switch HEIC to PDF through JavaScript libraries.

HEIC (High-Efficiency Image Coding) files are commonly used by Apple devices for storing photos. However, these files are not always easily accessible or shareable due to compatibility issues. Converting HEIC images to a more universally accepted format like PDF can be highly beneficial. In this article, we will learn how to convert HEIC files to PDF directly in the browser enviornment if you know a bit of js JavaScript.

Why Convert HEIC to PDF?

  • Compatibility: PDF is a widely supported format across different devices and operating systems.

  • Preservation of Quality: PDF ensures high-quality image rendering and supports various image formats within a single document.

  • Ease of Sharing: PDFs can be easily shared and viewed without worrying about compatibility issues.

  • Privacy: With the advent of AI, your data is not safe on any server. Everyone is using your data to train AI models. That's why Copilot is leaking AWS keys. So, be aware of uploading any data to any server. If your data is sent to server its not safe.

Overview of the Code

Our solution involves four main steps:

  1. Load the HEIC File

  2. Convert HEIC to an Image Format (JPEG)

  3. Create a PDF and Add the Image

  4. Download the PDF

Step 1: Load the HEIC File

We start by creating a file input element in HTML to allow users to select HEIC files from their device. This input element is designed to accept multiple files at once and restricts the file types to those with a .heic extension.

<input type="file" id="fileInput" accept=".heic" multiple />

Step 2: Convert HEIC to an Image Format (JPEG)

To convert HEIC files to JPEG, we utilize the heic2any library. This library can handle the conversion of HEIC files to various formats, including JPEG. We define an asynchronous function, convertHeicToJpeg, which takes a file as input and returns a blob of the converted image.

import heic2any from 'heic2any';

async function convertHeicToJpeg(file) {
  const blob = await heic2any({ blob: file, toType: 'image/jpeg' });
  return blob;
}

Step 3: Create a PDF and Add the Image

In this step, we create a PDF document using the jsPDF library and add the converted JPEG images to it. Here's a detailed breakdown of the process:

Creating the PDF Document

We begin by initializing a new instance of jsPDF.

import { jsPDF } from 'jspdf';

async function createPdf(files) {
  const pdf = new jsPDF();

Looping Through Files

We loop through each HEIC file selected by the user. For each file, we convert it to a JPEG image using the convertHeicToJpeg function, which we discussed earlier. We will learn about blobToDataUrl function later. What this function does is it converts image to a data url which can be passed aound in the browser.

  for (let i = 0; i < files.length; i++) {
    const jpegBlob = await convertHeicToJpeg(files[i]);
    const imgData = await blobToDataUrl(jpegBlob);

Loading the Image

We create a new blank Image object and whenever this image is loaded and it have a src we want to perform certain function on it which will be done by img.onload this allows us to pass a callback whenever an image loads.

    const img = new Image();
    img.onload = () => {

Converting to PDF

To convert to a pdf We first select the width of page and convert it to points img.width * (72 / 96) and we do same for height. Then we have to define if the image is in landscape or portrait mode which we calculate by checking which is longer height or width. If we don't provide the orientation its always loads in portrait mode. Then afetr that we delete the page that is automatically created when we call the new jsPDF(); function once we remove the first page we add a pdf page to our PDF using pdf.addPage([pageWidth, pageHeight], orientation); On this page we can add our image using the addImage function pdf.addImage(imgData, 'JPEG', 0, 0, pageWidth, pageHeight) finally we give it the src of our data url. Why we used data url is explained in the next step.

      const pageWidth = img.width * (72 / 96); // Convert pixels to points
      const pageHeight = img.height * (72 / 96);
      const orientation = pageWidth > pageHeight ? 'landscape' : 'portrait';
      if (index === 0) {
          pdf.deletePage(1);
      }
      pdf.addPage([pageWidth, pageHeight], orientation);

      // Add the image to the new page at its original size
      pdf.addImage(imgData, 'JPEG', 0, 0, pageWidth, pageHeight);
    };

    img.src = imgData;
  }
  return pdf;

Converting Blob to Data URL

We need to convert the image blob to a data URL so that it can be used as the source for the Image object. We use data url otherwise we have to create a file and save it to give it to the src. We do that using a FileReader() in js and read the file as data url to get the required data.

async function blobToDataUrl(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (event) => resolve(event.target.result);
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}

Final functions

Our final functions look something like this.

import { jsPDF } from 'jspdf';

async function createPdf(files) {
  const pdf = new jsPDF();

  for (let i = 0; i < files.length; i++) {
    const jpegBlob = await convertHeicToJpeg(files[i]);
    const imgData = await blobToDataUrl(jpegBlob);
    const img = new Image();

    img.onload = () => {
      const pageWidth = img.width * (72 / 96); // Convert pixels to points
      const pageHeight = img.height * (72 / 96);
      const orientation = pageWidth > pageHeight ? 'landscape' : 'portrait';

      if (index === 0) {
          pdf.deletePage(1);
      }
      pdf.addPage([pageWidth, pageHeight], orientation);

      // Add the image to the new page at its original size
      pdf.addImage(imgData, 'JPEG', 0, 0, pageWidth, pageHeight);
    };

    img.src = imgData;
  }

  return pdf;
}

async function blobToDataUrl(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (event) => resolve(event.target.result);
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}

Step 4: Download the PDF

In the final step, we provide functionality for the user to download the generated PDF.

Creating the Download Function

We define an asynchronous function downloadPdf that takes the selected files as input.

async function downloadPdf(files) {
  const pdf = await createPdf(files);

Generating PDF Blob

We use the output method of jsPDF to generate a blob from the PDF document as we can only give out data as data url.

  const pdfBlob = pdf.output('blob');
  const pdfUrl = URL.createObjectURL(pdfBlob);

Triggering the Download

We create a temporary anchor element (<a>), set its href attribute to the object URL of the PDF blob, and trigger a click event to start the download. After the download starts, we revoke the object URL to free up memory.

  const a = document.createElement('a');
  a.href = pdfUrl;
  a.download = 'converted-images.pdf';
  a.click();
  URL.revokeObjectURL(pdfUrl);
}

Adding Event Listener to File Input

We add an event listener to the file input element to call the downloadPdf function whenever files are selected.

document.getElementById('fileInput').addEventListener('change', (event) => {
  const files = Array.from(event.target.files);
  downloadPdf(files);
});

Final Functions
Our final functions look something like this.

async function downloadPdf(files) {
  const pdf = await createPdf(files);
  const pdfBlob = pdf.output('blob');
  const pdfUrl = URL.createObjectURL(pdfBlob);
  const a = document.createElement('a');
  a.href = pdfUrl;
  a.download = 'converted-images.pdf';
  a.click();
  URL.revokeObjectURL(pdfUrl);
}

document.getElementById('fileInput').addEventListener('change', (event) => {
  const files = Array.from(event.target.files);
  downloadPdf(files);
});

Conclusion

Converting HEIC files to PDF directly in the browser is a practical solution for overcoming compatibility issues and ensuring high-quality image rendering. By following the steps outlined in this article, you can easily convert and share your HEIC images in a universally accepted format. For a seamless and efficient conversion process, you can also visit our website, onlineheicconvert.com, where I have implemented this functionality so that you can convert HEIC files with full privacy.