diff --git a/scripts/find_image_size.php b/scripts/find_image_size.php index 7a3ca3a..aafa834 100644 --- a/scripts/find_image_size.php +++ b/scripts/find_image_size.php @@ -1,39 +1,14 @@ - #!/usr/bin/env php = 1) { + // Landscape or square: represent as 1/x where x <= 1 + $normalized = 1 / $ratio; + $display = "1/" . number_format($ratio, 3); + } else { + // Portrait: represent as 1/x where x > 1 + $normalized = $ratio; + $display = "1/" . number_format(1 / $ratio, 3); + } + + // Simplified ratio for display $gcd = function ($a, $b) use (&$gcd) { return $b ? $gcd($b, $a % $b) : $a; }; $divisor = $gcd($width, $height); + $simplified = $width / $divisor . ":" . $height / $divisor; + return [ - "ratio" => $width / $height, - "simplified" => $width / $divisor . ":" . $height / $divisor, + "ratio" => $ratio, + "normalized" => $normalized, + "display" => $display, + "simplified" => $simplified, ]; } -// Function to calculate similarity score -function calculateSimilarity($target, $existing) +// Function to calculate aspect ratio similarity (0-1, where 1 is perfect match) +function calculateAspectRatioSimilarity($targetRatio, $existingRatio) { - // Calculate aspect ratio difference (0-1, where 0 is perfect match) - $ratioScore = - abs($target["ratio"] - $existing["ratio"]) / - max($target["ratio"], $existing["ratio"]); + // Calculate the absolute difference between ratios + $difference = abs($targetRatio - $existingRatio); - // Calculate size difference (0-1, where 0 is perfect match) - $targetSize = $target["width"] * $target["height"]; - $existingSize = $existing["width"] * $existing["height"]; - $sizeScore = - abs($targetSize - $existingSize) / max($targetSize, $existingSize); + // Normalize the difference (smaller difference = higher similarity) + // Using an exponential decay function for better scoring + $similarity = exp(-$difference * 5); - // Calculate dimension differences - $widthScore = - abs($target["width"] - $existing["width"]) / - max($target["width"], $existing["width"]); - $heightScore = - abs($target["height"] - $existing["height"]) / - max($target["height"], $existing["height"]); - - // Weighted score (aspect ratio is most important) - $totalScore = - $ratioScore * 0.5 + - $sizeScore * 0.2 + - $widthScore * 0.15 + - $heightScore * 0.15; - - return 1 - $totalScore; // Convert to similarity (higher is better) + return $similarity; } // Collect all image sizes from all categories @@ -107,12 +81,16 @@ function collectAllImageSizes($image_folders) } foreach ($sizes as $sizeName => $config) { - if (isset($config["width"])) { + if ( + isset($config["width"]) && + isset($config["height"]) && + $config["height"] !== null + ) { $allSizes[] = [ "name" => $sizeName, "category" => $category, "width" => $config["width"], - "height" => $config["height"] ?? null, + "height" => $config["height"], "crop" => $config["crop"] ?? false, "forced" => $config["forced"] ?? false, "path" => $config["path"] ?? "", @@ -124,6 +102,12 @@ function collectAllImageSizes($image_folders) return $allSizes; } +// Main script +echo "\n"; +echo "===========================================\n"; +echo " Image Aspect Ratio Finder Tool\n"; +echo "===========================================\n\n"; + echo "Enter image dimensions (e.g., 565x369px or 1920x1080): "; $input = trim(fgets(STDIN)); @@ -136,78 +120,127 @@ if (!$dimensions) { echo "\nšŸ“ Analyzing dimensions: {$dimensions["width"]}x{$dimensions["height"]}px\n"; -$targetRatio = getAspectRatio($dimensions["width"], $dimensions["height"]); -echo " Aspect ratio: {$targetRatio["simplified"]} ({$targetRatio["ratio"]})\n\n"; +$targetRatio = getNormalizedAspectRatio( + $dimensions["width"], + $dimensions["height"], +); +echo " Aspect ratio: {$targetRatio["simplified"]} = {$targetRatio["display"]}\n\n"; // Collect all image sizes $allSizes = collectAllImageSizes($image_folders); -// Calculate similarity for each size +// Calculate similarity for each size based on aspect ratio only $matches = []; -foreach ($allSizes as $size) { - if ($size["height"] === null) { - // Skip sizes without height (proportional scaling only) - continue; - } +$seenRatios = []; // Track unique aspect ratios - $existingRatio = getAspectRatio($size["width"], $size["height"]); - $similarity = calculateSimilarity( - array_merge($dimensions, ["ratio" => $targetRatio["ratio"]]), - array_merge($size, ["ratio" => $existingRatio["ratio"]]), +foreach ($allSizes as $size) { + $existingRatio = getNormalizedAspectRatio($size["width"], $size["height"]); + $similarity = calculateAspectRatioSimilarity( + $targetRatio["ratio"], + $existingRatio["ratio"], ); - $matches[] = array_merge($size, [ + $ratioKey = $existingRatio["display"]; + + // Store the match + $match = array_merge($size, [ "aspect_ratio" => $existingRatio["simplified"], + "aspect_ratio_display" => $existingRatio["display"], "aspect_ratio_value" => $existingRatio["ratio"], "similarity" => $similarity, ]); + + $matches[] = $match; + + // Track unique aspect ratios for summary + if (!isset($seenRatios[$ratioKey])) { + $seenRatios[$ratioKey] = [ + "ratio" => $existingRatio, + "count" => 0, + "sizes" => [], + ]; + } + $seenRatios[$ratioKey]["count"]++; + $seenRatios[$ratioKey]["sizes"][] = $match; } // Sort by similarity (best matches first) usort($matches, function ($a, $b) { - return $b["similarity"] <=> $a["similarity"]; + $simDiff = $b["similarity"] <=> $a["similarity"]; + if ($simDiff !== 0) { + return $simDiff; + } + // If similarity is the same, sort by name + return $a["name"] <=> $b["name"]; }); -// Display results -echo "šŸ” Top 10 Most Similar Existing Sizes:\n"; +// Display results grouped by aspect ratio +echo "šŸ” Image Sizes Grouped by Aspect Ratio:\n"; echo "===========================================\n\n"; -$topMatches = array_slice($matches, 0, 10); +// Group matches by aspect ratio for display +$groupedMatches = []; +foreach ($matches as $match) { + $ratioKey = $match["aspect_ratio_display"]; + if (!isset($groupedMatches[$ratioKey])) { + $groupedMatches[$ratioKey] = [ + "ratio" => $match, + "sizes" => [], + ]; + } + $groupedMatches[$ratioKey]["sizes"][] = $match; +} -foreach ($topMatches as $index => $match) { - $matchPercent = round($match["similarity"] * 100, 1); - $matchBar = str_repeat("ā–ˆ", (int) ($matchPercent / 5)); +// Sort groups by similarity +uasort($groupedMatches, function ($a, $b) { + return $b["ratio"]["similarity"] <=> $a["ratio"]["similarity"]; +}); - echo $index + 1 . ". "; - echo "\033[1m{$match["name"]}\033[0m"; - echo " (Category: {$match["category"]})\n"; - echo " Size: {$match["width"]}x{$match["height"]}px\n"; - echo " Aspect Ratio: {$match["aspect_ratio"]}\n"; +// Display top 5 aspect ratio groups +$topGroups = array_slice($groupedMatches, 0, 5); +$displayCount = 0; + +foreach ($topGroups as $ratioKey => $group) { + $firstMatch = $group["ratio"]; + $matchPercent = round($firstMatch["similarity"] * 100, 1); + $matchBar = str_repeat("ā–ˆ", min(20, (int) ($matchPercent / 5))); + + echo "šŸ“Š Aspect Ratio: {$firstMatch["aspect_ratio"]} = {$firstMatch["aspect_ratio_display"]}\n"; echo " Match: {$matchBar} {$matchPercent}%\n"; - echo " Path: {$match["path"]}\n"; + echo " Found " . count($group["sizes"]) . " size(s):\n\n"; - if ($match["crop"]) { - echo " āœ‚ļø Cropped: Yes"; - if ($match["forced"]) { - echo " (Forced)"; + foreach ($group["sizes"] as $match) { + echo " • \033[1m{$match["name"]}\033[0m ({$match["category"]})\n"; + echo " Size: {$match["width"]}x{$match["height"]}px"; + if ($match["crop"]) { + echo " | āœ‚ļø Cropped"; + if ($match["forced"]) { + echo " (Forced)"; + } } echo "\n"; + echo " Path: {$match["path"]}\n\n"; + + $displayCount++; + if ($displayCount >= 15) { + break 2; // Stop after 15 total sizes + } } echo "\n"; } -// Check for exact matches -$exactMatches = array_filter($matches, function ($m) use ($dimensions) { - return $m["width"] === $dimensions["width"] && - $m["height"] === $dimensions["height"]; +// Check for exact aspect ratio matches +$exactMatches = array_filter($matches, function ($m) use ($targetRatio) { + return abs($m["aspect_ratio_value"] - $targetRatio["ratio"]) < 0.001; }); if (!empty($exactMatches)) { - echo "\nāœ… EXACT MATCH FOUND!\n"; + echo "\nāœ… EXACT ASPECT RATIO MATCHES FOUND!\n"; echo "===========================================\n"; + echo "These sizes have the exact same aspect ratio:\n\n"; foreach ($exactMatches as $match) { - echo " • {$match["name"]} ({$match["category"]})\n"; + echo " • {$match["name"]} ({$match["width"]}x{$match["height"]}px) - {$match["category"]}\n"; } echo "\n"; } @@ -216,18 +249,28 @@ if (!empty($exactMatches)) { echo "\nšŸ’” Recommendations:\n"; echo "===========================================\n"; -$bestMatch = $topMatches[0]; -$matchPercent = round($bestMatch["similarity"] * 100, 1); - -if ($matchPercent >= 95) { - echo "āœ… USE EXISTING: '{$bestMatch["name"]}' is very similar ({$matchPercent}% match)\n"; - echo " You can probably use this size instead.\n"; -} elseif ($matchPercent >= 80) { - echo "āš ļø CONSIDER: '{$bestMatch["name"]}' is fairly similar ({$matchPercent}% match)\n"; - echo " Evaluate if this size meets your needs or create a new one.\n"; +if (!empty($exactMatches)) { + echo "āœ… PERFECT MATCHES: " . + count($exactMatches) . + " size(s) with exact aspect ratio\n"; + echo " Use any of the sizes listed above.\n"; } else { - echo "šŸ†• CREATE NEW: No close matches found (best match: {$matchPercent}%)\n"; - echo " Consider creating a new image size configuration.\n"; + $bestMatch = $matches[0]; + $matchPercent = round($bestMatch["similarity"] * 100, 1); + + if ($matchPercent >= 95) { + echo "āœ… VERY CLOSE: '{$bestMatch["name"]}' has nearly identical aspect ratio ({$matchPercent}% match)\n"; + echo " Aspect ratio: {$bestMatch["aspect_ratio"]} = {$bestMatch["aspect_ratio_display"]}\n"; + echo " You can probably use this size.\n"; + } elseif ($matchPercent >= 80) { + echo "āš ļø SIMILAR: '{$bestMatch["name"]}' has a similar aspect ratio ({$matchPercent}% match)\n"; + echo " Aspect ratio: {$bestMatch["aspect_ratio"]} = {$bestMatch["aspect_ratio_display"]}\n"; + echo " Evaluate if this aspect ratio meets your needs.\n"; + } else { + echo "šŸ†• CREATE NEW: No close aspect ratio matches found (best: {$matchPercent}%)\n"; + echo " Your aspect ratio {$targetRatio["display"]} is unique.\n"; + echo " Consider creating a new image size configuration.\n"; + } } echo "\n";