Jelajahi Sumber

feat: add ImageMagick

issue: #295, #269
C4illin 2 bulan lalu
induk
melakukan
b47e5755f6
4 mengubah file dengan 508 tambahan dan 3 penghapusan
  1. 1 0
      Dockerfile
  2. 489 0
      src/converters/imagemagick.ts
  3. 8 3
      src/converters/main.ts
  4. 10 0
      src/helpers/printVersions.ts

+ 1 - 0
Dockerfile

@@ -48,6 +48,7 @@ RUN apt-get update && apt-get install -y \
   libjxl-tools \
   libva2 \
   libvips-tools \
+  imagemagick-7.q16 \
   pandoc \
   poppler-utils \
   potrace \

+ 489 - 0
src/converters/imagemagick.ts

@@ -0,0 +1,489 @@
+import { execFile } from "node:child_process";
+
+// declare possible conversions
+export const properties = {
+  from: {
+    images: [
+      "3fr",
+      "3g2",
+      "3gp",
+      "aai",
+      "ai",
+      "apng",
+      "art",
+      "arw",
+      "avci",
+      "avi",
+      "avif",
+      "avs",
+      "bayer",
+      "bayera",
+      "bgr",
+      "bgra",
+      "bgro",
+      "bmp",
+      "bmp2",
+      "bmp3",
+      "cal",
+      "cals",
+      "canvas",
+      "caption",
+      "cin",
+      "clip",
+      "clipboard",
+      "cmyk",
+      "cmyka",
+      "cr2",
+      "cr3",
+      "crw",
+      "cube",
+      "cur",
+      "cut",
+      "data",
+      "dcm",
+      "dcr",
+      "dcraw",
+      "dcx",
+      "dds",
+      "dfont",
+      "dng",
+      "dpx",
+      "dxt1",
+      "dxt5",
+      "emf",
+      "epdf",
+      "epi",
+      "eps",
+      "epsf",
+      "epsi",
+      "ept",
+      "ept2",
+      "ept3",
+      "erf",
+      "exr",
+      "farbfeld",
+      "fax",
+      "ff",
+      "fff",
+      "file",
+      "fits",
+      "fl32",
+      "flif",
+      "flv",
+      "fractal",
+      "ftp",
+      "fts",
+      "ftxt",
+      "g3",
+      "g4",
+      "gif",
+      "gif87",
+      "gradient",
+      "gray",
+      "graya",
+      "group4",
+      "hald",
+      "hdr",
+      "heic",
+      "heif",
+      "hrz",
+      "http",
+      "https",
+      "icb",
+      "ico",
+      "icon",
+      "iiq",
+      "inline",
+      "ipl",
+      "j2c",
+      "j2k",
+      "jng",
+      "jnx",
+      "jp2",
+      "jpc",
+      "jpe",
+      "jpeg",
+      "jpg",
+      "jpm",
+      "jps",
+      "jpt",
+      "jxl",
+      "k25",
+      "kdc",
+      "label",
+      "m2v",
+      "m4v",
+      "mac",
+      "map",
+      "mask",
+      "mat",
+      "mdc",
+      "mef",
+      "miff",
+      "mkv",
+      "mng",
+      "mono",
+      "mos",
+      "mov",
+      "mp4",
+      "mpc",
+      "mpeg",
+      "mpg",
+      "mpo",
+      "mrw",
+      "msl",
+      "msvg",
+      "mtv",
+      "mvg",
+      "nef",
+      "nrw",
+      "null",
+      "ora",
+      "orf",
+      "otb",
+      "otf",
+      "pal",
+      "palm",
+      "pam",
+      "pango",
+      "pattern",
+      "pbm",
+      "pcd",
+      "pcds",
+      "pcl",
+      "pct",
+      "pcx",
+      "pdb",
+      "pdf",
+      "pdfa",
+      "pef",
+      "pes",
+      "pfa",
+      "pfb",
+      "pfm",
+      "pgm",
+      "pgx",
+      "phm",
+      "picon",
+      "pict",
+      "pix",
+      "pjpeg",
+      "plasma",
+      "png",
+      "png00",
+      "png24",
+      "png32",
+      "png48",
+      "png64",
+      "png8",
+      "pnm",
+      "pocketmod",
+      "ppm",
+      "ps",
+      "psb",
+      "psd",
+      "ptif",
+      "pwp",
+      "qoi",
+      "radial",
+      "raf",
+      "ras",
+      "raw",
+      "rgb",
+      "rgb565",
+      "rgba",
+      "rgbo",
+      "rgf",
+      "rla",
+      "rle",
+      "rmf",
+      "rsvg",
+      "rw2",
+      "rwl",
+      "scr",
+      "screenshot",
+      "sct",
+      "sfw",
+      "sgi",
+      "six",
+      "sixel",
+      "sr2",
+      "srf",
+      "srw",
+      "stegano",
+      "sti",
+      "strimg",
+      "sun",
+      "svg",
+      "svgz",
+      "text",
+      "tga",
+      "tiff",
+      "tiff64",
+      "tile",
+      "tim",
+      "tm2",
+      "ttc",
+      "ttf",
+      "txt",
+      "uyvy",
+      "vda",
+      "vicar",
+      "vid",
+      "viff",
+      "vips",
+      "vst",
+      "wbmp",
+      "webm",
+      "webp",
+      "wmf",
+      "wmv",
+      "wpg",
+      "x3f",
+      "xbm",
+      "xc",
+      "xcf",
+      "xpm",
+      "xps",
+      "xv",
+      "ycbcr",
+      "ycbcra",
+      "yuv",
+    ],
+  },
+  to: {
+    images: [
+      "aai",
+      "ai",
+      "apng",
+      "art",
+      "ashlar",
+      "avif",
+      "avs",
+      "bayer",
+      "bayera",
+      "bgr",
+      "bgra",
+      "bgro",
+      "bmp",
+      "bmp2",
+      "bmp3",
+      "brf",
+      "cal",
+      "cals",
+      "cin",
+      "cip",
+      "clip",
+      "clipboard",
+      "cmyk",
+      "cmyka",
+      "cur",
+      "data",
+      "dcx",
+      "dds",
+      "dpx",
+      "dxt1",
+      "dxt5",
+      "epdf",
+      "epi",
+      "eps",
+      "eps2",
+      "eps3",
+      "epsf",
+      "epsi",
+      "ept",
+      "ept2",
+      "ept3",
+      "exr",
+      "farbfeld",
+      "fax",
+      "ff",
+      "fits",
+      "fl32",
+      "flif",
+      "flv",
+      "fts",
+      "ftxt",
+      "g3",
+      "g4",
+      "gif",
+      "gif87",
+      "gray",
+      "graya",
+      "group4",
+      "hdr",
+      "histogram",
+      "hrz",
+      "htm",
+      "html",
+      "icb",
+      "ico",
+      "icon",
+      "info",
+      "inline",
+      "ipl",
+      "isobrl",
+      "isobrl6",
+      "j2c",
+      "j2k",
+      "jng",
+      "jp2",
+      "jpc",
+      "jpe",
+      "jpeg",
+      "jpg",
+      "jpm",
+      "jps",
+      "jpt",
+      "json",
+      "jxl",
+      "m2v",
+      "m4v",
+      "map",
+      "mask",
+      "mat",
+      "matte",
+      "miff",
+      "mkv",
+      "mng",
+      "mono",
+      "mov",
+      "mp4",
+      "mpc",
+      "mpeg",
+      "mpg",
+      "msl",
+      "msvg",
+      "mtv",
+      "mvg",
+      "null",
+      "otb",
+      "pal",
+      "palm",
+      "pam",
+      "pbm",
+      "pcd",
+      "pcds",
+      "pcl",
+      "pct",
+      "pcx",
+      "pdb",
+      "pdf",
+      "pdfa",
+      "pfm",
+      "pgm",
+      "pgx",
+      "phm",
+      "picon",
+      "pict",
+      "pjpeg",
+      "png",
+      "png00",
+      "png24",
+      "png32",
+      "png48",
+      "png64",
+      "png8",
+      "pnm",
+      "pocketmod",
+      "ppm",
+      "ps",
+      "ps2",
+      "ps3",
+      "psb",
+      "psd",
+      "ptif",
+      "qoi",
+      "ras",
+      "rgb",
+      "rgba",
+      "rgbo",
+      "rgf",
+      "rsvg",
+      "sgi",
+      "shtml",
+      "six",
+      "sixel",
+      "sparse",
+      "strimg",
+      "sun",
+      "svg",
+      "svgz",
+      "tga",
+      "thumbnail",
+      "tiff",
+      "tiff64",
+      "txt",
+      "ubrl",
+      "ubrl6",
+      "uil",
+      "uyvy",
+      "vda",
+      "vicar",
+      "vid",
+      "viff",
+      "vips",
+      "vst",
+      "wbmp",
+      "webm",
+      "webp",
+      "wmv",
+      "wpg",
+      "xbm",
+      "xpm",
+      "xv",
+      "yaml",
+      "ycbcr",
+      "ycbcra",
+      "yuv",
+    ],
+  },
+};
+
+export function convert(
+  filePath: string,
+  fileType: string,
+  convertTo: string,
+  targetPath: string,
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  options?: unknown,
+): Promise<string> {
+  let outputArgs: string[] = [];
+  let inputArgs: string[] = [];
+
+  if (convertTo === "ico") {
+    outputArgs = [
+      "-define",
+      "icon:auto-resize=256,128,64,48,32,16",
+      "-background",
+      "none",
+    ];
+
+    if (fileType === "svg") {
+      // this might be a bit too much, but it works
+      inputArgs = ["-background", "none", "-density", "512"];
+    }
+  }
+
+  return new Promise((resolve, reject) => {
+    execFile(
+      "magick",
+      [...inputArgs, filePath, ...outputArgs, targetPath],
+      (error, stdout, stderr) => {
+        if (error) {
+          reject(`error: ${error}`);
+        }
+
+        if (stdout) {
+          console.log(`stdout: ${stdout}`);
+        }
+
+        if (stderr) {
+          console.error(`stderr: ${stderr}`);
+        }
+
+        resolve("Done");
+      },
+    );
+  });
+}

