> This article is also available in HTML at: http://www.vincentbruijn.nl/articles/node-gd/
> For a full index of articles, see: http://www.vincentbruijn.nl/llms.txt

# NodeJS image processing with node-gd

- **Date**: 2020-02-12
- **Author**: Vincent Bruijn
- **Description**: A history of JavaScript image manipulation module node-gd
- **Keywords**: node-gd, libgd2, graphics, nodejs

---

Since a couple of years, I am the maintainer of the NodeJS library called `node-gd`, which are JavaScript bindings for NodeJS to the [libgd](https://libgd.github.io/) graphics library. During the past years, many major changes have taken place in the code base of `node-gd` to keep it up to date with the pace of JavaScript evolution. In this article I will go deeper into the technical changes that I implemented in the past years. It is not an explanation of how `node-gd` works or what you can do with it. For that I would suggest to directly visit its [documentation page](https://y-a-v-a.github.io/node-gd/)

<firgure>

![Probably Monet](tumblr_loswho3cTt1qddwwlo1_500.jpg 'jpeg compression 0')

</figure>


Somewhere in June 2014, I was working on a hobby project in which I wanted to manipulate JPEG images via code. I used to use PHP for these kind of projects mostly, but with the rise of serverside JavaScript, I also wanted to use JavaScript for this purpose. This way, I thought, I would learn more about serverside JavaScript, especially NodeJS and the Express web-framework. At the time there were some other image manipulation libraries for NodeJS but, as far as I recall, they either did not fulfill my wishes or were just too hard to get installed. Besides, I was aquainted with PHP's image processing functions, like [imagecreatefromjpeg](https://www.php.net/manual/en/function.imagecreatefromjpeg.php) and the others of the `GD` API.

### LibGD

LibGD, not necessarily related to PHP, is a library written in C for creating and manipulating different kinds of images. The library exists already quite a while: the earliest copyright notice I could find in the code dates back to 1994. Within PHP, the earliest changelog message I could find with regard to libgd dates back to PHP [version 4.3.0](https://www.php.net/ChangeLog-4.php) stating:

<blockquote>
Bundled GD library 2.0.1 with php (ext/gd/libgd) (Rasmus, Jani, Markus, Edin)
</blockquote>

In the years I was writing PHP mostly, around 2008-2010, I had also written some hobby projects with the GD functions, so I knew quite well what was possible with it. One of these projects being [Maleglitch](http://www.maleglitch.net), which partly consists of a PHP script that does a trial-and-error bending of image data. The code injects arbitrary strings into Jpeg image data multiple times, with the purpose of getting a nice glitched end result.

<figure>

![Maleglitch Website](maleglitch.net_.png 'Maleglitch glitch • www.maleglitch.net')

</figure>

### node-gd

The origins of `node-gd` lay with [Taegon Kim](https://taegon.kim/), who started to develop `node-gd` in 2010. That means that at the time I got involved, it existed for about 4 years already. Taegon Kim wrote the initial C++ code that worked with the NodeJS 0.4.8 add on API. And indeed, it's C++ code that makes the binding between JavaScript and LibGD. This early version contains only a few functions available in libgd, the main functions for opening different types of images. By the time others got involved, the API of `node-gd` was extended with more and more functions which are available in libgd, for example functions to apply filters to images.

What I like about libgd, apart from the API that I already knew, was the extremes to which for example JPEG lossy compression could be bent. When saving a JPEG file via libgd with a compression level of zero (losing most image data), you will get a cubist-like image consisting of large pixel blocks of faint colors.

<blockquote>
Saving an image with JPEG compression 0, you will get a cubist-like image consisting of large pixel blocks of faint colors.
</blockquote>

### NAN

When I took the maintainance of `node-gd` upon me, I first fixed that it was able to build on MacOS. Intrigued by C++, I set off to see whether I was able to implement [NAN](https://github.com/nodejs/nan), the "Native Abstractions for Node.js". I have no experience and no schooling in C++, so all I did was set up the build tools, dig into NAN's github page and documentation, modify some code, build it, and analyze what happened. It took me a while, but at some point I got the hang of how NAN, v8 and libgd could work together (more or less).

More than half a year after getting `node-gd` to work on MacOS, I did my first commit for the port to using NAN. After getting the hang of it, I decided to expose more of the libgd API via `node-gd`. Also, since one of the earlier maintainers had added tests, I decided to add more tests. After that, I ditched a dependency on CoffeeScript because I wanted to have it depend on as few packages as possible.

Time passed, in which I did some additional private projects with `node-gd` and I kept maintaining the package. Not many changes were needed, nor were many issues opened or bugs found. This does not mean that `node-gd` is production ready, my C++ skills are not advanced enough in order for me to ensure all code works according best practices. I did invest additional spare time in extending the documentation: I read the libgd code to understand how certain things work and tried to add as many code examples as possible.

### N-API

Last year I noticed v8 had evolved, just like NAN, and deprecation warnings were thrown during build time. I considered it the right moment to fix these issues. The I came to know about the [Native Addons API](https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html), in short N-API, available in NodeJS since verison 6.x.x. And since I was up to something new, I decided to see if I could port `node-gd` to use N-API instead of NAN. But of course, via trial and error, I had not been working with C++ for a while. After a couple of evenings cursing, searching and writing, I had a base version of `node-gd` running with N-API ready! Wow, that went faster than I had expected.

I made major changes to the code base, not only did I move to N-API, I also:

- Added about 40 additional tests
- Simplified the JavaScript bridge between the bindings and the package's API
- Fixed multiple issues that caused NodeJS to exit due to uncaught exceptions in the C++ code
- Extended the test coverage from NodeJS version 6 up to 12
- Simplified the creation of Animated GIFs
- Added about 20 async operations using the AsyncWorker API
- Let all async tasks return Promises
- Added extra checks to reduce errors thrown after image destroy
- Aligned the directory structure with NPMs preferred layout

These changes lead me to decide to make a new major release, which became v2.0: `node-gd` is quite future proof again. I hope some developers out there will start using it, although some much more actively maintained image manipulation packages are currently available for NodeJS too. Feel free to give `node-gd` a try, and do not hesitate to open issues on GitHub. I cannot give any guarantee in when those bugs will be fixed, since I do all this in my spare time, but I will do my best.

<firgure>

![Daniel Spoerri](spoerri.jpg 'collage made with node-gd inspired on the works of Daniel Spoerri')

</figure>
