SVGcode: 래스터 이미지를 SVG 벡터 그래픽으로 변환하는 PWA

SVGcode는 JPG, PNG, GIF, WebP, AVIF 등의 래스터 이미지를 SVG 형식의 벡터 그래픽으로 변환할 수 있는 프로그레시브 웹 앱입니다. File System Access API, Async Clipboard API, File Handling API, 창 컨트롤 오버레이 맞춤설정을 사용합니다.

를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder"></ph> <ph type="x-smartling-placeholder">
</ph> (읽는 것보다 시청하려는 경우 이 도움말을 동영상으로도 볼 수 있습니다.)

래스터에서 벡터로

이미지 크기를 조정했는데 결과가 모자이크 처리되어 마음에 들지 않으셨나요? 만약 WebP, PNG 또는 JPG와 같은 래스터 이미지 형식을 다루었을 것입니다.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 래스터 이미지를 확대하면 모자이크처럼 보입니다.

반면에 벡터 그래픽은 좌표계에서 점으로 정의되는 이미지입니다. 이러한 점은 선과 곡선으로 연결되어 다각형 및 기타 도형을 형성합니다. 벡터 그래픽에는 래스터 그래픽에 비해 어떤 해상도로도 확대 또는 축소할 수 있다는 장점이 있습니다. 얻을 수 있습니다.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 품질 손실 없이 벡터 이미지 확장

SVGcode 소개

래스터 이미지를SVGcode 벡터로 변환합니다. 크레딧이 필요한 크레딧: 내가 만든 적이 없음 SVGcode를 사용하면 Potrace라는 명령줄 도구의 어깨 부분과 피터 셀링거Web Assembly로 변환하므로 웹 앱

<ph type="x-smartling-placeholder">
</ph> SVGcode 애플리케이션 스크린샷 <ph type="x-smartling-placeholder">
</ph> SVGcode

SVGcode 사용

먼저 앱 사용 방법을 보여드리겠습니다. 먼저 Chrome Dev Summit의 티저 이미지로 시작합니다. ChromiumDev Twitter 채널에서 다운로드했습니다 이것은 PNG 래스터 이미지로, SVGcode 앱으로 드래그합니다. 파일을 드롭하면 앱이 이미지 색상을 색상으로 추적하여 입력의 벡터화된 버전이 나타날 때까지입니다. 이제 이미지를 확대할 수 있습니다. 보시다시피 가장자리가 선명하게 유지됩니다. 하지만 Chrome 로고를 확대하면 추적이 제대로 되지 않았음을 알 수 있습니다. 특히 로고의 윤곽선이 약간 얼룩덜룩합니다. 결과를 개선하려면 최대 5픽셀의 스펙클을 억제하여 트레이싱의 스펙클링을 해제합니다.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 드롭된 이미지를 SVG로 변환

SVGcode의 포스터

벡터화, 특히 사진 이미지의 경우 중요한 단계는 입력을 포스터화하는 것입니다. 이미지를 줄여야 색상 수를 줄일 수 있습니다. SVGcode를 사용하면 색상 채널별로 이를 수행할 수 있고 SVG가 생성된 것을 볼 수 있습니다. 결과가 만족스러우면 SVG를 하드 디스크에 저장할 수 있고, 내가 원하는 곳 어디서나 사용할 수 있습니다.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 색상 수를 줄이기 위한 이미지 포스터

SVGcode에 사용되는 API

이제 앱이 할 수 있는 기능을 살펴봤으므로 이제 앱을 만드는 데 도움이 되는 몇 가지 API를 보여드리겠습니다. 마법이 일어납니다.

프로그레시브 웹 앱

SVGcode는 설치 가능한 프로그레시브 웹 앱이므로 완전히 오프라인으로 사용할 수 있습니다. 이 앱은 에 Vanilla JS 템플릿 Vite.js용이며 널리 사용되는 Vite 플러그인 PWA는 내부적으로 Workbox.js를 사용합니다. Workbox는 설정됨 프로그레시브 웹 앱에서 프로덕션에 즉시 사용 가능한 서비스 워커를 구동할 수 있는 여러 라이브러리를 제공합니다. 이 패턴은 모든 앱에서 반드시 작동하는 것은 아니지만 SVGcode의 사용 사례에서는 매우 좋습니다.

창 컨트롤 오버레이

사용 가능한 화면 공간을 극대화하기 위해 SVGcode는 기본 메뉴를 위로 이동하여 창 컨트롤 오버레이 맞춤설정 있습니다. 설치 과정이 끝날 때 활성화되는 것을 확인할 수 있습니다.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 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에 관한 도움말을 참고하세요. 관심이 있다면 src/js/filesystem.js

Async Clipboard API

또한 SVGcode는 Async Clipboard API를 통해 운영체제의 클립보드와 완전히 통합됩니다. 운영체제의 파일 탐색기에 있는 이미지를 앱에 붙여넣을 수도 있습니다. 이미지 붙여넣기 버튼을 누르거나 키보드에서 Command 또는 Ctrl + V를 누르세요.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 파일 탐색기에서 SVGcode에 이미지 붙여넣기

Async Clipboard API는 최근에 SVG 이미지도 처리할 수 있는 기능을 얻었습니다. 따라서 추가 처리를 위해 SVG 이미지를 복사하여 다른 애플리케이션에 붙여넣습니다.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 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에서 이미지를 마우스 오른쪽 버튼으로 클릭하고 SVG 코드를 생성합니다. 이 기능은 파일 처리라고 하며 앱이 전달된 파일을 사용할 수 있도록 허용하는 웹 앱 매니페스트 및 실행 큐

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 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);
      }
    }
  }
});
<ph type="x-smartling-placeholder">
</ph>
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);
      })(),
    );
  }
});
<ph type="x-smartling-placeholder">
</ph>
SVGcode 스크린샷 공유

결론

지금까지 SVGcode의 몇 가지 고급 앱 기능을 간단히 살펴보았습니다. 이 앱이 있으면 좋겠어 다음과 같은 놀라운 앱과 함께 이미지 처리에 필수적인 도구가 될 수 있습니다. Squoosh 또는 SVGOMG.

SVGcode는 svgco.de에서 제공됩니다. 내가 거기서 뭘 했는지 봐. 다음을 수행할 수 있습니다. GitHub에서 소스 코드를 검토할 수 있습니다. Potrace는 GPL 라이선스가 필요하며 SVGcode도 마찬가지입니다. 즐겁게 벡터화하시기 바랍니다. SVGcode가 도움이 되길 바랍니다. 다음 앱을 개발하는 데 도움이 될 수 있습니다

감사의 말씀

이 도움말은 Joe Medley가 검토했습니다.