Grid and Drawing
The drawing system of this tool is built around state management for a 2-dimensional array allocated in JavaScript's internal memory, rather than direct pixel manipulation using a Canvas element on the DOM.
During initialization, the grid size is defined as a square with a resolution specified from 8x8, 16x16, 32x32, or 64x64, and each cell is assigned a null value indicating transparency or a hexadecimal color code string.
When the user presses or drags the left mouse button on the canvas, the relative position of the mouse pointer in the browser's client coordinate system is acquired, and a calculation is performed to convert it into the cell's index coordinates based on the current grid size and the display area width of the container.
For the calculated array index, the state is updated by assigning the currently selected color if using the pen tool, or a null value if using the eraser tool.
Additionally, the eyedropper tool reads the color code stored in the array at the specified coordinates and reassigns it as the active drawing color.
For performance optimization, line segment interpolation processing to fill gaps that occur between mouse pointer movements is not implemented, resulting in a drawing engine that relies on continuous rewriting of single cells depending on event firing timing.
Fill and Symmetrical Drawing
The fill tool employs a 4-neighbor breadth-first search (BFS) algorithm to speed up extensive color changes in pixel art creation.
It retrieves color information from the array index of the clicked starting coordinates and holds it as the target color for replacement.
Then, an exploration queue array is prepared, the starting coordinates are enqueued, and iterative processing begins. Within the loop, coordinates are dequeued, and the cells adjacent in the four directions (up, down, left, right) are referenced.
If the reference target matches the target color for replacement, the array value is overwritten with the newly selected color code, and those coordinates are added to the queue to continue the search.
This process is repeated until all continuous areas of the same color are replaced. In addition, it features a symmetrical drawing system that streamlines pattern creation, allowing users to select one of the following modes: horizontal (left-right symmetry), vertical (up-down symmetry), or four-way symmetry that combines both.
When a drawing event is triggered while a symmetry mode is active, the inverted coordinates based on the grid size are immediately calculated in addition to the original manipulated coordinates, and color assignment processing is executed simultaneously for multiple locations in the internal array.
Frames and Layers
To achieve advanced animation expression, the drawing data is managed by a hierarchical data structure consisting of layers and frames.
Each frame is composed as an array of multiple layer objects with independent states, and each layer holds its own 2-dimensional grid array, a logical flag for visibility, and an opacity property specified in the range of 0 to 1.
The editing screen references the display target layer for each cell and shows the color. Because of the simplified method that displays the topmost color and its layer opacity, the overlapping on the editing screen may not perfectly match the Canvas composition when exporting the image.
In outputs such as PNG, the display target layers are drawn sequentially onto the Canvas and composited. For frame control, list operations are provided to insert new frames into the array or duplicate and delete existing frames.
During preview execution, timer processing runs based on the set 1 to 24 FPS value, playing the animation by sequentially switching the index of the active frame.
Also, to make it easier to check the connection of movements, an onion skin feature is incorporated that displays the composite result of the previous frame as a translucent underlay.
As protection for the editing process, an Undo/Redo function is implemented that deep copies the data of all frames and saves it in a history array every time an operation occurs, allowing you to go back up to 30 previous states and restore the array state.
PNG, GIF, and Sprite Sheets
Three types of approaches are provided for the export function of created graphic works, depending on the intended use. When outputting as a static image, the currently active single frame is rendered on the drawing context and converted into PNG format image data with transparency information using a method.
On the other hand, when outputting the entire animation, encoding processing based on the GIF89a standard is executed on the client-side JavaScript.
All frames are scanned, and their pixel information is extracted as an RGB index array while being converted into binary data using the LZW compression algorithm.
Furthermore, it has a sprite sheet output function that integrates all frames arranged at equal intervals horizontally into a single image, making it an easy format to handle as material for game development.
In this process, the width of an off-screen canvas is expanded based on the number of frames, grid size, and specified output scale, and rendering is performed sequentially while moving each frame along the X-axis, ultimately exporting it as a single PNG image.
These image outputs are intended for publication or use in external software, and editing information such as layer structures is not retained in the exported image data.
JSON Project
This editor does not implement functionality to persist the user's work state using the browser's local storage or IndexedDB, nor does it have an automatic save mechanism.
Therefore, if you close the browser tab or reload the page, the array data of layers and frames held in memory will be lost. To enable continuous editing work within these specifications, a function is provided to manually input and output the entire project state as text in JSON format.
When the export process is executed, the current grid size, FPS settings, custom palette, and 2-dimensional arrays of color information contained in all frames and layers are serialized while maintaining their hierarchical structure, and downloaded as a local file as string data.
When resuming work, loading the saved JSON file and deserializing the text re-expands the array data into memory, restoring the work state at the time of saving, such as layer opacity and frame composition.
Constraints and Production Workflow
Although it has an import function to bring existing image data into the tool and start editing, there are several constraints to adapt it to the internal data structure.
When an image is loaded, it is forcibly transformed to fit the square grid of the specified canvas size, and its RGB and alpha values are analyzed.
During this process, pixels with an alpha value below a certain threshold are treated as transparent, and the rest are converted into opaque color codes, so the original translucent mid-tones and layer information of the PNG file are not carried over.
Even if an animated GIF is loaded as an image, there is no function to expand it as multi-frame editing data. The read result is placed as a single image on the current layer.
Furthermore, as an important specification regarding the GIF export function, the number of colors that can be held in one frame is limited to a maximum of 256 colors.
If an image with many colors is loaded and GIF export is performed while exceeding 256 colors, the color reduction processing to find and assign approximate colors is not executed in the implementation of this tool; instead, the behavior is that all excess colors from the 256th onward are forcibly assigned to the palette color of index number 255.
Therefore, if you intend to output as a GIF animation, a production workflow is required where you place pixels while limiting the number of colors used in advance.
For PNG and sprite sheets, you can specify the output scale, but GIFs are exported at the original size of the selected grid. It is appropriate to operate by saving JSON during production and outputting images for specific uses when completed.
Additionally, because drawing operations are centered around mouse events, detailed production using only touch devices is not guaranteed.
Adjusting the aspect ratio and transparency before loading the image, and reducing the number of colors for GIFs, will make it easier to avoid unintended deformations and color replacements.