Skip to main content

How to install and use lwip (Light Weight Image Processor) in Windows for Node.js

The image processing is a heavy task to be handled in Javascript, therefore if you want to provide a smooth usage experience in the manipulation and image processing, you will choose lwip among other image processing libraries available for node.js (like jimp, an image processing module written in pure javascript) because lwip uses a native module written in C++, which will make the image processing fast and fluid.

The lwip module provides comprehensive, fast, and simple image processing and manipulation capabilities. There are no external runtime dependencies, which means you don't have to install anything else on your system.

Supported formats

Decoding (reading):

  • JPEG, 1 & 3 channels (grayscale & RGB).
  • PNG, transparency supported.
  • GIF, transparency supported. Animated GIFs can be read, but only the first frame will be retrieved.

Encoding (writing):

  • JPEG, 3 channels (RGB).
  • PNG (lossless), 3 channels (RGB) or 4 channels (RGBA).
  • GIF (no animations)

In this article you'll learn how to install and use the lwip module in your node.js project easily in a couple of minutes.

1. Install node-gyp globally

You'll need node-gyp in order to use the lwip module. Proceed with the installation of node-gyp as a global variable in the node command prompt executing the following command:

npm install -g node-gyp

node-gyp is a cross-platform command-line tool written in Node.js for compiling native addon modules for Node.js. It bundles the gyp project used by the Chromium team and takes away the pain of dealing with the various differences in build platforms.

2. Installing required tools

To work with lwip we'll need the following tools available on the system:

  • Visual C++ Build Environment.
  • Python v2.7.x , the v3.x versions aren't supported by node-gyp.

Option 1: Automatic installation

Execute the following command in the node command prompt (run as Administrator):

npm install --global --production windows-build-tools

This module will install python 2.7 and the Visual Studio C++ compiler. The installation may take a while, however will make the installation process easy for you.

Windows-build-tools setup and python

Option 2: Manual installation

Go to the downloads area in the official python website and download the latest 2.7.x installer and proceed with the installation as you would do with any installer. Do not forget to add python in your environment variable selecting the option in the setup.

Python 2.7 installer windows setup environment variable

In case you have another python version (i.e v3) you can identify which Python version node-gyp uses by setting the '--python' variable:

node-gyp --python /path/to/python2.7

If node-gyp is called by way of npm and you have multiple versions of Python installed, then you can set npm's 'python' config key to the appropriate value:

npm config set python /path/to/executable/python2.7

Now that you have python, we need only the Visual C++ Build Environment. This can be either installed by the Visual C++ Build environment setup here or the installation of Visual Studio 2015 (or modify an existing installation) and select Common Tools for Visual C++ during setup. This also works with the free Community and Express for Desktop editions.

Once the installation of Visual C++ Build environment is completed, execute the following command in the node command prompt to set the visual studio version to 2015 in the configuration:

npm config set msvs_version 2015

And you're ready to go. If the above steps didn't work for you, please visit Microsoft's Node.js Guidelines for Windows for additional tips.

3. Install lwip in the project

Now that we have all the required tools to compile the native module of lwip, we can start to use it, so proceed finally with the installation of the module executing the following command in the node command prompt:

npm install lwip

The download of the module will start, and it will immediately start the build process (which could take a while). To test if we did everything correctly, we are going to manipulate the following image (image.jpg):

Not now please meme code

And a little script to manipulate it using lwip in node.js (index.js):

var lwip = require('lwip');

lwip.open('image.jpg', function(err, image){
    // check err...
    // define a batch of manipulations and save to disk as JPEG:
    image.batch()
    .scale(0.75)          // scale to 75%
    .rotate(45, 'white')  // rotate 45degs clockwise (white fill)
    .writeFile('output.jpg', function(err){
        if(err){
            console.log(err);
        }
    });
});

Save the code in a js file (in this case index.js) and test the script using:

node index.js

The previous script should create an image (ouput.jpg) with the following image:

Not now orientation lwip module

All operations are asynchronous, and processing takes place in a thread pool managed by libuv which is part of NodeJS. This thread pool is separate from the event loop used to process HTTP requests, so use of lwip should not significantly affect the handling of HTTP requests by a web application. The thread pool is however shared with other threaded native modules such as those providing database and filesystem IO.

The default thread pool size of 4 will be appropriate for most applications. However if your application regularly processes many images concurrently and and you wish to take full advantage of a multicore system or prevent heavy image processing work from delaying database or filesystem IO, you may want to increase the size of the thread pool by setting the UV_THREADPOOL_SIZE environmental variable to the NodeJS process, e.g.:

UV_THREADPOOL_SIZE=8 node index.js

