2025-11-26 14:37:51 +02:00
|
|
|
#!/usr/bin/env php
|
|
|
|
|
<?php
|
|
|
|
|
/**
|
2025-12-16 16:35:06 +02:00
|
|
|
* Image Aspect Ratio Finder
|
2025-11-26 14:37:51 +02:00
|
|
|
*
|
2025-12-16 16:35:06 +02:00
|
|
|
* This script helps find image sizes from image_folders.php
|
|
|
|
|
* with matching aspect ratios.
|
2025-11-26 14:37:51 +02:00
|
|
|
*/
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
// Include the image folders configuration
|
|
|
|
|
require_once __DIR__ . "/sites/default/settings/image_folders.php";
|
2025-11-26 14:37:51 +02:00
|
|
|
|
|
|
|
|
// Function to parse dimension input like "565x369px"
|
|
|
|
|
function parseDimensions($input)
|
|
|
|
|
{
|
2025-12-15 15:27:55 +02:00
|
|
|
$input = strtolower(trim($input));
|
|
|
|
|
$input = str_replace("px", "", $input);
|
2025-11-26 14:37:51 +02:00
|
|
|
|
2025-12-15 15:27:55 +02:00
|
|
|
if (preg_match('/^(\d+)\s*x\s*(\d+)$/i', $input, $matches)) {
|
|
|
|
|
return [
|
|
|
|
|
"width" => (int) $matches[1],
|
|
|
|
|
"height" => (int) $matches[2],
|
|
|
|
|
];
|
|
|
|
|
}
|
2025-11-26 14:37:51 +02:00
|
|
|
|
2025-12-15 15:27:55 +02:00
|
|
|
return null;
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
// Function to calculate normalized aspect ratio (1/x format)
|
|
|
|
|
function getNormalizedAspectRatio($width, $height)
|
2025-11-26 14:37:51 +02:00
|
|
|
{
|
2025-12-16 16:35:06 +02:00
|
|
|
// Calculate the ratio as 1/x where x = height/width
|
|
|
|
|
$ratio = $width / $height;
|
|
|
|
|
|
|
|
|
|
if ($ratio >= 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
|
2025-12-15 15:27:55 +02:00
|
|
|
$gcd = function ($a, $b) use (&$gcd) {
|
|
|
|
|
return $b ? $gcd($b, $a % $b) : $a;
|
|
|
|
|
};
|
|
|
|
|
$divisor = $gcd($width, $height);
|
2025-12-16 16:35:06 +02:00
|
|
|
$simplified = $width / $divisor . ":" . $height / $divisor;
|
|
|
|
|
|
2025-12-15 15:27:55 +02:00
|
|
|
return [
|
2025-12-16 16:35:06 +02:00
|
|
|
"ratio" => $ratio,
|
|
|
|
|
"normalized" => $normalized,
|
|
|
|
|
"display" => $display,
|
|
|
|
|
"simplified" => $simplified,
|
2025-12-15 15:27:55 +02:00
|
|
|
];
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
// Function to calculate aspect ratio similarity (0-1, where 1 is perfect match)
|
|
|
|
|
function calculateAspectRatioSimilarity($targetRatio, $existingRatio)
|
2025-11-26 14:37:51 +02:00
|
|
|
{
|
2025-12-16 16:35:06 +02:00
|
|
|
// Calculate the absolute difference between ratios
|
|
|
|
|
$difference = abs($targetRatio - $existingRatio);
|
|
|
|
|
|
|
|
|
|
// Normalize the difference (smaller difference = higher similarity)
|
|
|
|
|
// Using an exponential decay function for better scoring
|
|
|
|
|
$similarity = exp(-$difference * 5);
|
|
|
|
|
|
|
|
|
|
return $similarity;
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Collect all image sizes from all categories
|
|
|
|
|
function collectAllImageSizes($image_folders)
|
|
|
|
|
{
|
2025-12-15 15:27:55 +02:00
|
|
|
$allSizes = [];
|
|
|
|
|
|
|
|
|
|
foreach ($image_folders as $category => $sizes) {
|
|
|
|
|
if ($category === "cms_images") {
|
|
|
|
|
continue; // Skip cms_images as it's a merged array
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($sizes as $sizeName => $config) {
|
2025-12-16 16:35:06 +02:00
|
|
|
if (
|
|
|
|
|
isset($config["width"]) &&
|
|
|
|
|
isset($config["height"]) &&
|
|
|
|
|
$config["height"] !== null
|
|
|
|
|
) {
|
2025-12-15 15:27:55 +02:00
|
|
|
$allSizes[] = [
|
|
|
|
|
"name" => $sizeName,
|
|
|
|
|
"category" => $category,
|
|
|
|
|
"width" => $config["width"],
|
2025-12-16 16:35:06 +02:00
|
|
|
"height" => $config["height"],
|
2025-12-15 15:27:55 +02:00
|
|
|
"crop" => $config["crop"] ?? false,
|
|
|
|
|
"forced" => $config["forced"] ?? false,
|
|
|
|
|
"path" => $config["path"] ?? "",
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $allSizes;
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
// Main script
|
|
|
|
|
echo "\n";
|
|
|
|
|
echo "===========================================\n";
|
|
|
|
|
echo " Image Aspect Ratio Finder Tool\n";
|
|
|
|
|
echo "===========================================\n\n";
|
|
|
|
|
|
2025-12-15 15:27:55 +02:00
|
|
|
echo "Enter image dimensions (e.g., 565x369px or 1920x1080): ";
|
2025-11-26 14:37:51 +02:00
|
|
|
$input = trim(fgets(STDIN));
|
|
|
|
|
|
|
|
|
|
$dimensions = parseDimensions($input);
|
|
|
|
|
|
|
|
|
|
if (!$dimensions) {
|
2025-12-15 15:27:55 +02:00
|
|
|
echo "\n❌ Invalid format! Please use format like: 565x369px or 1920x1080\n\n";
|
|
|
|
|
exit(1);
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
2025-12-15 15:27:55 +02:00
|
|
|
echo "\n📐 Analyzing dimensions: {$dimensions["width"]}x{$dimensions["height"]}px\n";
|
2025-11-26 14:37:51 +02:00
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
$targetRatio = getNormalizedAspectRatio(
|
|
|
|
|
$dimensions["width"],
|
|
|
|
|
$dimensions["height"],
|
|
|
|
|
);
|
|
|
|
|
echo " Aspect ratio: {$targetRatio["simplified"]} = {$targetRatio["display"]}\n\n";
|
2025-11-26 14:37:51 +02:00
|
|
|
|
|
|
|
|
// Collect all image sizes
|
|
|
|
|
$allSizes = collectAllImageSizes($image_folders);
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
// Calculate similarity for each size based on aspect ratio only
|
2025-11-26 14:37:51 +02:00
|
|
|
$matches = [];
|
2025-12-16 16:35:06 +02:00
|
|
|
$seenRatios = []; // Track unique aspect ratios
|
2025-12-15 15:27:55 +02:00
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
foreach ($allSizes as $size) {
|
|
|
|
|
$existingRatio = getNormalizedAspectRatio($size["width"], $size["height"]);
|
|
|
|
|
$similarity = calculateAspectRatioSimilarity(
|
|
|
|
|
$targetRatio["ratio"],
|
|
|
|
|
$existingRatio["ratio"],
|
2025-12-15 15:27:55 +02:00
|
|
|
);
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
$ratioKey = $existingRatio["display"];
|
|
|
|
|
|
|
|
|
|
// Store the match
|
|
|
|
|
$match = array_merge($size, [
|
2025-12-15 15:27:55 +02:00
|
|
|
"aspect_ratio" => $existingRatio["simplified"],
|
2025-12-16 16:35:06 +02:00
|
|
|
"aspect_ratio_display" => $existingRatio["display"],
|
2025-12-15 15:27:55 +02:00
|
|
|
"aspect_ratio_value" => $existingRatio["ratio"],
|
|
|
|
|
"similarity" => $similarity,
|
|
|
|
|
]);
|
2025-12-16 16:35:06 +02:00
|
|
|
|
|
|
|
|
$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;
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sort by similarity (best matches first)
|
|
|
|
|
usort($matches, function ($a, $b) {
|
2025-12-16 16:35:06 +02:00
|
|
|
$simDiff = $b["similarity"] <=> $a["similarity"];
|
|
|
|
|
if ($simDiff !== 0) {
|
|
|
|
|
return $simDiff;
|
|
|
|
|
}
|
|
|
|
|
// If similarity is the same, sort by name
|
|
|
|
|
return $a["name"] <=> $b["name"];
|
2025-11-26 14:37:51 +02:00
|
|
|
});
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
// Display results grouped by aspect ratio
|
|
|
|
|
echo "🔍 Image Sizes Grouped by Aspect Ratio:\n";
|
2025-11-26 14:37:51 +02:00
|
|
|
echo "===========================================\n\n";
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sort groups by similarity
|
|
|
|
|
uasort($groupedMatches, function ($a, $b) {
|
|
|
|
|
return $b["ratio"]["similarity"] <=> $a["ratio"]["similarity"];
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Display top 5 aspect ratio groups
|
|
|
|
|
$topGroups = array_slice($groupedMatches, 0, 5);
|
|
|
|
|
$displayCount = 0;
|
2025-11-26 14:37:51 +02:00
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
foreach ($topGroups as $ratioKey => $group) {
|
|
|
|
|
$firstMatch = $group["ratio"];
|
|
|
|
|
$matchPercent = round($firstMatch["similarity"] * 100, 1);
|
|
|
|
|
$matchBar = str_repeat("█", min(20, (int) ($matchPercent / 5)));
|
2025-12-15 15:27:55 +02:00
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
echo "📊 Aspect Ratio: {$firstMatch["aspect_ratio"]} = {$firstMatch["aspect_ratio_display"]}\n";
|
2025-12-15 15:27:55 +02:00
|
|
|
echo " Match: {$matchBar} {$matchPercent}%\n";
|
2025-12-16 16:35:06 +02:00
|
|
|
echo " Found " . count($group["sizes"]) . " size(s):\n\n";
|
|
|
|
|
|
|
|
|
|
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)";
|
|
|
|
|
}
|
2025-12-15 15:27:55 +02:00
|
|
|
}
|
|
|
|
|
echo "\n";
|
2025-12-16 16:35:06 +02:00
|
|
|
echo " Path: {$match["path"]}\n\n";
|
|
|
|
|
|
|
|
|
|
$displayCount++;
|
|
|
|
|
if ($displayCount >= 15) {
|
|
|
|
|
break 2; // Stop after 15 total sizes
|
|
|
|
|
}
|
2025-12-15 15:27:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
echo "\n";
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
// Check for exact aspect ratio matches
|
|
|
|
|
$exactMatches = array_filter($matches, function ($m) use ($targetRatio) {
|
|
|
|
|
return abs($m["aspect_ratio_value"] - $targetRatio["ratio"]) < 0.001;
|
2025-11-26 14:37:51 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!empty($exactMatches)) {
|
2025-12-16 16:35:06 +02:00
|
|
|
echo "\n✅ EXACT ASPECT RATIO MATCHES FOUND!\n";
|
2025-12-15 15:27:55 +02:00
|
|
|
echo "===========================================\n";
|
2025-12-16 16:35:06 +02:00
|
|
|
echo "These sizes have the exact same aspect ratio:\n\n";
|
2025-12-15 15:27:55 +02:00
|
|
|
foreach ($exactMatches as $match) {
|
2025-12-16 16:35:06 +02:00
|
|
|
echo " • {$match["name"]} ({$match["width"]}x{$match["height"]}px) - {$match["category"]}\n";
|
2025-12-15 15:27:55 +02:00
|
|
|
}
|
|
|
|
|
echo "\n";
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Recommendations
|
|
|
|
|
echo "\n💡 Recommendations:\n";
|
|
|
|
|
echo "===========================================\n";
|
|
|
|
|
|
2025-12-16 16:35:06 +02:00
|
|
|
if (!empty($exactMatches)) {
|
|
|
|
|
echo "✅ PERFECT MATCHES: " .
|
|
|
|
|
count($exactMatches) .
|
|
|
|
|
" size(s) with exact aspect ratio\n";
|
|
|
|
|
echo " Use any of the sizes listed above.\n";
|
2025-11-26 14:37:51 +02:00
|
|
|
} else {
|
2025-12-16 16:35:06 +02:00
|
|
|
$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";
|
|
|
|
|
}
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
echo "\n";
|
|
|
|
|
echo "Would you like to:\n";
|
|
|
|
|
echo " 1) Use an existing size\n";
|
|
|
|
|
echo " 2) Create a new size\n";
|
|
|
|
|
echo " 3) Exit\n";
|
|
|
|
|
echo "\nYour choice (1-3): ";
|
|
|
|
|
|
|
|
|
|
$choice = trim(fgets(STDIN));
|
|
|
|
|
|
|
|
|
|
switch ($choice) {
|
2025-12-15 15:27:55 +02:00
|
|
|
case "1":
|
|
|
|
|
echo "\n✅ Great! Use the size name from the list above in your image configuration.\n";
|
|
|
|
|
break;
|
|
|
|
|
case "2":
|
|
|
|
|
echo "\n📝 To create a new size, add it to: sites/default/settings/image_folders.php\n";
|
|
|
|
|
echo " Use this template:\n\n";
|
|
|
|
|
echo " 'your_size_name' => [\n";
|
|
|
|
|
echo " 'path' => 'uploads/images/your_path',\n";
|
|
|
|
|
echo " 'width' => {$dimensions["width"]},\n";
|
|
|
|
|
echo " 'height' => {$dimensions["height"]},\n";
|
|
|
|
|
echo " 'forced' => true,\n";
|
|
|
|
|
echo " 'crop' => true,\n";
|
|
|
|
|
echo " ],\n\n";
|
|
|
|
|
break;
|
|
|
|
|
case "3":
|
|
|
|
|
echo "\n👋 Goodbye!\n";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
echo "\n❌ Invalid choice.\n";
|
2025-11-26 14:37:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
echo "\n";
|
|
|
|
|
|