Created
June 26, 2012 04:56
-
-
Save riaf/2993389 to your computer and use it in GitHub Desktop.
すごく手抜きな css sprite generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$filename = isset($argv[1]) ? realpath($argv[1]) : null; | |
$mixin = isset($argv[2]) ? $argv[2] : 'sprite-mixin'; | |
$retina = isset($argv[3]) ? true : false; | |
if (!$filename) { | |
echo "fail", PHP_EOL; | |
exit(1); | |
} | |
$json = json_decode(file_get_contents($filename), true); | |
$max_width = 0; | |
foreach ($json as $defs) { | |
if ($max_width < $defs['width']) { | |
$max_width = $defs['width']; | |
} | |
} | |
$output = ''; | |
$background_size = $retina ? sprintf(' background-size: %dpx auto;', $max_width / 2) : ''; | |
$output .= <<<HEAD | |
// generate code | |
.{$mixin}(@name) { | |
background-image: @{$mixin}-background; | |
{$background_size} | |
.{$mixin}-position(@name); | |
.{$mixin}-size(@name); | |
} | |
.{$mixin}-position(@name) { | |
.do () { | |
} | |
HEAD; | |
foreach ($json as $name => $defs) { | |
$offset_x = $defs['offset_x'] ? '-' . $defs['offset_x'] : 0; | |
$offset_y = $defs['offset_y'] ? '-' . $defs['offset_y'] : 0; | |
$width = $defs['width']; | |
$height = $defs['height']; | |
if ($retina) { | |
$width /= 2; | |
$height /= 2; | |
$offset_x /= 2; | |
$offset_y /= 2; | |
} | |
$normalize_name = preg_replace('/[^a-z0-9-]/i', '-', $name); | |
$output .= <<<DEF | |
.do () when(@name = {$normalize_name}) { | |
background-position: {$offset_x}px {$offset_y}px; | |
// width: {$width}px; | |
// height: {$height}px; | |
} | |
DEF; | |
} | |
$output .= <<<MID | |
.do(); | |
} | |
.{$mixin}-size(@name) { | |
.do () { | |
} | |
MID; | |
foreach ($json as $name => $defs) { | |
$offset_x = $defs['offset_x'] ? '-' . $defs['offset_x'] : 0; | |
$offset_y = $defs['offset_y'] ? '-' . $defs['offset_y'] : 0; | |
$width = $defs['width']; | |
$height = $defs['height']; | |
if ($retina) { | |
$width /= 2; | |
$height /= 2; | |
$offset_x /= 2; | |
$offset_y /= 2; | |
} | |
$normalize_name = preg_replace('/[^a-z0-9-]/i', '-', $name); | |
$output .= <<<DEF | |
.do () when(@name = {$normalize_name}) { | |
// background-position: {$offset_x}px {$offset_y}px; | |
width: {$width}px; | |
height: {$height}px; | |
} | |
DEF; | |
} | |
$output .= <<<FOOT | |
.do(); | |
} | |
// generated. | |
FOOT; | |
echo $output; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$src_dir = isset($argv[1]) ? realpath($argv[1]) : __DIR__.'/source'; | |
$NAME = isset($argv[2]) ? $argv[2] : 'sprite'; | |
if (!$src_dir) { | |
echo "dir not found", PHP_EOL; | |
exit(1); | |
} | |
// ================================================== | |
// image list | |
$image_files = array(); | |
foreach(new DirectoryIterator($src_dir) as $fileinfo) { | |
if (!in_array($fileinfo->getExtension(), array('png'))) { | |
continue; | |
} | |
list($width, $height, $type, $attr) = getimagesize($fileinfo->getPathname()); | |
$image_files[] = array( | |
'offset_x' => 0, | |
'offset_y' => 0, | |
'width' => $width, | |
'height' => $height + 1, | |
'filepath' => $fileinfo->getPathname(), | |
'basename' => $fileinfo->getBasename('.'.$fileinfo->getExtension()), | |
'calc_status' => 0, | |
); | |
} | |
// ================================================== | |
// sort | |
$image_files_width_asc | |
= $image_files_height_asc | |
= $image_files_width_desc | |
= $image_files_height_desc | |
= $image_files | |
; | |
$_width_ = array(); | |
$_height_ = array(); | |
foreach ($image_files as $image_file) { | |
$_width_[] = $image_file['width']; | |
$_height_ [] = $image_file['height']; | |
} | |
$_width_2 = $_width_; | |
$_height_2 = $_height_; | |
array_multisort($_width_, $image_files_width_asc); | |
array_multisort($_width_2, SORT_DESC, $image_files_width_desc); | |
array_multisort($_height_, $image_files_height_asc); | |
array_multisort($_height_2, SORT_DESC, $image_files_height_desc); | |
// ================================================== | |
// calc | |
// max width | |
$max_width = $image_files_width_desc[0]['width']; | |
$_ = 0; | |
$offset_x = 0; | |
$offset_y = 0; | |
$image_files = $image_files_width_desc; | |
while (true) { | |
// finish? | |
$fin = true; | |
foreach ($image_files as $image_file) { | |
if ($image_file['calc_status'] == 0) { | |
$fin = false; | |
} | |
} | |
if ($fin) { | |
break; | |
} | |
foreach ($image_files as $key => $image_file) { | |
$offset_x = 0; | |
if ($image_file['calc_status'] != 0) { | |
continue; | |
} | |
// head big | |
if ($image_file['width'] == $max_width) { | |
$image_files[$key]['offset_y'] = $offset_y; | |
$image_files[$key]['calc_status'] = 1; | |
$offset_y += $image_file['height'] + 1; | |
break; | |
} | |
$image_files[$key]['offset_y'] = $offset_y; | |
$image_files[$key]['calc_status'] = 1; | |
$offset_x = to_even($image_file['width'] + 1); | |
$offset_y = to_even($offset_y); | |
$next_width = $max_width - $offset_x; | |
$next_height = $image_file['height']; | |
$next_offset_y = to_even($offset_y); | |
// 横方向に並べる | |
$row_width = $max_width; | |
$row_height = $next_height; | |
$next_row_width = $next_width; | |
$next_row_height = $next_height; | |
$row_offset_x = to_even($offset_x); | |
$row_offset_y = to_even($next_offset_y); | |
$row_pointer_x = 0; | |
$ii = 0; | |
while (true) { | |
foreach ($image_files as $row_key => $row_image_file) { | |
if ($row_image_file['calc_status']) { | |
continue; | |
} | |
if ( | |
$next_row_width >= $row_image_file['width'] | |
&& $next_row_height >= $row_image_file['height'] | |
) { | |
$image_files[$row_key]['offset_x'] = $row_offset_x; | |
$image_files[$row_key]['offset_y'] = $row_offset_y; | |
$image_files[$row_key]['calc_status'] = 1; | |
$next_row_height -= $row_image_file['height'] + 1; | |
$row_offset_y += $row_image_file['height'] + 1; | |
$row_offset_y = to_even($row_offset_y); | |
$_w = $row_offset_x + $row_image_file['width'] + 1; | |
if ($_w > $row_pointer_x) { | |
$row_pointer_x = $_w; | |
} | |
} | |
} | |
if ($row_pointer_x == 0 || ++$ii > 100) { | |
break; | |
} | |
$next_row_width = $row_width - $row_pointer_x; | |
$next_row_height = $row_height; | |
$row_offset_x = to_even($row_pointer_x); | |
$row_offset_y = to_even($next_offset_y); | |
} | |
$offset_y += to_even($image_file['height'] + 1); | |
break; | |
} | |
if (++$_ > 100) { | |
// fin. | |
break; | |
} | |
} | |
$width = $max_width; | |
$height = 0; | |
foreach ($image_files as $image_file) { | |
$_h = $image_file['height'] + $image_file['offset_y'] + 1; | |
if ($_h > $height) { | |
$height = $_h; | |
} | |
} | |
$image = new Imagick(); | |
$image->newImage($width, $height, new ImagickPixel('transparent')); | |
$styles = array(); | |
$positions = array(); | |
foreach ($image_files as $image_file) { | |
$styles[$image_file['basename']] = array( | |
'width' => $image_file['width'].'px', | |
'height' => $image_file['height'].'px', | |
'background-position' => sprintf('%dpx %dpx', - $image_file['offset_x'], - $image_file['offset_y']), | |
); | |
$positions[$image_file['basename']] = array( | |
'width' => $image_file['width'], | |
'height' => $image_file['height'], | |
'offset_x' => $image_file['offset_x'], | |
'offset_y' => $image_file['offset_y'], | |
); | |
$image_part = new Imagick($image_file['filepath']); | |
$image->compositeImage($image_part, Imagick::COMPOSITE_DEFAULT, $image_file['offset_x'], $image_file['offset_y']); | |
$image_part->clear(); | |
$image_part->destroy(); | |
$image_part = null; | |
} | |
$css = ''; | |
foreach ($styles as $class => $defs) { | |
$css .= ".{$class} {" . PHP_EOL; | |
foreach ($defs as $key => $value) { | |
$css .= " {$key}: {$value};" . PHP_EOL; | |
} | |
$css .= "}" . PHP_EOL; | |
} | |
file_put_contents($NAME . '.css', $css); | |
file_put_contents($NAME . '.json', json_encode($positions)); | |
$image->writeImages($NAME . '.png', true); | |
echo "done.\n"; | |
$image->clear(); | |
$image->destroy(); | |
function to_even($number) | |
{ | |
if ($number % 2 != 0) { | |
$number += 1; | |
} | |
return $number; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
oh fu....