diff --git a/app/Conversion/Drivers/Image/Concerns/RendersSingleImagePdf.php b/app/Conversion/Drivers/Image/Concerns/RendersSingleImagePdf.php index c21db3d..31f3251 100644 --- a/app/Conversion/Drivers/Image/Concerns/RendersSingleImagePdf.php +++ b/app/Conversion/Drivers/Image/Concerns/RendersSingleImagePdf.php @@ -8,15 +8,26 @@ use App\Support\Conversions\DTO\ConversionResult; use Barryvdh\DomPDF\Facade\Pdf; use Illuminate\Support\Facades\Storage; +use Intervention\Image\Drivers\Gd\Driver; +use Intervention\Image\ImageManager; +use RuntimeException; trait RendersSingleImagePdf { private function renderPdf(ConversionContext $context, string $imageMimeType): ConversionResult { - $sourceContent = Storage::disk('local')->get($context->sourceFile->stored_path); + $storedPath = $context->sourceFile->stored_path; + + if (! Storage::disk('local')->exists($storedPath)) { + throw new RuntimeException( + "RendersSingleImagePdf: source file not found at [{$storedPath}]." + ); + } + + $sourceContent = Storage::disk('local')->get($storedPath); $imageDataUri = "data:{$imageMimeType};base64,".base64_encode($sourceContent); - $pageSize = $context->options['page_size'] ?? 'a4'; + $pageSize = $this->resolvePageSize($context->options['page_size'] ?? 'a4'); $orientation = $this->resolveOrientation($context->options['orientation'] ?? 'auto', $sourceContent); $margin = $this->resolveMargin($context->options['margin'] ?? 'small'); $fitMode = $context->options['fit_mode'] ?? 'contain'; @@ -37,22 +48,33 @@ private function renderPdf(ConversionContext $context, string $imageMimeType): C ); } + private function resolvePageSize(string $pageSize): string + { + if ($pageSize === 'auto' || $pageSize === '') { + return 'a4'; + } + + return $pageSize; + } + private function resolveOrientation(string $orientation, string $imageContent): string { if ($orientation !== 'auto') { return $orientation; } - $image = imagecreatefromstring($imageContent); - if ($image === false) { - return 'portrait'; - } + $manager = new ImageManager(new Driver); - $width = imagesx($image); - $height = imagesy($image); - imagedestroy($image); + try { + $image = $manager->decodeBinary($imageContent); + } catch (\Throwable $e) { + throw new RuntimeException( + "RendersSingleImagePdf: could not decode image binary to determine orientation. {$e->getMessage()}", + previous: $e, + ); + } - return $width > $height ? 'landscape' : 'portrait'; + return $image->width() > $image->height() ? 'landscape' : 'portrait'; } private function resolveMargin(string $margin): string diff --git a/app/Conversion/Drivers/Image/Concerns/ResolvesImageQuality.php b/app/Conversion/Drivers/Image/Concerns/ResolvesImageQuality.php new file mode 100644 index 0000000..d23cf44 --- /dev/null +++ b/app/Conversion/Drivers/Image/Concerns/ResolvesImageQuality.php @@ -0,0 +1,19 @@ + 60, + 'medium' => 75, + 'high' => 90, + 'max' => 100, + default => 85, + }; + } +} diff --git a/app/Conversion/Drivers/Image/JpgToPngDriver.php b/app/Conversion/Drivers/Image/JpgToPngDriver.php index 4885fb5..64b6049 100644 --- a/app/Conversion/Drivers/Image/JpgToPngDriver.php +++ b/app/Conversion/Drivers/Image/JpgToPngDriver.php @@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Storage; use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\ImageManager; +use RuntimeException; final class JpgToPngDriver implements ConverterDriver { @@ -20,10 +21,16 @@ public function key(): string public function convert(ConversionContext $context): ConversionResult { - $manager = new ImageManager(new Driver); + $storedPath = $context->sourceFile->stored_path; + + if (! Storage::disk('local')->exists($storedPath)) { + throw new RuntimeException( + "JpgToPngDriver: source file not found at [{$storedPath}]." + ); + } - $sourcePath = Storage::disk('local')->path($context->sourceFile->stored_path); - $image = $manager->decodePath($sourcePath); + $manager = new ImageManager(new Driver); + $image = $manager->decodePath(Storage::disk('local')->path($storedPath)); $encoded = $image->encodeUsingFileExtension('png'); diff --git a/app/Conversion/Drivers/Image/JpgToWebpDriver.php b/app/Conversion/Drivers/Image/JpgToWebpDriver.php index 455bba0..3064ba9 100644 --- a/app/Conversion/Drivers/Image/JpgToWebpDriver.php +++ b/app/Conversion/Drivers/Image/JpgToWebpDriver.php @@ -4,15 +4,19 @@ namespace App\Conversion\Drivers\Image; +use App\Conversion\Drivers\Image\Concerns\ResolvesImageQuality; use App\Support\Conversions\Contracts\ConverterDriver; use App\Support\Conversions\DTO\ConversionContext; use App\Support\Conversions\DTO\ConversionResult; use Illuminate\Support\Facades\Storage; use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\ImageManager; +use RuntimeException; final class JpgToWebpDriver implements ConverterDriver { + use ResolvesImageQuality; + public function key(): string { return 'jpg_to_webp'; @@ -20,10 +24,16 @@ public function key(): string public function convert(ConversionContext $context): ConversionResult { - $manager = new ImageManager(new Driver); + $storedPath = $context->sourceFile->stored_path; - $sourcePath = Storage::disk('local')->path($context->sourceFile->stored_path); - $image = $manager->decodePath($sourcePath); + if (! Storage::disk('local')->exists($storedPath)) { + throw new RuntimeException( + "JpgToWebpDriver: source file not found at [{$storedPath}]." + ); + } + + $manager = new ImageManager(new Driver); + $image = $manager->decodePath(Storage::disk('local')->path($storedPath)); $quality = $this->resolveQuality($context->options['quality'] ?? 'high'); @@ -40,15 +50,4 @@ public function convert(ConversionContext $context): ConversionResult sizeBytes: Storage::disk('local')->size($outputPath), ); } - - private function resolveQuality(mixed $quality): int - { - return match ($quality) { - 'low' => 60, - 'medium' => 75, - 'high' => 90, - 'max' => 100, - default => 85, - }; - } } diff --git a/app/Conversion/Drivers/Image/PngToJpgDriver.php b/app/Conversion/Drivers/Image/PngToJpgDriver.php index 3a50876..0995c48 100644 --- a/app/Conversion/Drivers/Image/PngToJpgDriver.php +++ b/app/Conversion/Drivers/Image/PngToJpgDriver.php @@ -4,15 +4,19 @@ namespace App\Conversion\Drivers\Image; +use App\Conversion\Drivers\Image\Concerns\ResolvesImageQuality; use App\Support\Conversions\Contracts\ConverterDriver; use App\Support\Conversions\DTO\ConversionContext; use App\Support\Conversions\DTO\ConversionResult; use Illuminate\Support\Facades\Storage; use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\ImageManager; +use RuntimeException; final class PngToJpgDriver implements ConverterDriver { + use ResolvesImageQuality; + public function key(): string { return 'png_to_jpg'; @@ -20,10 +24,16 @@ public function key(): string public function convert(ConversionContext $context): ConversionResult { - $manager = new ImageManager(new Driver); + $storedPath = $context->sourceFile->stored_path; - $sourcePath = Storage::disk('local')->path($context->sourceFile->stored_path); - $image = $manager->decodePath($sourcePath); + if (! Storage::disk('local')->exists($storedPath)) { + throw new RuntimeException( + "PngToJpgDriver: source file not found at [{$storedPath}]." + ); + } + + $manager = new ImageManager(new Driver); + $image = $manager->decodePath(Storage::disk('local')->path($storedPath)); $background = $context->options['background'] ?? '#ffffff'; $quality = $this->resolveQuality($context->options['quality'] ?? 'high'); @@ -43,15 +53,4 @@ public function convert(ConversionContext $context): ConversionResult sizeBytes: Storage::disk('local')->size($outputPath), ); } - - private function resolveQuality(mixed $quality): int - { - return match ($quality) { - 'low' => 60, - 'medium' => 75, - 'high' => 90, - 'max' => 100, - default => 85, - }; - } } diff --git a/app/Conversion/Drivers/Image/PngToWebpDriver.php b/app/Conversion/Drivers/Image/PngToWebpDriver.php index a5efb8e..348258d 100644 --- a/app/Conversion/Drivers/Image/PngToWebpDriver.php +++ b/app/Conversion/Drivers/Image/PngToWebpDriver.php @@ -4,15 +4,19 @@ namespace App\Conversion\Drivers\Image; +use App\Conversion\Drivers\Image\Concerns\ResolvesImageQuality; use App\Support\Conversions\Contracts\ConverterDriver; use App\Support\Conversions\DTO\ConversionContext; use App\Support\Conversions\DTO\ConversionResult; use Illuminate\Support\Facades\Storage; use Intervention\Image\Drivers\Gd\Driver; use Intervention\Image\ImageManager; +use RuntimeException; final class PngToWebpDriver implements ConverterDriver { + use ResolvesImageQuality; + public function key(): string { return 'png_to_webp'; @@ -20,10 +24,16 @@ public function key(): string public function convert(ConversionContext $context): ConversionResult { - $manager = new ImageManager(new Driver); + $storedPath = $context->sourceFile->stored_path; - $sourcePath = Storage::disk('local')->path($context->sourceFile->stored_path); - $image = $manager->decodePath($sourcePath); + if (! Storage::disk('local')->exists($storedPath)) { + throw new RuntimeException( + "PngToWebpDriver: source file not found at [{$storedPath}]." + ); + } + + $manager = new ImageManager(new Driver); + $image = $manager->decodePath(Storage::disk('local')->path($storedPath)); $quality = $this->resolveQuality($context->options['quality'] ?? 'high'); @@ -40,15 +50,4 @@ public function convert(ConversionContext $context): ConversionResult sizeBytes: Storage::disk('local')->size($outputPath), ); } - - private function resolveQuality(mixed $quality): int - { - return match ($quality) { - 'low' => 60, - 'medium' => 75, - 'high' => 90, - 'max' => 100, - default => 85, - }; - } } diff --git a/resources/views/pdf/single-image.blade.php b/resources/views/pdf/single-image.blade.php index f92872e..83ef84d 100644 --- a/resources/views/pdf/single-image.blade.php +++ b/resources/views/pdf/single-image.blade.php @@ -3,35 +3,24 @@
-