DEV Community

Jack H. Peterson
Jack H. Peterson

Posted on

Batch Convert SVG to PNG.

If you need to batch convert a bunch of SVG files into PNG files, look no further.
This script should do the trick.

Fast Solution

  1. Modify the Script to suit your needs.
  2. npm i svgexport
  3. node thisScript.js
  4. You're done!

Overview

I'll explain how this script works, so you'll have an easier time adjusting it to suit your needs. The full script is at the bottom for easier copypasta.

Imports

const svgexport = require("svgexport");
const fs = require("fs");
const path = require("path");
Enter fullscreen mode Exit fullscreen mode

Settings

Set up what files, sizes, and colors you want to use.

  • I'm importing files from the /svg directory this script is located in.
  • I'm setting sizes to 32, 64, 128, 256, 512; Set it to whatever you want.
  • I'm setting colors to white, black, and a custom hex. (This is put in color css property, which is then used by the fill="currentColor" to set the color.
const inputs = fs.readdirSync("./svg");
const allColors = ["white", "black", "#357dcc"];
const allSizes = [32, 64, 128, 256, 512];
Enter fullscreen mode Exit fullscreen mode

Convert

This is the function which builds an object for the svgexport datafile array.
There's more info at the Docs for svgexport.
svgexport can take an input file path, some optional transforms for the svg (color, size, etc), and will output the desired file to a given path. Our output path will resolve like this: png/COLOR/SIZE/INPUT.png. You can change this by changing the file const. ie: png/INPUT_COLOR_SIZE.png is valid too! You'll just have all of your PNGs in the same folder with very detailed names.

const convert = (i, color, size) => {
  const file = `./png/${String(color).replace(/\W/g, '')}/${String(size).replace(/\W/g, '')}/${i.replace(".svg", ".png")}`;
  const dir = file.substring(0, file.lastIndexOf("/"));
  //   Creates directory if the directory does NOT exist
  !fs.existsSync(dir) && fs.mkdirSync(dir, { recursive: true });

  return {
    input: [
      path.resolve(__dirname, `./svg/${i}`),
      `${size}:`,
      `svg{width:100%;color:${color};}`,
    ],
    output: [path.resolve(__dirname, file)],
  };
};
Enter fullscreen mode Exit fullscreen mode

Combine

Now we take all of our defined variations — inputs, sizes, colors — and flatMap them into an array. This array is the datafile we will give to svgexport.

const datafile = inputs.flatMap((input) =>
  allColors.flatMap((color) => allSizes.flatMap((size) => convert(input, color, size)))
);
Enter fullscreen mode Exit fullscreen mode

Transform SVGs into PNGs!

That's it! We just feed our datafile to svgexport and viola! We got our batch of PNGs.

svgexport.render(datafile, console.log("complete"));
Enter fullscreen mode Exit fullscreen mode

AFAIK svgexport uses puppeteer under the hood to render and export the PNG. So this isn't a severless friendly solution. But it'll work great locally, and will likely work nicely in something like Netlify.

Full Script

const svgexport = require("svgexport");
const fs = require("fs");
const path = require("path");

const inputs = fs.readdirSync("./svg");
const allColors = ["white", "black", "#357dcc"];
const allSizes = [32, 64, 128, 256, 512];

const convert = (i, color, size) => {
  const file = `./png/${String(color).replace(/\W/g, '')}/${String(size).replace(/\W/g, '')}/${i.replace(".svg", ".png")}`;
  const dir = file.substring(0, file.lastIndexOf("/"));
  //   Creates directory if the directory does NOT exist
  !fs.existsSync(dir) && fs.mkdirSync(dir, { recursive: true });

  return {
    input: [
      path.resolve(__dirname, `./svg/${i}`),
      `${size}:`,
      `svg{width:100%;color:${color};}`,
    ],
    output: [path.resolve(__dirname, file)],
  };
};

const datafile = inputs.flatMap((input) =>
  allColors.flatMap((color) => allSizes.flatMap((size) => convert(input, color, size)))
);

svgexport.render(datafile, console.log("complete"));

Enter fullscreen mode Exit fullscreen mode

Discussion (0)