19

У меня есть файл SVG, который содержит по крайней мере одно встроенное изображение JPG/PNG внутри. Я хочу извлечь изображения JPG/PNG из этого файла SVG и сохранить их на диске.

Я добавляю тег inkscape как это программа, которую я использую для редактирования файлов SVG, но я также принимаю решения с использованием других инструментов.

6 ответов6

24

Мое собственное решение (или ... обходной путь):

  1. Выберите изображение в Inkscape
  2. Откройте встроенный XML Editor (Shift+Ctrl+X)
  3. Выберите xlink:href , который будет содержать изображение в качестве данных: URI
  4. Скопируйте все data: URI
  5. Вставьте эти data: URI в браузер и сохраните его оттуда.

Кроме того, я могу открыть файл SVG в любом текстовом редакторе, найти data: URI и скопировать их оттуда.

Хотя это решение работает, оно довольно обременительно, и я бы хотел изучить его лучше.

14

Вместо этого есть лучшее решение:

перейдите в Extensions -> Images -> Extract Image... , там вы можете сохранить выбранное растровое изображение в виде файла. Однако это расширение работает странно и как-то работает довольно медленно (но совершенно хорошо).

Еще одно замечание: это расширение громоздко и умирает на разных больших изображениях. Кроме того, с большим количеством растровых изображений это может увеличить использование памяти inkscape до ужасных уровней (например, 3 ГБ после нескольких извлеченных изображений).

Поскольку у меня есть около 20 SVG-файлов с около 70 растровыми изображениями в каждом, каждое размером не менее 1 МБ, мне нужно было другое решение. После небольшой проверки с помощью Denilson S tip я разработал следующий php-скрипт, который извлекает изображения из SVG-файлов:

#!/usr/bin/env php
<?php

$svgs = glob('*.svg');

$existing = array();

foreach ($svgs as $svg){
    mkdir("./{$svg}.images");
    $lines = file($svg);
    $img = 0;
    foreach ($lines as $line){
        if (preg_match('%xlink:href="data:([a-z0-9-/]+);base64,([^"]+)"%i', $line, $regs)) {
            $type = $regs[1];
            $data = $regs[2];
            $md5 = md5($data);
            if (!in_array($md5, $existing)) {
                $data = str_replace(' ', "\r\n", $data);
                $data = base64_decode($data);
                $type = explode('/', $type);
                $save = "./{$svg}.images/{$img}.{$type[1]}";
                file_put_contents($save, $data);
                $img++;
                $existing[] = $md5;
            }
        } else {
            $result = "";
        }
    }
}

echo count($existing);

Таким образом, я могу получить все нужные изображения, а md5 избавляет меня от повторных изображений.

Могу поспорить, что должен быть другой способ, который намного проще, но разработчики Inkscape должны сделать это лучше.

7

Наконец, спустя годы, я написал сценарий для правильного извлечения всех изображений из файла SVG, используя правильную библиотеку XML для анализа кода SVG.

http://bitbucket.org/denilsonsa/small_scripts/src/tip/extract_embedded_images_from_svg.py

Этот скрипт написан для Python 2.7, но его довольно легко конвертировать в Python 3. Более того, около 50 строк могут быть удалены после преобразования в Python 3.4 благодаря новым функциям, представленным в этой версии.

4

Как еще один обходной путь, вы можете сохранить в формате PDF, а затем открыть этот документ с помощью Inkscape.

Снимите флажок "вставлять изображения" и, бинго, все pngs/jpegs будут выброшены в ваш домашний каталог.

Грязно, но быстрее, чем дурачиться с данными: URL.

0

Откройте свой файл в Inkscape и выберите растровое изображение, которое вы хотите экспортировать. Нажмите File-> Export Bitmap (Ctrl+Shift+E), и он должен экспортировать только выбранное растровое изображение.

0

Я улучшаю php-скрипт @Johnny_Bit. Новая версия скрипта может использовать SVG с новыми строками. Он извлекает несколько изображений из SVG-файла и сохраняет их во внешних PNG-файлах. Файлы SVG и PNG находятся в каталоге 'SVG', но вы можете изменить его в константе 'SVG_DIR'.

<?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/>Embeded image has benn saved to file: ';

               $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++) . '.png';
                    file_put_contents(SVG_DIR.$image_file, $data);
                    $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', $svg_data);
    }

   echo '</p>';
}

?>

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .