SVGcode: PWA เพื่อแปลงรูปภาพแรสเตอร์เป็นกราฟิกเวกเตอร์ SVG

SVGcode คือ Progressive Web App ที่ให้คุณแปลงรูปภาพแรสเตอร์ เช่น 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 ที่ฉันดาวน์โหลดมาจากช่องทาง Twitter ของ ChromiumDev นี่คือรูปภาพแรสเตอร์ PNG ลากไปยังแอป SVGcode พอวางไฟล์ลงไป แอปจะติดตามสีรูปภาพตามสี จนกว่าอินพุตในรูปแบบเวกเตอร์จะปรากฏขึ้น ตอนนี้ผมสามารถซูมเข้าไปในรูปภาพ และอย่างที่คุณเห็น ขอบจะคมชัดเสมอ แต่เมื่อซูมเข้าไปที่โลโก้ Chrome คุณจะเห็นได้ว่าการติดตาม สมบูรณ์แบบ และโดยเฉพาะอย่างยิ่งขอบของโลโก้ดูด่างดำ ฉันสามารถปรับปรุงผลลัพธ์ได้โดย การลดจุดด่างดำโดยระงับจุดไม่เกิน 5 พิกเซล

กำลังแปลงรูปภาพที่วางลงเป็น SVG

การโปสเตอร์ใน SVGcode

ขั้นตอนที่สำคัญสำหรับการทำเวกเตอร์ โดยเฉพาะสำหรับภาพถ่ายภาพ คือการทำอินพุตตามโปสเตอร์ เพื่อลดจำนวนสี SVGcode ทำให้คุณสามารถดำเนินการนี้ ตามช่องสีและดู SVG ทันทีที่มีการทำการเปลี่ยนแปลง เมื่อพอใจกับผลลัพธ์แล้ว ก็สามารถบันทึก SVG ลงในฮาร์ดดิสก์ได้ และใช้ได้ทุกที่ที่ผมชอบ

การทำโปสเตอร์เพื่อลดจำนวนสี

API ที่ใช้ใน SVGcode

ตอนนี้คุณก็ได้รู้แล้วว่าแอปนี้มีความสามารถอย่างไร ต่อไปฉันจะแสดง API บางอย่างที่จะช่วยให้ สิ่งมหัศจรรย์นี้ก็เกิดขึ้นได้

Progressive Web App

SVGcode เป็น Progressive Web App ที่ติดตั้งได้จึงพร้อมใช้งานแบบออฟไลน์โดยสมบูรณ์ แอปอิงตาม ใน เทมเพลต Vala JS สำหรับ Vite.js และใช้ลิงก์ Vite ปลั๊กอิน PWA ซึ่งจะสร้าง Service Worker ที่ ใช้ Workbox.js ขั้นสูง กล่องงานเป็นชุด ของไลบรารีที่สามารถขับเคลื่อน Service Worker ที่พร้อมสำหรับการใช้งานจริงสำหรับ Progressive Web App รูปแบบนี้ อาจใช้ไม่ได้กับบางแอป แต่สำหรับกรณีการใช้งานของ SVGcode ก็ถือว่าดีแล้ว

การวางซ้อนการควบคุมหน้าต่าง

SVGcode จะใช้พื้นที่หน้าจอที่มีอยู่ให้ได้มากที่สุด การปรับแต่งการวางซ้อนการควบคุมหน้าต่างโดยย้ายเมนูหลักขึ้นไปยัง บริเวณแถบชื่อ คุณจะเห็นการเปิดใช้งานนี้เมื่อสิ้นสุดขั้นตอนการติดตั้ง

การติดตั้ง SVGcode และเปิดใช้งานการปรับแต่งการวางซ้อนการควบคุมหน้าต่าง

File System Access 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 และ หากคุณสนใจ คุณสามารถศึกษาซอร์สโค้ด SVG src/js/filesystem.js

Async Clipboard API

SVGcode ยังทำงานร่วมกับคลิปบอร์ดของระบบปฏิบัติการได้อย่างสมบูรณ์ผ่าน Async Clipboard API คุณสามารถวางรูปภาพจากโปรแกรมสำรวจไฟล์ของระบบปฏิบัติการลงในแอปโดยคลิก วางปุ่มรูปภาพ หรือกดปุ่ม Command หรือ Control + v บนแป้นพิมพ์

การวางรูปภาพจากโปรแกรมสำรวจไฟล์ลงใน 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'));
});

หากต้องการดูข้อมูลเพิ่มเติม โปรดอ่านบทความ Async Clipboard หรือดูไฟล์ src/js/clipboard.js

การจัดการไฟล์

ฟีเจอร์หนึ่งที่ฉันชอบมากของ SVGcode ก็คือความกลมกลืนกับระบบปฏิบัติการ ในฐานะ ติดตั้ง PWA แล้ว จึงกลายเป็นตัวแฮนเดิลไฟล์หรือแม้กระทั่งตัวแฮนเดิลไฟล์เริ่มต้นสำหรับไฟล์ภาพได้ ช่วงเวลานี้ หมายความว่าเมื่อฉันอยู่ใน Finder บนเครื่อง macOS ฉันจะสามารถคลิกขวาที่รูปภาพแล้วเปิดด้วย SVGcode ฟีเจอร์นี้เรียกว่าการจัดการไฟล์และทำงานโดยอิงตามพร็อพเพอร์ตี้ file_handlers ใน ไฟล์ 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 เกี่ยวกับประเภทข้อมูลที่รับได้ ซึ่งจะเกิดขึ้นผ่าน ช่องในไฟล์ Manifest ของเว็บแอปโดยเฉพาะ

{
  "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 ของ Service Worker เท่านั้น ซึ่งจะส่งต่อไฟล์ที่ได้รับเพื่อประมวลผลจริงในแอป

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 จะเป็นประโยชน์และ ฟีเจอร์บางส่วนของโมเดล อาจสร้างแรงบันดาลใจในการสร้างแอปต่อไปของคุณ

กิตติกรรมประกาศ

บทความนี้ได้รับการตรวจสอบโดย Joe Medley