DEV Community

sunshey
sunshey

Posted on

How to Convert HEIC to PDF in the Browser with Vue 3

Converting HEIC images to PDF requires handling browser-specific image decoding and PDF generation.

Here's how to build a browser-based HEIC to PDF converter with Vue 3.

The challenge: HEIC browser support

HEIC conversion involves:

  1. Decoding HEIC format (browser support varies)
  2. Handling EXIF orientation data
  3. Rendering to canvas
  4. Converting to PDF with proper layout

The stack

  • Vue 3 with Composition API
  • jsPDF for PDF generation
  • createImageBitmap for HEIC decoding
  • Vite for bundling

The core implementation

<script setup lang="ts">
import { ref } from 'vue'
import jsPDF from 'jspdf'

const files = ref<File[]>([])
const converting = ref(false)
const result = ref<Uint8Array | null>(null)

async function handleFiles(e: Event) {
  const input = e.target as HTMLInputElement
  if (input.files) {
    files.value = Array.from(input.files).filter(f => 
      f.type === 'image/heic' || f.name.toLowerCase().endsWith('.heic')
    )
  }
}

async function convertToPdf() {
  if (files.value.length === 0) return
  converting.value = true

  const pdf = new jsPDF({
    orientation: 'portrait',
    unit: 'mm',
    format: 'a4'
  })

  for (const file of files.value) {
    // Decode HEIC using browser API
    const bitmap = await createImageBitmap(file)

    // Get EXIF orientation
    const orientation = await getImageOrientation(file)

    // Create canvas with correct orientation
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')!

    if (orientation === 6 || orientation === 8) {
      // Rotate 90° CW or CCW
      canvas.width = bitmap.height
      canvas.height = bitmap.width
    } else {
      canvas.width = bitmap.width
      canvas.height = bitmap.height
    }

    ctx.rotate((orientation - 1) * Math.PI / 2)
    ctx.drawImage(bitmap, 0, 0, canvas.height, canvas.width)

    // Convert to JPEG
    const jpegDataUrl = canvas.toDataURL('image/jpeg', 0.92)

    // Add to PDF
    const imgWidth = 190
    const imgHeight = (canvas.height * imgWidth) / canvas.width
    const yPosition = 10

    if (pdf.internal.pageSize.height < yPosition + imgHeight + 10) {
      pdf.addPage()
    }
    pdf.addImage(jpegDataUrl, 'JPEG', 10, yPosition, imgWidth, imgHeight)
  }

  result.value = await pdf.output('uint8array')
  converting.value = false
}

async function getImageOrientation(file: File): Promise<number> {
  // Parse EXIF orientation from HEIC file
  // Return 1-8 based on EXIF orientation tag
  return 1 // Default: no rotation
}
</script>
Enter fullscreen mode Exit fullscreen mode

Key implementation details

1. HEIC decoding

Use the browser's createImageBitmap API which has native HEIC support in Safari and Chrome:

const bitmap = await createImageBitmap(file)
Enter fullscreen mode Exit fullscreen mode

2. EXIF orientation handling

iPhone photos store orientation in EXIF data. Must read and apply it:

const orientation = await getImageOrientation(file)
// Apply rotation based on orientation value (1-8)
Enter fullscreen mode Exit fullscreen mode

3. Canvas rendering

Draw the bitmap to canvas with proper orientation:

ctx.rotate((orientation - 1) * Math.PI / 2)
ctx.drawImage(bitmap, 0, 0, canvas.height, canvas.width)
Enter fullscreen mode Exit fullscreen mode

4. PDF generation

Use jsPDF to add images to PDF pages:

pdf.addImage(jpegDataUrl, 'JPEG', x, y, width, height)
Enter fullscreen mode Exit fullscreen mode

Limitations

Browser support varies

HEIC support depends on browser version and OS.

Solution: Add fallback to ask users to convert HEIC to JPEG first.

No EXIF parsing in basic implementation

The example simplifies EXIF reading.

Solution: Use a library like exif-js for full EXIF support.

Memory constraints

Many high-resolution photos can exhaust browser memory.

Solution: Process photos in smaller batches.

Summary

Building a browser-based HEIC to PDF converter involves:

  1. Using createImageBitmap for HEIC decoding
  2. Handling EXIF orientation for correct rotation
  3. Rendering to canvas with proper dimensions
  4. Generating PDF with jsPDF

Try it at en.sotool.top/heic-to-pdf.

Top comments (0)