Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node native modules #154

Open
vincaslt opened this issue Mar 1, 2024 · 3 comments
Open

Node native modules #154

vincaslt opened this issue Mar 1, 2024 · 3 comments

Comments

@vincaslt
Copy link

vincaslt commented Mar 1, 2024

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

@dlemstra
Copy link
Owner

dlemstra commented Mar 1, 2024

Not sure what you are trying to do? You can use this library with node.

@vincaslt
Copy link
Author

vincaslt commented Mar 1, 2024

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

@dlemstra
Copy link
Owner

dlemstra commented Mar 2, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants