10-04-2026
This commit is contained in:
parent
4d6b4930b2
commit
4bb89aad8c
836 changed files with 52961 additions and 5950 deletions
124
app/Console/Commands/ConvertImagesToWebP.php
Normal file
124
app/Console/Commands/ConvertImagesToWebP.php
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class ConvertImagesToWebP extends Command
|
||||
{
|
||||
protected $signature = 'images:convert-webp
|
||||
{--path=img/assets : Relative path inside public/}
|
||||
{--quality=85 : WebP quality (1-100)}
|
||||
{--force : Overwrite existing WebP files}
|
||||
{--dry-run : Show what would be converted without doing it}';
|
||||
|
||||
protected $description = 'Convert JPG/JPEG/PNG images to WebP format using GD';
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
$relativePath = $this->option('path');
|
||||
$quality = (int) $this->option('quality');
|
||||
$force = (bool) $this->option('force');
|
||||
$dryRun = (bool) $this->option('dry-run');
|
||||
$basePath = public_path($relativePath);
|
||||
|
||||
if (! File::isDirectory($basePath)) {
|
||||
$this->error("Directory not found: {$basePath}");
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$extensions = ['jpg', 'jpeg', 'png'];
|
||||
$files = collect(File::allFiles($basePath))
|
||||
->filter(fn ($file) => in_array(strtolower($file->getExtension()), $extensions));
|
||||
|
||||
if ($files->isEmpty()) {
|
||||
$this->info('No images found to convert.');
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$this->info(sprintf('Found %d images in %s', $files->count(), $relativePath));
|
||||
|
||||
$converted = 0;
|
||||
$skipped = 0;
|
||||
$savedBytes = 0;
|
||||
|
||||
foreach ($files as $file) {
|
||||
$webpPath = preg_replace('/\.(jpe?g|png)$/i', '.webp', $file->getPathname());
|
||||
|
||||
if (File::exists($webpPath) && ! $force) {
|
||||
$skipped++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($dryRun) {
|
||||
$this->line(" Would convert: {$file->getRelativePathname()}");
|
||||
$converted++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->convertToWebP($file->getPathname(), $webpPath, $quality);
|
||||
|
||||
if ($result) {
|
||||
$originalSize = $file->getSize();
|
||||
$webpSize = filesize($webpPath);
|
||||
$saving = $originalSize - $webpSize;
|
||||
$savedBytes += $saving;
|
||||
$percent = $originalSize > 0 ? round(($saving / $originalSize) * 100, 1) : 0;
|
||||
|
||||
$this->line(sprintf(
|
||||
' <info>✓</info> %s → %s KB → %s KB (<comment>-%s%%</comment>)',
|
||||
$file->getRelativePathname(),
|
||||
round($originalSize / 1024, 1),
|
||||
round($webpSize / 1024, 1),
|
||||
$percent
|
||||
));
|
||||
$converted++;
|
||||
} else {
|
||||
$this->warn(" ✗ Failed: {$file->getRelativePathname()}");
|
||||
}
|
||||
}
|
||||
|
||||
$this->newLine();
|
||||
$this->info(sprintf(
|
||||
'Done: %d converted, %d skipped, %.1f KB saved',
|
||||
$converted,
|
||||
$skipped,
|
||||
$savedBytes / 1024
|
||||
));
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function convertToWebP(string $sourcePath, string $destPath, int $quality): bool
|
||||
{
|
||||
$extension = strtolower(pathinfo($sourcePath, PATHINFO_EXTENSION));
|
||||
|
||||
$image = match ($extension) {
|
||||
'jpg', 'jpeg' => @imagecreatefromjpeg($sourcePath),
|
||||
'png' => @imagecreatefrompng($sourcePath),
|
||||
default => false,
|
||||
};
|
||||
|
||||
if ($image === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($extension === 'png') {
|
||||
imagepalettetotruecolor($image);
|
||||
imagealphablending($image, true);
|
||||
imagesavealpha($image, true);
|
||||
}
|
||||
|
||||
$result = imagewebp($image, $destPath, $quality);
|
||||
imagedestroy($image);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue