SVGcode: रास्टर इमेज को SVG वेक्टर ग्राफ़िक में बदलने के लिए एक PWA

SVGcode एक प्रोग्रेसिव वेब ऐप्लिकेशन है. इसकी मदद से, JPG, PNG, GIF, WebP, AVIF वगैरह जैसी रेस्टर इमेज को SVG फ़ॉर्मैट में वेक्टर ग्राफ़िक में बदला जा सकता है. यह File System Access API, Async Clipboard API, File Handling API, और Window Controls Overlay के कस्टमाइज़ेशन का इस्तेमाल करता है.

(अगर आपको पढ़ने के बजाय वीडियो देखना पसंद है, तो यह लेख वीडियो के तौर पर भी उपलब्ध है.)

रेस्टर से वेक्टर में बदलना

क्या आपने कभी किसी इमेज को स्केल किया है और नतीजा पिक्सल वाला और खराब रहा है? अगर ऐसा है, तो हो सकता है कि आपने WebP, PNG या JPG जैसे रास्टर इमेज फ़ॉर्मैट का इस्तेमाल किया हो.

रेस्टर इमेज को बड़ा करने पर, वह पिक्सल वाली दिखती है.

इसके उलट, वेक्टर ग्राफ़िक ऐसी इमेज होती हैं जिन्हें निर्देशांक सिस्टम में पॉइंट के हिसाब से तय किया जाता है. इन बिंदुओं को लाइनों और कर्व से जोड़कर पॉलीगॉन और अन्य आकार बनाए जाते हैं. वेक्टर ग्राफ़िक का फ़ायदा, रेस्टर ग्राफ़िक की तुलना में यह है कि इन्हें पिक्सल किए बिना, किसी भी रिज़ॉल्यूशन में स्केल किया जा सकता है.

क्वालिटी में कोई बदलाव किए बिना वेक्टर इमेज को बड़ा करना.

पेश है SVGcode

मैंने SVGcode नाम का एक PWA बनाया है. इसकी मदद से, रेस्टर इमेज को वैक्टर में बदला जा सकता है. क्रेडिट का अधिकार: मैंने यह तरीका नहीं बनाया है. SVGcode में, मैंने पीटर सेलिंगर के बनाए Potrace नाम के कमांड लाइन टूल का इस्तेमाल किया है. मैंने इस टूल को वेब असेंबली में बदला है, ताकि इसका इस्तेमाल वेब ऐप्लिकेशन में किया जा सके.

SVGcode ऐप्लिकेशन का स्क्रीनशॉट.
SVGcode ऐप्लिकेशन.

SVG कोड का इस्तेमाल करना

सबसे पहले, मैं आपको ऐप्लिकेशन इस्तेमाल करने का तरीका बताना चाहती हूं. इसके लिए, मैं Chrome Dev Summit के टीज़र इमेज से शुरुआत करूंगी. इसे मैंने ChromiumDev के ट्विटर चैनल से डाउनलोड किया है. यह एक PNG रेस्टर इमेज है, जिसे मैंने SVGcode ऐप्लिकेशन पर खींचकर छोड़ा है. फ़ाइल को छोड़ने के बाद, ऐप्लिकेशन इमेज के रंग को एक-एक करके ट्रैक करता है. ऐसा तब तक होता है, जब तक इनपुट का वेक्टर वर्शन नहीं दिख जाता. अब मैं इमेज में ज़ूम इन कर सकती हूं. जैसा कि आप देख सकते हैं, इसके किनारे शार्प बने रहते हैं. हालांकि, Chrome के लोगो पर ज़ूम इन करके देखा जा सकता है कि ट्रैसिंग पूरी तरह से सही नहीं है. खास तौर पर, लोगो की आउटलाइन थोड़ी धुंधली दिख रही हैं. मैं नतीजे को बेहतर बना सकता हूं. इसके लिए, ट्रैसिंग में मौजूद स्पिकल को हटाकर, पांच पिक्सल तक के स्पिकल को दबाया जा सकता है.

ड्रॉप की गई इमेज को SVG में बदलना.

SVGcode में पोस्टराइज़ेशन

वेक्टराइज़ेशन के लिए, खास तौर पर फ़ोटोग्राफ़िक इमेज के लिए, इनपुट इमेज को पोस्टराइज़ करना एक अहम चरण है. इससे रंगों की संख्या कम हो जाती है. SVGcode की मदद से, हर कलर चैनल के लिए ऐसा किया जा सकता है. साथ ही, बदलाव करते समय नतीजा के तौर पर मिलने वाला SVG देखा जा सकता है. जब मुझे नतीजा पसंद आता है, तो मैं एसवीजी फ़ाइल को अपनी हार्ड डिस्क पर सेव कर सकता/सकती हूं और उसे कहीं भी इस्तेमाल कर सकता/सकती हूं.

