SVG 파일에서 임베디드 이미지를 추출하는 방법은 무엇입니까?


26

내부에 하나 이상의 임베디드 JPG / PNG 이미지가 포함 된 SVG 파일이 있습니다. 해당 SVG 파일에서 JPG / PNG 이미지를 추출하여 디스크에 저장하고 싶습니다.

inkscapeSVG 파일을 편집하는 데 사용하는 프로그램이므로 태그를 추가하고 있지만 다른 도구를 사용하는 솔루션도 허용합니다.


1
다른 것이 없다면 파이썬은 아마도 lxml과 PIL (또는 이와 동등한)을 사용하는 커스텀 접착제로 할 수 있습니다.
Keith

@Keith는 실제로이 질문을 해결하기 위해 Python 스크립트 를 작성 했습니다 . 내장 xml.etree라이브러리를 사용합니다 .
Denilson Sá Maia

답변:


30

내 자신의 솔루션 (또는 ... 해결 방법) :

  1. Inkscape에서 이미지를 선택하십시오
  2. 내장 XML Editor( Shift+ Ctrl+ X)을 엽니 다
  3. xlink:href이미지를 데이터 로 포함 할 속성을 선택하십시오 . URI
  4. 전체 data:URI를 복사하십시오.
  5. 해당 data:URI를 브라우저에 붙여 넣고 거기에서 저장하십시오.

또는 텍스트 편집기에서 SVG 파일을 열고 data:URI를 찾아 복사 할 수 있습니다.

이 솔루션은 효과가 있지만 다소 번거롭고 더 나은 것을 배우고 싶습니다.


2
+1-이 방법을 사용하여 3.5MB 이미지를 내보냈지만 시간이 오래 걸렸습니다. 어떻게 든 "이미지 추출"기능이 작동하지 않았습니다.
Martin

이 목적을 위해 명령 행 Python 스크립트 도 참조하십시오 .
Denilson Sá Maia

17

대신 더 나은 해결책이 있습니다.

로 이동 Extensions -> Images -> Extract Image...하면 선택한 래스터 이미지를 파일로 저장할 수 있습니다. 그러나이 확장은 이상하게 작동하고 다소 느리게 작동하지만 완벽하게 작동합니다.

또 다른 참고 사항 :이 확장은 번거롭고 다양한 대형 이미지에서 자동으로 죽습니다. 또한 많은 수의 래스터 이미지를 사용하면 잉크 스케이프의 메모리 사용량을 끔찍한 수준으로 끌어 올릴 수 있습니다 (소량의 이미지 만 추출한 후 3GB).

각각 약 70MB의 래스터 이미지가있는 약 20 개의 svg 파일이 있고 각 이미지의 크기는 최소 1MB이므로 다른 솔루션이 필요했습니다. Denilson Sá 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는 반복되는 이미지를 얻지 못하게합니다.

훨씬 더 간단한 다른 방법이 있어야하지만 내기를 더 잘하는 것은 잉크 스케이프 개발자에게 달려 있습니다.


참고 : 스크립트는 한 data:줄에 하나의 URL 만 지원하며 href 속성 내에서 줄 바꿈을 지원하지 않습니다 (inkscape는 데이터 URL에 추가하고, base64 사양은 줄이 76 자 이하 여야합니다 ). 빠른 해킹을위한 멋진 스크립트이지만 모든 종류의 SVG에서는 작동하지 않습니다.
Denilson Sá Maia '12

파일 복제를 방지하기 위해 md5 sum을 사용하는 경우 @Johnny_Bit +1 아래 스크립트를 개선 합니다 .
Ivan Z

좋은 2019 년 3 월이며 상당히 큰 이미지로 쉽게 그랜드 작업했습니다. 그리고 오래된 노트북 / 우분투 / 잉크 스케이프 0.48.4. 감사!
gaoithe

9

마지막으로 몇 년 후, 적절한 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 줄을 삭제할 수 있습니다.


작동하기 때문에 감사합니다. 그러나 PDF 해결 방법보다 훨씬 느립니다. 병렬 처리에 대해 생각해 보셨습니까? 현재 스크립트는 단일 CPU 코어 / 스레드 만 사용합니다.
DanMan

@DanMan 불행히도, 병렬만드는 것은 속도를 높이는 마법의 해결책이 아닙니다. 병목 현상을 식별하기 위해 코드를 프로파일 링해야합니다. 병목 현상이 XML 구문 분석 인 경우 죄송합니다. 해당 부분을 병렬로 수행 할 수 없습니다. 너무 느린 SVG 파일을 정확하게 이메일로 보내 주시겠습니까? 시간이있을 때마다 성능을 조사 할 수 있습니다.
Denilson Sá Maia

네, 직접 해 보았습니다 .XML 파싱은 이미지를 디코딩하지 않고 속도가 느린 것으로 나타났습니다. 즉, cElementTree더 빨라야합니다. 그러나 Sax와 ​​같은 것이 더 잘 작동 할 수도 있습니다.
DanMan

@ DanMan cElementTree이 더 빠를 것입니다. 그러나 Python 3.3에서는 둘 다 동일 합니다. 어느 시점에서 나는 그 스크립트를 파이썬 3으로 업데이트 할 것이다.
Denilson Sá Maia

5

또 다른 해결 방법으로 PDF로 저장 한 다음 Inkscape로 해당 문서를 열 수 있습니다.

"포함 된 이미지"및 빙고를 선택 취소하면 모든 png / jpeg가 홈 디렉토리로 배출됩니다.

지저분하지만 data : URL을 다루는 것보다 빠릅니다.


"포함 된 이미지"옵션을 어디에서 찾았습니까?
mik01aj

1
inkscape에서 PDF 문서를 열면 다음 대화 상자에 있습니다.
Nicholas Wilson

Inkscape에서 이미지를 가져 와서 이미지를 추출하려고 시도한 PDF가 있습니다. 이 경우,이 작업을 수행 할 수있는 수입보다는 한 후 가져 오기가 훨씬 더 유용합니다.
user149408

확실하지는 않지만이 방법으로 임베디드 ICC 프로파일이 프로세스에서 손실되는 것처럼 보입니다. 해당 Python 스크립트를 통해 SVG에서 직접 추출한 이미지에는 ICC 프로파일이 포함되어 있습니다.
DanMan

1

@Johnny_BitPHP 스크립트를 향상시킵니다 . 스크립트의 새로운 릴리스는 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>';
}

?>

0

Inkscape에서 파일을 열고 내보낼 비트 맵을 선택하십시오. 파일-> 비트 맵 내보내기 (Ctrl + Shift + E)를 클릭하면 선택한 비트 맵 만 내 보내야합니다.


이미지를 다시 인코딩하기 때문에이 솔루션이 마음에 들지 않습니다. 이미지를 원래 형식으로 추출하는 솔루션을 선호합니다.
Denilson Sá Maia

1
예, Inkscape가 이미지를 다시 인코딩하는 것처럼 보이지만 기본적으로 PNG 이미지를 저장합니다. 그래서 나는 재 인코딩이 적어도 무손실이라고 가정합니다.
Chris

1
글쎄,별로. 포함 된 이미지에 변형 (스케일링, 회전 등)이 있거나, 잘렸거나, 내가 모르는 것이있을 수 있습니다. Inkscape는 이러한 모든 변환을 적용한 후에 선택한 개체를 확실히 내보내므로이 솔루션이 손실이없는 것은 아닙니다.
Denilson Sá Maia '
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.