0

I'm using GraphicsMagick for node to take a source image, resize, crop and then apply a mask:

      gm(tempfile)
        .quality(90)
        .resize(null, 38)
        .gravity('Center')
        .crop(20, 34)
        .mask('./public/assets/mask.png')
        .write(thumb, function (err) {
          if (err) throw err
          console.log('success')
        })

After running, The image is resized and cropped successfully, but the mask is not applied. No error is thrown (i.e. the console prints 'success').

Attached to this is also the mask image I'm trying to use. I want the image to draw only on the black part. I've tried using a transparent png (the gm docs say it masks based on alpha channel), as well as a black and white jpg, but the result is the same.

sample mask img

I'm sure I'm missing something obvious, but I'm stumped Thanks!

Pirijan
  • 3,430
  • 3
  • 19
  • 29

1 Answers1

7

So after another day or so on this I've figured it out:

Mask doesn't do anything on it's own, it's pretty useless really. It merely takes the supplied mask image and uses it to write protect the masked pixels from subsequent alteration if additional processing / drawing is performed on the image.

Because Node GM doesn't support composite, my solution is to apply the mask using a system call. Because there doesn't seem to be any way to combine cropping and composite in a single step (graphicsmagick composite and crop in the same command), I've done it in two steps:

      var exec = require('child_process').exec
      gm = require('gm')

      gm(tempfile)
        .quality(90)
        .resize(null, thumbOffset)
        .gravity('Center')
        .crop(thumbWidth, thumbHeight)
        .write(thumb, function (err) {
          if (err) throw err
          console.log('thumb sized')
          compositeMask(thumb, mask, function(){
            console.log('mask1 done')
          })
        })

      function compositeMask(thumb, mask, next) {
        var gmComposite = 'gm composite -compose in ' + thumb + ' ' + mask + ' ' + thumb
        exec(gmComposite, function(err) {
          if (err) throw err
          pathUpdate(entryID, { thumb: thumb })
          next()
        })
      }
Community
  • 1
  • 1
Pirijan
  • 3,430
  • 3
  • 19
  • 29
  • I know this post is 8 years old, but I must praise you for your patience. I have been struggling with this issue for days now. I am using Angular Electron and in the NodeJs controlled ipcMain, I am using GM. I have used mask(mask), clip(), composite(image,mask) and also I have tried drawing shapes & then compose(). But nothing happens. Just absolutely nothing. I am thinking, why on Earth, have the authors of GM, spent so much time, writing documentation on the various masking techniques, when it just does NOT work? Very, very surreal :) Anyway, I will try your approach tomorrow. – Charles Robertson Nov 09 '21 at 22:09
  • I have just found out that NodeJs now includes the ‘child_process’ module. The npm version has been placed in quarantine, due to security issues. I pray your solution works. It is the last chance saloon. ‍♀️ Unfortunately, node-canvas does not seem to work inside Electron. This would have been a much solution for my needs. It’s a shame there isn’t a modern, robust solution for manipulating images in NodeJs? – Charles Robertson Nov 09 '21 at 22:46