iPhone images HEIC to a PDF

2024-06-12
By: O Wolfson

Handling HEIC files from an iPhone and converting them to more commonly used formats like PDF can be a crucial step in many workflows, especially when dealing with large numbers of images. Additionally, compiling these images into a single PDF document can make sharing and storing these images more convenient. This article will walk you through a Node.js script that accomplishes both tasks efficiently.

Requirements

Before we dive into the code, ensure you have the following Node.js packages installed:

sh
npm install fs-extra heic-convert sharp pdf-lib

The Script

Here's the complete script to convert HEIC images to JPEG and then compile them into a PDF:

javascript
const fs = require("fs");
const path = require("path");
const heicConvert = require("heic-convert");
const fsExtra = require("fs-extra");
const sharp = require("sharp");
const { PDFDocument, rgb } = require("pdf-lib");

const inputDirectory = "/path/to/HEIC";
const outputDirectory = "/path/to/jpegs";
const outputPdfPath = "/path/to/output.pdf";

// Ensure the output directory exists
fsExtra.ensureDirSync(outputDirectory);

// Function to convert HEIC to JPEG and compress
async function convertHeicToJpeg(inputPath, outputPath) {
  try {
    const inputBuffer = fs.readFileSync(inputPath);
    const outputBuffer = await heicConvert({
      buffer: inputBuffer, // the HEIC file buffer
      format: "JPEG", // output format
      quality: 0.85, // the jpeg compression quality, between 0 and 1
    });

    // Resize and compress the image using sharp
    await sharp(outputBuffer)
      .resize({ width: 1920 }) // Adjust the width as needed, maintaining aspect ratio
      .jpeg({ quality: 70 }) // Adjust the quality as needed
      .toFile(outputPath);

    console.log(`Converted ${inputPath} to ${outputPath}`);
  } catch (error) {
    console.error(`Error converting ${inputPath}:`, error);
  }
}

// Function to create a PDF from JPEG files
async function createPdfFromJpegs(jpegPaths, pdfPath) {
  const pdfDoc = await PDFDocument.create();

  for (const jpegPath of jpegPaths) {
    const jpegImageBytes = fs.readFileSync(jpegPath);
    const jpegImage = await pdfDoc.embedJpg(jpegImageBytes);
    const page = pdfDoc.addPage([jpegImage.width, jpegImage.height]);
    page.drawImage(jpegImage, {
      x: 0,
      y: 0,
      width: jpegImage.width,
      height: jpegImage.height,
    });
  }

  const pdfBytes = await pdfDoc.save();
  fs.writeFileSync(pdfPath, pdfBytes);
  console.log(`Created PDF at ${pdfPath}`);
}

// Process all HEIC files in the input directory
fs.readdir(inputDirectory, async (err, files) => {
  if (err) {
    console.error("Error reading input directory:", err);
    return;
  }

  const jpegPaths = [];

  for (const file of files) {
    if (file.toLowerCase().endsWith(".heic")) {
      const inputPath = path.join(inputDirectory, file);
      const outputFilename = path.basename(file, path.extname(file)) + ".jpg";
      const outputPath = path.join(outputDirectory, outputFilename);
      await convertHeicToJpeg(inputPath, outputPath);
      jpegPaths.push(outputPath);
    }
  }

  // Create PDF from the converted JPEGs
  if (jpegPaths.length > 0) {
    await createPdfFromJpegs(jpegPaths, outputPdfPath);
  }
});

Explanation

  1. Dependencies:

    • fs and path: Node.js core modules for file system operations and handling file paths.
    • heic-convert: Converts HEIC images to JPEG.
    • fs-extra: Provides extra methods for working with the file system.
    • sharp: An image processing library for resizing and compressing JPEG images.
    • pdf-lib: A library to create and modify PDFs.
  2. Input and Output Directories:

    • Define the input directory containing HEIC files and the output directory for JPEG files and the final PDF.
  3. Ensure Output Directory Exists:

    • Use fsExtra.ensureDirSync(outputDirectory) to make sure the output directory is created if it doesn't exist.
  4. Convert HEIC to JPEG:

    • The convertHeicToJpeg function reads the HEIC file, converts it to JPEG using heic-convert, and then resizes and compresses the image using sharp.
  5. Create PDF from JPEGs:

    • The createPdfFromJpegs function reads each JPEG file, embeds it into a PDF page using pdf-lib, and saves the final PDF.
  6. Process HEIC Files:

    • The script reads all HEIC files from the input directory, converts each to JPEG, and then compiles these JPEGs into a single PDF.

Conclusion

This script efficiently converts HEIC images to JPEG and then compiles them into a PDF, making it easier to handle and share a large number of images. By leveraging Node.js and powerful libraries like sharp and pdf-lib, you can automate this process and ensure high-quality image conversion and PDF creation.