import * as pdfjsLib from 'pdfjs-dist'; import pdfjsWorker from 'pdfjs-dist/build/pdf.worker?worker&url'; // eslint-disable-next-line @typescript-eslint/no-explicit-any (pdfjsLib as any).GlobalWorkerOptions.workerSrc = pdfjsWorker; type RotationsMap = Record; export async function generateThumbnails( arrayBuffer: ArrayBuffer, maxHeight = 150 ): Promise { return generateThumbnailsInternal(arrayBuffer, {}, maxHeight); } export async function generateThumbnailsWithRotations( arrayBuffer: ArrayBuffer, rotations: RotationsMap, maxHeight = 150 ): Promise { return generateThumbnailsInternal(arrayBuffer, rotations, maxHeight); } async function generateThumbnailsInternal( arrayBuffer: ArrayBuffer, rotations: RotationsMap, maxHeight: number ): Promise { const loadingTask = pdfjsLib.getDocument({ data: arrayBuffer }); const pdf = await loadingTask.promise; const thumbs: string[] = []; for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) { const page = await pdf.getPage(pageNum); const viewport = page.getViewport({ scale: 1 }); const scale = maxHeight / viewport.height; const scaledViewport = page.getViewport({ scale }); const baseCanvas = document.createElement('canvas'); const baseCtx = baseCanvas.getContext('2d'); if (!baseCtx) { thumbs.push(''); continue; } baseCanvas.width = scaledViewport.width; baseCanvas.height = scaledViewport.height; const renderTask = page.render({ canvasContext: baseCtx, viewport: scaledViewport, }); await renderTask.promise; const originalIndex = pageNum - 1; const rotationDegRaw = rotations[originalIndex] ?? 0; const rotationDeg = ((rotationDegRaw % 360) + 360) % 360; if (rotationDeg === 0) { thumbs.push(baseCanvas.toDataURL('image/png')); continue; } const rotatedCanvas = document.createElement('canvas'); const rotatedCtx = rotatedCanvas.getContext('2d'); if (!rotatedCtx) { thumbs.push(baseCanvas.toDataURL('image/png')); continue; } const rad = (rotationDeg * Math.PI) / 180; if (rotationDeg === 90 || rotationDeg === 270) { rotatedCanvas.width = baseCanvas.height; rotatedCanvas.height = baseCanvas.width; } else { rotatedCanvas.width = baseCanvas.width; rotatedCanvas.height = baseCanvas.height; } rotatedCtx.save(); switch (rotationDeg) { case 90: rotatedCtx.translate(rotatedCanvas.width, 0); rotatedCtx.rotate(rad); break; case 180: rotatedCtx.translate(rotatedCanvas.width, rotatedCanvas.height); rotatedCtx.rotate(rad); break; case 270: rotatedCtx.translate(0, rotatedCanvas.height); rotatedCtx.rotate(rad); break; default: break; } rotatedCtx.drawImage(baseCanvas, 0, 0); rotatedCtx.restore(); thumbs.push(rotatedCanvas.toDataURL('image/png')); } return thumbs; }