इमेज में मौजूद रंगों की संख्या कम करने के लिए, उसे पोस्टर में बदलना.

SVGcode में इस्तेमाल किए जाने वाले एपीआई

अब आपको पता चल गया है कि यह ऐप्लिकेशन क्या-क्या कर सकता है. अब हम आपको कुछ ऐसे एपीआई के बारे में बताएंगे जिनकी मदद से यह ऐप्लिकेशन ऐसा कर पाता है.

प्रोग्रेसिव वेब ऐप्लिकेशन

SVGcode एक इंस्टॉल किया जा सकने वाला प्रोग्रेसिव वेब ऐप्लिकेशन है. इसलिए, यह पूरी तरह से ऑफ़लाइन काम करता है. यह ऐप्लिकेशन, Vite.js के लिए Vanilla JS टेंप्लेट पर आधारित है. साथ ही, यह लोकप्रिय Vite प्लग इन PWA का इस्तेमाल करता है. यह एक ऐसा सेवा वर्कर बनाता है जो Workbox.js का इस्तेमाल करता है. Workbox, लाइब्रेरी का एक सेट है. इससे प्रगतिशील वेब ऐप्लिकेशन के लिए, प्रोडक्शन के लिए तैयार सर्विस वर्कर को बेहतर बनाया जा सकता है. ऐसा ज़रूरी नहीं है कि यह पैटर्न सभी ऐप्लिकेशन के लिए काम करे, लेकिन SVGcode के इस्तेमाल के उदाहरण के लिए यह बेहतरीन है.

विंडो कंट्रोल ओवरले

SVGcode, स्क्रीन पर ज़्यादा से ज़्यादा जगह पाने के लिए, Window Controls Overlay की सुविधा का इस्तेमाल करता है. इसके लिए, यह अपने मुख्य मेन्यू को टाइटल बार के ऊपर ले जाता है. इंस्टॉल फ़्लो के आखिर में, यह सुविधा चालू हो जाती है.

SVG कोड इंस्टॉल करना और विंडो कंट्रोल ओवरले को पसंद के मुताबिक बनाना.

फ़ाइल सिस्टम को ऐक्सेस करने का एपीआई

इनपुट इमेज फ़ाइलों को खोलने और उनसे जनरेट हुए SVG को सेव करने के लिए, File System Access API का इस्तेमाल किया जाता है. इससे, मैंने पहले जो फ़ाइलें खोली थीं उनका रेफ़रंस सेव रहता है. साथ ही, ऐप्लिकेशन को फिर से लोड करने के बाद भी, जहां से मैंने पढ़ना छोड़ा था वहीं से पढ़ना जारी रखा जा सकता है. जब भी कोई इमेज सेव की जाती है, तो उसे svgo लाइब्रेरी की मदद से ऑप्टिमाइज़ किया जाता है. इसमें SVG की जटिलता के हिसाब से, कुछ समय लग सकता है. फ़ाइल सेव करने का डायलॉग दिखाने के लिए, उपयोगकर्ता के जेस्चर की ज़रूरत होती है. इसलिए, SVG को ऑप्टिमाइज़ करने से पहले फ़ाइल हैंडल पाना ज़रूरी है, ताकि ऑप्टिमाइज़ किया गया SVG तैयार होने तक, उपयोगकर्ता के जेस्चर को अमान्य न किया जाए.

try {
  let svg = svgOutput.innerHTML;
  let handle = null;
  // To not consume the user gesture obtain the handle before preparing the
  // blob, which may take longer.
  if (supported) {
    handle = await showSaveFilePicker({
      types: [{description: 'SVG file', accept: {'image/svg+xml': ['.svg']}}],
    });
  }
  showToast(i18n.t('optimizingSVG'), Infinity);
  svg = await optimizeSVG(svg);
  showToast(i18n.t('savedSVG'));
  const blob = new Blob([svg], {type: 'image/svg+xml'});
  await fileSave(blob, {description: 'SVG file'}, handle);
} catch (err) {
  console.error(err.name, err.message);
  showToast(err.message);
}

खींचें और छोड़ें

इनपुट इमेज खोलने के लिए, फ़ाइल खोलने की सुविधा का इस्तेमाल किया जा सकता है. इसके अलावा, जैसा कि आपने ऊपर देखा है, इमेज फ़ाइल को ऐप्लिकेशन पर खींचकर छोड़ा जा सकता है. फ़ाइल खोलने की सुविधा का इस्तेमाल करना बहुत आसान है. हालांकि, खींचकर छोड़ने की सुविधा ज़्यादा दिलचस्प है. इस बारे में खास बात यह है कि getAsFileSystemHandle() के ज़रिए, डेटा ट्रांसफ़र आइटम से फ़ाइल सिस्टम हैंडल पाया जा सकता है. जैसा कि पहले बताया गया है, मैं इस हैंडल को सेव कर सकता/सकती हूं, ताकि ऐप्लिकेशन फिर से लोड होने पर यह हैंडल तैयार हो.

