Add Watermark to Image in PHP

You may have visited websites where you upload an image and website's watermark is automatically added  to image on fly. In this post we are going to add watermark to an image in PHP.

Add Watermark to Image in PHP

Many creators add watermarks to images for copyright reasons making it difficult for others to use those images without creator's permission. Some creators also use image watermark for branding option to promote their work. In this post we are going show you how to upload and watermark an image in PHP. We are also going to allow user to select position of watermark on image.

For this post we are going to create following files:

  1. index.php: The index page containing form to upload an image for watermark to be added on.
  2. process-watermark.php: The file to process form submission and add watermark to uploaded image.
  3. style.css: The CSS styles for index.php
 

Create HTML Form to Upload Image

First we need to create an HTML page containing a form with file upload field and radio buttons to select position of watermark on uploaded image. When user uploads an image it will be submitted to server to add watermark to uploaded image. We are giving users options to position the watermark on image. Possible options are top left, top right, bottom right, bottom left, center and repeat watermark over all 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"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="css/style.css" />
</head>
<body>
<div class="container">
<div class="my-4">
<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>
</div>
</body>
</html>

Add Watermark to Image in PHP

Our process-watermark.php file is handling the server side processing of uploaded image. We are using GD Image library of PHP for image manipulation. We check what option user selected for watermark position over image. We then add watermark to image and redirect back to display the image with watermark.

  • Check if there was a file uploaded and has no errors.
  • Check the file type is an image and file size is below desired allowed file size.
  • Create destination image resource and stamp image resource using imagecreatefromstring() and imagecreatefrompng().
  • Adjust the watermark spacing in case of user selected the option to repeat it over whole image.
  • Check which option user selected to for watermark and add watermark to image using imagecopy().
  • Finally, save the image using imagepng() and redirect back to display 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', FILTER_SANITIZE_STRING)){
// 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: ' . $_SERVER['HTTP_REFERER']);

Add CSS Styles

Add CSS styles for entire HTML page and form fields including 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;
}
.my-4{
margin-top: 1rem;
margin-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;
}