Joe Doherty Joe Doherty -4 years ago 344
Node.js Question

Add label to image NodeJS ImageMagick

Apologies if this has been asked but I am struggling to find the answer.

I am using the Node GM package with ImageMagick. As I am under the impression the

label
only works there.

I want to take an image and add a
label
over the top of it.

I was originally using
drawText()
to acheive this, however I need to take advantage of the auto sizing of the
label
in IM. What I have is:

im(path.join(__dirname, '../public/images/imgen/backgrounds/', color + '_' + type + '.png'))
.gravity('West')
.fill('#FFFFFF')
.font(path.join(__dirname, '../public/fonts/Lato/Lato-Bold.ttf'))
.out('label: ' + text)
.write(
path.join(__dirname, '../public/images/imgen/generated/', fileName), function(err) {
if (!err) {
// If the write was successful then redirect to the new image
res.redirect('/images/imgen/generated/' + fileName);
} else {
console.error(err);
res.status(500).end();
}
});


The above generates two images instead of one. I'm guessing I need to create an empty image and insert the image as a background. Yet I can not work out how to do this.

im(1080, 1080)
.gravity('West')
.fill('#FFFFFF')
.font(path.join(__dirname, '../public/fonts/Lato/Lato-Bold.ttf'))
// Add the image as a background here
.out('label: ' + text)
.write(
path.join(__dirname, '../public/generated/', fileName), function(err) {
if (!err) {
// If the write was successful then redirect to the new image
res.redirect('/images/imgen/generated/' + fileName);
} else {
console.error(err);
res.status(500).end();
}
});


Where it says Add the image as a background here, I don't know what to do to add an image. I can't find it anywhere in the gm docs to insert an image.

I have tried
.out('texture: ...')
and
.out('background: ...')
but no look. I get the following error from IM
convert: no decode delegate for this image format
TEXTURE' @ error/constitute.c/ReadImage/501.`

I'm probably not understanding correctly the out() method. But digging through Github issues and search results hasn't yielded the answer.

Thanks in advance for any help you can give.

Answer Source

I have a real mental block with all those parentheses in node.js but you said any help is welcome, so maybe we can get you sorted out by working a bit towards each other. I'll start at the command-line with ImageMagick and then you will maybe understand what is going on behind the scenes and be able to translate that to node.js.

The first thing is that ImageMagick operators without a dash before them and with a colon after them generate their own canvas - that means they don't don't need some pre-existing thing to write or draw on. Examples are canvas:, xc:, gradient:, label::

convert -size 100x80 canvas:red a.jpg               # "canvas: is same as "xc:"

enter image description here

convert -size 100x80 gradient:cyan-magenta a.jpg    # "gradient:" has a colon

enter image description here

convert -size 400x60 -undercolor yellow label:"This will be autosized to fit" -trim c.jpg

enter image description here

convert -size 400x60 -undercolor yellow label:"... so will this" -trim c.jpg

enter image description here

Hopefully you can see ImageMagick chose a bigger font for the shorter message.

All that is fine, but if you want to use -annotate (which you will notice is preceded by a dash and does not have a colon after it), you need to create a canvas first and then annotate it afterwards like this:

convert -size 400x120 xc:blue -fill yellow -annotate +40+80  "Annotation" c.jpg

enter image description here

What I am getting to, is that if you create a canvas AND a label (which creates its own canvas, remember), you will effectively have two canvases and get two output images. So, you have two options on how to get around that. You either:

  • use a canvas and annotate it, or

  • you create a label and background image and then composite the label over the canvas.

I just showed you the first option already, so let's look at the second. You can create a label of the correct size and then position it over a background wherever you like and then composite it onto the background as you wish:

convert -size 150x40 -undercolor yellow label:"Some funky text" -trim \
  -size 300x200 -gravity center xc:red +swap -composite result.jpg

enter image description here

So, what that does is create a label that is 150x40 and puts the text on it. The second line then creates another canvas in red of 300x200 and puts it behind the text label (using +swap) and composites it into the middle. You see, because I composited the label onto the canvas, they have become a single composite image rather than remaining two independent images.

Here is another example where we have an image of the White House and want to create a label and overlay it. First we create the label, all the correct size and colour, then we load the White House image and swap it to the back before compositing the label on top:

magick -size 300x200 -background none -fill magenta label:"Some funky label" -trim whitehouse.jpg +swap -gravity southeast -composite result.png

enter image description here

Hopefully you can see how to put all the beloved parentheses around that to make it into node.js....

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download