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:
- Decoding HEIC format (browser support varies)
- Handling EXIF orientation data
- Rendering to canvas
- 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>
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)
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)
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)
4. PDF generation
Use jsPDF to add images to PDF pages:
pdf.addImage(jpegDataUrl, 'JPEG', x, y, width, height)
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:
- Using
createImageBitmapfor HEIC decoding - Handling EXIF orientation for correct rotation
- Rendering to canvas with proper dimensions
- Generating PDF with jsPDF
Try it at en.sotool.top/heic-to-pdf.
Top comments (0)