How To Compress Images In PHP (Plus Free Library)

Running a website that allows image uploads? But things are getting out of hand with large images? Now you need to do some image compression, save some space, and speed up the loading.

An easy way to compress images in PHP is to use the GD library:

  • Create an image object from the original image – $img = imagecreatefromjpeg("ORIGINAL.JPG");
  • Compress the image – imagejpeg($img, "COMPRESSED.JPG", 30);

The last parameter of imagejpeg() is the image quality, a number from 0 to 100. A lower number will result in smaller file size, but lower image quality.

That covers the quick-and-dirty solution for people who are working with JPG files. But how about the other formats? What if we need to resize the image as well? Read on for a simple image compress library that I have created – Read on!

ⓘ I have included a zip file with all the example source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

QUICK SLIDES

 

TABLE OF CONTENTS

Download & Examples How It Works Useful Bits & Links
The End

 

DOWNLOAD & EXAMPLES

First, here is the download link to the example source code as promised.

 

QUICK NOTES

  • Ensure that the GD extension extension=gd (gd2 prior to PHP8) is enabled in the php.ini file.
  • Open img-compressor.php, change the default settings in A1 if you want.
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

 

EXAMPLE 1) SIMPLE IMAGE COMPRESS

1-simple.php
// (A) LOAD LIBRARY
require "img-compressor.php";
 
// (B) EASY COMPRESS
// DEFAULT WILL OUTPUT TO BIRB.WEBP, 30 QUALITY
echo $_IC->pack("birb.jpg") ? "OK" : $_IC->error;
 
// (C) SPECIFY PATH & FILE NAME
echo $_IC->pack("birb.jpg", "d:/packed.jpg") ? "OK" : $_IC->error;

To use the image compress library:

  1. Load the library – require "img-compressor.php".
  2. Simply call $_IC->pack(SOURCE) to compress images, this will use the default settings in the library. Take note, this returns a boolean. If it is false, you can check the error message in $_IC->error.
  3. You can also specify the output file path/format – $_IC->pack(SOURCE, TARGET). Of course, only jpg and webp are compressed…

 

EXAMPLE 2) COMPRESS IMAGE SETTINGS

2-options.php
<?php
// (A) LOAD LIBRARY
require "img-compressor.php";

// (B) CHANGE DEFAULT SETTINGS
// $_IC->SET(FORMAT, QUALITY, MAX SIZE)
$_IC->set("jpg", 50, 300);

// (C) WILL OUTPUT TO PACKED.JPG, 50 QUALITY, MAX 300 PX WIDTH/HEIGHT
echo $_IC->pack("birb.jpg", "packed.jpg") ? "OK" : $_IC->error;

If you want to change the settings during runtime, just call $_IC->set().

 

 

EXAMPLE 3) COMPRESS UPLOADED FILES

3-output.php
<!-- (A) HTML UPLOAD FORM -->
<form method="post" enctype="multipart/form-data">
  <input type="file" name="upload" accept=".png,.gif,.jpg,.jpeg,.bmp,.webp" required>
  <input type="submit" name="submit" value="Upload Image">
</form>
 
<?php
// (B) DEAL WITH IMAGE UPLOAD
if (isset($_FILES["upload"])) {
  // (B1) SAVE UPLOADED IMAGE
  move_uploaded_file($_FILES["upload"]["tmp_name"], $_FILES["upload"]["name"]);
 
  // (B2) COMPRESS
  require "img-compressor.php";
  echo $_IC->pack($_FILES["upload"]["name"], "uploaded.webp")
    ? "OK" : $_IC->error;
 
  // (B3) REMOVE ORIGINAL - IF YOU DON'T NEED IT
  unlink($_FILES["upload"]["name"]);
}
?>

Just upload the file “as usual”, then call the library to compress it.

 

 

PHP IMAGE COMPRESS LIBRARY

All right, let us now get into a little more detail on how the PHP image compress library work.

 

PART A) PROPERTIES & SETTINGS

img-compressor.php
// (A) PROPERTIES
// (A1) DEFAULT SETTINGS
private $format = "webp"; // COMPRESSED FILE FORMAT
private $quality = 30; // COMPRESSED QUALITY (0 TO 100)
private $maxSize = 0; // MAX ALLOWED WIDTH/HEIGHT (0 FOR NONE)
 
// (A2) FLAGS
public $error = "";
private $allow = ["jpeg", "jpg", "gif", "png", "bmp", "webp"];

This entire section should be pretty self-explanatory.

  • $format The default output format. Recommended to use jpg or webp.
  • $quality As in the introduction, the image quality. This only applies to jpg or webp… If you do not know already know the difference between lossy and lossless images, I will leave some links below.
  • $maxSize Restrict the maximum width/height of the image.
  • $error Used to hold error messages.
  • $allow The allowed image file types… Just don’t mess with these. These are the file types that GD can handle.

 

