Open vincaslt opened 4 months ago
Not sure what you are trying to do? You can use this library with node.
I'm trying to generate a bunch of images sequentially. I'm writing them out to images, but might as well stream to ffmpeg or whatever else. From my test, the part that's taking the longest is the draw
command. I'm not familiar with imagemagick at all, but I assume it rasterizes the image? I was wondering if there were ways to improve the performance over using canvas (Cairo or Skia based) by working directly with images in Nodejs.
import {
DrawableFillColor,
DrawableFontPointSize,
DrawableStrokeColor,
DrawableStrokeWidth,
DrawableText,
IMagickImage,
Magick,
MagickColors,
MagickFormat,
MagickImage,
initializeImageMagick,
} from "@imagemagick/magick-wasm";
import { readFileSync } from "node:fs";
import { readFile, writeFile } from "node:fs/promises";
const totalFrames = 100;
const wasmLocation = "./src/magick.wasm";
async function main() {
const wasmBytes = await readFileSync(wasmLocation);
await initializeImageMagick(wasmBytes);
const fontData = await readFile("./Calibri.ttf");
Magick.addFont("Calibri", fontData);
const promises: Promise<void>[] = [];
console.log("Start rendering frames", totalFrames);
const start = process.hrtime();
const pointSize = new DrawableFontPointSize(64);
const color = new DrawableFillColor(MagickColors.White);
const stroke = new DrawableStrokeColor(MagickColors.Black);
const strokeWidth = new DrawableStrokeWidth(2);
for (let frameNum = 1; frameNum <= totalFrames; frameNum++) {
const image = MagickImage.create(MagickColors.DarkRed, 1080, 1920);
image.settings.font = "Calibri";
const text = new DrawableText(100, 100, `Frame ${frameNum}`);
image.draw(pointSize, color, stroke, strokeWidth, text);
const promise = write(image, frameNum);
promises.push(promise);
}
await Promise.all(promises);
const elapsed = process.hrtime(start)[1] / 1000000; // divide by a million to get nano to milli
console.log(
`${process.hrtime(start)[0]}s ${Math.floor(
elapsed
)}ms - Finished writing files`
);
}
function write(image: IMagickImage, frameNum: number) {
return new Promise<void>((resolve) =>
image.write(MagickFormat.Rgba, (data) => {
const buffer = Buffer.from(data);
console.log("Done frame", frameNum, buffer.byteLength);
return writeFile(`out/${frameNum}.raw`, buffer).then(resolve);
})
);
}
I am a bit surprised that the draw
method takes a long time. It also looks like you are not disposing the images which could result in memory issues when you have a lot of frames. It might help if you use label:Your text
as the filename of the image instead and use the MagickReadSettings
to set those settings.
Is your feature request related to a problem? Please describe.
No response
Describe the solution you'd like
Would it be possible to package imagemagick as a node nativem module?
I'm trying to generate lots of images (video frames) and I'm not getting as good of a performance with WASM on node, as https://github.com/Automattic/node-canvas which I think uses compiled C code. It seems like imagick should be faster as it doesn't need to work with the abstraction of canvas.
Describe alternatives you've considered
No response
Additional context
No response