SVGcode: une PWA permettant de convertir des images matricielles en images vectorielles SVG

SVGcode est une progressive web app qui vous permet de convertir des images matricielles telles que JPG, PNG, GIF, WebP, AVIF, etc. en images vectorielles au format SVG. Il utilise l'API File System Access, l'API Async Clipboard, l'API File Handling et la personnalisation de la superposition des commandes de fenêtre.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> (Si vous préférez le regarder plutôt que le lire, cet article est également disponible sous forme de vidéo.)

De la trame au vecteur

Avez-vous déjà mis à l'échelle une image dont le résultat était pixelisé et n'était pas satisfaisant ? Si vous avez probablement déjà utilisé un format d'image matricielle, tel que WebP, PNG ou JPG.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> La mise à l'échelle d'une image matricielle donne l'impression qu'elle est pixélisée.

En revanche, les graphiques vectoriels sont des images définies par des points dans un système de coordonnées. Ces les points sont reliés par des lignes et des courbes pour former des polygones et d'autres formes. Les graphiques vectoriels ont une par rapport aux graphiques matriciels, car ils peuvent être ajustés à la hausse ou à la baisse pour n'importe quelle résolution. sans pixellisation.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Mise à l'échelle d'une image vectorielle sans perte de qualité.

Présentation du code SVG

J'ai créé une PWA appelée SVGcode, qui peut vous aider à convertir des images matricielles en des vecteurs. Motif du crédit: je n'ai pas inventé cela. Avec le code SVG, je me place d'un outil de ligne de commande appelé Potrace Peter Selinger, converti en assembleur Web pour pouvoir être utilisé dans un Application Web.

<ph type="x-smartling-placeholder">
</ph> Capture d&#39;écran de l&#39;application SVGcode. <ph type="x-smartling-placeholder">
</ph> L'application SVGcode

Utiliser le code SVG

Tout d'abord, je veux vous montrer comment utiliser l'application. Commençons par l'image d'accroche du Chrome Dev Summit. que j'ai téléchargée sur le canal Twitter de ChromiumDev. Il s'agit d'une image matricielle PNG que j'ai ensuite faites glisser le curseur dans l'application SVGcode. Lorsque je dépose le fichier, l'application trace l'image couleur par couleur, jusqu'à ce qu'une version vectorisée de l'entrée s'affiche. Je peux faire un zoom avant sur l'image. Comme vous pouvez le voir, et les bords restent nets. Mais en zoomant sur le logo Chrome, vous pouvez voir que le traçage n'était pas parfait, et surtout les contours du logo sont un peu tachetés. Je peux améliorer le résultat en en supprimant le traçage en supprimant les taches jusqu'à cinq pixels.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Convertir une image déposée au format SVG

Postérisation en SVG

Une étape importante de la vectorisation, en particulier pour les images photographiques, est la postérisation de l'entrée pour réduire le nombre de couleurs. Le code SVG me permet de le faire par canal de couleur, et de voir tout en faisant des modifications. Lorsque le résultat me convient, je peux enregistrer le SVG sur mon disque dur et l'utiliser où je veux.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Postérisation d'une image pour réduire le nombre de couleurs

API utilisées dans le code SVG

Maintenant que vous savez à quoi sert l'application, laissez-moi vous montrer certaines des API qui contribuent la magie opère.

Progressive web app

Le code SVG est une progressive web app installable qui est donc entièrement hors connexion. L'application est basée le Modèle JS Vanilla pour Vite.js et utilise le PWA du plug-in Vite, qui crée un service worker qui utilise Workbox.js en arrière-plan. Workbox est un ensemble de bibliothèques permettant d'alimenter un service worker prêt pour la production pour des progressive web apps. Ce modèle ne fonctionne pas nécessairement pour toutes les applications, mais pour le cas d'utilisation du code SVG, c'est idéal.

Superposition des commandes de fenêtre

Pour maximiser l'espace disponible à l'écran, le code SVG utilise la personnalisation de la superposition des commandes des fenêtres en déplaçant son menu principal vers le haut dans dans la zone de la barre de titre. Vous pouvez voir que cette option est activée à la fin du processus d'installation.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Installation du code SVG et activation de la personnalisation de superposition des commandes de fenêtre.

API File System Access

Pour ouvrir les fichiers image d'entrée et enregistrer les fichiers SVG obtenus, j'utilise la classe API File System Access : Cela me permet de garder une référence à des fichiers ouverts et de reprendre là où je m'étais arrêté, même après avoir actualisé une application. Chaque fois qu'une image est enregistré, il est optimisé via la bibliothèque svgo, ce qui peut prendre un moment. en fonction de la complexité du SVG. Un geste de l'utilisateur est nécessaire pour afficher la boîte de dialogue d'enregistrement du fichier. Il est Il est donc important d'obtenir le handle du fichier avant l'optimisation SVG. L'utilisateur Le geste n'est pas invalidé lorsque le SVG optimisé est prêt.

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

