SVG फ़ाइल से एम्बेडेड छवि कैसे निकालें?


26

मेरे पास एक एसवीजी फ़ाइल है जिसमें कम से कम एक एम्बेडेड जेपीजी / पीएनजी छवि अंदर है। मैं उस एसवीजी फ़ाइल से जेपीजी / पीएनजी छवियों को निकालना चाहता हूं और उन्हें डिस्क पर सहेजना चाहता हूं।

मैं inkscapeटैग जोड़ रहा हूं क्योंकि यह वह कार्यक्रम है जिसका उपयोग मैं एसवीजी फ़ाइलों को संपादित करने के लिए करता हूं, लेकिन मैं अन्य उपकरणों का उपयोग करके समाधान भी स्वीकार करता हूं।


1
यदि और कुछ नहीं, तो अजगर शायद एलएक्सएमएल और पीआईएल (या समकक्ष) का उपयोग करके कुछ कस्टम गोंद के साथ कर सकता है।
कीथ

@ कीथ, वास्तव में, मैंने इस प्रश्न को हल करने के लिए सिर्फ पायथन स्क्रिप्ट लिखी है । यह बिल्ट-इन xml.etreeलाइब्रेरी का उपयोग करता है ।
डेनीलसन सा मैया

जवाबों:


30

मेरा अपना समाधान (या ... समाधान):

  1. Inkscape में छवि का चयन करें
  2. अंतर्निहित XML Editor( Shift+ Ctrl+ X) खोलें
  3. उस xlink:hrefविशेषता का चयन करें , जिसमें डेटा के रूप में छवि होगी : URI
  4. पूरे data:यूआरआई को कॉपी करें
  5. उस data:URI को एक ब्राउज़र में पेस्ट करें , और उसे वहां से सहेजें।

वैकल्पिक रूप से, मैं किसी भी टेक्स्ट एडिटर में SVG फाइल खोल सकता हूं, data:URI का पता लगा सकता हूं और वहां से कॉपी कर सकता हूं ।

हालांकि यह समाधान काम करता है, यह थोड़े बोझिल है और मैं एक बेहतर सीखना चाहूंगा।


2
+1 - मैंने इस पद्धति का उपयोग करके 3.5 एमबी की छवि का निर्यात किया, जिसमें कुछ समय लगा लेकिन काम किया। किसी तरह "एक्सट्रेक्ट इमेज" फंक्शन मेरे काम नहीं आया।
मार्टिन

कृपया इस उद्देश्य के लिए एक कमांड-लाइन पायथन लिपि भी देखें ।
डेनिलसन सा मैया

17

इसके बजाय एक बेहतर उपाय है:

पर जाएँ Extensions -> Images -> Extract Image..., वहाँ आप एक फ़ाइल के रूप में चयनित रेखापुंज छवि को बचा सकते हैं। हालाँकि यह विस्तार अजीब काम करता है और किसी तरह धीरे-धीरे (लेकिन पूरी तरह से) काम करता है।

एक और नोट: यह विस्तार बोझिल है और अलग-अलग बड़ी छवियों पर चुपचाप मर जाता है। इसके अलावा, बड़ी संख्या में रेखापुंज छवियों के साथ यह स्मृति के उपयोग की भयावहता को भयावह स्तर तक बढ़ा सकता है (जैसे कि 3GB केवल कुछ ही चित्र निकाले जाने के बाद)।

क्योंकि मुझे उनमें से प्रत्येक में लगभग 70 रेखापुंज छवियों के साथ 20 svg फाइलें मिली हैं, प्रत्येक छवि का आकार कम से कम 1 एमबी है, मुझे एक अलग समाधान की आवश्यकता है। Denilson Sá टिप का उपयोग करते हुए एक छोटी जाँच के बाद मैंने निम्न 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 मुझे बार-बार प्राप्त होने वाली छवियों से बचाता है।

मुझे यकीन है कि एक और तरीका होना चाहिए जो बहुत सरल है, लेकिन यह बेहतर करने के लिए इनस्केप देवों पर निर्भर है।


नोट: आपकी स्क्रिप्ट data:प्रति पंक्ति केवल एक URL का समर्थन करती है, और href विशेषता के अंदर नईलाइन्स का समर्थन नहीं करती है (inkscape उन्हें डेटा URL के लिए जोड़ता है, और बेस 64 युक्ति यह भी बताती है कि लाइनें 76 वर्णों से अधिक लंबी नहीं होनी चाहिए )। एक त्वरित हैक के लिए अच्छी स्क्रिप्ट, लेकिन यह सभी प्रकार के एसवीजी के साथ काम नहीं करता है।
डेनिल्सन सिया मिया

@Johnny_Bit +1 md5 राशि के उपयोग के लिए फ़ाइलों के दोहराव को रोकने के लिए। मैं नीचे अपनी स्क्रिप्ट की नकल करता हूं ।
इवान जेड

अच्छा, मार्च 2019 और एक बड़ी छवि के साथ आसान भव्य काम किया। और बहुत पुराना लैपटॉप / ubuntu / tokscape 0.48.4। धन्यवाद!
17

9

