/
githubmirror
/
framework
Обзор
Документация
Войти
/
githubmirror
/
framework
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
13.x
src/Illuminate/Image/Drivers/InterventionDriver.php
226 строк
8 KB
Zac Hiler
[13.x] Fix incorrect image dimensions for HEIC (#61010)
05 авг 2026, 17:41
Не верифицирован
05 авг 2026, 17:41
eade0a1
Код
Авторство
О чём код?
<?php namespace Illuminate\Image\Drivers; use finfo; use Illuminate\Contracts\Image\Driver; use Illuminate\Image\ImageException; use Illuminate\Image\ImageOutputOptions; use Illuminate\Image\ImagePipeline; use Illuminate\Image\Transformations\Blur; use Illuminate\Image\Transformations\Contain; use Illuminate\Image\Transformations\Cover; use Illuminate\Image\Transformations\Crop; use Illuminate\Image\Transformations\FlipHorizontally; use Illuminate\Image\Transformations\FlipVertically; use Illuminate\Image\Transformations\Grayscale; use Illuminate\Image\Transformations\Orient; use Illuminate\Image\Transformations\Resize; use Illuminate\Image\Transformations\Rotate; use Illuminate\Image\Transformations\Scale; use Illuminate\Image\Transformations\Sharpen; use Intervention\Image\Direction; use Intervention\Image\Encoders\AvifEncoder; use Intervention\Image\Encoders\BmpEncoder; use Intervention\Image\Encoders\GifEncoder; use Intervention\Image\Encoders\HeicEncoder; use Intervention\Image\Encoders\JpegEncoder; use Intervention\Image\Encoders\MediaTypeEncoder; use Intervention\Image\Encoders\PngEncoder; use Intervention\Image\Encoders\WebpEncoder; use Intervention\Image\ImageManager; use Intervention\Image\Interfaces\ImageInterface; abstract class InterventionDriver implements Driver { /** * The registered transformation handlers. * * @var array<class-string<\Illuminate\Contracts\Image\Transformation>, callable> */ protected array $transformationHandlers = []; /** * The Intervention image manager instance. */ protected ImageManager $manager; /** * Create a new Intervention driver instance. */ public function __construct() { $this->manager = $this->createManager(); } /** * Create the underlying Intervention image manager. */ abstract protected function createManager(): ImageManager; /** * Ensure Intervention Image is installed. * * @throws ImageException */ public function ensureRequirementsAreMet(): void { if (! class_exists(ImageManager::class)) { throw new ImageException( 'Intervention Image is required to use this driver. '. 'You may install it via: composer require intervention/image:^4.0', ); } } /** * Process the given image contents with the specified pipeline. */ public function process(string $contents, ImagePipeline $pipeline): string { $mimeType = (new finfo(FILEINFO_MIME_TYPE))->buffer($contents); if (! in_array($mimeType, ['image/jpeg', 'image/png', 'image/bmp', 'image/gif', 'image/webp', 'image/avif', 'image/x-avif', 'image/heic', 'image/x-heic', 'image/heif'])) { throw new ImageException("The image format [{$mimeType}] is not supported."); } $image = $this->manager->decode($contents); foreach ($pipeline->transformations as $transformation) { if ($handler = $this->transformationHandlerFor($transformation)) { $image = $handler($image, $transformation); continue; } $image = match (true) { $transformation instanceof Orient => $image->orient(), $transformation instanceof Cover => $image->cover($transformation->width, $transformation->height), $transformation instanceof Contain => $image->contain( $transformation->width, $transformation->height, $this->resolveBackground($image, $transformation->background), ), $transformation instanceof Crop => $image->crop($transformation->width, $transformation->height, $transformation->x, $transformation->y), $transformation instanceof Resize => $image->resize($transformation->width, $transformation->height), $transformation instanceof Rotate => $image->rotate( $transformation->angle, $this->resolveBackground($image, $transformation->background), ), $transformation instanceof Scale => $image->scaleDown($transformation->width, $transformation->height), $transformation instanceof Blur => $image->blur($transformation->amount), $transformation instanceof Grayscale => $image->grayscale(), $transformation instanceof Sharpen => $image->sharpen($transformation->amount), $transformation instanceof FlipVertically => $image->flip(Direction::VERTICAL), $transformation instanceof FlipHorizontally => $image->flip(Direction::HORIZONTAL), default => throw new ImageException('The image transformation ['.get_class($transformation).'] is not supported.'), }; } $quality = $pipeline->output->quality ?? ImageOutputOptions::DEFAULT_QUALITY; try { if ($pipeline->output->format !== null) { return $image->encode(match ($pipeline->output->format) { 'webp' => new WebpEncoder($quality), 'jpg', 'jpeg' => new JpegEncoder($quality), 'png' => new PngEncoder, 'gif' => new GifEncoder, 'avif' => new AvifEncoder($quality), 'heic' => new HeicEncoder($quality), 'bmp' => new BmpEncoder, })->toString(); } $mediaType = match ($image->origin()->mediaType()) { 'image/x-gif' => 'image/gif', default => null, }; return $image->encode(new MediaTypeEncoder($mediaType, quality: $quality))->toString(); } finally { unset($image); } } /** * Get the dimensions of the given image contents. * * @return array{0: int, 1: int} */ public function dimensions(string $contents): array { $image = $this->manager->decode($contents); try { return [$image->width(), $image->height()]; } finally { unset($image); } } /** * Resolve a background color, expanding the "dominant" sentinel when needed. */ protected function resolveBackground(ImageInterface $image, ?string $background): ?string { return $background === 'dominant' ? $this->dominantColorFrom($image) : $background; } /** * Get the dominant (average) color of the image as a hex string. */ public function dominantColor(string $contents): string { $image = $this->manager->decode($contents); try { return $this->dominantColorFrom($image); } finally { unset($image); } } /** * Sample the dominant color by resizing the image to a single pixel. */ protected function dominantColorFrom(ImageInterface $image): string { $sample = clone $image; try { // Interpolation during the 1x1 resize can leave alpha slightly non-opaque, so it's dropped here. return substr($sample->resize(1, 1)->colorAt(0, 0)->toHex(true), 0, 7); } finally { unset($sample); } } /** * Register a transformation handler. * * @param class-string<\Illuminate\Contracts\Image\Transformation> $transformation */ public function transformUsing(string $transformation, callable $callback): static { $this->transformationHandlers[$transformation] = $callback; return $this; } /** * Get the handler for the given transformation. */ protected function transformationHandlerFor(object $transformation): ?callable { foreach ($this->transformationHandlers as $class => $handler) { if ($transformation instanceof $class) { return $handler; } } return null; } }