document.addEventListener('drop', async (event) => {
  event.preventDefault();
  dropContainer.classList.remove('dropenter');
  const item = event.dataTransfer.items[0];
  if (item.kind === 'file') {
    inputImage.addEventListener(
      'load',
      () => {
        URL.revokeObjectURL(blobURL);
      },
      {once: true},
    );
    const handle = await item.getAsFileSystemHandle();
    if (handle.kind !== 'file') {
      return;
    }
    const file = await handle.getFile();
    const blobURL = URL.createObjectURL(file);
    inputImage.src = blobURL;
    await set(FILE_HANDLE, handle);
  }
});

ज़्यादा जानकारी के लिए, फ़ाइल सिस्टम ऐक्सेस एपीआई के बारे में लेख पढ़ें. अगर आप चाहें, तो src/js/filesystem.js में SVGcode का सोर्स कोड देखें.

Async Clipboard API

SVGcode, Async Clipboard API के ज़रिए ऑपरेटिंग सिस्टम के क्लिपबोर्ड के साथ भी पूरी तरह से इंटिग्रेट है. ऑपरेटिंग सिस्टम के फ़ाइल एक्सप्लोरर से इमेज को ऐप्लिकेशन में चिपकाया जा सकता है. इसके लिए, इमेज चिपकाएं बटन पर क्लिक करें या अपने कीबोर्ड पर कमांड या कंट्रोल के साथ v दबाएं.

File Explorer से SVG कोड में इमेज चिपकाना.

Async Clipboard API में हाल ही में, SVG इमेज को भी शामिल किया गया है. इसलिए, अब आपके पास किसी SVG इमेज को कॉपी करने और उसे किसी दूसरे ऐप्लिकेशन में चिपकाने का विकल्प भी है, ताकि उसे आगे प्रोसेस किया जा सके.

SVGcode से SVGOMG में इमेज कॉपी करना.
copyButton.addEventListener('click', async () => {
  let svg = svgOutput.innerHTML;
  showToast(i18n.t('optimizingSVG'), Infinity);
  svg = await optimizeSVG(svg);
  const textBlob = new Blob([svg], {type: 'text/plain'});
  const svgBlob = new Blob([svg], {type: 'image/svg+xml'});
  navigator.clipboard.write([
    new ClipboardItem({
      [svgBlob.type]: svgBlob,
      [textBlob.type]: textBlob,
    }),
  ]);
  showToast(i18n.t('copiedSVG'));
});

ज़्यादा जानने के लिए, असाइन किए गए क्लिपबोर्ड लेख पढ़ें या फ़ाइल देखेंsrc/js/clipboard.js.

फ़ाइल मैनेज करना

SVGcode की मेरी पसंदीदा सुविधाओं में से एक यह है कि यह ऑपरेटिंग सिस्टम के साथ कितनी अच्छी तरह से ब्लेंड होती है. इंस्टॉल किए गए PWA के तौर पर, यह इमेज फ़ाइलों के लिए फ़ाइल हैंडलर या डिफ़ॉल्ट फ़ाइल हैंडलर बन सकता है. इसका मतलब है कि macOS मशीन पर Finder में मौजूद किसी इमेज पर दायां क्लिक करके, उसे SVGcode में खोला जा सकता है. इस सुविधा को फ़ाइल मैनेजमेंट कहा जाता है. यह वेब ऐप्लिकेशन मेनिफ़ेस्ट और लॉन्च सूची में मौजूद file_handlers प्रॉपर्टी के आधार पर काम करती है. इससे ऐप्लिकेशन को पास की गई फ़ाइल का इस्तेमाल करने में मदद मिलती है.

इंस्टॉल किए गए SVGcode ऐप्लिकेशन की मदद से, डेस्कटॉप से फ़ाइल खोलना.
window.launchQueue.setConsumer(async (launchParams) => {
  if (!launchParams.files.length) {
    return;
  }
  for (const handle of launchParams.files) {
    const file = await handle.getFile();
    if (file.type.startsWith('image/')) {
      const blobURL = URL.createObjectURL(file);
      inputImage.addEventListener(
        'load',
        () => {
          URL.revokeObjectURL(blobURL);
        },
        {once: true},
      );
      inputImage.src = blobURL;
      await set(FILE_HANDLE, handle);
      return;
    }
  }
});

