@pdfme/converter
Version:
TypeScript base PDF generator and React base UI. Open source, developed by the community, and completely free to use under the MIT license!
88 lines • 3.77 kB
JavaScript
import { PDFDocument } from '@pdfme/pdf-lib';
import { mm2pt } from '@pdfme/common';
function detectImageType(buffer) {
const bytes = new Uint8Array(buffer);
if (bytes.length >= 2 && bytes[0] === 0xff && bytes[1] === 0xd8) {
return 'jpeg';
}
if (bytes.length >= 8 &&
bytes[0] === 0x89 &&
bytes[1] === 0x50 &&
bytes[2] === 0x4e &&
bytes[3] === 0x47 &&
bytes[4] === 0x0d &&
bytes[5] === 0x0a &&
bytes[6] === 0x1a &&
bytes[7] === 0x0a) {
return 'png';
}
return 'unknown';
}
export async function img2pdf(imgs, options = {}) {
try {
const { scale = 1, size, margin = [0, 0, 0, 0] } = options;
if (!Array.isArray(imgs) || imgs.length === 0) {
throw new Error('Input must be a non-empty array of image buffers');
}
const doc = await PDFDocument.create();
for (const img of imgs) {
try {
let image;
const type = detectImageType(img);
if (type === 'jpeg') {
image = await doc.embedJpg(img);
}
else if (type === 'png') {
image = await doc.embedPng(img);
}
else {
try {
image = await doc.embedJpg(img);
}
catch {
image = await doc.embedPng(img);
}
}
const page = doc.addPage();
const { width: imgWidth, height: imgHeight } = image.scale(scale);
// Set page size based on size option or image dimensions
const pageWidth = size ? mm2pt(size.width) : imgWidth;
const pageHeight = size ? mm2pt(size.height) : imgHeight;
page.setSize(pageWidth, pageHeight);
// Convert margins from mm to points
const [topMargin, rightMargin, bottomMargin, leftMargin] = margin.map(mm2pt);
// Calculate available space for the image after applying margins
const availableWidth = pageWidth - leftMargin - rightMargin;
const availableHeight = pageHeight - topMargin - bottomMargin;
// Calculate scaling to fit image within available space while maintaining aspect ratio
const widthRatio = availableWidth / imgWidth;
const heightRatio = availableHeight / imgHeight;
const ratio = Math.min(widthRatio, heightRatio, 1); // Don't upscale images
// Calculate final image dimensions and position
const finalWidth = imgWidth * ratio;
const finalHeight = imgHeight * ratio;
const x = leftMargin + (availableWidth - finalWidth) / 2; // Center horizontally
const y = bottomMargin + (availableHeight - finalHeight) / 2; // Center vertically
page.drawImage(image, {
x,
y,
width: finalWidth,
height: finalHeight,
});
}
catch (error) {
throw new Error(`Failed to process image: ${error.message}`);
}
}
const pdfUint8Array = await doc.save();
// Create a new ArrayBuffer from the Uint8Array to ensure we return only ArrayBuffer
const buffer = new ArrayBuffer(pdfUint8Array.byteLength);
const view = new Uint8Array(buffer);
view.set(pdfUint8Array);
return buffer;
}
catch (error) {
throw new Error(`[@pdfme/converter] img2pdf failed: ${error.message}`);
}
}
//# sourceMappingURL=img2pdf.js.map