FPDI/FPDF: Watermark and Print Multiple Pages

Mr A picture Mr A · May 6, 2012 · Viewed 22.8k times · Source

I modified this stack question: Applying watermarks on pdf files when users try to download the files but I encountered an error, though there was a comment that says on how to fix it, it wasn't elaborate enough.

Here is the code:

require_once('fpdf/fpdf.php');
require_once('fpdi/fpdi.php');

class WaterMark

{
    public $pdf, $file, $newFile,
        $wmText = "STACKOVERFLOW";

/** $file and $newFile have to include the full path. */
public function __construct($file, $newFile)
{
    $this->pdf = new FPDI();
    $this->file = $file;
    $this->newFile = $newFile;
}

/** $file and $newFile have to include the full path. */
public static function applyAndSpit($file, $newFile)
{
    $wm = new WaterMark($file, $newFile);

    if($wm->isWaterMarked())
        return $wm->spitWaterMarked();
    else{
        $wm->doWaterMark();
        return $wm->spitWaterMarked();
    }
}

/** @todo Make the text nicer and add to all pages */
public function doWaterMark()
{
    $currentFile = $this->file;
    $newFile = $this->newFile;

    $this->pdf->addPage();
    $pagecount = $this->pdf->setSourceFile($currentFile);

    for($i = 1; $i <= $pagecount; $i++){
        $tplidx = $this->pdf->importPage($i);
        $this->pdf->useTemplate($tplidx, 10, 10, 100);
        // now write some text above the imported page
        $this->pdf->SetFont('Arial', 'I', 40);
        $this->pdf->SetTextColor(255,0,0);
        $this->pdf->SetXY(25, 135);
        $this->_rotate(55);
        $this->pdf->Write(0, $this->wmText);
    }

    $this->pdf->Output($newFile, 'F');
}

public function isWaterMarked()
{
    return (file_exists($this->newFile));
}

public function spitWaterMarked()
{
    return readfile($this->newFile);
}

protected function _rotate($angle,$x=-1,$y=-1) {

    if($x==-1)
        $x=$this->pdf->x;
    if($y==-1)
        $y=$this->pdf->y;
    if($this->pdf->angle!=0)
        $this->pdf->_out('Q');
    $this->pdf->angle=$angle;

    if($angle!=0){
        $angle*=M_PI/180;
        $c=cos($angle);
        $s=sin($angle);
        $cx=$x*$this->pdf->k;
        $cy=($this->pdf->h-$y)*$this->pdf->k;

        $this->pdf->_out(sprintf(
            'q %.5f %.5f %.5f %.5f %.2f %.2f cm 1 0 0 1 %.2f %.2f cm',
            $c,$s,-$s,$c,$cx,$cy,-$cx,-$cy));
    }
    } 

}
header('Content-type: application/pdf');
//header('Content-Disposition: attachment; filename="downloaded.pdf"');
WaterMark::applyAndSpit('C:\xampp\htdocs\tst\test0.pdf','C:\xampp\htdocs\tst\output0.pdf');

When I load a pdf that has more than 2 all of the pages merges in one page. I attached the image in this post. enter image description here

Thanks.

Answer

vascowhite picture vascowhite · May 6, 2012

I have found a couple of things wrong with that script. To get it working change the doWatermark() method to this:-

public function doWaterMark()
{
    $currentFile = $this->file;
    $newFile = $this->newFile;

    $pagecount = $this->pdf->setSourceFile($currentFile);

    for($i = 1; $i <= $pagecount; $i++){
        $this->pdf->addPage();//<- moved from outside loop
        $tplidx = $this->pdf->importPage($i);
        $this->pdf->useTemplate($tplidx, 10, 10, 100);
        // now write some text above the imported page
        $this->pdf->SetFont('Arial', 'I', 40);
        $this->pdf->SetTextColor(255,0,0);
        $this->pdf->SetXY(25, 135);
        $this->_rotate(55);
        $this->pdf->Write(0, $this->wmText);
        $this->_rotate(0);//<-added
    }

    $this->pdf->Output($newFile, 'F');
}

I moved the line $this->pdf->addPage(); into the loop, as otherwise everything is output onto one page. I also added $this->_rotate(0); to bring the document back upright before saving it out. Pretty simple really. I have commented the changed lines for you.

I tested it on a 32 page pdf and it seemed to work fine.