Why Add Watermarks to PDF Documents?
Before diving into the implementation, let's understand why PHP PDF watermark functionality is crucial for modern web applications:
- Copyright Protection: Mark documents as proprietary or confidential
- Brand Identity: Add company logos or branding elements
- Document Status: Indicate draft, confidential, or approved status
- Security: Prevent unauthorized distribution of sensitive documents
- Traceability: Add user-specific watermarks for tracking
Prerequisites and Requirements
To add watermark in PDF using PHP, you'll need the following:
- PHP 7.4 or higher installed on your server
- Composer for dependency management
- FPDI library PHP (Free PDF Document Importer)
- TCPDF watermark library for PDF generation
- Basic understanding of PHP and object-oriented programming
Project Structure Setup
First, create a proper project structure. Here's the recommended folder organization for your PDF manipulation PHP project:
project-root/
│
├── vendor/ # Composer dependencies
├── input/ # Original PDF files
├── output/ # Watermarked PDF files
├── watermarks/ # Watermark images (logos, stamps)
├── src/
│ ├── PdfWatermark.php # Main watermark class
│ └── config.php # Configuration file
├── examples/
│ ├── text-watermark.php # Text watermark example
│ └── image-watermark.php # Image watermark example
├── composer.json # Composer dependencies
└── index.php # Main application file
Step 1: Install Required Libraries
To begin adding watermarks to PDFs, install the necessary libraries using Composer. Create a composer.json
file in your project root:
{
"require": {
"setasign/fpdi": "^2.3",
"tecnickcom/tcpdf": "^6.6"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Run the following command in your terminal to install the dependencies:
composer install
Step 2: Create Configuration File
Create a src/config.php
file to store configuration settings for your watermark PDF document PHP application:
<?php
return [
'input_path' => __DIR__ . '/../input/',
'output_path' => __DIR__ . '/../output/',
'watermark_path' => __DIR__ . '/../watermarks/',
// Default text watermark settings
'text_watermark' => [
'font' => 'helvetica',
'font_size' => 50,
'color' => [200, 200, 200], // RGB
'opacity' => 0.3,
'angle' => 45,
'text' => 'CONFIDENTIAL'
],
// Default image watermark settings
'image_watermark' => [
'opacity' => 0.3,
'width' => 100,
'height' => 100,
'position' => 'center' // center, top-left, top-right, bottom-left, bottom-right
]
];
Step 3: Create the PDF Watermark Class
Now, create the main class for PHP PDF processing. Create a file src/PdfWatermark.php
:
<?php
namespace App;
use setasign\Fpdi\Tcpdf\Fpdi;
class PdfWatermark extends Fpdi
{
private $config;
public function __construct()
{
parent::__construct();
$this->config = include __DIR__ . '/config.php';
$this->SetAutoPageBreak(false);
}
/**
* Add text watermark to PDF
*
* @param string $inputFile Input PDF file path
* @param string $outputFile Output PDF file path
* @param string $watermarkText Watermark text
* @param array $options Custom options (font_size, color, opacity, angle)
* @return bool Success status
*/
public function addTextWatermark($inputFile, $outputFile, $watermarkText = null, $options = [])
{
try {
// Set default watermark text
$watermarkText = $watermarkText ?? $this->config['text_watermark']['text'];
// Merge options with defaults
$settings = array_merge($this->config['text_watermark'], $options);
// Get total number of pages
$pageCount = $this->setSourceFile($inputFile);
// Process each page
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
// Import page
$templateId = $this->importPage($pageNo);
$size = $this->getTemplateSize($templateId);
// Add a page with same orientation and size
$orientation = ($size['width'] > $size['height']) ? 'L' : 'P';
$this->AddPage($orientation, [$size['width'], $size['height']]);
// Use the imported page
$this->useTemplate($templateId);
// Add text watermark
$this->addTextToPage(
$watermarkText,
$size['width'],
$size['height'],
$settings
);
}
// Output the PDF
return $this->Output($outputFile, 'F');
} catch (\Exception $e) {
error_log("Error adding text watermark: " . $e->getMessage());
return false;
}
}
/**
* Add image watermark to PDF
*
* @param string $inputFile Input PDF file path
* @param string $outputFile Output PDF file path
* @param string $watermarkImage Watermark image file path
* @param array $options Custom options (opacity, width, height, position)
* @return bool Success status
*/
public function addImageWatermark($inputFile, $outputFile, $watermarkImage, $options = [])
{
try {
// Check if watermark image exists
if (!file_exists($watermarkImage)) {
throw new \Exception("Watermark image not found: " . $watermarkImage);
}
// Merge options with defaults
$settings = array_merge($this->config['image_watermark'], $options);
// Get total number of pages
$pageCount = $this->setSourceFile($inputFile);
// Process each page
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
// Import page
$templateId = $this->importPage($pageNo);
$size = $this->getTemplateSize($templateId);
// Add a page with same orientation and size
$orientation = ($size['width'] > $size['height']) ? 'L' : 'P';
$this->AddPage($orientation, [$size['width'], $size['height']]);
// Use the imported page
$this->useTemplate($templateId);
// Add image watermark
$this->addImageToPage(
$watermarkImage,
$size['width'],
$size['height'],
$settings
);
}
// Output the PDF
return $this->Output($outputFile, 'F');
} catch (\Exception $e) {
error_log("Error adding image watermark: " . $e->getMessage());
return false;
}
}
/**
* Add text to a page
*
* @param string $text Watermark text
* @param float $pageWidth Page width
* @param float $pageHeight Page height
* @param array $settings Watermark settings
*/
private function addTextToPage($text, $pageWidth, $pageHeight, $settings)
{
// Set font
$this->SetFont($settings['font'], 'B', $settings['font_size']);
// Set text color
$this->SetTextColor(
$settings['color'][0],
$settings['color'][1],
$settings['color'][2]
);
// Set opacity
$this->SetAlpha($settings['opacity']);
// Calculate center position
$x = $pageWidth / 2;
$y = $pageHeight / 2;
// Start transformation
$this->StartTransform();
// Rotate text
$this->Rotate($settings['angle'], $x, $y);
// Add text centered
$this->Text($x, $y, $text, false, false, true, 0, 0, 'C');
// Stop transformation
$this->StopTransform();
// Reset opacity
$this->SetAlpha(1);
}
/**
* Add image to a page
*
* @param string $imagePath Watermark image path
* @param float $pageWidth Page width
* @param float $pageHeight Page height
* @param array $settings Watermark settings
*/
private function addImageToPage($imagePath, $pageWidth, $pageHeight, $settings)
{
// Set opacity
$this->SetAlpha($settings['opacity']);
// Calculate position based on settings
$positions = $this->calculateImagePosition(
$pageWidth,
$pageHeight,
$settings['width'],
$settings['height'],
$settings['position']
);
// Add image
$this->Image(
$imagePath,
$positions['x'],
$positions['y'],
$settings['width'],
$settings['height'],
'',
'',
'',
true,
300
);
// Reset opacity
$this->SetAlpha(1);
}
/**
* Calculate image position
*
* @param float $pageWidth Page width
* @param float $pageHeight Page height
* @param float $imgWidth Image width
* @param float $imgHeight Image height
* @param string $position Position (center, top-left, etc.)
* @return array X and Y coordinates
*/
private function calculateImagePosition($pageWidth, $pageHeight, $imgWidth, $imgHeight, $position)
{
$positions = [
'center' => [
'x' => ($pageWidth - $imgWidth) / 2,
'y' => ($pageHeight - $imgHeight) / 2
],
'top-left' => [
'x' => 10,
'y' => 10
],
'top-right' => [
'x' => $pageWidth - $imgWidth - 10,
'y' => 10
],
'bottom-left' => [
'x' => 10,
'y' => $pageHeight - $imgHeight - 10
],
'bottom-right' => [
'x' => $pageWidth - $imgWidth - 10,
'y' => $pageHeight - $imgHeight - 10
]
];
return $positions[$position] ?? $positions['center'];
}
}
Step 4: Create Text Watermark Example
Create a file examples/text-watermark.php
to demonstrate how to add text watermark PDF:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use App\PdfWatermark;
// Initialize PDF Watermark
$pdf = new PdfWatermark();
// Define input and output files
$inputFile = __DIR__ . '/../input/sample.pdf';
$outputFile = __DIR__ . '/../output/watermarked-text.pdf';
// Add text watermark with default settings
$success = $pdf->addTextWatermark($inputFile, $outputFile);
if ($success) {
echo "Text watermark added successfully!\n";
echo "Output file: " . $outputFile . "\n";
} else {
echo "Failed to add text watermark.\n";
}
// Example with custom options
$customOptions = [
'font_size' => 60,
'color' => [255, 0, 0], // Red color
'opacity' => 0.5,
'angle' => 30
];
$outputFileCustom = __DIR__ . '/../output/watermarked-custom.pdf';
$success = $pdf->addTextWatermark(
$inputFile,
$outputFileCustom,
'DRAFT - DO NOT DISTRIBUTE',
$customOptions
);
if ($success) {
echo "Custom text watermark added successfully!\n";
echo "Output file: " . $outputFileCustom . "\n";
}
Step 5: Create Image Watermark Example
Create a file examples/image-watermark.php
to demonstrate how to add image watermark PDF:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use App\PdfWatermark;
// Initialize PDF Watermark
$pdf = new PdfWatermark();
// Define input and output files
$inputFile = __DIR__ . '/../input/sample.pdf';
$outputFile = __DIR__ . '/../output/watermarked-image.pdf';
$watermarkImage = __DIR__ . '/../watermarks/logo.png';
// Add image watermark with default settings (center position)
$success = $pdf->addImageWatermark($inputFile, $outputFile, $watermarkImage);
if ($success) {
echo "Image watermark added successfully!\n";
echo "Output file: " . $outputFile . "\n";
} else {
echo "Failed to add image watermark.\n";
}
// Example with custom options (bottom-right position)
$customOptions = [
'opacity' => 0.4,
'width' => 150,
'height' => 150,
'position' => 'bottom-right'
];
$outputFileCustom = __DIR__ . '/../output/watermarked-logo-corner.pdf';
$success = $pdf->addImageWatermark(
$inputFile,
$outputFileCustom,
$watermarkImage,
$customOptions
);
if ($success) {
echo "Custom image watermark added successfully!\n";
echo "Output file: " . $outputFileCustom . "\n";
}
Step 6: Create Main Application File
Create an index.php
file as the main entry point for your application:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use App\PdfWatermark;
// Check if form is submitted
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pdf = new PdfWatermark();
$config = include __DIR__ . '/src/config.php';
// Handle file upload
if (isset($_FILES['pdf_file']) && $_FILES['pdf_file']['error'] === UPLOAD_ERR_OK) {
$uploadedFile = $_FILES['pdf_file']['tmp_name'];
$originalName = $_FILES['pdf_file']['name'];
$watermarkType = $_POST['watermark_type'] ?? 'text';
// Generate output filename
$outputFile = $config['output_path'] . 'watermarked_' . time() . '_' . $originalName;
if ($watermarkType === 'text') {
// Text watermark
$watermarkText = $_POST['watermark_text'] ?? 'CONFIDENTIAL';
$fontSize = intval($_POST['font_size'] ?? 50);
$opacity = floatval($_POST['opacity'] ?? 0.3);
$angle = intval($_POST['angle'] ?? 45);
$options = [
'font_size' => $fontSize,
'opacity' => $opacity,
'angle' => $angle
];
$success = $pdf->addTextWatermark($uploadedFile, $outputFile, $watermarkText, $options);
} else {
// Image watermark
if (isset($_FILES['watermark_image']) && $_FILES['watermark_image']['error'] === UPLOAD_ERR_OK) {
$watermarkImage = $_FILES['watermark_image']['tmp_name'];
$width = intval($_POST['image_width'] ?? 100);
$height = intval($_POST['image_height'] ?? 100);
$opacity = floatval($_POST['image_opacity'] ?? 0.3);
$position = $_POST['position'] ?? 'center';
$options = [
'width' => $width,
'height' => $height,
'opacity' => $opacity,
'position' => $position
];
$success = $pdf->addImageWatermark($uploadedFile, $outputFile, $watermarkImage, $options);
} else {
$success = false;
$error = "Please upload a watermark image.";
}
}
if ($success) {
// Download the watermarked PDF
header('Content-Type: application/pdf');
header('Content-Disposition: attachment; filename="' . basename($outputFile) . '"');
header('Content-Length: ' . filesize($outputFile));
readfile($outputFile);
exit;
} else {
$error = $error ?? "Failed to add watermark to PDF.";
}
} else {
$error = "Please upload a PDF file.";
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Add Watermark to PDF using PHP</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #01AEEF 0%, #0288D1 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.container {
background: white;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
max-width: 600px;
width: 100%;
padding: 40px;
}
h1 {
color: #01AEEF;
margin-bottom: 10px;
font-size: 28px;
}
.subtitle {
color: #666;
margin-bottom: 30px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
color: #333;
font-weight: 600;
}
input[type="file"],
input[type="text"],
input[type="number"],
select {
width: 100%;
padding: 12px;
border: 2px solid #e0e0e0;
border-radius: 6px;
font-size: 14px;
transition: border-color 0.3s;
}
input:focus,
select:focus {
outline: none;
border-color: #01AEEF;
}
.radio-group {
display: flex;
gap: 20px;
margin-top: 8px;
}
.radio-group label {
display: flex;
align-items: center;
gap: 8px;
font-weight: normal;
cursor: pointer;
}
.watermark-options {
display: none;
animation: fadeIn 0.3s;
}
.watermark-options.active {
display: block;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
button {
width: 100%;
padding: 14px;
background: #01AEEF;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: background 0.3s;
}
button:hover {
background: #0288D1;
}
.error {
background: #ffebee;
color: #c62828;
padding: 12px;
border-radius: 6px;
margin-bottom: 20px;
}
</style>
</head>
<body>
<div class="container">
<h1>PDF Watermark Tool</h1>
<p class="subtitle">Add text or image watermarks to your PDF documents</p>
<?php if (isset($error)): ?>
<div class="error"><?php echo htmlspecialchars($error); ?></div>
<?php endif; ?>
<form method="POST" enctype="multipart/form-data">
<div class="form-group">
<label>Upload PDF File</label>
<input type="file" name="pdf_file" accept=".pdf" required>
</div>
<div class="form-group">
<label>Watermark Type</label>
<div class="radio-group">
<label>
<input type="radio" name="watermark_type" value="text" checked onchange="toggleWatermarkOptions()">
Text Watermark
</label>
<label>
<input type="radio" name="watermark_type" value="image" onchange="toggleWatermarkOptions()">
Image Watermark
</label>
</div>
</div>
<div id="textOptions" class="watermark-options active">
<div class="form-group">
<label>Watermark Text</label>
<input type="text" name="watermark_text" value="CONFIDENTIAL">
</div>
<div class="form-group">
<label>Font Size</label>
<input type="number" name="font_size" value="50" min="10" max="100">
</div>
<div class="form-group">
<label>Opacity (0.1 - 1.0)</label>
<input type="number" name="opacity" value="0.3" step="0.1" min="0.1" max="1.0">
</div>
<div class="form-group">
<label>Rotation Angle (degrees)</label>
<input type="number" name="angle" value="45" min="0" max="360">
</div>
</div>
<div id="imageOptions" class="watermark-options">
<div class="form-group">
<label>Upload Watermark Image</label>
<input type="file" name="watermark_image" accept="image/*">
</div>
<div class="form-group">
<label>Image Width (px)</label>
<input type="number" name="image_width" value="100" min="10">
</div>
<div class="form-group">
<label>Image Height (px)</label>
<input type="number" name="image_height" value="100" min="10">
</div>
<div class="form-group">
<label>Opacity (0.1 - 1.0)</label>
<input type="number" name="image_opacity" value="0.3" step="0.1" min="0.1" max="1.0">
</div>
<div class="form-group">
<label>Position</label>
<select name="position">
<option value="center">Center</option>
<option value="top-left">Top Left</option>
<option value="top-right">Top Right</option>
<option value="bottom-left">Bottom Left</option>
<option value="bottom-right">Bottom Right</option>
</select>
</div>
</div>
<button type="submit">Add Watermark & Download</button>
</form>
</div>
<script>
function toggleWatermarkOptions() {
const textRadio = document.querySelector('input[name="watermark_type"][value="text"]');
const textOptions = document.getElementById('textOptions');
const imageOptions = document.getElementById('imageOptions');
if (textRadio.checked) {
textOptions.classList.add('active');
imageOptions.classList.remove('active');
} else {
textOptions.classList.remove('active');
imageOptions.classList.add('active');
}
}
</script>
</body>
</html>
Advanced Features and Customization
1. Multiple Watermarks on Single Page
You can extend the PHP PDF watermark functionality to add multiple watermarks. Add this method to your PdfWatermark
class:
/**
* Add multiple watermarks to PDF
*
* @param string $inputFile Input PDF file path
* @param string $outputFile Output PDF file path
* @param array $watermarks Array of watermark configurations
* @return bool Success status
*/
public function addMultipleWatermarks($inputFile, $outputFile, $watermarks)
{
try {
$pageCount = $this->setSourceFile($inputFile);
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
$templateId = $this->importPage($pageNo);
$size = $this->getTemplateSize($templateId);
$orientation = ($size['width'] > $size['height']) ? 'L' : 'P';
$this->AddPage($orientation, [$size['width'], $size['height']]);
$this->useTemplate($templateId);
// Add each watermark
foreach ($watermarks as $watermark) {
if ($watermark['type'] === 'text') {
$this->addTextToPage(
$watermark['text'],
$size['width'],
$size['height'],
$watermark['settings']
);
} elseif ($watermark['type'] === 'image') {
$this->addImageToPage(
$watermark['image'],
$size['width'],
$size['height'],
$watermark['settings']
);
}
}
}
return $this->Output($outputFile, 'F');
} catch (\Exception $e) {
error_log("Error adding multiple watermarks: " . $e->getMessage());
return false;
}
}
2. Page-Specific Watermarks
To add watermarks to specific pages only, create this method:
/**
* Add watermark to specific pages
*
* @param string $inputFile Input PDF file path
* @param string $outputFile Output PDF file path
* @param array $pageNumbers Array of page numbers to watermark
* @param string $watermarkText Watermark text
* @param array $options Watermark options
* @return bool Success status
*/
public function addWatermarkToPages($inputFile, $outputFile, $pageNumbers, $watermarkText, $options = [])
{
try {
$settings = array_merge($this->config['text_watermark'], $options);
$pageCount = $this->setSourceFile($inputFile);
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
$templateId = $this->importPage($pageNo);
$size = $this->getTemplateSize($templateId);
$orientation = ($size['width'] > $size['height']) ? 'L' : 'P';
$this->AddPage($orientation, [$size['width'], $size['height']]);
$this->useTemplate($templateId);
// Only add watermark to specified pages
if (in_array($pageNo, $pageNumbers)) {
$this->addTextToPage($watermarkText, $size['width'], $size['height'], $settings);
}
}
return $this->Output($outputFile, 'F');
} catch (\Exception $e) {
error_log("Error adding watermark to specific pages: " . $e->getMessage());
return false;
}
}
3. Dynamic User-Based Watermarks
For document tracking, add user-specific watermarks. Create a new example file examples/user-watermark.php
:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use App\PdfWatermark;
// User information
$userName = "John Doe";
$userEmail = "john.doe@example.com";
$timestamp = date('Y-m-d H:i:s');
// Create watermark text with user info
$watermarkText = $userName . "\n" . $userEmail . "\n" . $timestamp;
// Initialize PDF Watermark
$pdf = new PdfWatermark();
$inputFile = __DIR__ . '/../input/document.pdf';
$outputFile = __DIR__ . '/../output/tracked-document.pdf';
// Custom settings for user watermark (smaller, in corner)
$options = [
'font_size' => 8,
'color' => [128, 128, 128],
'opacity' => 0.5,
'angle' => 0
];
$success = $pdf->addTextWatermark($inputFile, $outputFile, $watermarkText, $options);
if ($success) {
echo "User-specific watermark added successfully!\n";
}
Best Practices for PDF Watermarking
Performance Optimization
When working with large PDFs or batch processing, follow these optimization tips:
- Memory Management: Process files in batches and clear memory between operations
- Caching: Cache frequently used watermark images
- Asynchronous Processing: Use queue systems for bulk watermarking
- File Size: Compress watermark images before applying
// Example: Batch processing with memory management
function batchWatermark($inputFiles, $watermarkText)
{
foreach ($inputFiles as $inputFile) {
$pdf = new PdfWatermark();
$outputFile = str_replace('.pdf', '_watermarked.pdf', $inputFile);
$pdf->addTextWatermark($inputFile, $outputFile, $watermarkText);
// Clear memory
unset($pdf);
gc_collect_cycles();
}
}
Security Considerations
Implement these security measures when handling PDF files:
- File Validation: Always validate uploaded files are genuine PDFs
- Size Limits: Set maximum file size limits to prevent DoS attacks
- Sanitization: Sanitize watermark text input to prevent injection attacks
- Permissions: Set appropriate file permissions on output directories
// File validation example
function validatePdfFile($filePath, $maxSize = 10485760) // 10MB default
{
// Check file exists
if (!file_exists($filePath)) {
throw new Exception("File does not exist");
}
// Check file size
if (filesize($filePath) > $maxSize) {
throw new Exception("File size exceeds maximum allowed");
}
// Check MIME type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mimeType = finfo_file($finfo, $filePath);
finfo_close($finfo);
if ($mimeType !== 'application/pdf') {
throw new Exception("Invalid file type. Only PDF files are allowed");
}
// Check PDF signature
$handle = fopen($filePath, 'r');
$header = fread($handle, 5);
fclose($handle);
if (strpos($header, '%PDF') !== 0) {
throw new Exception("Invalid PDF file");
}
return true;
}
Troubleshooting Common Issues
Issue 1: Memory Exhaustion
Problem: "Allowed memory size exhausted" error when processing large PDFs.
Solution: Increase PHP memory limit or process pages individually:
// In your PHP script or php.ini
ini_set('memory_limit', '256M');
// Or process in chunks
set_time_limit(300); // 5 minutes
ini_set('memory_limit', '512M');
Issue 2: Watermark Not Visible
Problem: Watermark is added but not visible in the PDF.
Solution: Adjust opacity and color settings:
$options = [
'opacity' => 0.5, // Increase from 0.3
'color' => [100, 100, 100], // Darker gray
'font_size' => 60 // Larger font
];
Issue 3: Text Encoding Problems
Problem: Special characters not displaying correctly.
Solution: Use UTF-8 encoding and appropriate fonts:
// Ensure UTF-8 encoding
$watermarkText = mb_convert_encoding($watermarkText, 'UTF-8', 'auto');
// Use Unicode-compatible fonts
$this->SetFont('dejavusans', 'B', 50); // Instead of helvetica
Testing Your Implementation
Create a test file tests/watermark-test.php
to verify your implementation:
<?php
require_once __DIR__ . '/../vendor/autoload.php';
use App\PdfWatermark;
echo "Starting PDF Watermark Tests...\n\n";
// Test 1: Basic Text Watermark
echo "Test 1: Basic Text Watermark... ";
$pdf1 = new PdfWatermark();
$result1 = $pdf1->addTextWatermark(
__DIR__ . '/../input/test.pdf',
__DIR__ . '/../output/test-basic-text.pdf'
);
echo $result1 ? "PASSED\n" : "FAILED\n";
// Test 2: Custom Text Watermark
echo "Test 2: Custom Text Watermark... ";
$pdf2 = new PdfWatermark();
$result2 = $pdf2->addTextWatermark(
__DIR__ . '/../input/test.pdf',
__DIR__ . '/../output/test-custom-text.pdf',
'DRAFT',
['font_size' => 70, 'opacity' => 0.4, 'angle' => 30]
);
echo $result2 ? "PASSED\n" : "FAILED\n";
// Test 3: Image Watermark
echo "Test 3: Image Watermark... ";
$pdf3 = new PdfWatermark();
$result3 = $pdf3->addImageWatermark(
__DIR__ . '/../input/test.pdf',
__DIR__ . '/../output/test-image.pdf',
__DIR__ . '/../watermarks/logo.png'
);
echo $result3 ? "PASSED\n" : "FAILED\n";
// Test 4: Multiple Watermarks
echo "Test 4: Multiple Watermarks... ";
$pdf4 = new PdfWatermark();
$watermarks = [
[
'type' => 'text',
'text' => 'CONFIDENTIAL',
'settings' => ['font_size' => 50, 'opacity' => 0.3, 'angle' => 45, 'font' => 'helvetica', 'color' => [200, 200, 200]]
],
[
'type' => 'image',
'image' => __DIR__ . '/../watermarks/logo.png',
'settings' => ['opacity' => 0.3, 'width' => 80, 'height' => 80, 'position' => 'bottom-right']
]
];
$result4 = $pdf4->addMultipleWatermarks(
__DIR__ . '/../input/test.pdf',
__DIR__ . '/../output/test-multiple.pdf',
$watermarks
);
echo $result4 ? "PASSED\n" : "FAILED\n";
echo "\nAll tests completed!\n";
Conclusion
You now have a complete, production-ready solution to add watermark in PDF using PHP. This implementation using the FPDI library PHP and TCPDF watermark functionality provides:
- Text watermarks with customizable fonts, colors, and rotation
- Image watermarks with flexible positioning and opacity
- Batch processing capabilities for multiple documents
- User-specific watermarks for document tracking
- Security measures and error handling
- Web interface for easy use
This PDF manipulation PHP solution can be integrated into document management systems, invoice generators, certificate creators, or any application requiring document watermarking. The modular design allows easy customization and extension for specific business requirements.