9

The solutions for my school's assignments all have waterstamps on the PDFs with our username on it.

I was wondering if you guys know how to do something like that using PHP? Do they run a script prior to the download process?

Thanks.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
ryan
  • 171
  • 1
  • 2
  • 5
  • Their downloader script likely grabs your username, creates a basic image, and uses the `pdf_php` library to layer that image on top of the PDF. – drudge Oct 21 '10 at 00:49
  • How are you generating (or planing to) the PDFs? If you haven't done anything yet, have a look at Webkit to PDF: http://code.google.com/p/wkhtmltopdf/ – Petah Oct 21 '10 at 01:29

4 Answers4

6

Although there are several very good PDF libs for PHP, if I were writing such a program I'd just shell out to run pdftk but you' still need to generate your watermark.

$tempfile=tempnam();
system("pdftk input_file.pdf background watermark.pdf output $tempfile dont_ask", $errcode);
if (!$errcode && $ih=fopen($tempfile, 'r')) {
    header('Content-Type: application/pdf');
    fpassthru($ih);
    fclose($ih);
} else {
    print "Whoops";
}
unlink($tempfile);
symcbean
  • 47,736
  • 6
  • 59
  • 94
5

Needed to do this yesterday and here's how without any external non-PHP libs that need to be installed. The only 2 libs needed are both PHP libs and are easy to get.

Now you can use the class below to achieve watermarking

/** MAKE SURE TO HAVE THE INCLUDES RUNNING PROPERLY */
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;

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

        for($i = 1; $i <= $pagecount; $i++){
                            $this->pdf->addPage();
            $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);
        }

        $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));
        }
    } 

}

You now can run this as:

WaterMark::applyAndSpit($fileWithFullPath);
vascowhite
  • 18,120
  • 9
  • 61
  • 77
haknick
  • 1,892
  • 1
  • 20
  • 28
  • I used this and was getting all the pages displaying on the first page. I was able to fix this by adding `$this->pdf->addPage();` to the end of the loop in `doWaterMark()`. I made some other minor changes so I'm not confident to edit your answer but this may help if others have this problem. – Duane Gran Apr 11 '12 at 15:43
  • I corrected this code in response to [this question](http://stackoverflow.com/q/10468478/212940) – vascowhite May 08 '12 at 06:33
  • Thanks for the code. A couple of little things I've found so far keeping this from being plug-n-play. The "run this" command needs two args: WaterMark::applyAndSpit($fileWithFullPath,$newfilenameWithFullPath); ,and the class uses =&, which is deprecated in current php, just use = . – rpilkey Nov 05 '15 at 14:05
2

There is an excellent opensource php library http://www.tcpdf.org/ , I use it for all pdf generating tasks.

galymzhan
  • 5,505
  • 2
  • 29
  • 45
0

Here are the steps that I tried with water marking using fpdi:

<?php
use setasign\Fpdi\Fpdi;
use setasign\Fpdi\PdfReader;
    function PlaceWatermark($file, $text, $xxx, $yyy, $op, $outdir) {
require_once('fpdi/vendor/autoload.php');
require_once 'fpdi/vendor/setasign/fpdf/fpdf.php';
function copyTransparent($src, $output)
    {
        $dimensions = getimagesize($src);
        $x = $dimensions[0];
        $y = $dimensions[1];
        $im = imagecreatetruecolor($x,$y); 
        $src_ = imagecreatefrompng($src); 
        // Prepare alpha channel for transparent background
        $alpha_channel = imagecolorallocatealpha($im, 255, 255, 255, 127); 
        imagecolortransparent($im, $alpha_channel); 
        // Fill image
        imagefill($im, 0, 0, $alpha_channel); 
        // Copy from other
        imagecopy($im,$src_, 0, 0, 0, 0, $x, $y); 
        // Save transparency
        imagesavealpha($im,true); 
        // Save PNG
        imagepng($im,$output,9); 
        imagedestroy($im); 
    }
$png = 'https://www.office-deals.nl/images/logo_60x37.png';

    copyTransparent($png,"png.png");
$imageURL = 'png.png'; 

     $imgWidth = 20;
$pdf = new FPDI();
    if (file_exists("./".$file)){
        $pagecount = $pdf->setSourceFile($file);
    } else {
        return FALSE;
    }
for($i=1; $i <= $pagecount; $i++) { 
     $tpl = $pdf->importPage($i);               
     $pdf->addPage(); 
     $pdf->useTemplate($tpl, 5, 5);
$pdf->Image($imageURL, $xxx, $yyy,'png');
}


    if ($outdir === TRUE){
        return $pdf->Output($file,'I');
    } else {
        return $pdf->Output();
    }
}
$images='https://www.office-deals.nl/images/logo_60x37.png';
PlaceWatermark("laravel.pdf", $images, 180, 275, 100,TRUE);
?>
Shredator
  • 940
  • 3
  • 17
  • 32
jeenus
  • 53
  • 8