SVGcode: یک PWA برای تبدیل تصاویر شطرنجی به گرافیک برداری SVG

SVGcode یک برنامه وب پیشرفته است که به شما امکان می دهد تصاویر شطرنجی مانند JPG، PNG، GIF، WebP، AVIF و غیره را به گرافیک های برداری با فرمت SVG تبدیل کنید. از File System Access API، Async Clipboard API، File Handling API و Window Controls Overlay استفاده می کند.

(اگر تماشا کردن را به خواندن ترجیح می دهید، این مقاله به صورت ویدیویی نیز موجود است.)

از شطرنجی تا وکتور

آیا تا به حال یک تصویر را مقیاس بندی کرده اید و نتیجه پیکسلی و رضایت بخش نیست؟ اگر چنین است، احتمالاً با فرمت تصویر شطرنجی مانند WebP، PNG یا JPG سروکار داشته اید.

بزرگ کردن یک تصویر شطرنجی باعث می شود که پیکسلی به نظر برسد.

در مقابل، گرافیک برداری تصاویری هستند که با نقاط یک سیستم مختصات تعریف می شوند. این نقاط با خطوط و منحنی ها به هم متصل می شوند تا چند ضلعی ها و اشکال دیگر را تشکیل دهند. گرافیک های برداری مزیتی نسبت به گرافیک های شطرنجی دارند، زیرا ممکن است به هر رزولوشنی بدون پیکسل بندی کوچک شوند.

بزرگ کردن یک تصویر برداری بدون افت کیفیت.

معرفی SVGcode

من یک PWA به نام SVGcode ساخته ام که می تواند به شما در تبدیل تصاویر شطرنجی به وکتور کمک کند. اعتبار در جایی که اعتبار است: من این را اختراع نکردم. با SVGcode، من فقط روی یک ابزار خط فرمان به نام Potrace توسط Peter Selinger که به Web Assembly تبدیل کرده ام، می ایستم، بنابراین می توان از آن در یک برنامه وب استفاده کرد.

اسکرین شات برنامه SVGcode.
برنامه SVGcode .

با استفاده از SVGcode

ابتدا می خواهم نحوه استفاده از برنامه را به شما نشان دهم. من با تصویر تیزر برای Chrome Dev Summit که از کانال توییتر ChromiumDev دانلود کردم شروع می کنم. این یک تصویر شطرنجی PNG است که سپس آن را روی برنامه SVGcode می کشم. وقتی فایل را رها می‌کنم، برنامه تصویر را رنگ به رنگ دنبال می‌کند تا زمانی که یک نسخه برداری از ورودی ظاهر شود. اکنون می توانم روی تصویر زوم کنم و همانطور که می بینید، لبه ها واضح می مانند. اما با زوم کردن روی لوگوی کروم، می‌بینید که ردیابی کامل نبوده و به خصوص خطوط اصلی لوگو کمی خالدار به نظر می‌رسند. من می‌توانم نتیجه را با لکه‌زدایی از ردیابی با حذف لکه‌های تا مثلاً پنج پیکسل، بهبود بخشم.

تبدیل تصویر رها شده به SVG.

پوسترسازی در SVGcode

یک مرحله مهم برای برداری، به ویژه برای تصاویر عکاسی، پوستر کردن تصویر ورودی برای کاهش تعداد رنگ ها است. SVGcode به من این امکان را می دهد که این کار را در هر کانال رنگی انجام دهم و در حین ایجاد تغییرات، SVG حاصل را ببینم. وقتی از نتیجه راضی باشم، می‌توانم SVG را روی هارد دیسکم ذخیره کنم و از آن در هر کجا که دوست دارم استفاده کنم.

پوستر کردن یک تصویر برای کاهش تعداد رنگ ها.

API های مورد استفاده در SVGcode

اکنون که دیدید برنامه چه توانایی هایی دارد، اجازه دهید برخی از API هایی را به شما نشان دهم که به انجام جادو کمک می کنند.

برنامه وب پیشرو

SVGcode یک برنامه وب پیشرفته قابل نصب است و بنابراین کاملاً آفلاین فعال است. این برنامه بر اساس الگوی Vanilla JS برای Vite.js است و از افزونه محبوب Vite PWA استفاده می کند که یک سرویس دهنده ایجاد می کند که از Workbox.js در زیر هود استفاده می کند. Workbox مجموعه‌ای از کتابخانه‌ها است که می‌تواند یک سرویس‌دهنده آماده تولید برای برنامه‌های وب پیشرفته را تامین کند، این الگو ممکن است لزوما برای همه برنامه‌ها کار نکند، اما برای موارد استفاده SVGcode عالی است.

پوشش کنترل های پنجره

برای به حداکثر رساندن املاک موجود روی صفحه، SVGcode از سفارشی سازی Window Controls Overlay با انتقال منوی اصلی خود به سمت بالا در ناحیه نوار عنوان استفاده می کند. می توانید مشاهده کنید که در پایان جریان نصب فعال می شود.

نصب SVGcode و فعال سازی سفارشی سازی Overlay Controls Window.

API دسترسی به فایل سیستم

برای باز کردن فایل های تصویری ورودی و ذخیره 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);
  }
});

برای جزئیات بیشتر، مقاله مربوط به File System Access API را بررسی کنید و اگر علاقه دارید، کد منبع SVGcode را در src/js/filesystem.js مطالعه کنید.

Async Clipboard API

SVGcode همچنین به طور کامل با کلیپ بورد سیستم عامل از طریق Async Clipboard API یکپارچه شده است. می‌توانید با کلیک کردن روی دکمه چسباندن تصویر یا با فشار دادن فرمان یا کنترل به‌علاوه v روی صفحه‌کلید، تصاویر را از کاوشگر فایل سیستم عامل در برنامه جای‌گذاری کنید.

چسباندن یک تصویر از کاوشگر فایل در SVGcode.

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

برای کسب اطلاعات بیشتر، مقاله Async Clipboard را بخوانید یا فایل src/js/clipboard.js را ببینید.

مدیریت فایل

یکی از ویژگی های مورد علاقه من SVGcode این است که چگونه با سیستم عامل ترکیب می شود. به عنوان یک PWA نصب شده، می تواند به یک کنترل کننده فایل یا حتی کنترل کننده فایل پیش فرض برای فایل های تصویری تبدیل شود. این بدان معناست که وقتی در Finder در دستگاه macOS خود هستم، می‌توانم روی یک تصویر کلیک راست کرده و آن را با SVGcode باز کنم. این ویژگی File Handling نام دارد و بر اساس ویژگی file_handlers در Web App Manifest و صف راه‌اندازی کار می‌کند که به برنامه اجازه می‌دهد فایل ارسال شده را مصرف کند.

باز کردن یک فایل از دسکتاپ با برنامه 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 مشاهده کنید.

اشتراک گذاری وب (فایل ها)

نمونه دیگری از ترکیب با سیستم عامل، ویژگی اشتراک گذاری برنامه است. با فرض اینکه می‌خواهم یک SVG ایجاد شده با SVGcode را ویرایش کنم، یکی از راه‌های مقابله با این موضوع ذخیره فایل، راه‌اندازی برنامه ویرایش 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);
      }
    }
  }
});
به اشتراک گذاری یک تصویر SVG در Gmail.

هدف اشتراک گذاری وب (فایل ها)

برعکس، 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 نیز چنین است. و با آن، بردار سازی مبارک! امیدوارم SVGcode مفید واقع شود و برخی از ویژگی های آن بتواند الهام بخش برنامه بعدی شما باشد.

قدردانی ها

این مقاله توسط جو مدلی بررسی شده است.