|
2 | 2 |
|
3 | 3 | namespace App\Services; |
4 | 4 |
|
5 | | -use Spatie\Image\Image; |
6 | 5 | use App\Services\Interfaces\ImageProcessorInterface; |
7 | 6 |
|
8 | 7 | class ImageProcessor implements ImageProcessorInterface |
9 | 8 | { |
10 | 9 | public function processImage(string $sourcePath, string $destinationPath, array $config): bool |
11 | 10 | { |
12 | 11 | try { |
13 | | - $image = Image::load($sourcePath); |
| 12 | + // Check if we have GD extension available, otherwise use Intervention Image |
| 13 | + if (extension_loaded('gd')) { |
| 14 | + return $this->processWithGD($sourcePath, $destinationPath, $config); |
| 15 | + } elseif (class_exists('\Spatie\Image\Image')) { |
| 16 | + return $this->processWithSpatie($sourcePath, $destinationPath, $config); |
| 17 | + } else { |
| 18 | + // Fallback - just copy the file without processing |
| 19 | + return copy($sourcePath, $destinationPath); |
| 20 | + } |
| 21 | + } catch (\Exception $e) { |
| 22 | + return false; |
| 23 | + } |
| 24 | + } |
| 25 | + |
| 26 | + private function processWithGD(string $sourcePath, string $destinationPath, array $config): bool |
| 27 | + { |
| 28 | + // Get image info |
| 29 | + $imageInfo = getimagesize($sourcePath); |
| 30 | + if (!$imageInfo) { |
| 31 | + return false; |
| 32 | + } |
| 33 | + |
| 34 | + $mimeType = $imageInfo['mime']; |
| 35 | + $width = $imageInfo[0]; |
| 36 | + $height = $imageInfo[1]; |
| 37 | + |
| 38 | + // Create image resource based on type |
| 39 | + switch ($mimeType) { |
| 40 | + case 'image/jpeg': |
| 41 | + $sourceImage = imagecreatefromjpeg($sourcePath); |
| 42 | + break; |
| 43 | + case 'image/png': |
| 44 | + $sourceImage = imagecreatefrompng($sourcePath); |
| 45 | + break; |
| 46 | + case 'image/gif': |
| 47 | + $sourceImage = imagecreatefromgif($sourcePath); |
| 48 | + break; |
| 49 | + case 'image/webp': |
| 50 | + $sourceImage = imagecreatefromwebp($sourcePath); |
| 51 | + break; |
| 52 | + default: |
| 53 | + return false; |
| 54 | + } |
| 55 | + |
| 56 | + if (!$sourceImage) { |
| 57 | + return false; |
| 58 | + } |
| 59 | + |
| 60 | + // Calculate new dimensions |
| 61 | + $newWidth = $config['width'] ?? $width; |
| 62 | + $newHeight = $config['height'] ?? $height; |
| 63 | + |
| 64 | + // If both width and height are specified, maintain aspect ratio |
| 65 | + if (!empty($config['width']) && !empty($config['height'])) { |
| 66 | + $aspectRatio = $width / $height; |
| 67 | + $newAspectRatio = $newWidth / $newHeight; |
| 68 | + |
| 69 | + if ($aspectRatio > $newAspectRatio) { |
| 70 | + // Image is wider than target ratio, fit by width |
| 71 | + $newHeight = $newWidth / $aspectRatio; |
| 72 | + } else { |
| 73 | + // Image is taller than target ratio, fit by height |
| 74 | + $newWidth = $newHeight * $aspectRatio; |
| 75 | + } |
| 76 | + } |
| 77 | + |
| 78 | + // Create new image |
| 79 | + $newImage = imagecreatetruecolor((int)$newWidth, (int)$newHeight); |
| 80 | + |
| 81 | + // Preserve transparency for PNG |
| 82 | + if ($mimeType === 'image/png') { |
| 83 | + imagealphablending($newImage, false); |
| 84 | + imagesavealpha($newImage, true); |
| 85 | + $transparent = imagecolorallocatealpha($newImage, 255, 255, 255, 127); |
| 86 | + imagefill($newImage, 0, 0, $transparent); |
| 87 | + } |
| 88 | + |
| 89 | + // Resize image |
| 90 | + imagecopyresampled($newImage, $sourceImage, 0, 0, 0, 0, (int)$newWidth, (int)$newHeight, $width, $height); |
| 91 | + |
| 92 | + // Determine output format and quality |
| 93 | + $outputFormat = strtolower($config['format'] ?? 'original'); |
| 94 | + $quality = $config['quality'] ?? 85; |
| 95 | + |
| 96 | + // Set destination path with new format if specified |
| 97 | + if ($outputFormat !== 'original' && $outputFormat !== 'jpg') { |
| 98 | + $destinationPath = preg_replace('/\.[^.]+$/', '.' . $outputFormat, $destinationPath); |
| 99 | + } |
| 100 | + |
| 101 | + // Save image based on format |
| 102 | + $result = false; |
| 103 | + switch ($outputFormat) { |
| 104 | + case 'png': |
| 105 | + $result = imagepng($newImage, $destinationPath, 9); // Max compression for PNG |
| 106 | + break; |
| 107 | + case 'gif': |
| 108 | + $result = imagegif($newImage, $destinationPath); |
| 109 | + break; |
| 110 | + case 'webp': |
| 111 | + $result = imagewebp($newImage, $destinationPath, $quality); |
| 112 | + break; |
| 113 | + case 'jpg': |
| 114 | + case 'jpeg': |
| 115 | + default: |
| 116 | + $result = imagejpeg($newImage, $destinationPath, $quality); |
| 117 | + break; |
| 118 | + } |
| 119 | + |
| 120 | + // Clean up memory |
| 121 | + imagedestroy($sourceImage); |
| 122 | + imagedestroy($newImage); |
| 123 | + |
| 124 | + return $result; |
| 125 | + } |
| 126 | + |
| 127 | + private function processWithSpatie(string $sourcePath, string $destinationPath, array $config): bool |
| 128 | + { |
| 129 | + try { |
| 130 | + $image = \Spatie\Image\Image::load($sourcePath); |
14 | 131 |
|
15 | 132 | // Ustaw rozmiar |
16 | 133 | if (!empty($config['width']) && !empty($config['height'])) { |
|
0 commit comments