diff options
-rw-r--r-- | src/gen-thumbs.js | 65 | ||||
-rw-r--r-- | src/util/node-utils.js | 9 |
2 files changed, 71 insertions, 3 deletions
diff --git a/src/gen-thumbs.js b/src/gen-thumbs.js index e6dfeae7..839c1d42 100644 --- a/src/gen-thumbs.js +++ b/src/gen-thumbs.js @@ -100,6 +100,7 @@ import { } from './util/cli.js'; import { + commandExists, isMain, promisifyProcess, } from './util/node-utils.js'; @@ -133,18 +134,62 @@ function readFileMD5(filePath) { }); } -function generateImageThumbnails(filePath) { +async function getImageMagickVersion(spawnConvert) { + const proc = spawnConvert(['--version'], false); + + let allData = ''; + proc.stdout.on('data', data => { + allData += data.toString(); + }); + + await promisifyProcess(proc, false); + + if (!allData.match(/ImageMagick/i)) { + return null; + } + + const match = allData.match(/Version: (.*)/i); + if (!match) { + return 'unknown version'; + } + + return match[1]; +} + +async function getSpawnConvert() { + let fn, description, version; + if (await commandExists('convert')) { + fn = args => spawn('convert', args); + description = 'convert'; + } else if (await commandExists('magick')) { + fn = (args, prefix = true) => spawn('magick', + (prefix ? ['convert', ...args] : args)); + description = 'magick convert'; + } else { + return [`no convert or magick binary`, null]; + } + + version = await getImageMagickVersion(fn); + + if (version === null) { + return [`binary --version output didn't indicate it's ImageMagick`]; + } + + return [`${description} (${version})`, fn]; +} + +function generateImageThumbnails(filePath, {spawnConvert}) { const dirname = path.dirname(filePath); const extname = path.extname(filePath); const basename = path.basename(filePath, extname); const output = name => path.join(dirname, basename + name + '.jpg'); - const convert = (name, {size, quality}) => spawn('convert', [ + const convert = (name, {size, quality}) => spawnConvert([ + filePath, '-strip', '-resize', `${size}x${size}>`, '-interlace', 'Plane', '-quality', `${quality}%`, - filePath, output(name) ]); @@ -192,6 +237,20 @@ export default async function genThumbs(mediaPath, { return true; }; + const [convertInfo, spawnConvert] = await getSpawnConvert() ?? []; + if (!spawnConvert) { + logError`${`It looks like you don't have ImageMagick installed.`}`; + logError`ImageMagick is required to generate thumbnails for display on the wiki.`; + logError`(Error message: ${convertInfo})`; + logInfo`You can find info to help install ImageMagick on Linux, Windows, or macOS`; + logInfo`from its official website: ${`https://imagemagick.org/script/download.php`}`; + logInfo`If you have trouble working ImageMagick and would like some help, feel free`; + logInfo`to drop a message in the HSMusic Discord server! ${'https://hsmusic.wiki/discord/'}`; + return false; + } else { + logInfo`Found ImageMagick binary: ${convertInfo}`; + } + let cache, firstRun = false, failedReadingCache = false; try { cache = JSON.parse(await readFile(path.join(mediaPath, CACHE_FILE))); diff --git a/src/util/node-utils.js b/src/util/node-utils.js index a46d6141..ad87cae3 100644 --- a/src/util/node-utils.js +++ b/src/util/node-utils.js @@ -2,6 +2,15 @@ import { fileURLToPath } from 'url'; +import _commandExists from 'command-exists'; + +// This package throws an error instead of returning false when the command +// doesn't exist, for some reason. Yay for making logic more difficult! +// Here's a straightforward workaround. +export function commandExists(command) { + return _commandExists(command).then(() => true, () => false); +} + // Very cool function origin8ting in... http-music pro8a8ly! // Sorry if we happen to 8e violating past-us's copyright, lmao. export function promisifyProcess(proc, showLogging = true) { |