+ 8 - 3
src/converters/main.ts

@@ -10,7 +10,8 @@ import { convert as convertImage, properties as propertiesImage } from "./vips";
 import { convert as convertxelatex, properties as propertiesxelatex } from "./xelatex";
 import { convert as convertCalibre, properties as propertiesCalibre } from "./calibre";
 import { convert as convertLibheif, properties as propertiesLibheif } from "./libheif";
-import { convert as convertpotrace, properties as propertiespotrace } from "./potrace";
+import { convert as convertPotrace, properties as propertiesPotrace } from "./potrace";
+import { convert as convertImagemagick, properties as propertiesImagemagick } from "./imagemagick";
 
 
 // This should probably be reconstructed so that the functions are not imported instead the functions hook into this to make the converters more modular
@@ -71,6 +72,10 @@ const properties: Record<
     properties: propertiesPandoc,
     converter: convertPandoc,
   },
+  imagemagick: {
+    properties: propertiesImagemagick,
+    converter: convertImagemagick,
+  },
   graphicsmagick: {
     properties: propertiesGraphicsmagick,
     converter: convertGraphicsmagick,
@@ -88,8 +93,8 @@ const properties: Record<
     converter: convertFFmpeg,
   },
   potrace: {
-    properties: propertiespotrace,
-    converter: convertpotrace,
+    properties: propertiesPotrace,
+    converter: convertPotrace,
   },
 };
 

+ 10 - 0
src/helpers/printVersions.ts

@@ -44,6 +44,16 @@ if (process.env.NODE_ENV === "production") {
     }
   });
 
+  exec("magick --version", (error, stdout) => {
+    if (error) {
+      console.error("ImageMagick is not installed.");
+    }
+
+    if (stdout) {
+      console.log(stdout.split("\n")[0]?.replace("Version: ", ""));
+    }
+  });
+
   exec("gm version", (error, stdout) => {
     if (error) {
       console.error("GraphicsMagick is not installed.");