Add Watermark to an Image in PHP (GD Library)
You may have visited websites where you upload an image, and the website's watermark is automatically added to the image on the fly. Learn how to add a watermark to an image in PHP with an image class.

Watermarks are usually added for copyright reasons and to restrict others from using someone's content without their permission or giving them credit. The image watermarks are also used for branding purposes or to promotion.
How to Add a Watermark to an Image in PHP (With Watermark Position)
Automatically adding a watermark to an image in PHP can be achieved in simple steps. Steps involved to achieve this:
- Create a file upload interface.
- Send form files to the server-side script.
- Add a watermark to an image using the GD library.
- Finally, save the image with a watermark.
In this post, we are going to upload an image and add a watermark to it in PHP. We are also going to allow users to select the position of the watermark on the image.
For this post, we are going to create the following files:
- index.php: The index page containing a form to upload an image for a watermark to be added.
- process-watermark.php: The file to process form submission and add a watermark to the uploaded image.
- style.css: The CSS styles for index.php.
Create an HTML Form to Upload an Image
First, we need to create an HTML page containing a form with a file upload field and radio buttons to select the position of the watermark on the uploaded image. When a user uploads an image, it will be submitted to the server to add a watermark to the uploaded image in a server-side script. We are giving users options to position the watermark on the image. Possible options are top left, top right, bottom right, bottom left, center, and repeat watermark over the entire image.
index.php
<!DOCTYPE html>
<html>
<head>
<title>Add Watermark to Image in PHP - Demo</title>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<meta content="width=device-width, initial-scale=1, maximum-scale=1" name="viewport"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"/>
<link rel="stylesheet" href="css/style.css"/>
</head>
<body>
<section class="section py-4">
<div class="container">
<form class="mb-4" action="process-watermark.php" method="POST" enctype="multipart/form-data">
<div class="row">
<div class="col-12">
<div class="config-wrapper">
<label>
<input type="radio" name="position" value="repeat_all" checked="checked">
Repeat All
</label>
<label>
<input type="radio" name="position" value="top_left">
Top Left
</label>
<label>
<input type="radio" name="position" value="top_right">
Top Right
</label>
<label>
<input type="radio" name="position" value="bottom_left">
Bottom Left
</label>
<label>
<input type="radio" name="position" value="bottom_right">
Bottom Right
</label>
<label>
<input type="radio" name="position" value="center">
Center
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<input type="file" class="file-input" name="image_file"/>
</div>
<div class="col-6 text-right">
<button type="submit" class="btn btn-blue">
<i class="fa fa-upload"></i>
Upload
</button>
</div>
</div>
</form>
<?php if (file_exists('images/watermark-image.png')) { ?>
<div class="row">
<div class="col-12">
<img src="images/watermark-image.png?v=<?= time() ?>" class="img-responsive"/>
</div>
</div>
<?php } ?>
</div>
</section>
</body>
</html>
Add Watermark to Image in PHP
Our process-watermark.php file is handling the server side processing of the uploaded image. We are using the GD Image library of PHP for image manipulation. We check what option the user selected for the watermark position over the image. We then add a watermark to the image and redirect back to display the image with the watermark.
- Check if there was a file uploaded and has no errors.
- Check that the file type is an image and the file size is below the allowed file size.
- Create destination image resource and stamp image resource using
imagecreatefromstring()andimagecreatefrompng()functions. - Adjust the watermark spacing in case the user selected the option to repeat it over the whole image.
- Check which option the user selected to use for watermark and add it to the image using the
imagecopy()function. - Finally, save the image using
imagepng()and redirect back to display the resulting image.
process-watermark.php
<?php
// If image was uploaded without any errors, Proceed to watermarking
if (!empty($_FILES) && $_FILES['image_file']['error'] === 0) {
$file = $_FILES['image_file'];
$file_type = substr($_FILES['image_file']['type'], 0, 5);
$file_size = number_format($_FILES['image_file']['size'] / 1024, 2);
if ($file_type == 'image' && $file_size < 2048) {
$destination_image = imagecreatefromstring(file_get_contents($file['tmp_name']));
$stamp = imagecreatefrompng('images/watermark.png');
$spacing = 15;
$spacing_double = $spacing * 2;
list($width, $height) = getimagesize($file['tmp_name']);
list($stamp_width, $stamp_height) = getimagesize('images/watermark.png');
switch (filter_input(INPUT_POST, 'position')) {
// Repeat watermark over whole image
case 'repeat_all':
// calculate how many rows & columns watermark will repeat
$rows = floor($height / ($stamp_height + $spacing_double));
$cols = floor($width / ($stamp_width + $spacing_double));
// Initial offset (point to start) of watermark
$offsetX = intval(($width - ($cols * ($stamp_width + $spacing_double))) / 2 + $spacing);
$offsetY = intval(($height - ($rows * ($stamp_height + $spacing_double))) / 2 + $spacing);
// Loop through all rows & columns and place watermark
for ($rc = 0; $rc < $rows; $rc++) {
for ($cc = 0; $cc < $cols; $cc++) {
imagecopy($destination_image, $stamp, $cc * ($stamp_width + $spacing_double) + $offsetX, $rc * ($stamp_height + $spacing_double) + $offsetY, 0, 0, $stamp_width, $stamp_height);
}
}
break;
// Place watermark to top left of uploaded image
case 'top_left':
$offsetX = $spacing;
$offsetY = $spacing;
imagecopy($destination_image, $stamp, $offsetX, $offsetY, 0, 0, $stamp_width, $stamp_height);
break;
// Place watermark to top right of uploaded image
case 'top_right':
$offsetX = $width - ($stamp_width + $spacing);
$offsetY = $spacing;
imagecopy($destination_image, $stamp, $offsetX, $offsetY, 0, 0, $stamp_width, $stamp_height);
break;
// Place watermark to bottom left of uploaded image
case 'bottom_left':
$offsetX = $spacing;
$offsetY = $height - ($stamp_height + $spacing);
imagecopy($destination_image, $stamp, $offsetX, $offsetY, 0, 0, $stamp_width, $stamp_height);
break;
// Place watermark to bottom right of uploaded image
case 'bottom_right':
$offsetX = $width - ($stamp_width + $spacing);
$offsetY = $height - ($stamp_height + $spacing);
imagecopy($destination_image, $stamp, $offsetX, $offsetY, 0, 0, $stamp_width, $stamp_height);
break;
// Place watermark to center of uploaded image, Also the default case
case 'center':
default:
$offsetX = ($width - ($stamp_width + $spacing)) / 2;
$offsetY = ($height - ($stamp_height + $spacing)) / 2;
imagecopy($destination_image, $stamp, $offsetX, $offsetY, 0, 0, $stamp_width, $stamp_height);
break;
}
// Save image after adding watermark
imagepng($destination_image, 'images/watermark-image.png', 9);
}
}
header('Location: ' . filter_var($_SERVER['HTTP_REFERER'], FILTER_SANITIZE_URL));
Add Watermark CSS Styles
Add CSS styles for the entire HTML page and form fields, including the file upload field and radio fields.
style.css
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
}
body {
background-color: #f6f6f6;
font-family: "Segoe UI", "Roboto", "Helvetica", sans-serif;
font-size: 15px;
font-weight: normal;
font-style: normal;
line-height: 1.5;
}
.container {
width: 100%;
max-width: 1140px;
margin-right: auto;
margin-left: auto;
padding-right: 15px;
padding-left: 15px;
}
.py-4, .pt-4 {
padding-top: 1rem;
}
.py-4, .pb-4 {
padding-bottom: 1rem;
}
.mb-4 {
margin-bottom: 1rem;
}
.text-right {
text-align: right;
}
.row {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
margin-right: -15px;
margin-left: -15px;
}
.col-6,
.col-12 {
width: 100%;
min-height: 1px;
padding-right: 15px;
padding-left: 15px;
}
.col-6 {
-webkit-box-flex: 0;
-ms-flex: 0 0 50%;
flex: 0 0 50%;
max-width: 50%;
}
.col-12 {
-webkit-box-flex: 0;
-ms-flex: 0 0 100%;
flex: 0 0 100%;
max-width: 100%;
}
.img-responsive {
max-width: 100%;
height: auto;
}
.btn {
display: inline-block;
padding: 5px 10px;
cursor: pointer;
font: inherit;
}
.btn-blue {
background-color: #006699;
border: 1px solid #2b7cab;
color: #ffffff;
}
.config-wrapper {
background: #fff;
padding: 0.75rem;
margin-bottom: 1rem;
}
.config-wrapper label {
display: inline-block;
margin-right: 10px;
}We just demonstrated how to add watermark to an image that can be used for stamping image before storing or sharing them. The code can be modified to add opacity to watermark or change the size of it.