如何使用 PHP 向现有 PDF 文件添加水印?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2913934/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I add a watermark to an existing PDF file using PHP?
提问by Yasir
I am in need of adding a watermark to an existing PDF file using PHP. I have searched on Google for it, but couldn't find any suitable library.
我需要使用 PHP 向现有 PDF 文件添加水印。我在谷歌上搜索过,但找不到任何合适的图书馆。
I found the fpdflibrary that creates preview thumbnails of PDF files, but I don't know if it adds watermarks to existing PDF files or not. Can anyone suggest a PHP library than can show preview and add watermarks to existing PDF files?
我找到了创建 PDF 文件预览缩略图的fpdf库,但我不知道它是否会向现有 PDF 文件添加水印。谁能建议一个 PHP 库,而不是可以显示预览并向现有 PDF 文件添加水印?
回答by ePirat
Just a quick'n'dirty example using FPDF and the FPDI Classes:
只是一个使用 FPDF 和 FPDI 类的快速示例:
function PlaceWatermark($file, $text, $xxx, $yyy, $op, $outdir) {
require_once('fpdf.php');
require_once('fpdi.php');
$name = uniqid();
$font_size = 5;
$ts=explode("\n",$text);
$width=0;
foreach ($ts as $k=>$string) {
$width=max($width,strlen($string));
}
$width = imagefontwidth($font_size)*$width;
$height = imagefontheight($font_size)*count($ts);
$el=imagefontheight($font_size);
$em=imagefontwidth($font_size);
$img = imagecreatetruecolor($width,$height);
// Background color
$bg = imagecolorallocate($img, 255, 255, 255);
imagefilledrectangle($img, 0, 0,$width ,$height , $bg);
// Font color
$color = imagecolorallocate($img, 0, 0, 0);
foreach ($ts as $k=>$string) {
$len = strlen($string);
$ypos = 0;
for($i=0;$i<$len;$i++){
$xpos = $i * $em;
$ypos = $k * $el;
imagechar($img, $font_size, $xpos, $ypos, $string, $color);
$string = substr($string, 1);
}
}
imagecolortransparent($img, $bg);
$blank = imagecreatetruecolor($width, $height);
$tbg = imagecolorallocate($blank, 255, 255, 255);
imagefilledrectangle($blank, 0, 0,$width ,$height , $tbg);
imagecolortransparent($blank, $tbg);
if ( ($op < 0) OR ($op >100) ){
$op = 100;
}
imagecopymerge($blank, $img, 0, 0, 0, 0, $width, $height, $op);
imagepng($blank,$name.".png");
// Created Watermark Image
$pdf = new FPDI();
if (file_exists("./".$file)){
$pagecount = $pdf->setSourceFile($file);
} else {
return FALSE;
}
$tpl = $pdf->importPage(1);
$pdf->addPage();
$pdf->useTemplate($tpl, 1, 1, 0, 0, TRUE);
//Put the watermark
$pdf->Image($name.'.png', $xxx, $yyy, 0, 0, 'png');
if ($outdir === TRUE){
return $pdf->Output();
} else {
return $pdf;
}
}
PlaceWatermark("filename.pdf", "This is a lazy, but still simple test\n This should stand on a new line!", 30, 120, 100,TRUE);
Usage: PlaceWatermark($filename, $text, $x, $y, $opacity, $directoutput);
用法: PlaceWatermark($filename, $text, $x, $y, $opacity, $directoutput);
$filename– The path of the PDF in which you want to put the Watermark$text– The Watermark text you want to add$x– x coordinate where you want to put the Watermark$y– y coordinate where you want to put the Watermark$opacity– Opacity of the text$directoutput– If TRUE function will output a PDF File, else it will return the $pdf
As I already said, this is a very quick and dirty example, it needs some improvements.
$filename– 要放置水印的 PDF 路径$text– 要添加的水印文本$x– 要放置水印的 x 坐标 – 要放置水印的$yy 坐标$opacity– 文本的不透明度$directoutput– 如果为 TRUE函数将输出一个 PDF 文件,否则它将返回 $pdf
正如我已经说过的,这是一个非常快速和肮脏的例子,它需要一些改进。
回答by Nathan
For anyone else that stumbles upon this post you can generate more pages using a for loop
对于偶然发现这篇文章的其他人,您可以使用 for 循环生成更多页面
for($i=1; $i <= $pagecount; $i++) {
$tpl = $pdf->importPage($i);
$pdf->addPage();
$pdf->useTemplate($tpl, 1, 1, 0, 0, TRUE);
//Put the watermark
$pdf->Image($name.'.png', $xxx, $yyy, 0, 0, 'png');}
回答by cyberfreak
/* index.php */
require('rotation.php');
class PDF extends PDF_Rotate{
protected $_outerText1;// dynamic text
protected $_outerText2;
function setWaterText($txt1="", $txt2=""){
$this->_outerText1 = $txt1;
$this->_outerText2 = $txt2;
}
function Header(){
//Put the watermark
$this->SetFont('Arial','B',40);
$this->SetTextColor(255,192,203);
$this->SetAlpha(0.5);
$this->RotatedText(35,190, $this->_outerText1, 45);
$this->RotatedText(75,190, $this->_outerText2, 45);
}
function RotatedText($x, $y, $txt, $angle){
//Text rotated around its origin
$this->Rotate($angle,$x,$y);
$this->Text($x,$y,$txt);
$this->Rotate(0);
}
}
$file = "path/filename.pdf";// path: file name
$pdf = new PDF();
if (file_exists($file)){
$pagecount = $pdf->setSourceFile($file);
} else {
return FALSE;
}
$pdf->setWaterText("w a t e r M a r k d e m o ", "s e c o n d L i n e o f t e x t");
/* loop for multipage pdf */
for($i=1; $i <= $pagecount; $i++) {
$tpl = $pdf->importPage($i);
$pdf->addPage();
$pdf->useTemplate($tpl, 1, 1, 0, 0, TRUE);
}
$pdf->Output(); //specify path filename to save or keep as it is to view in browser
/* rotation.php */
require('fpdf.php');
require('fpdi.php');
class PDF_Rotate extends FPDI
{
var $angle=0;
var $extgstates = array();
function Rotate($angle,$x=-1,$y=-1)
{
if($x==-1)
$x=$this->x;
if($y==-1)
$y=$this->y;
if($this->angle!=0)
$this->_out('Q');
$this->angle=$angle;
if($angle!=0)
{
$angle*=M_PI/180;
$c=cos($angle);
$s=sin($angle);
$cx=$x*$this->k;
$cy=($this->h-$y)*$this->k;
$this->_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));
}
}
function _endpage()
{
if($this->angle!=0)
{
$this->angle=0;
$this->_out('Q');
}
parent::_endpage();
}
function SetAlpha($alpha, $bm='Normal')
{
// set alpha for stroking (CA) and non-stroking (ca) operations
$gs = $this->AddExtGState(array('ca'=>$alpha, 'CA'=>$alpha, 'BM'=>'/'.$bm));
$this->SetExtGState($gs);
}
function AddExtGState($parms)
{
$n = count($this->extgstates)+1;
$this->extgstates[$n]['parms'] = $parms;
return $n;
}
function SetExtGState($gs)
{
$this->_out(sprintf('/GS%d gs', $gs));
}
function _enddoc()
{
if(!empty($this->extgstates) && $this->PDFVersion<'1.4')
$this->PDFVersion='1.4';
parent::_enddoc();
}
function _putextgstates()
{
for ($i = 1; $i <= count($this->extgstates); $i++)
{
$this->_newobj();
$this->extgstates[$i]['n'] = $this->n;
$this->_out('<</Type /ExtGState');
foreach ($this->extgstates[$i]['parms'] as $k=>$v)
$this->_out('/'.$k.' '.$v);
$this->_out('>>');
$this->_out('endobj');
}
}
function _putresourcedict()
{
parent::_putresourcedict();
$this->_out('/ExtGState <<');
foreach($this->extgstates as $k=>$extgstate)
$this->_out('/GS'.$k.' '.$extgstate['n'].' 0 R');
$this->_out('>>');
}
function _putresources()
{
$this->_putextgstates();
parent::_putresources();
}
}
try this.modified script from fpdf example scripts. Edit : Added opacityuse $this->SetAlpha(0.5)
从 fpdf 示例脚本尝试 this.modified 脚本。 编辑:添加不透明度使用 $this->SetAlpha(0.5)
回答by Yasir
got it by help of Mark here we go http://www.fpdf.de/downloads/addons/9/if you guys think yes it is i will mark my answer as winner.
在马克的帮助下得到它,我们去http://www.fpdf.de/downloads/addons/9/如果你们认为是的,我会将我的答案标记为赢家。
Thanks Jyelton for the answer to my question looks like stackover flow is inactive....
感谢 Jyelton 对我的问题的回答看起来像 stackover 流是不活动的....
回答by Mou Hsiao
Here is a MPDFpractice, adding watermarks to every page of a landscape oriented PDF.
这是一个MPDF实践,为横向 PDF 的每一页添加水印。
//First, get the correct document size.
$mpdf = new \Mpdf\Mpdf([
'tempDir' => storage_path('app'),
'orientation' => 'L'
]);
$pagecount = $mpdf->SetSourceFile('[path]');
$tplId = $mpdf->ImportPage(1);
$size = $mpdf->getTemplateSize($tplId);
//Open a new instance with specified width and height, read the file again
$mpdf = new \Mpdf\Mpdf([
'tempDir' => storage_path('app'),
'format' => [$size['width'], $size['height']]
]);
$mpdf->SetSourceFile('[path]');
//Write into the instance and output it
for ($i=1; $i <= $pagecount; $i++) {
$tplId = $mpdf->ImportPage($i);
$mpdf->addPage();
$mpdf->UseTemplate($tplId);
$mpdf->SetWatermarkText('[Watermark Text]');
$mpdf->showWatermarkText = true;
}
return $mpdf->output();
It took me a while to make the output result in correct size, and finally found the key is that you need to specify the width and height to the instance you are going to write. In my case, the input PDF files may have different sizes, so I have to initiate another instance for getting size before working on the writing one.
If your PDF version is newer than 1.4, PDFI will not work with it. You have to convert it to 1.4. I use xthiago/pdf-version-converterin my Laravel work.
我花了一段时间才使输出结果的大小正确,最后发现关键是您需要为要编写的实例指定宽度和高度。就我而言,输入的 PDF 文件可能具有不同的大小,因此我必须在开始编写文件之前启动另一个实例来获取大小。
如果您的 PDF 版本高于 1.4,PDFI 将无法使用它。您必须将其转换为 1.4。我在 Laravel 工作中使用xthiago/pdf-version-converter。

