3

Problem

  • Currently working on creating a live PDF generation preview in Laravel PHP using using PDFI + TCPDF so that a user can import a base PDF and embed text on top of it
  • PDF generation is working fine for all sizes, but large PDFs (e.g. A1 size) generates a 10+ MB file that is too large to serve back to the front end for preview
  • Looking for the quickest and best method to either optimise and reduce the PDF file size, or resize the actual PDF dimension to serve a minified version for preview only

TLDR
Looking for suggestions (other than those I've tried below), or improvements on what I've tried to create a PDF preview file either through resizing or converting to image file of original large PDF.


What I've Tried So Far


Imagick PDF to Image Conversion - Good output size (31mb > 700kb) but slow (1secs > 10secs)
Converting PDF to image using Imagick before creating a minified PDF using the image was my original idea however I found that Imagick was really slow at reading the PDF blob image (takes about 9 seconds compared to sub 1 second for the PDF generation itself). Code is as follows

    // $output === the PDF generated
    $downscaleSizeFactor = $this->jsonFile->canvas['downscale_size_factor'] ?? 1;
    $previewWidth = $this->size['width'] / $downscaleSizeFactor;
    $previewHeight = $this->size['height'] / $downscaleSizeFactor;

    $im = new Imagick;
    $im->readImageBlob($output); // SLOW HERE!!!
    $numPages = $im->getNumberImages();

    $pdfPreview = new TCPDF($this->size["orientation"], 'mm', [$previewWidth,  $previewHeight], true, 'UTF-8', false);
    $pdfPreview->setPrintHeader(false);
    $pdfPreview->setPrintFooter(false);
    $pdfPreview->SetAutoPageBreak(false, 0);

    for($i=0;$i<$numPages;$i++) {
      $im->setIteratorIndex($i);
      $selectedIm = $im->getImage();
      $selectedIm->resizeImage($previewWidth,  $previewHeight, imagick::FILTER_LANCZOS, 1, true);
      $selectedIm->setImageBackgroundColor('white');
      $selectedIm->setImageAlphaChannel(Imagick::ALPHACHANNEL_REMOVE);
      $selectedIm->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);
      $selectedIm->setImageFormat('png');
      $selectedIm->setImageCompressionQuality(100);
      $imageString = $selectedIm->getImageBlob();

      // add a page
      $pdfPreview->AddPage();
      // set JPEG quality
      $pdfPreview->setJPEGQuality(100);
      $pdfPreview->Image('@'.$imageString, 0, 0, $previewWidth,  $previewHeight);
    }

    $im->clear();
    $im->destroy();

    return $pdfPreview->output('', 'S');


Rerun FPDI + TCPDF to generated Minified Version - Bad output size (31mb > 31mb) but extremely fast (1secs > 1.5secs)
Saving the generated PDF to a temporary folder, then using the generated PDF to generate a minified version for preview only. This worked great in terms of speed, however it didn't change the file size at all. Reducing from [600 mm x 800 mm] to [10 mm x 10 mm] did not reduce the file size at all, which is weird. Maybe I missed something if anyone can see. Code as follows

    $reducedPdf = new FpdiTcpdfCustom();
    $tempPdfFile = storage_path('app/templates/pdf/temp/'.$name.'');
    $pageCount = $reducedPdf->setSourceFile($tempPdfFile);

    $pageNo = 1;
    for ($pageNo; $pageNo <= $pageCount; $pageNo++) {
      // Checks if the page is to be skipped

      // Import a page from the blank by setting the
      $pageId = $reducedPdf->importPage($pageNo);
      // Return the size of the imported page
      $size = $reducedPdf->getTemplateSize($pageId);

      // Remove default header/footer
      $reducedPdf->setPrintHeader(false);
      $reducedPdf->setPrintFooter(false);
      $reducedPdf->SetAutoPageBreak(false, 0);

      // Creates the PDF page
      $reducedPdf->AddPage($size['orientation'], [10,10]);
      $reducedPdf->useTemplate($pageId, 0, 0, 10, 10);
    }

    return $reducedPdf->output('', 'S');


Using Spatie\PdfToImage to generate Image File - Good output size (31mb > 218kb) but rubbish speed (1secs > 27secs just to convert and save image)
Similar to previous, looking to convert the PDF to an image file, before resizing and embedding the image into a PDF for preview. But it is extremely slow so I gave up on this method before even generating the PDF.

    $tempPdf = new \Spatie\PdfToImage\Pdf(storage_path('app/templates/pdf/temp/'.$name));
    $tempPdf->setCompressionQuality(10); 
    $tempPdf->saveImage(storage_path('app/templates/pdf/temp/'));



Suggestions?
Does anyone have suggestion on either improving my attempts, or another way of achieving what I need?

Ryan N.
  • 356
  • 4
  • 17

0 Answers0