marcdacz / compare-pdf

Standalone node module that compares pdfs
MIT License
62 stars 21 forks source link

Latest version not compatible with ImageMagick 7+ #29

Open humphreyn opened 1 year ago

humphreyn commented 1 year ago

As ImageMagick version 6 is no longer being evolved and it recommended to use 7+. but you cannot do so because of the way it uses GraphicsMagic.

To use the ImageMagick 7+, the npm library gm (GraphicsMagick) v1.25.0+ is required. With this version you can enable ImageMagick 7+ as follows:

const gm = require('gm').subClass({ imageMagick: '7+' });

or to use legacy <7:

const gm = require('gm').subClass({ imageMagick: true });

Currrently compare-pdf uses the later and thus cannot use ImageMagick 7+. But also GraphicsMagick now handles creating the cli command correctly for either running on windows or linux, see sample code taken from GraphicsMagick command.js below:

 proto._exec = function _exec (args, callback) {
    return this._spawn(args, true, callback);
  }

  /**
    * Execute the command with stdin, returning stdout and stderr streams or buffers.
    * @param {String} bin
    * @param {Array} args
    * @param {ReadableStream} stream
    * @param {Boolean} shouldBuffer
    * @param {Function} callback, signature (err, stdout, stderr) -> *
    * @return {Object} gm
    * @TODO refactor this mess
    */

  proto._spawn = function _spawn (args, bufferOutput, callback) {
    var appPath = this._options.appPath || '';
    var bin

    // Resolve executable
    switch (this._options.imageMagick) {
      // legacy behavior
      case true:
        bin = args.shift();
        break;

      // ImgeMagick >= 7
      case '7+':
        bin = 'magick'
        break;

      // GraphicsMagick
      default:
        bin = 'gm';
        break;
    }

    // Prepend app path
    bin = appPath + bin

    var cmd = bin + ' ' + args.map(utils.escape).join(' ')
      , self = this
      , proc, err
      , timeout = parseInt(this._options.timeout)
      , disposers = this._options.disposers
      , timeoutId;

It is thus not necessary for compare-pdf to check if the platform ==='win32' as below:

    return new Promise((resolve, reject) => {
        const command = process.platform === 'win32' ? 'magick' : 'convert';
        const pdfBuffer = pdfDetails.buffer;
        const pdfFilename = path.parse(pdfDetails.filename).name

        gm(pdfBuffer, pdfFilename)
            .command(command)
            .density(config.settings.density, config.settings.density)
            .quality(config.settings.quality)
            .write(pngFilePath, (err) => {
                err ? reject(err) : resolve();
            });
    });

Instead the following will suffice:

    return new Promise((resolve, reject) => {
        const pdfBuffer = pdfDetails.buffer;
        const pdfFilename = path.parse(pdfDetails.filename).name

        gm(pdfBuffer, pdfFilename)
            .command('convert')
            .density(config.settings.density, config.settings.density)
            .quality(config.settings.quality)
            .write(pngFilePath, (err) => {
                err ? reject(err) : resolve();
            });
    });

I will create a PR to upgrade the dependency of GraphicsMagick to v1.25.0 and alter the code to work with ImageMagick 7+