Bitweaver - Spritesheet management
Created by: Lester Caine, Last modification: 25 August 2025
This was pushing things a bit too much ;) Basically Mistral does not have enough process time to actually print the whole script for a super set of code. I will have to play with things myself to patch up the second half which is cobbled from the single size set of code.
<?php
// Directory containing the icons
$iconDir = 'icons/';
$spritesheetPath16 = 'spritesheet_16.png';
$spritesheetPath32 = 'spritesheet_32.png';
$outputCssFile16 = 'icon_map_16.css';
$outputCssFile32 = 'icon_map_32.css';
$outputImagePath16 = 'icon_map_16.png';
$outputImagePath32 = 'icon_map_32.png';
// Get a list of all icon files
$iconFiles16 = glob($iconDir . '16/*.png');
$iconFiles32 = glob($iconDir . '32/*.png');
// Initialize the icon maps
$iconMap16 = [];
$iconMap32 = [];
// Define the spritesheet dimensions and icon sizes
$spritesheetWidth16 = 1024; // Example width for 16x16
$spritesheetHeight16 = 1024; // Example height for 16x16
$spritesheetWidth32 = 1024; // Example width for 32x32
$spritesheetHeight32 = 1024; // Example height for 32x32
$iconWidth16 = 16; // Example width for 16x16
$iconHeight16 = 16; // Example height for 16x16
$iconWidth32 = 32; // Example width for 32x32
$iconHeight32 = 32; // Example height for 32x32
// Load the spritesheets using Imagick
$spritesheet16 = new Imagick($spritesheetPath16);
$spritesheet32 = new Imagick($spritesheetPath32);
// Calculate the position of each icon in the spritesheets
$x16 = 0;
$y16 = 0;
$x32 = 0;
$y32 = 0;
foreach ($iconFiles16 as $iconFile16) {
$iconName = basename($iconFile16, '.png');
$iconMap16[$iconName] = [
"x" => $x16,
"y" => $y16,
"width" => $iconWidth16,
"height" => $iconHeight16
];
$x16 += $iconWidth16;
if ($x16 >= $spritesheetWidth16) {
$x16 = 0;
$y16 += $iconHeight16;
}
}
foreach ($iconFiles32 as $iconFile32) {
$iconName = basename($iconFile32, '.png');
$iconMap32[$iconName] = [
"x" => $x32,
"y" => $y32,
"width" => $iconWidth32,
"height" => $iconHeight32
];
$x32 += $iconWidth32;
if ($x32 >= $spritesheetWidth32) {
$x32 = 0;
$y32 += $iconHeight32;
}
}
// Generate CSS code for 16x16 icons
$cssContent16 = ".icon-16 {n";
foreach ($iconMap16 as $iconName => $icon) {
$cssContent16 .= " .icon-16-$iconName {n";
$cssContent16 .= " width: 16px;n";
$cssContent16 .= " height: 16px;n";
$cssContent16 .= " background-image: url('$spritesheetPath16');n";
$cssContent16 .= " background-position: -{$icon['x']}px -{$icon['y']}px;n";
$cssContent16 .= " }n";
}
$cssContent16 .= "}n";
// Save CSS code for 16x16 icons to a file
file_put_contents($outputCssFile16, $cssContent16);
// Generate CSS code for 32x32 icons
$cssContent32 = ".icon-32 {n";
foreach ($iconMap32 as $iconName => $icon) {
$cssContent32 .= " .icon-32-$iconName {n";
$cssContent32 .= " width: 32px;n";
$cssContent32 .= " height: 32px;n";
$cssContent32 .= " background-image: url('$spritesheetPath32');n";
$cssContent32 .= " background-position: -{$icon['x']}px -{$icon['y']}px;n";
$cssContent32 .= " }n";
}
$cssContent32 .= "}n";
// Save CSS code for 32x32 icons to a file
file_put_contents($outputCssFile32, $cssContent32);
// Create a matching image using Imagick
$matchingImage = new Imagick();
$matchingImage->newImage($spritesheetWidth, $spritesheetHeight, new ImagickPixel('transparent'));
$matchingImage->setImageFormat('png');
foreach ($iconMap as $iconName => $icon) {
$iconImage = new Imagick($iconDir . $iconName . '.png');
$iconImage->resizeImage($iconWidth, $iconHeight, Imagick::FILTER_LANCZOS, 1);
$iconImage->setImagePage(0, 0, 0, 0);
$matchingImage->compositeImage($iconImage, Imagick::COMPOSITE_OVER, $icon['x'], $icon['y']);
}
$matchingImage->writeImage($outputImagePath);
// Display icons
echo "<div style='display: flex; flex-wrap: wrap;'>";
foreach ($iconMap as $iconName => $icon) {
echo "<div class='icon icon-$iconName' style='margin: 5px;'></div>";
}
echo "</div>";
Taking a step back and just looking at a more realistic starting point
<?php
// Directory containing the icons
$iconDir = 'icons/';
$spritesheetPath = 'spritesheet.png';
$outputCssFile = 'icon_map.css';
$outputImagePath = 'icon_map.png';
// Get a list of all icon files
$iconFiles = glob($iconDir . '*.png');
// Initialize the icon map
$iconMap = [];
// Define the spritesheet dimensions and icon size
$spritesheetWidth = 1024; // Example width
$spritesheetHeight = 1024; // Example height
$iconWidth = 32; // Example width
$iconHeight = 32; // Example height
// Load the spritesheet using Imagick
$spritesheet = new Imagick($spritesheetPath);
// Calculate the position of each icon in the spritesheet
$x = 0;
$y = 0;
foreach ($iconFiles as $iconFile) {
$iconName = basename($iconFile, '.png');
$iconMap[$iconName] = [
"x" => $x,
"y" => $y,
"width" => $iconWidth,
"height" => $iconHeight
];
$x += $iconWidth;
if ($x >= $spritesheetWidth) {
$x = 0;
$y += $iconHeight;
}
}
// Generate CSS code
$cssContent = ".icon {n";
foreach ($iconMap as $iconName => $icon) {
$cssContent .= " .icon-$iconName {n";
$cssContent .= " width: {$icon['width']}px;n";
$cssContent .= " height: {$icon['height']}px;n";
$cssContent .= " background-image: url('$spritesheetPath');n";
$cssContent .= " background-position: -{$icon['x']}px -{$icon['y']}px;n";
$cssContent .= " }n";
}
$cssContent .= "}n";
// Save CSS code to a file
file_put_contents($outputCssFile, $cssContent);
// Create a matching image using Imagick
$matchingImage = new Imagick();
$matchingImage->newImage($spritesheetWidth, $spritesheetHeight, new ImagickPixel('transparent'));
$matchingImage->setImageFormat('png');
foreach ($iconMap as $iconName => $icon) {
$iconImage = new Imagick($iconDir . $iconName . '.png');
$iconImage->resizeImage($iconWidth, $iconHeight, Imagick::FILTER_LANCZOS, 1);
$iconImage->setImagePage(0, 0, 0, 0);
$matchingImage->compositeImage($iconImage, Imagick::COMPOSITE_OVER, $icon['x'], $icon['y']);
}
$matchingImage->writeImage($outputImagePath);
// Display icons
echo "<div style='display: flex; flex-wrap: wrap;'>";
foreach ($iconMap as $iconName => $icon) {
echo "<div class='icon icon-$iconName' style='margin: 5px;'></div>";
}
echo "</div>";