3 Commits

Author SHA1 Message Date
DESKTOP\Administrator e5109dfd39 Added support for multiple image processing drivers 2026-05-03 00:20:29 +03:00
Andrew fef495df07 Update README.md 2025-07-24 00:40:49 +03:00
Andrew e3c759a75a Update README.md 2024-09-27 14:26:29 +03:00
4 changed files with 111 additions and 62 deletions
+10 -11
View File
@@ -8,7 +8,7 @@
![Downloads](https://img.shields.io/packagist/dt/geckon01/simple-image-compressor) ![Downloads](https://img.shields.io/packagist/dt/geckon01/simple-image-compressor)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/d773335a657d467faaa0ebb12bc2abe1)](https://app.codacy.com/gh/Geckon01/simple-image-compressor/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/d773335a657d467faaa0ebb12bc2abe1)](https://app.codacy.com/gh/Geckon01/simple-image-compressor/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
**SimpleImageCompressor** - is a tiny simple PHP image resizer/compressor lib which allows you to resize and compress any image easily on the fly. **SimpleImageCompressor** - is a tiny simple PHP image resizer lib which allows you to resize and compress any image easily on the fly.
## Installation ## Installation
@@ -20,8 +20,8 @@ composer require "geckon01/simple-image-compressor"
### Without composer ### Without composer
1. Download latest release [here](https://github.com/Geckon01/simple-image-compressor/releases). 1. Download latest release [here](https://github.com/Geckon01/simple-image-compressor/releases).
2. Unpack archive to any folder of your project you wish. 2. Unpack the archive to your project directory.
3. Load main lib files: 3. Include the library files:
```php ```php
require "src/SimpleImageCompressor.php"; require "src/SimpleImageCompressor.php";
@@ -31,7 +31,7 @@ use geckon01\SimpleImageCompressor\SimpleImageCompressor;
## Usage ## Usage
To resize and compress your image you can use next code: Resize and compress an image:
```php ```php
$resolutionTargetPercent = 50; $resolutionTargetPercent = 50;
$targetQuality = 50; $targetQuality = 50;
@@ -43,14 +43,13 @@ load method supports loading from local file, or you can specify any valid URL i
```php ```php
$compressor = SimpleImageCompressor::load("https://example.com/image.jpg"); $compressor = SimpleImageCompressor::load("https://example.com/image.jpg");
``` ```
This lib support chaining, so you can do something like this: Method chaining is supported:
```php ```php
SimpleImageCompressor::load("image.png") SimpleImageCompressor::load("image.png")
->resizeAndCompress(50, 50) ->resizeAndCompress(50, 50)
->toFile("image"); ->toFile("image");
``` ```
> Note that you don't need to specify file extension. The lib will save > Note: File extensions are automatically added. Use toFile("filename") without extension.
> file with proper one automatically.
### Output format ### Output format
You can specify output format. Supported output fomats are: You can specify output format. Supported output fomats are:
@@ -64,14 +63,14 @@ $compressedImage->toBase64();
```php ```php
$compressedImage->toGdImage(); $compressedImage->toGdImage();
``` ```
### Max/min height/width ### Size Constraints
Also you can set approximate minumum and maximum image size. Set approximate minimum dimensions (aspect ratio preserved):
```php ```php
$compressor->setApproxMinimumHeight(500); $compressor->setApproxMinimumHeight(500);
$compressor->setApproxMinimumWidth(500); $compressor->setApproxMinimumWidth(500);
``` ```
> Note that Due to saving proportion lib can't guarantee that width and height be equals max and min . > Note actual dimensions may differ due to aspect ratio preservation.
As example, if we have original image 1920x1080 which we want to get 50% of original resolution and save original 16x9 aspect ration the reduced image must be 960x540. Example: 1920×1080 image reduced to 50% becomes 960×540 (maintaining 16:9).
## License ## License
+25 -49
View File
@@ -9,6 +9,9 @@
namespace geckon01\SimpleImageCompressor; namespace geckon01\SimpleImageCompressor;
use geckon01\SimpleImageCompressor\Drivers\DriverInterface;
use geckon01\SimpleImageCompressor\Drivers\GdDriver;
/** /**
* Class SimpleImageCompressor * Class SimpleImageCompressor
* @package geckon01\SimpleImageCompressor * @package geckon01\SimpleImageCompressor
@@ -17,7 +20,6 @@ class SimpleImageCompressor
{ {
private const ALLOWED_IMAGE_FORMAT = "image/jpeg,image/png,image/gif,image/webp,image/bmp"; private const ALLOWED_IMAGE_FORMAT = "image/jpeg,image/png,image/gif,image/webp,image/bmp";
private string $imageResourceUrl; private string $imageResourceUrl;
private string $imageData;
private string $imageType; private string $imageType;
private int $approxMinimumHeight = 90; private int $approxMinimumHeight = 90;
@@ -25,17 +27,25 @@ class SimpleImageCompressor
private bool $exifLoaded = false; private bool $exifLoaded = false;
private ?DriverInterface $driver;
/** /**
* SimpleImageCompressor constructor. * SimpleImageCompressor constructor.
* @param $url url or path from where to load file * @param $url string url or path from where to load file
* @param DriverInterface|null $driver
*/ */
private function __construct($url) private function __construct(string $url, ?DriverInterface $driver = null)
{ {
$this->imageResourceUrl = $url; $this->imageResourceUrl = $url;
$this->exifLoaded = in_array("exif", get_loaded_extensions()); $this->exifLoaded = in_array("exif", get_loaded_extensions());
if($driver == null)
{
$this->driver = new GdDriver();
} else {
$this->driver = $driver;
} }
}
/** /**
* Returns current loaded image type * Returns current loaded image type
@@ -83,7 +93,7 @@ class SimpleImageCompressor
/** /**
* Determine current loaded image type * Determine current loaded image type
*/ */
private function loadImageType() { private function loadImageType(string $imageBinary) {
$this->imageType = "image"; $this->imageType = "image";
if($this->exifLoaded) { if($this->exifLoaded) {
@@ -116,77 +126,43 @@ class SimpleImageCompressor
// Fallback to bytes recognition // Fallback to bytes recognition
trigger_error("simple-image-compressor: Exif extension not found. Image MIME type recognition may be inaccurate."); trigger_error("simple-image-compressor: Exif extension not found. Image MIME type recognition may be inaccurate.");
if (substr($this->imageData, 0, 2) === "\xFF\xD8") { if (substr($imageBinary, 0, 2) === "\xFF\xD8") {
$this->imageType = 'image/jpeg'; $this->imageType = 'image/jpeg';
} }
if (substr($this->imageData, 0, 3) === "\x89\x50\x4E") { if (substr($imageBinary, 0, 3) === "\x89\x50\x4E") {
$this->imageType = 'image/png'; $this->imageType = 'image/png';
} }
if (substr($this->imageData, 0, 4) === "\x47\x49\x46\x38") { if (substr($imageBinary, 0, 4) === "\x47\x49\x46\x38") {
$this->imageType = 'image/gif'; $this->imageType = 'image/gif';
} }
} }
/**
* Loading image from provided url. Whether it local file or internet resource
*/
private function readImageToString(): void {
$imageData = file_get_contents($this->imageResourceUrl);
if($imageData === false)
throw new \Exception("Cannot load image from provided resource: ".$this->imageResourceUrl);
$this->imageData = $imageData;
}
/** /**
* Resizes and compressing image. * Resizes and compressing image.
* Note that gif compression not supported * Note that gif compression not supported
* @param int $reductionPercent percent shows how much image resolution to original will be. The greater percent, the lower resolution * @param int $reductionPercent percent shows how much image resolution to original will be. The greater percent, the lower resolution
* @param int $quality * @param int $quality
* @return CompressedImage * @return CompressedImage
* @throws \Exception
*/ */
public function resizeAndCompress($reductionPercent = 5, $quality = 90): CompressedImage public function resizeAndCompress($reductionPercent = 5, $quality = 90): CompressedImage
{ {
$originImage = imagecreatefromstring($this->imageData); return $this->driver
->resize($reductionPercent, $quality, $this->approxMinimumWidth, $this->approxMinimumHeight, $this->imageType);
if($originImage === false)
throw new \Exception("Can not read provided file");
$width = imagesx($originImage);
$height = imagesy($originImage);
$totalPixelCount = $width * $height;
$minimumPixelCount = $this->approxMinimumWidth * $this->approxMinimumHeight;
$maxReductionPercent = round(abs(100 - ($minimumPixelCount / $totalPixelCount * 100)));
// Due to saving proportion we can't guarantee that width and height be equals max and min
// As example, if we have original image 1920*1080 which we want to get 50% of original resolution
// If we want to save 16*9 aspect ration it must be 960*540
// So, we override $maxReductionPercent to value which satisfy origin aspect ratio
if($maxReductionPercent < $reductionPercent)
$reductionPercent = $maxReductionPercent;
$newWidth = round($width - ($width * $reductionPercent) / 100);
$newHeight = round($height - ($height * $reductionPercent) / 100);
$thumb = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresized($thumb, $originImage, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
return new CompressedImage($quality, $this->imageType,$thumb);
} }
/** /**
* Initalize lib from provided image file path * Initalize lib from provided image file path
* @param string $urlImageResource image resource path. Can be local file or internet URL * @param string $urlImageResource image resource path. Can be local file or internet URL
* @param DriverInterface|null $driver
* @return SimpleImageCompressor * @return SimpleImageCompressor
* @throws \Exception * @throws \Exception
*/ */
public static function load(string $urlImageResource): SimpleImageCompressor public static function load(string $urlImageResource, ?DriverInterface $driver = null): SimpleImageCompressor
{ {
$compressorObject = new SimpleImageCompressor($urlImageResource); $compressorObject = new SimpleImageCompressor($urlImageResource, $driver);
$compressorObject->readImageToString(); $compressorObject->driver->load($urlImageResource);
$compressorObject->loadImageType(); $compressorObject->loadImageType($compressorObject->driver->getImageBinary());
if(!str_contains(self::ALLOWED_IMAGE_FORMAT, $compressorObject->getImageType()) if(!str_contains(self::ALLOWED_IMAGE_FORMAT, $compressorObject->getImageType())
|| $compressorObject->getImageType() === "") || $compressorObject->getImageType() === "")
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace geckon01\SimpleImageCompressor\Drivers;
use geckon01\SimpleImageCompressor\CompressedImage;
use geckon01\SimpleImageCompressor\SimpleImageCompressor;
interface DriverInterface
{
function resize(int $reductionPercent, int $quality, int $approxMinimumWidth, int $approxMinimumHeight, string $imageType): CompressedImage;
function load(string $path): DriverInterface;
function getImageBinary(): string;
}
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace geckon01\SimpleImageCompressor\Drivers;
use geckon01\SimpleImageCompressor\CompressedImage;
class GdDriver implements DriverInterface
{
private string $imageData;
function resize(int $reductionPercent, int $quality, int $approxMinimumWidth, int $approxMinimumHeight, string $imageType): CompressedImage
{
$originImage = imagecreatefromstring($this->imageData);
if($originImage === false)
throw new \Exception("Can not read provided file");
$width = imagesx($originImage);
$height = imagesy($originImage);
$totalPixelCount = $width * $height;
$minimumPixelCount = $approxMinimumWidth * $approxMinimumHeight;
$maxReductionPercent = round(abs(100 - ($minimumPixelCount / $totalPixelCount * 100)));
// Due to saving proportion we can't guarantee that width and height be equals max and min
// As example, if we have original image 1920*1080 which we want to get 50% of original resolution
// If we want to save 16*9 aspect ration it must be 960*540
// So, we override $maxReductionPercent to value which satisfy origin aspect ratio
if($maxReductionPercent < $reductionPercent)
$reductionPercent = $maxReductionPercent;
$newWidth = round($width - ($width * $reductionPercent) / 100);
$newHeight = round($height - ($height * $reductionPercent) / 100);
$thumb = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresized($thumb, $originImage, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
return new CompressedImage($quality, $imageType, $thumb);
}
function load(string $path): DriverInterface
{
$this->imageData = file_get_contents($path);
if($this->imageData === false)
throw new \Exception("Cannot load image from provided resource: ".$path);
return $this;
}
function getImageBinary(): string
{
if($this->imageData == null)
throw new \Exception("Load image before getting its binary.");
return $this->imageData;
}
}