UNPKG

ase-parser

Version:
289 lines (238 loc) 13.1 kB
[![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: * none Returns: * none Example: ```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)