imageResourceUrl = $url; } /** * Returns current loaded image type * @return string */ public function getImageType(): string { return $this->imageType; } /** * @return int */ public function getApproxMinimumHeight(): int { return $this->approxMinimumHeight; } /** * @return int */ public function getApproxMinimumWidth(): int { return $this->approxMinimumWidth; } /** * @param int $approxMinimumHeight */ public function setApproxMinimumHeight(int $approxMinimumHeight): SimpleImageCompressor { $this->approxMinimumHeight = $approxMinimumHeight; return $this; } /** * @param int $approxMinimumWidth */ public function setApproxMinimumWidth(int $approxMinimumWidth): SimpleImageCompressor { $this->approxMinimumWidth = $approxMinimumWidth; return $this; } /** * Determine current loaded image type */ private function loadImageType() { $filetype = ''; if (substr($this->imageData, 0, 2) === "\xFF\xD8") { $filetype = 'image/jpeg'; } else if (substr($this->imageData, 0, 3) === "\x89\x50\x4E") { $filetype = 'image/png'; } else if (substr($this->imageData, 0, 4) === "\x47\x49\x46\x38") { $filetype = 'image/gif'; } $this->imageType = $filetype; } /** * 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 BadUrlException("Cannot load image from provided resource: ".$this->imageResourceUrl); $this->imageData = $imageData; } /** * Resizes and compressing image. * 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 $quality * @return CompressedImage */ public function resizeAndCompress($reductionPercent = 5, $quality = 90): 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 = $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 * @param string $urlImageResource image resource path. Can be local file or internet URL * @return SimpleImageCompressor * @throws \Exception */ public static function load(string $urlImageResource): SimpleImageCompressor { $compressorObject = new SimpleImageCompressor($urlImageResource); $compressorObject->readImageToString(); $compressorObject->loadImageType(); if(!str_contains(self::ALLOWED_IMAGE_FORMAT, $compressorObject->getImageType()) || $compressorObject->getImageType() === "") throw new \Exception("Provided file resource must contain one of image mime types: ".self::ALLOWED_IMAGE_FORMAT); return $compressorObject; } }