web-dev-qa-db-ja.com

SVGファイルから埋め込み画像を抽出する方法は?

内部に少なくとも1つの埋め込まれたJPG/PNG画像を含むSVGファイルがあります。そのSVGファイルからJPG/PNG画像を抽出して、ディスクに保存したいと思います。

inkscapeタグを追加しています。これは、SVGファイルの編集に使用するプログラムですが、他のツールを使用した解決策も受け入れます。

26

最後に、数年後、適切なXMLライブラリを使用してSVGコードを解析し、S​​VGファイルからすべての画像を正しく抽出するスクリプトを作成しました。

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

このスクリプトはPython 2.7用に書かれていますが、Pythonへの変換は非常に簡単です。3。Pythonへの変換後に約50行を削除できます。 、そのバージョンで導入された新機能のため。

10

私自身の解決策(または...回避策):

  1. Inkscapeで画像を選択します
  2. 組み込みXML EditorShift+Ctrl+X
  3. を選択 xlink:href属性。画像が data:URI として含まれます
  4. 全体をコピーdata: URI
  5. 貼り付けdata: URIをブラウザに入力し、そこから保存します。

または、任意のテキストエディターでSVGファイルを開き、data: URIとそこからコピーします。

このソリューションは機能しますが、少し面倒なので、もっと良いソリューションを学びたいです。

30

代わりに、より良い解決策があります:

Extensions -> Images -> Extract Image...に移動すると、選択したラスターイメージをファイルとして保存できます。ただし、この拡張機能は奇妙に動作し、どういうわけかかなりゆっくりと動作します(ただし、完全にうまく動作します)。

もう1つのメモ:この拡張機能は扱いにくく、さまざまな大きな画像で静かに終了します。また、ラスターイメージの数が多いと、inkscapeのメモリ使用量が恐ろしいレベルに急上昇する可能性があります(ほんの一握りのイメージが抽出された後の3GBなど)。

それぞれに約70のラスターイメージが含まれる約20のsvgファイルがあり、各イメージのサイズが少なくとも1MBであるため、別のソリューションが必要でした。 DenilsonSátip を使用して簡単に確認した後、svgファイルから画像を抽出する次のphpスクリプトを考案しました。

#!/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を使用すると、繰り返し画像を取得する必要がなくなります。

もっと簡単な別の方法があるに違いないと思いますが、それをうまく行うかどうかは、インクスケープ開発者次第です。

18
Johnny_Bit

さらに別の回避策として、PDFとして保存してから、そのドキュメントをInkscapeで開くことができます。

「埋め込み画像」のチェックを外すと、ビンゴ、すべてのpng/jpegsがあなたのホームディレクトリに吐き出されます。

厄介ですが、データ:URLをいじるよりも高速です。

5
Nicholas Wilson

@ Johnny_Bitのphpスクリプト を改善します。スクリプトの新しいリリースでは、新しい行で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>';
}

?>
1
Ivan Z

Inkscapeでファイルを開き、エクスポートするビットマップを選択します。 [ファイル]-> [ビットマップのエクスポート](Ctrl + Shift + E)をクリックすると、選択したビットマップのみがエクスポートされます。

0
Chris