25 февраля 2017
Формат СВГ разрешает внедрять изображения внутрь файла. Это значительно увеличивает его размер, потому что изображения не сжимаются, а записываются в расточительной кодировке base64.
Чтобы уменьшить размер СВГ, написал ПХП скрипт. Он извлекает внедренные изображения и сохраняет их в джипегах.
<?php
define ( 'SVG_DIR', 'svg/' );
define ( 'SVG_PREFIX', 'new-' );
$svgs = glob(SVG_DIR.'*.svg');
$external = array();
$img = 1;
foreach ($svgs as $svg) {
echo '<p>';
$svg_data = file_get_contents( $svg );
$svg_data = str_replace( array("\n\r","\n","\r"), "", $svg_data);
$svg_file = substr($svg, strlen(SVG_DIR) );
echo $svg_file.': '.strlen($svg_data).' байт';
if ( preg_match_all( '|<image[^>]+>|', $svg_data, $images, PREG_SET_ORDER) ) {
foreach ($images as $image_tag) {
if ( preg_match('%xlink:href="data:([a-z0-9-/]+);base64,([^"]+)"%i', $image_tag[0], $regs) ) {
echo '<br/>Внедренное изображение сохранено в файле: ';
$type = $old_type = $regs[1];
$data = $old_data = $regs[2];
$md5 = md5($data);
if ( array_key_exists($md5, $external) ) {
$image_file = $external[$md5];
} else {
$data = str_replace(" ", "\r\n", $data);
$data = base64_decode($data);
$type = explode('/', $type);
$image_file = substr( $svg_file, 0, strlen($svg_file)-4 ) . '-' . ($img++) . '.jpg';
file_put_contents( SVG_DIR.$image_file, $data);
$image_jpg = imagecreatefrompng( SVG_DIR.$image_file );
imagejpeg( $image_jpg, SVG_DIR.$image_file, 86);
$external[$md5] = $image_file;
}
echo $image_file;
$svg_data = str_replace('xlink:href="data:'.$old_type.';base64,'.$old_data.'"', 'xlink:href="'.$image_file.'"', $svg_data);
}
}
file_put_contents(SVG_DIR.SVG_PREFIX.$svg_file, $svg_data);
}
echo '</p>';
}
?>
Идея cкрипта подсмотрена у Джони Бита. Он прикольно придумал проверять уникальность картинок при помощи алгоритма md5.
Вы можете пользоваться скриптом как вам заблагорассудится. Если нравится, кликайте вверх на Стакэксченже.
Заметка в блоге «Вырезаем растровую графику из СВГ».