`;
elements.outputPlaceholder.classList.remove('hidden');
elements.outputContainer.classList.add('hidden');
} else {
elements.generateBtn.innerHTML = `Generate Portrait`;
checkEnableButton();
}
}
function displayResult(base64Data) {
const imageUrl = `data:image/png;base64,${base64Data}`;
elements.resultImage.src = imageUrl;
elements.downloadImageBtn.href = imageUrl;
elements.outputContainer.classList.remove('hidden');
elements.outputPlaceholder.classList.add('hidden');
}
function displayError(message) {
elements.outputPlaceholder.innerHTML = ``;
}
// --- PDF Generation ---
async function generatePdf() {
const resultSrc = elements.resultImage.src;
if (!sourceFile || !targetFile || !resultSrc.startsWith('data:image')) return;
const sourceDataUrl = await toBase64(sourceFile);
const targetDataUrl = await toBase64(targetFile);
const { jsPDF } = window.jspdf;
const doc = new jsPDF('p', 'mm', 'a4');
const margin = 15;
const pageWidth = doc.internal.pageSize.getWidth();
const usableWidth = pageWidth - (margin * 2);
doc.setFont('helvetica', 'bold');
doc.setFontSize(18);
doc.text('AI Portrait Generation Report', pageWidth / 2, 20, { align: 'center' });
doc.autoTable({
startY: 30,
head: [['Source Image (Face)', 'Target Image (Pose)']],
body: [
[{ image: sourceDataUrl, width: 60 }, { image: targetDataUrl, width: 60 }]
],
theme: 'plain',
styles: { halign: 'center' }
});
doc.setFont('helvetica', 'bold');
doc.setFontSize(14);
doc.text('Generated Fictional Portrait', pageWidth / 2, doc.autoTable.previous.finalY + 15, { align: 'center' });
doc.addImage(resultSrc, 'PNG', margin, doc.autoTable.previous.finalY + 20, usableWidth, 0);
doc.save('ai-portrait-report.pdf');
}
});
Generation Failed
${message}
