Como extrair uma imagem incorporada de um arquivo SVG?

18

Eu tenho um arquivo SVG que contém pelo menos uma imagem JPG / PNG incorporada. Quero extrair as imagens JPG / PNG desse arquivo SVG e salvá-las no disco.

Estou adicionando a tag inkscape , pois é o programa que uso para editar arquivos SVG, mas também aceito soluções usando outras ferramentas.

    
por Denilson Sá Maia 21.06.2011 / 09:09

6 respostas

6

Finalmente, anos depois, escrevi um script para extrair corretamente todas as imagens de um arquivo SVG, usando uma biblioteca XML adequada para analisar o código SVG.

link

Este script é escrito para o Python 2.7, mas deve ser muito fácil de converter para o Python 3. Ainda melhor, cerca de 50 linhas podem ser excluídas após a conversão para o Python 3.4, devido aos novos recursos introduzidos nessa versão.

    
por 04.12.2013 / 00:30
23

Minha própria solução (ou ... solução alternativa):

  1. Selecione a imagem no Inkscape
  2. Abra o XML Editor ( Deslocamento + Ctrl + X )
  3. Selecione o atributo xlink:href , que conterá a imagem como data: URI
  4. Copie todo o data: URI
  5. Cole esse data: URI em um navegador e salve-o de lá.

Como alternativa, posso abrir o arquivo SVG em qualquer editor de texto, localizar o data: URI e copiá-lo de lá.

Embora esta solução funcione, é um pouco complicado e eu adoraria aprender uma melhor.

    
por 21.06.2011 / 09:13
12

Existe uma solução melhor:

vá para Extensions -> Images -> Extract Image... , lá você pode salvar a imagem raster selecionada como um arquivo. No entanto, esta extensão funciona de forma estranha e de alguma forma funciona bem devagar (mas perfeitamente bem).

Outra nota: esta extensão é incômoda e morre silenciosamente em imagens grandes. Além disso, com um grande número de imagens rasterizadas, pode-se aumentar o uso de memória do inkscape para níveis horrendos (como 3GB depois de apenas um punhado de imagens extraídas).

Como eu tenho cerca de 20 arquivos SVG com cerca de 70 imagens rasterizadas em cada, cada imagem tem pelo menos 1 MB de tamanho, eu precisava de uma solução diferente. Depois de uma breve checagem usando a ponta do Denilson Sá eu criei o seguinte script php, que extrai imagens dos arquivos 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);

Dessa forma, posso obter todas as imagens que quero e o md5 me impede de obter imagens repetidas.

Aposto que deve haver outra maneira muito mais simples, mas cabe ao inkscape devs fazer melhor.

    
por 13.02.2012 / 22:16
4

Como mais uma alternativa, você pode salvar como PDF e abrir esse documento com o Inkscape.

Desmarque a opção "incorporar imagens" e o bingo, todos os pngs / jpegs serão lançados no seu diretório pessoal.

Confuso, mas mais rápido do que brincar com os dados: URL.

    
por 05.06.2013 / 14:52
0

Abra seu arquivo no Inkscape e selecione o bitmap que você deseja exportar. Clique em File- > Export Bitmap (Ctrl + Shift + E) e deve exportar apenas o bitmap selecionado.

    
por 29.11.2013 / 10:57
0

Eu melhoro o script do @Johnny_Bit . Nova versão do script pode usar svg com novas linhas. Ele extrai várias imagens do arquivo svg e salvá-los em arquivos PNG externos. Os arquivos Svg e png estão no diretório 'svg', mas você pode alterá-lo em 'SVG_DIR' constante.

<?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>';
}

?>
    
por 25.02.2017 / 15:58

Tags