Скрипт для замены внедренных в СВГ изображений ссылками на внешние джипеги

25 февраля 2017

Формат СВГ разрешает внедрять изображения внутрь файла. Это значительно увеличивает его размер, потому что изображения не сжимаются, а записываются в расточительной кодировке base64.

Чтобы уменьшить размер СВГ, написал ПХП скрипт. Он извлекает внедренные изображения и сохраняет их в джипегах.

  1. Берет СВГ-файл из каталога svg.
  2. Вырезает из него внедренные рисунки.
  3. Сохраняет рисунки в формате джипег.
  4. Вставляет в СВГ-файл ссылки на эти джипеги.
  5. Сохраняет результат с новым названием с префиксом new-.

<?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.

Вы можете пользоваться скриптом как вам заблагорассудится. Если нравится, кликайте вверх на Стакэксченже.

Заметка в блоге «Вырезаем растровую графику из СВГ».