I Made A Thing: Pixel Art Creator
Recently I’ve been working on things that I think are cool. Mostly for no reason other than they were interesting at the time. So I’m gonna tell you about those things and how I did it (and if they ever get updated I’ll make a new post about it).
Today’s thing that I made is a simple pixel art gif creation tool.

I came across this idea after observing the art of many indie games, most of which feature a pixel art style. It almost made me want to make my own pixel art! Almost… but I’m not a creative person. But what I can do is program, and somehow this observation inspired me to explore HTML5 canvas by creating a tool to make animated pixel art.
Having never used the canvas API before I wanted to know how it really worked. So I decided to not use any libraries or frameworks for this project.
Getting it to paint on the canvas was one thing. Getting it to paint in squares and in a grid-like fashion was another. Getting it to paint in squares in a grid-like fashion on a grid of varying size was yet another thing. I suck at math so I thought this would take longer than it actually did, but once I figured that out I could move on to something better (math makes me anxious).
The next thing I needed to work on was making the created images animate-able, otherwise this project is nothing and entirely too easy. Well, the solution to this part seemed pretty obvious:
- make an array for the frames
- make a variable to track the working frame
- create a function that would store the image data in the array
Okay, that’s done. Sick.
Lastly I made a function to create a visual representation of the frames and put them in the DOM. I can click on these frames and see the image data for that frame.
Neat!
Now what’s the point of making a pixel art gif creation tool if you can’t make gifs? Well, that’s where Graphics Magick comes in (with the help of the GM Node package). Having already experimented with GM before I already new how to use it… server side. How would I get the image data to the server to process and make a gif? Well, the steps are as follows:
- get image data URL for each frame
- put that image data in an object
- send said object to the server
- convert the image data into binary for each frame
- ask Graphics Magick nicely to turn the binary data into a gif
Then at this point I had the option of either immediately sending the gif back to the client, or store it and send a URL that they can use to access it. I don’t know why I chose the latter… I should probably change it to the former… but, anyway, I went with the latter, which deletes the gif from the server once requested.
Now, at this point I realized that I was really enjoying this project. I did not plan on working on this project much longer than I already have. But here I am… and I got this crazy idea that I should add a selection tool.
Okay, so all I need to do is use the API to move pixels around… right?
Nah.
The canvas API does not have any such method of moving pixels around… uhh… what do I do now?
Well, the only option was obvious… I had to restructure my data. I needed an object to maintain the pixel data so that I could manipulated later.
Here’s what I came up with:

This frame data object would hold the pixel data for every frame. Seems legit. Now that I had data I could work with this selection tool.
I think this would be a good time to explain a bit about how the grid works:
- the canvas is x width and height (canvasWidth = x)
- the grid will be y by y pixels
- the position of the pixel needs to be offset by the position of the mouse: e.g., offsetX = Math.floor( (mouseX / canvasWidth) * x)
- the left of the pixel will be (offsetX / y) * canvasWidth
- a pixel will x / y width and height (height = width = x / y)
- the center of a pixel is pixelWidth / 2 (e.g., centerX)
Okay, that took me a while to explain. I hope I explained it well. Here’s the whole function:

So now that I have this data all I need to do is get the coordinates for the pixels. I wont go into details here but here’s the basic idea: by manipulating the x and y coord numbers (they’re key’d as “centerX” and “centerY” in the object) and recreating the coordinate key in the frame data ([centerX]_[centerY]) I can select all of the pixels in an area, move them around, and reset their position in a frame.
Neat!
Layers. This was a little tough but not as tough as tough as moving pixels. Basically I had to move what I was already doing one level deeper, if that makes sense.
Here’s that frame data I showed before but with layers taken into account:

For this I had to:
- create a variable to maintain the current layer
- create a simple function that gets the current layer
- alter the rest of my code so that references to the frame data also take the layer into account
Aight, coo’.
Okay, this one was the most frustrating. It’s somewhat similar to the selection tool in that I needed to search for pixels but this one was different.
- The first thing I need to do is remember what color pixels I’m replacing. I do this when the user clicks on an existing pixel. If there is no existing pixel, well, essentially “null” is the space we’re filling
- After that’s set I needed to search in 4 directions: up, down, left, and right, and capture those pixels that match the above criteria
- Store a reference to the captured pixels so that hey can’t be searched again
- Repeat steps 1–3 until the program stops capturing pixels
- Draw new pixels in place of the captured pixels
For performance reasons this algorithm should not run if the color of the pixel matches the draw color (the color you choose to draw pixel with). Also I am using a web worker for this operation so it doesn’t block the main thread. Even still it’s a slow operation in it’s current form, but it works without issue.
Dope.
The last thing I’ve added was the ability to swap layers.
This isn’t very deep. It’s basically this:
this:
- layer0: [originally layer 0 data]
- layer1: [originally layer 1 data]
becomes this:
- layer0: [originally layer 1 data]
- layer1: [originally layer 0 data]
Dassit.
Allllllrighty then! That’s the current state of the project. It’s been an interesting project to work on but I’m liking the way it has turned out. If you wanna give it a try you can try it here.
If you wanna say hi my twitter is @PieceDigital, but I don’t post much about web development or anything like that.

Alright, nothing more to see here. Scoot!
