内部に少なくとも1つの埋め込みJPG / PNGイメージを含むSVGファイルがあります。そのSVGファイルからJPG / PNG画像を抽出し、ディスクに保存したい。
inkscape
SVGファイルの編集に使用するプログラムであるため、タグを追加していますが、他のツールを使用したソリューションも受け入れます。
内部に少なくとも1つの埋め込みJPG / PNGイメージを含むSVGファイルがあります。そのSVGファイルからJPG / PNG画像を抽出し、ディスクに保存したい。
inkscape
SVGファイルの編集に使用するプログラムであるため、タグを追加していますが、他のツールを使用したソリューションも受け入れます。
回答:
私自身のソリューション(または...回避策):
XML Editor
(Shift+ Ctrl+ X)を開きますxlink:href
として画像を含む属性を選択します:URIdata:
URI 全体をコピーしますdata:
URIをブラウザーに貼り付け、そこから保存します。または、テキストエディターでSVGファイルを開き、data:
URIを見つけてそこからコピーすることもできます。
このソリューションは機能しますが、ちょっと面倒ですし、もっと良いものを学びたいです。
代わりに、より良い解決策があります。
に移動するとExtensions -> Images -> Extract Image...
、選択したラスターイメージをファイルとして保存できます。ただし、この拡張機能は奇妙に動作し、どういうわけかかなりゆっくり動作します(ただし、完全に良好です)。
別の注意:この拡張機能は扱いにくく、さまざまな大きな画像で静かに終了します。また、多数のラスターイメージを使用すると、inkscapeのメモリ使用量が途方もないレベルに達する可能性があります(ほんの一握りのイメージを抽出した後の3GBなど)。
それぞれが少なくとも1MBのサイズの約70個のラスターイメージを含む約20個のsvgファイルを持っているため、別のソリューションが必要でした。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を使用すると、繰り返し画像を取得する必要がなくなります。
もっと簡単な別の方法があるに違いないが、それをもっと良くするのはinkscapeの開発者次第だ。
data:
1行につき1 つのURL のみをサポートし、href属性内の改行をサポートしません(inkscapeはデータURLに改行を追加し、base64仕様では、行が76文字を超えないように義務付けています)。簡単なハック用の素晴らしいスクリプトですが、すべての種類のSVGでは機能しません。
最後に、数年後、適切なXMLライブラリを使用してSVGコードを解析し、SVGファイルからすべての画像を正しく抽出するスクリプトを作成しました。
http://bitbucket.org/denilsonsa/small_scripts/src/tip/extract_embedded_images_from_svg.py
このスクリプトはPython 2.7用に書かれていますが、Python 3への変換は非常に簡単です。さらに良いことに、そのバージョンで導入された新機能により、Python 3.4への変換後に約50行を削除できます。
cElementTree
は言うものの、より高速になるはずです。しかし、Saxのようなものもうまく機能しているのかもしれません。
cElementTree
はおそらくより高速です。ただし、Python 3.3では、両方とも同じです。いつか、そのスクリプトをPython 3に更新するでしょう。
さらに別の回避策として、PDFとして保存し、Inkscapeでそのドキュメントを開くことができます。
「埋め込み画像」のチェックを外すと、ビンゴ、すべてのpng / jpegがホームディレクトリに吐き出されます。
厄介ですが、URLのデータをだまし取るよりも速いです。
私は改善@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>';
}
?>
Inkscapeでファイルを開き、エクスポートするビットマップを選択します。[ファイル]-> [ビットマップのエクスポート](Ctrl + Shift + E)をクリックすると、選択したビットマップのみがエクスポートされます。