When you’re developing an Android mobile application, it is critical that you come up with a nice launcher icon for all possible Android screen densities. If you’re not too familiar with Android, there are mdpi, hdpi, xhdpi, xxhdpi, and xxxhdpi densities as of now. This number could change in the future.

Once you’ve got your icon, resampling or resizing it for each possible screen density can become a pain in the butt. Instead, it makes sense to use or create a script for this.

We’re going to see how to create a RESTful API that accepts an image and generates various sizes of that same image, bundled within a ZIP archive. We’re going to accomplish this task with Node.js and Express.

Create a New Node.js Project

To be successful with this project, it will help to start fresh. With Node.js installed, execute the following from somewhere on your computer:

The above commands will initialize a new project with a package.json file, install our dependencies, and create an app.js file to hold our logic. If you don’t have the touch command, create the file however you see fit.

Before we start development, let’s have another look at those dependencies. We’ll be serving an API, hence the express package. To receive POST bodies, we’ll need the body-parser package. To receive files, we’ll need the multer package. More information on receiving files in an Express based project can be found in an article I wrote titled, Upload Files to a Minio Object Storage Cloud with Node.js and Multer.

The jimp package will allow us to do image manipulations with JavaScript and the node-zip package will allow us to create ZIP archives. Since everything we do is asynchronous, we’ll need the help of the bluebird package to turn things into promises and monitor them.

Including the Application Logic for Jimp, Bluebird, and File Archiving

With the project created, let’s dive into some code. It makes sense to add our boilerplate code for bootstrapping our API before we worry ourselves with the heavy lifting of image manipulations.

In the above code we’ve imported each of our downloaded dependencies. Not every method in Jimp uses promises, but instead callbacks. It is very important for this example that we use promises which is why we’re wrapping Jimp with Bluebird.

We’re specifying that we’re accepting files up to 4MB in size and the FormData key must be uploads. All uploads will be held in memory, not saved to the filesystem.

Notice that we’re populating an array with each image related operation. Each operation sizes the image differently and outputs a buffer. The buffer alone isn’t useful to use which is why we have a chained promise that includes the buffer as well as the image size that the buffer represents.

With the array of executing promises, we can monitor them with the following:

The code is quite long, but honestly it is very repetitive. Remember, we’re only accepting an image from the client, reading the image file and resizing it five times, then creating an archive after all image manipulations have completed.

Testing the RESTful API with cURL

With the single endpoint API created, we can make an attempt at processing our image for Android compatibility. To be successful in testing, we probably want to use cURL rather than a utility like Postman because we intend to download data rather than display it.

Before we try to test the code, let’s first run it. From the command line, execute the following:

The above command will issue a multi-part form HTTP request to our endpoint. By using >> we’re saying we want to save the response to a file. The [email protected]/myimage.jpg is the local file we wish to send, hence the @ symbol.

Try to extract the ZIP archive that was downloaded. The content should include numerous directories with files of varying sizes.

Conclusion

You just saw how to create a RESTful API that manipulates images and returns them to the client in the form of a ZIP archive. This particular example created Android launcher icons from some main icon, but it could be expanded into many other things. Node.js with Express and Jimp are very powerful when it comes to web applications and image processing.

Want to upload the files with Angular rather than cURL. Check out a previous article I wrote on the topic.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.