document.addEventListener('DOMContentLoaded', function() { // DOM Elements const dropZone = document.getElementById('dropZone'); const imageUpload = document.getElementById('imageUpload'); const uploadBtn = document.getElementById('uploadBtn'); const generateBtn = document.getElementById('generateBtn'); const previewContainer = document.getElementById('previewContainer'); const resultsSection = document.getElementById('resultsSection'); const posterPages = document.getElementById('posterPages'); const printAllBtn = document.getElementById('printAllBtn'); const downloadAllBtn = document.getElementById('downloadAllBtn'); const resetBtn = document.getElementById('resetBtn'); const pageCount = document.getElementById('pageCount'); const orientation = document.getElementById('orientation'); const overlapX = document.getElementById('overlapX'); const overlapY = document.getElementById('overlapY'); const showGrid = document.getElementById('showGrid'); const centerOverlap = document.getElementById('centerOverlap'); let uploadedImage = null; // Event Listeners uploadBtn.addEventListener('click', () => imageUpload.click()); imageUpload.addEventListener('change', handleImageUpload); dropZone.addEventListener('dragover', handleDragOver); dropZone.addEventListener('dragleave', handleDragLeave); dropZone.addEventListener('drop', handleDrop); generateBtn.addEventListener('click', generatePosterPages); printAllBtn.addEventListener('click', printAllPages); downloadAllBtn.addEventListener('click', downloadAllPages); resetBtn.addEventListener('click', resetApp); // Functions function handleImageUpload(e) { const file = e.target.files[0]; if (file && file.type.match('image.*')) { processImageFile(file); } } function handleDragOver(e) { e.preventDefault(); e.stopPropagation(); dropZone.classList.add('drag-over'); } function handleDragLeave(e) { e.preventDefault(); e.stopPropagation(); dropZone.classList.remove('drag-over'); } function handleDrop(e) { e.preventDefault(); e.stopPropagation(); dropZone.classList.remove('drag-over'); const file = e.dataTransfer.files[0]; if (file && file.type.match('image.*')) { processImageFile(file); } } function processImageFile(file) { const reader = new FileReader(); reader.onload = function(e) { uploadedImage = new Image(); uploadedImage.onload = function() { displayPreview(uploadedImage); generateBtn.disabled = false; }; uploadedImage.src = e.target.result; }; reader.readAsDataURL(file); } function displayPreview(image) { previewContainer.innerHTML = ''; const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const maxWidth = 400; const maxHeight = 300; let width = image.width; let height = image.height; if (width > maxWidth) { height = (maxWidth / width) * height; width = maxWidth; } if (height > maxHeight) { width = (maxHeight / height) * width; height = maxHeight; } canvas.width = width; canvas.height = height; ctx.drawImage(image, 0, 0, width, height); previewContainer.appendChild(canvas); } function generatePosterPages() { if (!uploadedImage) return; posterPages.innerHTML = ''; resultsSection.classList.remove('hidden'); const pages = parseInt(pageCount.value); const gridSize = Math.sqrt(pages); const orient = orientation.value; const overlapXPx = (parseInt(overlapX.value) / 25.4) * 96; // Convert mm to pixels (96dpi) const overlapYPx = (parseInt(overlapY.value) / 25.4) * 96; // Convert mm to pixels (96dpi) const showGuides = showGrid.checked; const centerOverlaps = centerOverlap.checked; // Calculate the size of each segment including overlaps const totalOverlapXPx = overlapXPx * (gridSize - 1); const totalOverlapYPx = overlapYPx * (gridSize - 1); // Original image dimensions minus total overlaps const baseWidth = uploadedImage.width - totalOverlapXPx; const baseHeight = uploadedImage.height - totalOverlapYPx; const segmentWidth = baseWidth / gridSize; const segmentHeight = baseHeight / gridSize; // Create a canvas for each page for (let row = 0; row < gridSize; row++) { for (let col = 0; col < gridSize; col++) { const pageNumber = row * gridSize + col + 1; const pageDiv = document.createElement('div'); pageDiv.className = 'poster-page relative'; const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // Set canvas dimensions based on orientation if (orient === 'landscape') { canvas.width = 842; // A4 height as width (landscape) canvas.height = 595; // A4 width as height (landscape) } else { canvas.width = 595; // A4 width in pixels at 72dpi canvas.height = 842; // A4 height in pixels at 72dpi } // Calculate source rectangle with overlaps let sx = col * (segmentWidth) + (col * overlapXPx); let sy = row * (segmentHeight) + (row * overlapYPx); let sw = segmentWidth + (col < gridSize-1 ? overlapXPx : 0); let sh = segmentHeight + (row < gridSize-1 ? overlapYPx : 0); // Ensure we don't exceed image bounds sx = Math.max(0, Math.min(sx, uploadedImage.width - sw)); sy = Math.max(0, Math.min(sy, uploadedImage.height - sh)); sw = Math.min(sw, uploadedImage.width - sx); sh = Math.min(sh, uploadedImage.height - sy); // Draw the image segment ctx.save(); if (orient === 'diagonal') { // Diagonal orientation ctx.translate(canvas.width/2, canvas.height/2); ctx.rotate(Math.PI/4); ctx.drawImage( uploadedImage, sx, sy, sw, sh, -canvas.width/2, -canvas.height/2, canvas.width, canvas.height ); } else { // Standard orientation (portrait or landscape) // Maintain aspect ratio while filling canvas const imgRatio = sw / sh; const canvasRatio = canvas.width / canvas.height; let drawWidth, drawHeight, offsetX = 0, offsetY = 0; if (imgRatio > canvasRatio) { // Image is wider than canvas - fill width drawWidth = canvas.width; drawHeight = canvas.width / imgRatio; offsetY = (canvas.height - drawHeight) / 2; } else { // Image is taller than canvas - fill height drawHeight = canvas.height; drawWidth = canvas.height * imgRatio; offsetX = (canvas.width - drawWidth) / 2; } ctx.drawImage( uploadedImage, sx, sy, sw, sh, offsetX, offsetY, drawWidth, drawHeight ); } // Draw cutting guides if enabled if (showGuides) { ctx.strokeStyle = 'rgba(255, 0, 0, 0.7)'; ctx.lineWidth = 2; if (orient === 'portrait' || orient === 'landscape') { // Draw border for overlap areas const borderX = 10; const borderY = 10; const borderWidth = canvas.width - 20; const borderHeight = canvas.height - 20; ctx.strokeRect(borderX, borderY, borderWidth, borderHeight); // Draw center marks ctx.beginPath(); ctx.moveTo(canvas.width/2 - 15, canvas.height/2); ctx.lineTo(canvas.width/2 + 15, canvas.height/2); ctx.moveTo(canvas.width/2, canvas.height/2 - 15); ctx.lineTo(canvas.width/2, canvas.height/2 + 15); ctx.stroke(); } } // Draw border around the entire canvas ctx.strokeStyle = 'rgba(0, 0, 0, 0.5)'; ctx.lineWidth = 2; ctx.strokeRect(0, 0, canvas.width, canvas.height); ctx.restore(); // Add page number const pageNumDiv = document.createElement('div'); pageNumDiv.className = 'absolute top-2 right-2 bg-white bg-opacity-80 px-2 py-1 rounded text-sm font-bold'; pageNumDiv.textContent = pageNumber; pageDiv.appendChild(pageNumDiv); // Add canvas to page pageDiv.appendChild(canvas); posterPages.appendChild(pageDiv); } } // Scroll to results resultsSection.scrollIntoView({ behavior: 'smooth' }); } function printAllPages() { window.print(); } function downloadAllPages() { alert('PDF generation would be implemented here with a library like jsPDF or browser print to PDF'); } function resetApp() { uploadedImage = null; previewContainer.innerHTML = `

Your image preview will appear here

`; feather.replace(); posterPages.innerHTML = ''; resultsSection.classList.add('hidden'); generateBtn.disabled = true; imageUpload.value = ''; } });