ज़्यादा जानकारी के लिए, इंस्टॉल किए गए वेब ऐप्लिकेशन को फ़ाइल हैंडलर बनाने दें लेख पढ़ें. साथ ही, src/js/filehandling.js में सोर्स कोड देखें.

वेब शेयर (फ़ाइलें)

ऑपरेटिंग सिस्टम के साथ मिलते-जुलते होने का एक और उदाहरण, ऐप्लिकेशन की शेयर करने की सुविधा है. मान लें कि मुझे SVGcode की मदद से बनाई गई किसी SVG फ़ाइल में बदलाव करना है, तो इसके लिए एक तरीका यह है कि फ़ाइल को सेव करें, SVG फ़ाइल में बदलाव करने वाला ऐप्लिकेशन लॉन्च करें, और फिर उसमें SVG फ़ाइल खोलें. हालांकि, Web Share API का इस्तेमाल करने पर, फ़ाइलें आसानी से शेयर की जा सकती हैं. इसलिए, अगर SVG फ़ाइल में बदलाव करने वाला ऐप्लिकेशन शेयर करने का टारगेट है, तो वह सीधे तौर पर फ़ाइल को बिना किसी रुकावट के पा सकता है.

shareSVGButton.addEventListener('click', async () => {
  let svg = svgOutput.innerHTML;
  svg = await optimizeSVG(svg);
  const suggestedFileName =
    getSuggestedFileName(await get(FILE_HANDLE)) || 'Untitled.svg';
  const file = new File([svg], suggestedFileName, { type: 'image/svg+xml' });
  const data = {
    files: [file],
  };
  if (navigator.canShare(data)) {
    try {
      await navigator.share(data);
    } catch (err) {
      if (err.name !== 'AbortError') {
        console.error(err.name, err.message);
      }
    }
  }
});
Gmail में SVG इमेज शेयर करना.

वेब शेयर टारगेट (फ़ाइलें)

इसके अलावा, SVGcode को शेयर करने के टारगेट के तौर पर भी इस्तेमाल किया जा सकता है. साथ ही, इसमें अन्य ऐप्लिकेशन से फ़ाइलें भी ली जा सकती हैं. इस सुविधा को काम करने के लिए, ऐप्लिकेशन को Web Share Target API के ज़रिए ऑपरेटिंग सिस्टम को यह बताना होगा कि वह किस तरह का डेटा स्वीकार कर सकता है. यह वेब ऐप्लिकेशन मेनिफ़ेस्ट में मौजूद एक खास फ़ील्ड की मदद से होता है.

{
  "share_target": {
    "action": "https://svgco.de/share-target/",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "files": [
        {
          "name": "image",
          "accept": ["image/jpeg", "image/png", "image/webp", "image/gif"]
        }
      ]
    }
  }
}

action रूट असल में मौजूद नहीं है. इसे पूरी तरह से सेवा वर्कर के fetch हैंडलर में मैनेज किया जाता है. इसके बाद, ऐप्लिकेशन में असल प्रोसेसिंग के लिए, मिली फ़ाइलों को पास किया जाता है.

self.addEventListener('fetch', (fetchEvent) => {
  if (
    fetchEvent.request.url.endsWith('/share-target/') &&
    fetchEvent.request.method === 'POST'
  ) {
    return fetchEvent.respondWith(
      (async () => {
        const formData = await fetchEvent.request.formData();
        const image = formData.get('image');
        const keys = await caches.keys();
        const mediaCache = await caches.open(
          keys.filter((key) => key.startsWith('media'))[0],
        );
        await mediaCache.put('shared-image', new Response(image));
        return Response.redirect('./?share-target', 303);
      })(),
    );
  }
});
SVG कोड में स्क्रीनशॉट शेयर करना.

नतीजा

ठीक है, हमने SVGcode ऐप्लिकेशन की कुछ बेहतर सुविधाओं के बारे में आपको बताया. हमें उम्मीद है कि यह ऐप्लिकेशन, Squoosh या SVGOMG जैसे अन्य शानदार ऐप्लिकेशन के साथ-साथ, इमेज प्रोसेस करने की आपकी ज़रूरतों के लिए एक ज़रूरी टूल बन सकता है.

SVGcode, svgco.de पर उपलब्ध है. देखें कि मैंने वहां क्या किया? GitHub पर इसके सोर्स कोड की समीक्षा की जा सकती है. ध्यान दें कि Potrace के पास GPL लाइसेंस है और SVGcode के पास भी GPL लाइसेंस है. इसके बाद, वेक्टर में बदलने का आनंद लें! हमें उम्मीद है कि SVGcode आपके लिए मददगार साबित होगा. साथ ही, इसकी कुछ सुविधाओं से आपको अपने अगले ऐप्लिकेशन के लिए प्रेरणा मिलेगी.

आभार

इस लेख की समीक्षा जो मेडली ने की है.