अंत में, वर्षों बाद, मैंने एसवीजी फ़ाइल से सभी छवियों को सही ढंग से निकालने के लिए एक स्क्रिप्ट लिखी है, एसवीजी कोड को पार्स करने के लिए एक उचित XML लाइब्रेरी का उपयोग कर रहा है।

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

यह स्क्रिप्ट पाइथन 2.7 के लिए लिखी गई है, लेकिन इसे पाइथन 3 में बदलना काफी आसान होना चाहिए। इससे भी बेहतर, पाइथन 3.4 में रूपांतरण के बाद लगभग 50 लाइनों को हटाया जा सकता है, क्योंकि उस संस्करण में पेश किए गए नए फीचर्स के कारण।


धन्यवाद, क्योंकि यह काम करता है। लेकिन यह पीडीएफ वर्कअराउंड की तुलना में बहुत धीमा है। क्या आपने समानांतर प्रसंस्करण के बारे में सोचा है? अभी, स्क्रिप्ट केवल एक ही CPU कोर / थ्रेड का उपयोग करती है।
डैनमैन

@ डानमैन दुर्भाग्य से, इसे समानांतर बनाना किसी भी चीज़ को गति देने के लिए एक जादुई समाधान नहीं है। अड़चन की पहचान करने के लिए मुझे कोड को प्रोफाइल करना होगा। यदि अड़चन XML पार्सिंग है, तो मुझे क्षमा करें, वह हिस्सा समानांतर में नहीं किया जा सकता है। क्या आप मुझे सही एसवीजी फाइलें ई-मेल द्वारा भेज सकते हैं जो बहुत धीमी हैं? जब भी मेरे पास कुछ समय होगा, मैं प्रदर्शन की जांच कर सकता हूं।
डेनिलसन सिया मिया

हाँ, मैंने इसे स्वयं करने की कोशिश की, और यह पता चला कि XML पार्सिंग धीमा हिस्सा है, छवियों को डिकोड नहीं कर रहा है। उस ने कहा, cElementTreeतेजी से माना जाता है। लेकिन शायद कुछ ऐसा ही सैक्स बेहतर काम करता है।
डैनमैन

@ डनमैन cElementTreeतेजी से होने की संभावना है। हालाँकि, Python 3.3 पर, दोनों समान हैं । कुछ बिंदु पर मैं संभवत: उस स्क्रिप्ट को पायथन 3 में अपडेट करूंगा
डेनिल्सन सिया मिया

5

अभी तक एक और समाधान के रूप में, आप पीडीएफ के रूप में सहेज सकते हैं, फिर उस दस्तावेज़ को इंकस्केप के साथ खोलें।

"छवियों को एम्बेड करें" को अनचेक करें, और बिंगो, सभी pngs / jpegs को आपके घर निर्देशिका में उगल दिया जाएगा।

गन्दा, लेकिन डेटा के बारे में नासमझ से तेज: URL।


आपने कहाँ पाया कि "इमेजेज एम्बेड करें" विकल्प?
mik01aj

1
जब आप पीडीएफ दस्तावेज़ को इंकस्केप में खोलते हैं, तो यह अगले संवाद पर होता है।
निकोलस विल्सन

मेरे पास एक पीडीएफ था जिसमें से मैंने एक छवि को इंकस्केप में आयात करके निकालने की कोशिश की। उस मामले में, यह करने के लिए सक्षम किया जा रहा पर आयात के बजाय के बाद आयात और भी काम में आता।
user149408

मुझे यकीन नहीं है, लेकिन इस तरह से कोई भी एम्बेडेड ICC प्रोफाइल प्रक्रिया में खो जाती है। उस अजगर स्क्रिप्ट के माध्यम से मैंने SVG से सीधे निकाले गए चित्रों में ICC प्रोफाइल सन्निहित है।
डैनमैन

1

मैं @Johnny_Bit की php-script सुधारता हूं । स्क्रिप्ट का नया रिलीज़ नई लाइनों के साथ 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) पर क्लिक करें और इसे केवल चयनित बिटमैप निर्यात करना चाहिए।


मुझे यह समाधान पसंद नहीं है क्योंकि यह छवि को फिर से एनकोड करेगा। मैं एक ऐसे समाधान को प्राथमिकता दूंगा जो छवि को उसके मूल प्रारूप में निकाले।
डेनिल्सन सा मैया

1
हां, ऐसा लगता है कि इंकस्केप ने छवि को फिर से एनकोड किया है लेकिन यह पीएनजी छवियों को डिफ़ॉल्ट रूप से बचाता है। इसलिए मैं मान रहा हूं कि री-एन्कोडिंग कम से कम दोषरहित है।
क्रिस 10

1
असल में ऐसा नहीं है। एम्बेडेड छवि में परिवर्तन (स्केलिंग, रोटेशन…) हो सकता है, क्लिप किया गया हो सकता है, या कुछ और भी जो मुझे पता नहीं है। इनस्केप इन सभी परिवर्तनों को लागू करने के बाद निश्चित रूप से चयनित वस्तु को निर्यात करेगा, जिसका अर्थ है कि यह समाधान बिल्कुल दोषरहित नहीं है।
डेनिल्सन सा मैया
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.