npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

node-red-contrib-image-output

v0.6.4

Published

Easy way of previewing and examining images in your flows

Downloads

2,397

Readme

🏞 node-red-contrib-image-output

Simple image output node. Useful for previewing images (of face detecting, object recognition etc...) inside the Node-RED flow editor.

The expected input should be a jpg or png image, which need to be delivered in one of the following formats:

  • A buffer
  • A base64 encoded string
  • A Jimp object
  • A url to an image

Installation

Either use the Editor - Menu - Manage Palette - Install option, or run the following npm command in your Node-RED user directory (typically ~/.node-red):

npm i node-red-contrib-image-output

Node usage

This node can be used to preview images inside the Node-RED flow editor. The following examples explain how the different kind of input image formats can be visualized. All these example flows are also available via the 'Import' menu in the Node-RED flow editor.

Buffer input image

Apply an image as a binary Buffer (i.e. bits and bytes ...):

Buffer flow

[{"id":"46ffc819.b736f8","type":"http request","z":"30fb1577.8f556a","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"https://dummyimage.com/200x150/000/fff&text={{{payload}}}","tls":"","persist":false,"proxy":"","authType":"","x":610,"y":640,"wires":[["d603e881.2fa1c8"]]},{"id":"25d928c1.708098","type":"inject","z":"30fb1577.8f556a","name":"Generate next image","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":200,"y":640,"wires":[["878f8ec1.effe4"]]},{"id":"878f8ec1.effe4","type":"function","z":"30fb1577.8f556a","name":"image counter","func":"var count = flow.get(\"count\")||0;\n\ncount++;\n\nnode.status({fill:\"blue\",shape:\"ring\",text:\"Image \" + count});\n\n// Save the new value back to context so it will be available next time\nflow.set('count',count);\n\n// Update the message payload and return - no need to create a new msg\nmsg.payload = \"Image \" + count;\nreturn msg;","outputs":1,"noerr":0,"x":420,"y":640,"wires":[["46ffc819.b736f8"]]},{"id":"d603e881.2fa1c8","type":"image","z":"30fb1577.8f556a","name":"","width":160,"data":"payload","dataType":"msg","thumbnail":true,"active":true,"x":800,"y":640,"wires":[]}]

Base64 input image

Apply an image as a base64 encoded string:

Base64 flow

[{"id":"46ffc819.b736f8","type":"http request","z":"30fb1577.8f556a","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"https://dummyimage.com/200x150/000/fff&text={{{payload}}}","tls":"","persist":false,"proxy":"","authType":"","x":610,"y":640,"wires":[["27a53fad.5c768"]]},{"id":"25d928c1.708098","type":"inject","z":"30fb1577.8f556a","name":"Generate next image","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":200,"y":640,"wires":[["878f8ec1.effe4"]]},{"id":"878f8ec1.effe4","type":"function","z":"30fb1577.8f556a","name":"image counter","func":"var count = flow.get(\"count\")||0;\n\ncount++;\n\nnode.status({fill:\"blue\",shape:\"ring\",text:\"Image \" + count});\n\n// Save the new value back to context so it will be available next time\nflow.set('count',count);\n\n// Update the message payload and return - no need to create a new msg\nmsg.payload = \"Image \" + count;\nreturn msg;","outputs":1,"noerr":0,"x":420,"y":640,"wires":[["46ffc819.b736f8"]]},{"id":"27a53fad.5c768","type":"base64","z":"30fb1577.8f556a","name":"","action":"str","property":"payload","x":780,"y":640,"wires":[["d603e881.2fa1c8"]]},{"id":"d603e881.2fa1c8","type":"image","z":"30fb1577.8f556a","name":"","width":160,"data":"payload","dataType":"msg","thumbnail":true,"active":true,"x":960,"y":640,"wires":[]}]

Jimp input image

Apply an image as a Jimp object. This node allows Jimp images to be previewed, which are send by other Jimp related nodes. The following example shows a Jimp image, generated by the node-red-contrib-image-tools nodes:

Jimp flow

Note: the node-red-contrib-image-tools node should be installed, prior to importing this example.

[{"id":"27719e17.2169f2","type":"jimp-image","z":"30fb1577.8f556a","name":"","data":"payload","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","parameterCount":0,"jimpFunction":"none","selectedJimpFunction":{"name":"none","fn":"none","description":"Just loads the image.","parameters":[]},"x":770,"y":640,"wires":[["d603e881.2fa1c8"]]},{"id":"46ffc819.b736f8","type":"http request","z":"30fb1577.8f556a","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"https://dummyimage.com/200x150/000/fff&text={{{payload}}}","tls":"","persist":false,"proxy":"","authType":"","x":610,"y":640,"wires":[["27719e17.2169f2"]]},{"id":"25d928c1.708098","type":"inject","z":"30fb1577.8f556a","name":"Generate next image","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":200,"y":640,"wires":[["878f8ec1.effe4"]]},{"id":"878f8ec1.effe4","type":"function","z":"30fb1577.8f556a","name":"image counter","func":"var count = flow.get(\"count\")||0;\n\ncount++;\n\nnode.status({fill:\"blue\",shape:\"ring\",text:\"Image \" + count});\n\n// Save the new value back to context so it will be available next time\nflow.set('count',count);\n\n// Update the message payload and return - no need to create a new msg\nmsg.payload = \"Image \" + count;\nreturn msg;","outputs":1,"noerr":0,"x":420,"y":640,"wires":[["46ffc819.b736f8"]]},{"id":"d603e881.2fa1c8","type":"image","z":"30fb1577.8f556a","name":"","width":160,"data":"payload","dataType":"msg","thumbnail":true,"active":true,"x":960,"y":640,"wires":[]}]

Hide image

When the node is currently displaying an image, that image can be hidden via those values:

  1. A null image (e.g. msg.payload = null).
  2. No image (e.g. delete msg.payload).
  3. An empty string image (e.g. msg.payload = "").

The following demo hides the previewed image based on the msg.payload:

hide image

[{"id":"acae4788.db10e8","type":"http request","z":"e2675d9d.6854e","name":"","method":"GET","ret":"bin","paytoqs":false,"url":"https://dummyimage.com/200x150/000/fff&text={{{payload}}}.jpg","tls":"","persist":false,"proxy":"","authType":"","x":570,"y":360,"wires":[["b548876a.e2f8b8"]]},{"id":"8ff5f74b.d2efb8","type":"inject","z":"e2675d9d.6854e","name":"Generate next image","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":200,"y":360,"wires":[["ea222193.08df9"]]},{"id":"ea222193.08df9","type":"function","z":"e2675d9d.6854e","name":"image counter","func":"var count = flow.get(\"count\")||0;\n\ncount++;\n\nnode.status({fill:\"blue\",shape:\"ring\",text:\"Image \" + count});\n\n// Save the new value back to context so it will be available next time\nflow.set('count',count);\n\n// Update the message payload and return - no need to create a new msg\nmsg.payload = \"Image \" + count;\nreturn msg;","outputs":1,"noerr":0,"x":400,"y":360,"wires":[["acae4788.db10e8"]]},{"id":"670b37d4.e67658","type":"inject","z":"e2675d9d.6854e","name":"Msg without payload","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":470,"y":260,"wires":[["6d9c5aa.2d5e6a4"]]},{"id":"b548876a.e2f8b8","type":"base64","z":"e2675d9d.6854e","name":"","action":"","property":"payload","x":720,"y":360,"wires":[["f8d56b3b.3bb1f8"]]},{"id":"6d9c5aa.2d5e6a4","type":"change","z":"e2675d9d.6854e","name":"","rules":[{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":260,"wires":[["f8d56b3b.3bb1f8"]]},{"id":"636d9da2.959fb4","type":"inject","z":"e2675d9d.6854e","name":"Msg with empty string","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":460,"y":300,"wires":[["6dce2d91.6158f4"]]},{"id":"c6c47147.1972a","type":"inject","z":"e2675d9d.6854e","name":"Msg with null value","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":470,"y":220,"wires":[["d21096f2.632ed8"]]},{"id":"6dce2d91.6158f4","type":"change","z":"e2675d9d.6854e","name":"msg.payload = \"\"","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":690,"y":300,"wires":[["f8d56b3b.3bb1f8"]]},{"id":"d21096f2.632ed8","type":"function","z":"e2675d9d.6854e","name":"msg.payload = null","func":"msg.payload = null;\nreturn msg;","outputs":1,"noerr":0,"x":690,"y":220,"wires":[["f8d56b3b.3bb1f8"]]},{"id":"b99d140c.ce4448","type":"comment","z":"e2675d9d.6854e","name":"Multiple ways to hide the preview image:","info":"","x":520,"y":180,"wires":[]},{"id":"f8d56b3b.3bb1f8","type":"image","z":"e2675d9d.6854e","name":"","width":160,"data":"payload","dataType":"msg","thumbnail":false,"active":true,"x":920,"y":360,"wires":[]}]

Control image stream

Via the button on the right side, the image stream can be stopped or (re)started again:

image_output_deactivate

Remark: the server will stop sending images to the client, so there will be no more data traffic involved!

Node configuration

Width

The width (in pixels) that the image needs to be displayed in the flow. The height will be calculated automatically, with the same aspect ratio as the original image.

Property

Specify how the input image will be delivered to this node. By default the image needs to be delivered in the msg.payload of the input message.

Resize images on server side

By transferring smaller images the bandwith can be reduced, i.e. the number of bytes that is being send across the network. When too much data is pushed (across the websocket), the flow editor can become unresponsive.

  • When this option is activated, the images will be resized (to the specified width) on the server side. Then those small thumbnail images will be send to the browser, to reduce the bandwith.
  • When this option is not activated, the (original) large images will be send to the browser. Once they arrive there, the browser will resize them to the specified width. As a result much more data needs to be transferred between the server and the browser.

Caution: resizing images on the server will require server-side CPU usage. So it has to be decided what is prefered: lower bandwidth or lower cpu usage on the server. This decision will depend on the use case and hardware...

Allow image passthrough

When selected this adds an output wire to the node in order to pass the original message through to a following node. This performs better than forking the wires, however it does remove the enable/disable button.