4. Use lwip

All operations are done on an image object. An imageobject can be obtained by:

  1. Openning an existing image file or buffer with the open method.
  2. Creating a new image object with the createmethod.
  3. Cloning an existing image object with the image.clone method.
  4. Extracting a sub-image from an existing image object with the image.extract method.

Here you'll find a couple of examples of weird tasks that you can achieve with lwip:

Creating an image

The creation of an image comes in handy when you want to take the image as a canvas in which more images are going to be rendered or modified etc. The third parameter provides the color of the canvas, defaults to transparent.

var lwip = require('lwip');

lwip.create(500, 500, 'yellow', function(err, image){
    image.writeFile('myimage.jpg', function(err){
        if(err){
            console.log(err);
        }
    });
});

The previous snippet will create an image (square) of 500x500px with yellow background.

Exporting an image to base64

You can retrieve the base64 content of an image converting the buffer to a string.

var lwip = require('lwip');

lwip.create(300, 300, 'yellow', function(err, image){
    image.toBuffer('png', function(err,buffer) {
        var base64data = buffer.toString('base64');
        var finalBase64String = 'data:image/png;base64,' + base64data;

        console.log(finalBase64String);
    });
});

Note that the buffer will provide the plain base64 data, so if you want to provide a base64 string that can be shown directly in the browser, you need to add the "inlined format".

Manipulating base64 images

You can manipulate images from base64 format directly in lwip without create a static file. Instead, create a new instance of Buffer with the Base64 data on it (remember to remove the unnecesary data, the buffer expects the plain base64 content or the file will be corrupted).

var lwip = require('lwip');

var base64String = "data:image/jpeg;base64,qweqwe.......";

var encondedImageBuffer = new Buffer(base64String.replace(/^data:image\/(png|gif|jpeg);base64,/,''), 'base64');

lwip.open(encondedImageBuffer, 'jpg', function(err, image){
    // check err...
    // define a batch of manipulations and save to disk as JPEG:
    image.batch().writeFile('myimage.jpg', function(err){
        if(err){
            console.log(err);
        }
    });
});

You can read more examples and the documentation of the library in the official repository or the usage area of the readme file.

Have fun !

Comments

Popular posts from this blog

4 Ways to Communicate Across Browser Tabs in Realtime

1. Local Storage Events You might have already used LocalStorage, which is accessible across Tabs within the same application origin. But do you know that it also supports events? You can use this feature to communicate across Browser Tabs, where other Tabs will receive the event once the storage is updated. For example, let’s say in one Tab, we execute the following JavaScript code. window.localStorage.setItem("loggedIn", "true"); The other Tabs which listen to the event will receive it, as shown below. window.addEventListener('storage', (event) => { if (event.storageArea != localStorage) return; if (event.key === 'loggedIn') { // Do something with event.newValue } }); 2. Broadcast Channel API The Broadcast Channel API allows communication between Tabs, Windows, Frames, Iframes, and  Web Workers . One Tab can create and post to a channel as follows. const channel = new BroadcastChannel('app-data'); channel.postMessage(data); And oth...

Certbot SSL configuration in ubuntu

  Introduction Let’s Encrypt is a Certificate Authority (CA) that provides an easy way to obtain and install free  TLS/SSL certificates , thereby enabling encrypted HTTPS on web servers. It simplifies the process by providing a software client, Certbot, that attempts to automate most (if not all) of the required steps. Currently, the entire process of obtaining and installing a certificate is fully automated on both Apache and Nginx. In this tutorial, you will use Certbot to obtain a free SSL certificate for Apache on Ubuntu 18.04 and set up your certificate to renew automatically. This tutorial will use a separate Apache virtual host file instead of the default configuration file.  We recommend  creating new Apache virtual host files for each domain because it helps to avoid common mistakes and maintains the default files as a fallback configuration. Prerequisites To follow this tutorial, you will need: One Ubuntu 18.04 server set up by following this  initial ...

Working with Node.js streams

  Introduction Streams are one of the major features that most Node.js applications rely on, especially when handling HTTP requests, reading/writing files, and making socket communications. Streams are very predictable since we can always expect data, error, and end events when using streams. This article will teach Node developers how to use streams to efficiently handle large amounts of data. This is a typical real-world challenge faced by Node developers when they have to deal with a large data source, and it may not be feasible to process this data all at once. This article will cover the following topics: Types of streams When to adopt Node.js streams Batching Composing streams in Node.js Transforming data with transform streams Piping streams Error handling Node.js streams Types of streams The following are four main types of streams in Node.js: Readable streams: The readable stream is responsible for reading data from a source file Writable streams: The writable stream is re...