Perl / Делаем спрайт-иконки на Perl

в 14:50, , рубрики: icons, perl, sprite, метки: , ,

Как ни странно, не удалось мне найти простую консольную утилиту для склеивания в один спрайт кучи png-иконок, поэтому пришлось взять в руки mcedit (все, что было под рукой) и написать небольшой скрипт, который учитывает, в отличие от других реализаций, что при слишком большой ширине/высоте картинки возникают проблемы с реализацией просмотра png в Windows GDI (там ограничение, похоже, signed int).
Под катом, собственно код с небольшими пояснениями.

#!/usr/bin/perl  use strict; use GD;  my ($size,$dir,$outpng,$outcss) = @ARGV;  my $line = 100; # Это кол-во иконок на одну строку, т.е. выходной файл будет шириной $size*$line пикселей  # Если пропустили параметр, выдаем подсказку unless ((defined $size) and (defined $dir) and (defined $outpng) and (defined $outcss)){ # Собственно,  #     size - размер исходной иконки #     dir - каталог с иконками #     outpng - выходной png файл #     outcss - выходной css файл die <<"--info--"; $0 <size> <dir> <outpng> <outcss> --info-- }  # Поехали! opendir(my $dhandle,$dir); my @pngs = grep !/^..?$/,readdir($dhandle); closedir($dhandle);  my $width = $line*$size; my $height = $size*(int($#pngs/$line)+1);  my $im = new GD::Image($width,$height,1); # Вот эта единица, это truecolor включаем # Альфа-канал из иконок будет сохранен $im->alphaBlending(0); $im->saveAlpha(1);  my $i=0; my $j=0;  open(my $css,">",$outcss); # Поскольку я использую bootstrap from twitter в этом проекте, тут у меня bootstrap-like стили для иконок print $css <<"--css--"; [class^="mcrm-i-"]     {     display:inline-block;     width:${size}px;     height:${size}px;     vertical-align:text-top;     background-image:url(/images/mcm-icons.png);     background-position:${size}px ${size}px;     background-repeat:no-repeat;*margin-right:.3em;     } [class^="mcm-i-"]:last-child{*margin-left:0;} --css-- for (sort @pngs) { my $png = GD::Image->newFromPng($dir.'/'.$_,1); $im->copy($png,$i*$size,$j*$size,0,0,$size,$size); my ($name,$ext) = split /./,$_; printf $css "      .mcm-i-$name {background-position:%dpx %dpx;}",-$size*$i,-$size*$j; $i++; if($i>=$line){$j++;$i=0;} } close($outcss);  open(my $png,">",$outpng); binmode($png); print $png $im->png(9); # Пожмем как сможем вывод close($png); 

В итоге получаем спрайт и css описание иконок на нем. Использование традиционно (как в bootstrap):

<a href="#" class="btn"><i class="mcm-i-icon-name"></i> Кнопка</a> 

Размер у меня при >3000 иконок вышел 900КБ, перевел в индексированные цвета, стало 190КБ. Если еще пооптимизировать, можно, думаю, и сильнее пожать.

Как говорится, feel free to use this code, 'cos it's a public domain :)

Автор: Rumka


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js