Glisser-déposer

Pour ouvrir une image d'entrée, je peux utiliser la fonction d'ouverture de fichier ou, comme vous l'avez vu ci-dessus, glisser-déposer un fichier image sur l'application. La fonction d'ouverture de fichier est assez simple, plus intéressant est le cas du glisser-déposer. Ce qui est particulièrement intéressant, c'est que vous pouvez obtenir un traitement de système de fichiers à partir de l'élément de transfert de données via getAsFileSystemHandle() . Comme indiqué précédemment, je peux conserver ce handle, afin qu'il soit prêt lorsque l'application sera actualisée.

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

Pour en savoir plus, consultez l'article sur l'API File System Access. Si vous le souhaitez, étudiez le code source du code SVG src/js/filesystem.js

API Async Clipboard

Le SVG est entièrement intégré au presse-papiers du système d'exploitation via l'API Async Clipboard. Vous pouvez coller des images depuis l'explorateur de fichiers du système d'exploitation dans l'application en cliquant sur l'icône bouton "Coller une image", ou en appuyant sur les touches Commande ou Ctrl+v de votre clavier.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Collage d'une image de l'explorateur de fichiers dans le code SVG...

Depuis peu, l'API Async Clipboard permet également de traiter des images SVG. copier une image SVG et la coller dans une autre application pour un traitement ultérieur.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Copie d'une image à partir du code SVG dans 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'));
});

Pour en savoir plus, consultez l'article Presse-papiers asynchrone ou le fichier src/js/clipboard.js

Gestion des fichiers

L'une de mes fonctionnalités préférées du code SVG est sa compatibilité avec le système d'exploitation. En tant que installé PWA, il peut devenir un gestionnaire de fichiers, ou même le gestionnaire de fichiers par défaut, pour les fichiers image. Ce signifie que lorsque je suis dans le Finder sur mon ordinateur macOS, je peux faire un clic droit sur une image et l'ouvrir avec SVG. Cette fonctionnalité, appelée "Gestion des fichiers", repose sur la propriété "file_handlers" dans Fichier manifeste d'application Web et file d'attente de lancement, qui permettent à l'application d'utiliser le fichier transmis.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> Ouverture d'un fichier à partir du bureau sur lequel l'application SVGcode est installée.
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;
    }
  }
});

Pour en savoir plus, consultez Autoriser les applications Web installées à être des gestionnaires de fichiers et afficher le code source dans src/js/filehandling.js

Partage Web (fichiers)

Un autre exemple d’intégration avec le système d’exploitation est la fonctionnalité de partage de l’application. Supposons que je veux pour modifier un SVG créé avec du code SVG, par exemple en enregistrant le fichier, lancez l'application d'édition SVG, puis ouvrez le fichier SVG. Un flux plus fluide, cependant, consiste à utiliser l'API Web Share, qui permet le partage direct des fichiers ; Si l'application d'édition SVG est une cible de partage : elle peut recevoir directement le fichier sans déviation.

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>
. Partager une image SVG avec Gmail

Cible de partage Web (fichiers)

À l'inverse, le code SVG peut également servir de cible de partage et recevoir des fichiers provenant d'autres applications. À pour que cela fonctionne, l'application doit en informer le système d'exploitation via la API Web Share Target indiquant les types de données qu'elle accepte Pour cela, dans le fichier manifeste d'application Web.

{
  "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"]
        }
      ]
    }
  }
}

La route action n'existe pas, mais elle est gérée uniquement dans le fichier fetch du service worker , qui transmet ensuite les fichiers reçus pour un traitement réel dans l'application.

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>
. Partage d'une capture d'écran au format SVG

Conclusion

Très bien, je vous ai présenté brièvement quelques-unes des fonctionnalités avancées de l'application en SVG. J'espère que cette application peut devenir un outil essentiel pour vos besoins en traitement d'image, avec d'autres applications incroyables comme Squoosh ou SVGOMG.

Le code SVG est disponible sur svgco.de. Vous voyez ce que j'ai fait ? Vous pouvez consultez son code source sur GitHub. Notez que Potrace étant sous licence GPL, tout comme le code SVG. Et voilà, bonne vectorisation ! J'espère que le code SVG vous sera utile. certaines de ses fonctionnalités peuvent inspirer votre prochaine application.

Remerciements

Joe Medley a rédigé cet article.