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( ' %s → %s KB → %s KB (-%s%%)', $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; } }