Upload and Resize Image in PHP (GD Library)
Image resizing is a technique where uploaded images are resized to a specific size or sizes to save disk space and improve image load time. Learn how to resize an uploaded image in PHP using the PHP GD library.

Image resizing can be a tricky implementation because it requires height, width and aspect ratio calculations. We also have to calculate the start point from which to begin cropping an image and where to stop. In this step-by-step guide, we will implement image resizing in PHP for multiple sizes of one image.
Why Resize Images in PHP?
Resizing images in PHP can be helpful in terms of saving disk space and faster page load time. For example, if you have a large number of images, all of them unnecessarily in large sizes can take more disk space and may result in slower page load time. This post demonstrates how to upload and resize an image in PHP with the following simple steps:
- Upload an image via an HTML form.
- Create an image class object and resize it to a desired size.
- Save the resized image at the end.
To achieve this, we will create the following files:
- image.php: An image class with different methods that will resize the image and save it.
- index.php: which will be used for an HTML form to upload an image.
- style.css: Contains all the CSS styles for the HTML page and form.
PHP Image Class to Resize Images
We create an image class to resize an image in PHP with the required methods to resize and save the image. This class will use PHP's GD Library function for image manipulation. The definition of image class is as follows:
$image: Will hold the original image object.$extension: The extension of the original image.$image_width: Width of the original image.$image_height: Height of the original image.$new_image: The new resized image object, initially set to the original image.$new_widthWidth of the new/resized image.$new_height: Height of the new/resized image.
The
methods constructor(), resize_image(),
save_image(), and show_image() are mainly used in the image class. Other methods are private methods used as
supporting methods for the above mentioned public methods.
__construct(): It is the constructor method that is called when the object is initialized. We first get the width and height of the uploaded image, then its extension, and assign them to the relevant class properties.resize_image(): The method that resizes the uploaded image and assigns it to the relevant class property. It accepts three parameters:$new_width,$new_height, and$cropped(if the image should be cropped or not). We use a switch statement for a conditional check. It checks if the uploaded image width is greater than its height (Landscape image), then it keeps the new width and calculates the new height for the image to maintain the aspect ratio. If the uploaded image height is greater than its width (Portrait image), then we keep the new height and calculate the new width to maintain the aspect ratio. The default case is that the image is square, then use the new width and new height (No need to calculate width or height). Then we create a new image of a new width and a new height. We useimagecopyresampled()to copy the original image to the new image object.save_image(): This method saves the image assigned to the$new_imageproperty. It accepts two parameters,$path(where we save the new image) and$quality(the quality of the new image).show_image(): This method will only print out the image without saving a new image.fill_transparent(): This method will fill the transparent background of a given image.get_image_width_ratio(): Calculates image width maintaining the aspect ratio. Accept two parameters,$widthand$height.get_image_height_ratio(): Calculates image height while maintaining the aspect ratio. It accepts two parameters, $width and $height.
We used the GD Library function in class methods; refer to GD and Image Functions for detailed usage of these functions.
image.php
<?php
class image
{
private GdImage $image;
private string $extension;
private int $image_width;
private int $image_height;
private GdImage $new_image;
private bool $is_transparent;
/**
* Constructs the current image class and sets local properties
* @param string $image
*/
function __construct(string $image)
{
list($width, $height, $type) = getimagesize($image);
$this->extension = image_type_to_extension($type, false);
$this->image = imagecreatefromstring(file_get_contents($image));
$this->image_width = $width;
$this->image_height = $height;
// Check transparency in constructor to avoid repeated loops
$this->is_transparent = $this->has_transparency($this->image);
// Initially set new image to received image
$this->new_image = $this->image;
$this->fill_transparent($this->new_image);
}
/**
* Resizes the current image for given width and height, Also crops image depending on passed parameter
* @param int $width
* @param int $height
* @param bool $crop
* @return void
*/
public function resize_image(int $width, int $height, bool $crop = false): void
{
switch (true) {
// If uploaded image is landscape keep new width and calculate new height
case ($this->image_width > $this->image_height):
$new_width = $width;
$new_height = $this->get_image_height_ratio($width);
// If crop is true set height to new height and calculate width again.
if ($new_height < $height && $crop) {
$new_height = $height;
$new_width = $this->get_image_width_ratio($height);
}
break;
// If uploaded image is portrait keep new height and calculate new width
case ($this->image_height > $this->image_width):
$new_width = $this->get_image_width_ratio($height);
$new_height = $height;
// If crop is true set width to new width and calculate height again.
if ($new_width < $width && $crop) {
$new_width = $width;
$new_height = $this->get_image_height_ratio($width);
}
break;
// If uploaded image is square keep new width and new height. calculate nothing.
default:
$new_width = $width;
$new_height = $height;
break;
}
$this->new_image = imagecreatetruecolor($width, $height);
$this->fill_transparent($this->new_image);
$cropX = intval(($new_width - $width) / 2);
$cropY = intval(($new_height - $height) / 2);
imagecopyresampled($this->new_image, $this->image, -$cropX, -$cropY, 0, 0, $new_width, $new_height, $this->image_width, $this->image_height);
}
/**
* Checks if image should be filled with transparent color
* @param GdImage $image
* @return void
*/
private function fill_transparent(GdImage $image): void
{
if ($this->is_transparent) {
$color = imagecolorallocatealpha($image, 255, 255, 255, 127);
imagefill($image, 0, 0, $color);
imagesavealpha($image, true);
}
}
/**
* Checks if passed/given image has transparent pixels
* @param GdImage $image
* @return bool
*/
private function has_transparency(GdImage $image): bool
{
$rows = imagesx($image);
$cols = imagesy($image);
for ($i = 0; $i < $rows; $i++) {
for ($j = 0; $j < $cols; $j++) {
$rgba = imagecolorat($image, $i, $j);
if (($rgba & 0x7F000000) >> 24) {
return true;
}
}
}
return false;
}
/**
* Returns height ratio for given width
* @param int $width
* @return int
*/
private function get_image_height_ratio(int $width): int
{
$ratio = $width / $this->image_width;
return round($ratio * $this->image_height);
}
/**
* Returns width ratio for given height
* @param int $height
* @return int
*/
private function get_image_width_ratio(int $height): int
{
$ratio = $height / $this->image_height;
return round($ratio * $this->image_width);
}
/**
* @param string $path
* @param int $quality
* @return void
*/
public function save_image(string $path, int $quality = 50): void
{
switch ($this->extension) {
case 'jpeg':
case 'jpg':
imagejpeg($this->new_image, $path, $quality);
break;
case 'gif':
imagegif($this->new_image, $path);
break;
case 'png':
imagepng($this->new_image, $path, 9);
break;
}
}
}
Create an HTML Form to Upload and Resize an Image
Create an HTML page with a form file input field to upload an image. Then, resize the uploaded image using the image class we created. Steps to upload an image and resize it in PHP are:
- Check if files were uploaded without any errors.
- Declare a variable to store the extension of the uploaded file.
- Declare an array variable to store allowed extensions for uploaded file.
- Declare a variable to store the filename of the resized image.
- Check if the uploaded file has the extension that exists in our allowed extensions array.
- Instantiate an image object of the image class, passing it the uploaded image as a parameter.
- Resize the image by passing values for the width and height parameters.
- Finally, we save the resized image at the end, passing it the name for the new resized image.
index.php
<?php
include_once('image.php');
$upload = false;
// Check if uploaded file was uploaded without errors
if (!empty($_FILES) && $_FILES['image']['error'] === 0) {
$extension = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION);
$allowed_extensions = ['jpg', 'jpeg', 'png', 'gif'];
$name = time();
// Check if uploaded image either of jpg,gif and png
if (in_array(strtolower($extension), $allowed_extensions)) {
$new_image = new image($_FILES['image']['tmp_name']);
$new_image->resize_image(100, 100, true); // Resize image to 100x100
$new_image->save_image($name . '-100x100.' . $extension); // Save resized image
$new_image->resize_image(150, 150, true); // Resize image to 150x150
$new_image->save_image($name . '-150x150.' . $extension); // Save resized image
$new_image->resize_image(200, 200, true); // Resize image to 200x200
$new_image->save_image($name . '-200x200.' . $extension); // Save resized image
$upload = true;
} else {
// If uploaded file was not jpg,gif or png show an error
$error = 'Uploaded file was not an image. Please upload an image and try again.';
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Upload and Resize 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="css/style.css"/>
</head>
<body>
<section class="section py-4">
<div class="container">
<div class="mb-4">
<div class="alert alert-blue">Upload an image to resize. For demo purpose we will create
<strong>200x200</strong>, <strong>150x150</strong> and <strong>100x100</strong> size images.
</div>
<form class="form" method="POST" name="image-form" enctype="multipart/form-data">
<div class="row">
<div class="col-6">
<input type="file" name="image"/>
</div>
<div class="col-6 text-right">
<input type="submit" value="Upload" class="btn btn-green"/>
</div>
</div>
</form>
</div>
<?php
// If image was uploaded show all resized images
if ($upload) {
?>
<div class="mb-4">
<div class="row">
<div class="col-auto">
<h4>200x200</h4>
<img src="<?= $name ?>-200x200.<?= $extension ?>"/>
</div>
<div class="col-auto">
<h4>150x150</h4>
<img src="<?= $name ?>-150x150.<?= $extension ?>"/>
</div>
<div class="col-auto">
<h4>100x100</h4>
<img src="<?= $name ?>-100x100.<?= $extension ?>"/>
</div>
</div>
</div>
<?php
}
// If there was an error uploading the image show it here.
if (isset($error)) {
?>
<div class="alert alert-red"><?= $error; ?></div>
<?php
} ?>
</div>
</section>
</body>
</html>
Add CSS Styles For Image Upload Interface
Add CSS styles for the entire HTML page and the form input field that is added for image upload.
style.css
* {
box-sizing: border-box;
}
html,body {
margin: 0px;
}
body {
background-color: #f6f6f6;
font-family: "Segoe UI", "Roboto", "Helvetica", sans-serif;
font-size: 15px;
font-weight: normal;
font-style: normal;
}
.py-4, .pt-4 {
padding-top: 1rem;
}
.py-4, .pb-4 {
padding-bottom: 1rem;
}
.my-4, .mb-4 {
margin-bottom: 1rem;
}
.container {
width: 100%;
margin-right: auto;
margin-left: auto;
padding-right: 15px;
padding-left: 15px;
max-width: 1140px;
}
.alert {
width: 100%;
padding: 10px;
margin-bottom: 10px;
color: #fff;
transition: opacity 0.5s;
}
.alert-blue {
background: #0369a1;
border: 1px solid #005D95;
}
.alert-red {
background: #e65442;
border: 1px solid #cc3a28;
}
.row {
margin-left: -10px;
margin-right: -10px;
margin-bottom: 10px;
}
.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-auto {
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-auto {
-webkit-box-flex: 0;
-ms-flex: 0 0 auto;
flex: 0 0 auto;
width: auto;
max-width: none;
}
.text-right {
text-align: right;
}
.btn-green {
display: inline-block;
padding: 5px 10px;
cursor: pointer;
font: inherit;
background: #00a65a;
border: 1px solid #009549;
color: #ffffff;
}