Node-red-contrib-image-tools - combining images

[{"id":"1778f6d3.186309","type":"image viewer","z":"af952aeaa20f4f97","name":"","width":160,"data":"merged","dataType":"msg","active":true,"x":1370,"y":1500,"wires":[[]]},{"id":"9d9012a6.2a615","type":"Barcode Generator","z":"af952aeaa20f4f97","name":"QR Code","data":"serial","dataType":"msg","barcode":"qrcode","barcodeType":"barcode","options":"","optionsType":"ui","sendProperty":"qrBuffer","props":[],"x":680,"y":1420,"wires":[["d9581a7e1b3a7366"]]},{"id":"f1bcfcf6.b6fea","type":"inject","z":"af952aeaa20f4f97","name":"Serial","props":[{"p":"serial","v":"00001066","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":510,"y":1420,"wires":[["9d9012a6.2a615"]]},{"id":"dfe6eb84.8d2a88","type":"jimp-image","z":"af952aeaa20f4f97","name":"QR Merge","data":"template","dataType":"msg","ret":"img","parameter1":"qr","parameter1Type":"msg","parameter2":"qrx","parameter2Type":"msg","parameter3":"qry","parameter3Type":"msg","parameter4":"0","parameter4Type":"num","parameter5":"0","parameter5Type":"num","parameter6":"qrw","parameter6Type":"msg","parameter7":"qrh","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","sendProperty":"merged","sendPropertyType":"msg","parameterCount":7,"jimpFunction":"blit","selectedJimpFunction":{"name":"blit","fn":"blit","description":"blit the image with another Jimp image at x, y, optionally cropped","parameters":[{"name":"src","type":"","required":true,"hint":"the source image (a Jimp instance)","defaultType":"msg","defaultValue":"payload"},{"name":"x","type":"num","required":true,"hint":"the x position to blit the image"},{"name":"y","type":"num","required":true,"hint":"the y position to blit the image"},{"name":"srcx","type":"num","required":false,"hint":"the x position from which to crop the source image"},{"name":"srcy","type":"num","required":false,"hint":"the y position from which to crop the source image"},{"name":"srcw","type":"num","required":false,"hint":"the width to which to crop the source image"},{"name":"srch","type":"num","required":false,"hint":"the height to which to crop the source image"}]},"x":1210,"y":1500,"wires":[["1778f6d3.186309"]]},{"id":"d1aad62a.7addc8","type":"image viewer","z":"af952aeaa20f4f97","name":"","width":160,"data":"qr","dataType":"msg","active":true,"x":510,"y":1500,"wires":[["274df8a7b5fe670f"]]},{"id":"98f87b98.c5a4b8","type":"image viewer","z":"af952aeaa20f4f97","name":"","width":160,"data":"template","dataType":"msg","active":true,"x":1030,"y":1500,"wires":[["dfe6eb84.8d2a88"]]},{"id":"274df8a7b5fe670f","type":"jimp-image","z":"af952aeaa20f4f97","name":"open template","data":"c:/temp/label_template_1.png","dataType":"str","ret":"img","parameter1":"","parameter1Type":"msg","parameter2":"","parameter2Type":"msg","parameter3":"","parameter3Type":"msg","parameter4":"","parameter4Type":"msg","parameter5":"","parameter5Type":"msg","parameter6":"","parameter6Type":"msg","parameter7":"","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","sendProperty":"template","sendPropertyType":"msg","parameterCount":0,"jimpFunction":"none","selectedJimpFunction":{"name":"none","fn":"none","description":"Just loads the image.","parameters":[]},"x":700,"y":1500,"wires":[["05aaba7fe1e31eb1"]]},{"id":"d9581a7e1b3a7366","type":"jimp-image","z":"af952aeaa20f4f97","name":"","data":"qrBuffer","dataType":"msg","ret":"img","parameter1":"","parameter1Type":"msg","parameter2":"","parameter2Type":"msg","parameter3":"","parameter3Type":"msg","parameter4":"","parameter4Type":"msg","parameter5":"","parameter5Type":"msg","parameter6":"","parameter6Type":"msg","parameter7":"","parameter7Type":"msg","parameter8":"","parameter8Type":"msg","sendProperty":"qr","sendPropertyType":"msg","parameterCount":0,"jimpFunction":"none","selectedJimpFunction":{"name":"none","fn":"none","description":"Just loads the image.","parameters":[]},"x":850,"y":1420,"wires":[["d1aad62a.7addc8"]]},{"id":"05aaba7fe1e31eb1","type":"function","z":"af952aeaa20f4f97","name":"calc center","func":"\nmsg.qrh = msg.qr.bitmap.height;\nmsg.qrw = msg.qr.bitmap.width;\n\nmsg.qrx = (msg.template.bitmap.height / 2) - (msg.qrh / 2);\nmsg.qry = (msg.template.bitmap.width / 2) - (msg.qrw / 2);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":870,"y":1500,"wires":[["98f87b98.c5a4b8"]]}]

Why it didnt work for you...

The blit src requires the incoming image to be a jimp image object.

  • The QR code is generated as a buffer - so an image node is required to convert the QR to a jimp image
  • The file node loads a buffer - so an image node is required to convert the template to a jimp image - OR - like i did, use an image node to load the template

PS, avoid flow context where possible as you can get into issues with concurrency when the flow runs faster that the images can be processed. Instead of flow, use msg props to carry the loaded image through the flow. (check the output property names I used)

PS 2 - avoid branching as much as possible when working with images - try to keep image msgs serial. This avoids unnecessary msg cloning (images are large when decoded into bitmaps in memory)

2 Likes