PART B) COMPRESS IMAGE

img-compressor.php
// (B) COMPRESS IMAGE
function pack ($source, $target=null) {
  // (B1) CHECK SOURCE IMAGE
  if (!is_readable($source)) {
    $this->error = "Cannot read $source";
    return false;
  }
 
  // (B2) CHECK SOURCE IMAGE FILE TYPE
  $sInfo = pathinfo($source, PATHINFO_ALL);
  $sInfo["extension"] = !isset($sInfo["extension"]) ? "" : strtolower($sInfo["extension"]) ;
  if (!in_array($sInfo["extension"], $this->allow)) {
    $this->error = "Invalid input image - " . $sInfo["extension"];
    return false;
  }
 
  // (B3) CHECK TARGET (COMPRESSED) IMAGE
  $target = $target===null ? $sInfo["filename"].".". $this->format : $target ;
  $tInfo = pathinfo($target, PATHINFO_ALL);
  $tInfo["extension"] = !isset($tInfo["extension"]) ? "" : strtolower($tInfo["extension"]) ;
  if (!in_array($tInfo["extension"], $this->allow)) {
    $this->error = "Invalid output image - " . $tInfo["extension"];
    return false;
  }
 
  // (B4) GD OPEN SOURCE IMAGE
  $gdOpen = "imagecreatefrom" . ($sInfo["extension"]=="jpg" ? "jpeg" : $sInfo["extension"]);
  $img = $gdOpen($source);
  if ($img===false) {
    $this->error = "Failed to open $source";
    return false;
  }
 
  // (B5) RESIZE IMAGE IF NECESSARY
  if ($this->maxSize!=0) {
    // (B5-1) GET SOURCE IMAGE SIZE & ORIENTATION
    $srcW = imagesx($img);
    $srcH = imagesy($img);
    if ($srcW > $srcH) { $srcO = "L"; }
    else if ($srcH > $srcW) { $srcO = "P"; }
    else { $srcO = "S"; }
 
    // (B5-2) RESIZE
    if (($srcO=="L" || $srcO=="S") && $srcW > $this->maxSize) {
      $newW = $this->maxSize;
      $newH = floor(($this->maxSize / $srcW) * $srcH);
      $img = imagescale($img, $newW, $newH);
    }
    if ($srcO=="P" && $srcH > $this->maxSize) {
      $newW = floor(($this->maxSize / $srcH) * $srcW);
      $newH = $this->maxSize;
      $img = imagescale($img, $newW, $newH);
    }
  }
 
  // (B6) GD SAVE & COMPRESS IMAGE (IF JPG OR WEBP)
  $gdWrite = "image" . ($tInfo["extension"]=="jpg" ? "jpeg" : $tInfo["extension"]);
  $pass = ($tInfo["extension"]=="jpg" || $tInfo["extension"]=="jpeg" || $tInfo["extension"]=="webp")
  ? $gdWrite($img, $target, $this->quality) : $gdWrite($img, $target);
  if (!$pass) {
    $this->error = "Failed to write to $target";
    return false;
  }
 
  // (B7) ALL GOOD!
  return true;
}

What actually happens behind the scene. Not going to explain line-by-line, but a quick summary:

  • (B1 To B3) Check if the image source file can be read, check if valid image file formats are used.
  • (B4) Open and read the source image into an object.
  • (B5) Resize the image if necessary… Sadly, this is very Mathematical in nature.
    • Get the original image size.
    • Check the orientation of the image.
    • Calculate the new dimensions if the original image is too big.
  • (B6 & B7) Save the image object into a file.

 

 

PART C) CHANGE SETTINGS

img-compressor.php
// (C) CHANGE SETTINGS
function set ($format, $quality, $maxSize) {
  $this->format = $format;
  $this->quality = $quality;
  $this->maxSize = $maxSize;
} 

If you do not know this, you need to go back to basic OOP lessons…

 

USEFUL BITS & LINKS

That’s all for this guide, and here is a small section on some extras and links that may be useful to you.

 

THE TRANSPARENT BACKGROUND DISAPPEARED!?

For the uninitiated – Only webp, png, and gif supports a transparent background.

 

THE IMAGE IS NOT COMPRESSED!?

There are 2 types of image formats in general – Lossy and lossless. Only the lossy types can be compressed – jpeg and webp. Read this to learn more.

 

 

LINKS & REFERENCES

 

INFOGRAPHIC CHEAT SHEET

How To Compress Images In PHP (click to enlarge)

 

THE END

Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

Leave a Comment

Your email address will not be published. Required fields are marked *