fpdf
PHP powered
home was ist fpdf? downloads & add-ons dokumentation faq forum impressum links kontakt
 

Downloads > Add-On

 
         
 

Memory optimisation

Informations

Author: Philip Clarke
License: Freeware

Description

Normally FPDF compresses the entire PDF in the _putpages() method at the very end of PDF generation, this can lead to a large uncompressed PDF being stored in memory.

This modification compresses each finished page in _endpage() reducing the overall memory usage when generating large PDFs.

To test with minimal external influences, use a file such as the provided test.php. In one terminal window as root run top like so:

~> top -q | grep php

then run the script from the command line, using:

~> php -q test.php > with_opt.pdf

The "top" terminal window will scroll detailing memory usage of php (press q to exit). Then altering test.php to use the base class and running:

~> php -q test.php > no_opt.pdf

will show the original behaviour giving identical sized PDF files (no_opt.pdf and with_opt.pdf). On a 600 MHz dual processor typical results were that the optimised php code uses a maximum of 7.3 Megabytes wheareas the original uses 15 M. Both tests typically take 2 minutes 15 secs. Over very large reports (2000 pages +) the optimised version is very slightly slower by a few seconds.

Source

<?php
require('fpdf.php');

class PDF_Opt extends FPDF
{

function _putpages()
{
    $nb=$this->page;
    if(!empty($this->AliasNbPages))
    {
        //Replace number of pages
        for($n=1;$n<=$nb;$n++)
            $this->pages[$n]=($this->compress) ? gzcompress(str_replace($this->AliasNbPages, $nb, gzuncompress($this->pages[$n]))) : str_replace($this->AliasNbPages, $nb, $this->pages[$n]) ;
    }
    if($this->DefOrientation=='P')
    {
        $wPt=$this->fwPt;
        $hPt=$this->fhPt;
    }
    else
    
{
        $wPt=$this->fhPt;
        $hPt=$this->fwPt;
    }
    $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
    for($n=1;$n<=$nb;$n++)
    {
        //Page
        $this->_newobj();
        $this->_out('<</Type /Page');
        $this->_out('/Parent 1 0 R');
        if(isset($this->OrientationChanges[$n]))
            $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]', $hPt, $wPt));
        $this->_out('/Resources 2 0 R');
        if(isset($this->PageLinks[$n]))
        {
            //Links
            $annots='/Annots [';
            foreach($this->PageLinks[$n] as $pl)
            {
                $rect=sprintf('%.2f %.2f %.2f %.2f', $pl[0], $pl[1], $pl[0]+$pl[2], $pl[1]-$pl[3]);
                $annots.='<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
                if(is_string($pl[4]))
                    $annots.='/A <</S /URI /URI '.$this->_textstring($pl[4]).'>>>>';
                else
                
{
                    $l=$this->links[$pl[4]];
                    $h=isset($this->OrientationChanges[$l[0]]) ? $wPt : $hPt;
                    $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>', 1+2*$l[0], $h-$l[1]*$this->k);
                }
            }
            $this->_out($annots.']');
        }
        $this->_out('/Contents '.($this->n+1).' 0 R>>');
        $this->_out('endobj');
        //Page content
        $this->_newobj();
        $this->_out('<<'.$filter.'/Length '.strlen($this->pages[$n]).'>>');
        $this->_putstream($this->pages[$n]);
        $this->_out('endobj');
    }
    //Pages root
    $this->offsets[1]=strlen($this->buffer);
    $this->_out('1 0 obj');
    $this->_out('<</Type /Pages');
    $kids='/Kids [';
    for($i=0;$i<$nb;$i++)
        $kids.=(3+2*$i).' 0 R ';
    $this->_out($kids.']');
    $this->_out('/Count '.$nb);
    $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]', $wPt, $hPt));
    $this->_out('>>');
    $this->_out('endobj');
}

function _endpage()
{
    //End of page contents
    $this->pages[$this->page] = ($this->compress) ? gzcompress($this->pages[$this->page]) : $this->pages[$this->page];
    $this->state=1;
}

}

?>

Example

Here is an example of test script.

<?php
ini_set
('memory_limit', '100M');
ini_set('max_execution_time', 0);

define('FPDF_FONTPATH', 'font/');
require(
'memory_opt.php');

// for testing purposes only stops a bug where command line php
// believes that headers have already been sent

class TESTING_PDF extends PDF_Opt
{

    function Output()
    {
            echo $this->buffer;
    }

}

$pdf = new TESTING_PDF();
$pdf->Open();
$pdf->AddPage();
$pdf->SetFont('Arial', '', 9);
// generate a constant amount of text for testing
for($i=1; $i<200; $i++)
    $txt .= 'ashfsd kjsahkasjh akjhdsfjkh djshf sjkh ' ;
for(
$i=1; $i<1000; $i++)
    $pdf->Write(9, $txt);
$pdf->Close();
$pdf->Output();

?>

Download

ZIP | TGZ
 






 
         
         
 
 
fpdf.de © Copyright 2004-2006 carrib internet solutions - Beachten Sie bitte die Nutzungsbedingungen
Eine Verwendung der auf fpdf.de befindlichen Inhalte (Texte, Grafiken) ist nur mit Zustimmung des Betreibers zulässig.