Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/thecyberronin/ase-parser
Parse Aseprite files with Node.js, no external dependencies
https://github.com/thecyberronin/ase-parser
aseprite nodejs
Last synced: 2 months ago
JSON representation
Parse Aseprite files with Node.js, no external dependencies
- Host: GitHub
- URL: https://github.com/thecyberronin/ase-parser
- Owner: TheCyberRonin
- License: mit
- Created: 2019-09-04T02:41:04.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-10-09T00:35:24.000Z (about 1 year ago)
- Last Synced: 2024-10-27T21:33:31.203Z (2 months ago)
- Topics: aseprite, nodejs
- Language: JavaScript
- Homepage:
- Size: 40 KB
- Stars: 20
- Watchers: 2
- Forks: 6
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[![npm](https://img.shields.io/npm/v/ase-parser.svg)](https://www.npmjs.com/package/ase-parser)
[![npm](https://img.shields.io/npm/dt/ase-parser.svg?maxAge=3600)](https://www.npmjs.com/package/ase-parser)
[![install size](https://packagephobia.now.sh/badge?p=ase-parser)](https://packagephobia.now.sh/result?p=ase-parser)# ase-parser
Parse Aseprite files with Node.js, no external dependencies.### Install
To install for use:
```
npm i ase-parse
```## Instructions
You'll probably want to get the Buffer of the Aseprite file in whatever way you feel like. For the example, we'll just use `fs.readFileSync()`. But you can get it from a network request, etc.```js
const Aseprite = require('ase-parser');
const fs = require('fs');const buff = fs.readFileSync('./somefile.aseprite');
const aseFile = new Aseprite(buff, 'somefile.aseprite');aseFile.parse();
console.log(aseFile.numFrames);
```After parsing, you can get the data and do something like generate an image with the [`sharp`](https://www.npmjs.com/package/sharp) npm lib, which accepts raw pixel data and supports image composition.
Here is a more advanced example generating a `png` image of the first frame using the [`sharp`](https://www.npmjs.com/package/sharp) lib.
```js
const Aseprite = require('ase-parser');
const fs = require('fs');
const sharp = require('sharp');async function makePNG() {
const buff = fs.readFileSync('./my_chocobo.aseprite');
const ase = new Aseprite(buff, 'my_chocobo.aseprite');
ase.parse();
// Create a blank png image buffer that's the same size as the Aseprite sprite (only make the promise because we'll use Promise.all a little later)
const bgPromise = sharp({create: {
width: ase.width,
height: ase.height,
channels: 4,
background: {r: 0, g: 0, b: 0, alpha: 0}
}}).png().toBuffer();
// Get the cels for the first frame
const cels = ase.frames[0].cels
// copy the array
.map(a => a)
.sort((a, b) => {
const orderA = a.layerIndex + a.zIndex;
const orderB = b.layerIndex + b.zIndex;
// sort by order, then by zIndex
return orderA - orderB || a.zIndex - b.zIndex;
})
// Create png image buffers per cel to create an image of the first frame (creating the Promises to be used)
const otherPromises = cels.map(cel => {
return sharp(cel.rawCelData, {raw: {width: cel.w, height: cel.h, channels: 4}}).png().toBuffer();
});
// Run the promises all at once to get the buffers for the base image and the cels to combine
const [ bg, ...others ] = await Promise.all([bgPromise, ...otherPromises]).catch(console.log);
// take the first image and add on the png buffers on top of it (the cels should be in order from bottom to top from the parse)
const finalBuff = await sharp(bg)
.composite(others.map((img, index) => ({
input: img,
top: cels[index].ypos,
left: cels[index].xpos
})))
.png()
.toBuffer();
// saves the file as a png with the buffer from sharp.composite
fs.writeFileSync(ase.name.replace('.aseprite', '.png'), finalBuff);
}makePNG();
```
## Aseprite Functions
### `constructor`
Parameters:
* `buffer`: Expects a Node.js Buffer of the `Aseprite` file.
* `name`: Expects a string that's the name of the `Aseprite` file, including the extension.Returns:
* `Aseprite`: Returns [Aseprite](#aseprite-object).Example:
```js
const Aseprite = require('ase-parser');
const fs = require('fs');const buff = fs.readFileSync('./somefile.aseprite');
const aseFile = new Aseprite(buff, 'somefile.aseprite');
```### `parse`
Description:
Parses the Aseprite file and populates the `Aseprite` class with the information from the file.Parameters:
* noneReturns:
* noneExample:
```js
const Aseprite = require('ase-parser');
const fs = require('fs');const buff = fs.readFileSync('./somefile.aseprite');
const aseFile = new Aseprite(buff, 'somefile.aseprite');aseFile.parse();
```## Aseprite Object
| Field | Type | Description |
|--------------|------------------------|----------------------------------------|
| frames | array of [frame](#frame-object) objects | frames |
| layers | array of [layer](#layer-object) objects | layers |
| fileSize | integer | size of the file (in bytes) |
| numFrames | integer | number of frames the Aseprite file has |
| width | integer | width (in pixels) |
| height | integer | height (in pixels) |
| colorDepth | integer | color depth (in bits per pixel) |
| paletteIndex | integer | position of the indexed color based on the palette |
| numColors | integer | number of colors |
| pixelRatio | string | width:height |
| name | string | name of the file |
| tags | arry of [tag](#tag-object) objects | tags |
| colorProfile | [colorProfile](#color-profile-object) object | Color profile |
| palette | [palette](#palette-object) object | Palette |
| tilesets | array of [tileset](#tileset-object) objects | Tileset |
| slices | array of [slice](#slice-object) objects | Info on slices |## Frame Object
| Field | Type | Description |
|---------------|-----------------------|------------------|
| bytesInFrame | integer | size (in bytes) |
| frameDuration | integer | duration (in ms) |
| cels | array of [cel](#cel-object) objects | cels |## Layer Object
| Field | Type | Description |
|-----------------|---------|-------------------------------|
| flags | [layer flags](#layer-flags-object) | flags for the layer translated into a map |
| type | integer | type |
| layerChildLevel | integer | layer child level |
| opacity | integer | opacity (0-255) |
| tilesetIndex? | integer | the tileset id, if applicable |
| name | string | name of layer |## Tag Object
| Field | Type | Description |
|---------------|---------|----------------------------------------|
| from | integer | first frame index |
| to | integer | last frame index |
| animDirection | string | `Forward`, `Reverse`, `Ping-pong` or `Ping-pong Reverse` |
| repeat | integer | repeat animation N times |
| color | string | hex color of the tag (no `#` included) |
| name | string | name |## Color Profile Object
| Field | Type | Description |
|--------|---------|-------------------------|
| type | string | `None`, `sRGB` or `ICC` |
| flag | integer | fixed gamma flag |
| fGamma | integer | fixed gamma |
| icc? | buffer | ICC profile data |## Palette Object
| Field | Type | Description |
|-------------|------------------------|--------------------------|
| paletteSize | integer | number of colors |
| firstColor | integer | index of the first color |
| lastColor | integer | index of the last color |
| colors | array of [color](#color-object) objects | colors |
| index? | integer | position of the indexed color based on the palette |## Tileset Object
| Field | Type | Description |
|-----------------|------------------------|----------------------------|
| id | integer | tileset id number |
| tileCount | integer | number of tiles |
| tileWidth | integer | pixel width of each tile |
| tileHeight | integer | pixel height ofeach tile |
| name | string | name |
| externalFile? | [tileset external file](#tileset-external-file-object) object | external file linkage info, if applicable |
| rawTilesetData? | Buffer | raw pixel data for tiles, if applicable |## Tileset External File Object
| Field | Type | Description |
|-----------|---------|-------------------------------------------|
| id | integer | id of the external file |
| tilesetId | integer | id of the tileset in the external file |## Cel Object
| Field | Type | Description |
|------------------|---------|----------------------------------------------|
| layerIndex | integer | index of the layer associated |
| xpos | integer | x position of the cel compared to the sprite |
| ypos | integer | y position of the cel compared to the sprite |
| opacity | integer | opacity (0-255) |
| celType | integer | internally used |
| zIndex | integer | show this cel N layers later/back |
| w | integer | width (in pixels) |
| h | integer | height (in pixels) |
| tilemapMetadata? | [tilemap metadata](#tileset-external-file-object) object | tilemap metadata, if applicable |
| rawCelData | Buffer | raw cel pixel data |## Tilemap Metadata Object
| Field | Type | Description |
|------------------------|---------|---------------------------------------------------------|
| bitsPerTile | integer | number of bits used to represent each tile (usually 32) |
| bitmaskForTileId | integer | which bit(s) represent the tile ID |
| bitmaskForXFlip | integer | which bit(s) indicate X-axis flip |
| bitmaskForYFlip | integer | which bit(s) indicate Y-axis flip |
| bitmaskFor90CWRotation | integer | which bit(s) indicate 90-degree clockwise rotation flip |## Color Object
| Field | Type | Description |
|-------|---------|-----------------------------------------------|
| red | integer | red value (0-255) |
| green | integer | green value (0-255) |
| blue | integer | blue value (0-255) |
| alpha | integer | alpha value (0-255) |
| name | string | 'none' or the actual color name if it has one |## Slice Object
| Field | Type | Description |
|-------|---------|-----------------------|
| flags | integer | Flags set |
| keys | array of [SliceKey](#slicekey-object) objects | Array of keys and their values |
| name | string | Name of the slice |## SliceKey Object
| Field | Type | Description |
|-------|---------|-------------------|
| frameNumber | integer | Frame number that the slice is from |
| x | integer | X position of the slice |
| y | integer | Y position of the slice |
| width | integer | Width of the slice |
| height | integer | Height of the slice |
| patch? | [patch](#patch-object) object | Patch info on the slice |
| pivot? | [pivot](#pivot-object) object | Pivot info on the slice |## Patch Object
| Field | Type | Description |
|-------|---------|-------------------|
| x | integer | X postion of the patch |
| y | integer | Y position of the patch |
| width | integer | Width of the patch |
| height | integer | Height of the patch |## Pivot Object
| Field | Type | Description |
|-------|---------|-----------------|
| x | integer | X position of the pivot |
| y | integer | Y position of the pivot |## Layer Flags Object
This object is a utility object that will have ***ALL*** fields present. If a field is "on" it will be `true`, if the field is "off" it will be `false`.
| Field | Description |
|-------|---------|
| visible | Whether or not the layer is visible |
| editable | Whether or not the layer is editable |
| lockMovement | Whether or not the layer is a background layer |
| preferLinkedCels | Whether or not the layer prefers linked cels |
| collapsedGroup | Whether or not the layer group should be displayed collapsed |
| reference | Whether or not the layer is a reference layer |# Further Info
If you would like to read up on the Aseprite file spec: [Spec](https://github.com/aseprite/aseprite/blob/master/docs/ase-file-specs.md)