getRealPath())); if (! $source) { throw new RuntimeException('The uploaded image could not be processed.'); } $sourceWidth = imagesx($source); $sourceHeight = imagesy($source); $original = $this->resizeContain($source, $sourceWidth, $sourceHeight, self::MAX_ORIGINAL_SIDE); $preview = $this->resizeContain($source, $sourceWidth, $sourceHeight, self::PREVIEW_MAX_SIDE, 84); $thumbnail = $this->resizeCover($source, $sourceWidth, $sourceHeight, self::THUMBNAIL_SIZE); imagedestroy($source); return [ 'original' => $original['contents'], 'preview' => $preview['contents'], 'thumbnail' => $thumbnail['contents'], 'width' => $original['width'], 'height' => $original['height'], 'preview_width' => $preview['width'], 'preview_height' => $preview['height'], 'thumbnail_width' => self::THUMBNAIL_SIZE, 'thumbnail_height' => self::THUMBNAIL_SIZE, 'mime_type' => 'image/jpeg', 'size' => strlen($original['contents']), ]; } /** * @return array{contents: string, width: int, height: int} */ private function resizeContain( \GdImage $source, int $sourceWidth, int $sourceHeight, int $maxSide, int $quality = 90 ): array { $scale = min(1, $maxSide / max($sourceWidth, $sourceHeight)); $width = max(1, (int) round($sourceWidth * $scale)); $height = max(1, (int) round($sourceHeight * $scale)); $canvas = imagecreatetruecolor($width, $height); $this->fillCanvas($canvas, $width, $height); imagecopyresampled($canvas, $source, 0, 0, 0, 0, $width, $height, $sourceWidth, $sourceHeight); return [ 'contents' => $this->encodeJpeg($canvas, $quality), 'width' => $width, 'height' => $height, ]; } /** * @return array{contents: string, width: int, height: int} */ private function resizeCover(\GdImage $source, int $sourceWidth, int $sourceHeight, int $size): array { $scale = max($size / $sourceWidth, $size / $sourceHeight); $width = (int) round($sourceWidth * $scale); $height = (int) round($sourceHeight * $scale); $x = (int) round(($size - $width) / 2); $y = (int) round(($size - $height) / 2); $canvas = imagecreatetruecolor($size, $size); $this->fillCanvas($canvas, $size, $size); imagecopyresampled($canvas, $source, $x, $y, 0, 0, $width, $height, $sourceWidth, $sourceHeight); return [ 'contents' => $this->encodeJpeg($canvas, 80), 'width' => $size, 'height' => $size, ]; } private function fillCanvas(\GdImage $canvas, int $width, int $height): void { $background = imagecolorallocate($canvas, 255, 255, 255); imagefilledrectangle($canvas, 0, 0, $width, $height, $background); } private function encodeJpeg(\GdImage $image, int $quality): string { ob_start(); imagejpeg($image, null, $quality); $contents = (string) ob_get_clean(); imagedestroy($image); return $contents; } }