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 के ज़रिए ऑपरेटिंग सिस्टम के क्लिपबोर्ड के साथ भी पूरी तरह से इंटिग्रेट है. ऑपरेटिंग सिस्टम के फ़ाइल एक्सप्लोरर से इमेज को ऐप्लिकेशन में चिपकाया जा सकता है. इसके लिए, 'इमेज चिपकाएं' बटन पर क्लिक करें या अपने कीबोर्ड पर Command या Control + 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);
      })(),
    );
  }
});
SVGcode का स्क्रीनशॉट शेयर किया जा रहा है.

नतीजा

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

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

धन्यवाद

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