/// .ase & .aseprite file format specs: /// https://github.com/aseprite/aseprite/blob/main/docs/ase-file-specs.md using System; using System.Collections.ObjectModel; using System.IO; using UnityEngine.Assertions; namespace UnityEditor.U2D.Aseprite { /// /// Parsed representation of an Aseprite file. /// Should be disposed after use. /// public class AsepriteFile : IDisposable { /// /// File size in bytes. /// public uint fileSize { get; private set; } /// /// Number of frames in the file. /// public ushort noOfFrames { get; private set; } /// /// Canvas width in pixels. /// public ushort width { get; private set; } /// /// Canvas height in pixels. /// public ushort height { get; private set; } /// /// Color depth (bits per pixel). /// public ushort colorDepth { get; private set; } internal uint flags { get; private set; } /// /// Time per frame in milliseconds. /// public ushort animSpeed { get; private set; } /// /// Palette entry (index) which represent transparent color /// in all non-background layers (only for Indexed sprites). /// public byte alphaPaletteEntry { get; private set; } /// /// Number of colors (0 means 256 for old sprites). /// public ushort noOfColors { get; private set; } /// /// Pixel width (pixel ratio is "pixel width/pixel height"). /// If this or pixel height field is zero, pixel ratio is 1:1. /// public byte pixelWidth { get; private set; } /// /// Pixel height (pixel ratio is "pixel width/pixel height"). /// If this or pixel width field is zero, pixel ratio is 1:1. /// public byte pixelHeight { get; private set; } /// /// X position of the grid. /// public short gridPosX { get; private set; } /// /// Y position of the grid. /// public short gridPosY { get; private set; } /// /// Grid width (zero if there is no grid, grid size is 16x16 on Aseprite by default). /// public ushort gridWidth { get; private set; } /// /// Grid height (zero if there is no grid). /// public ushort gridHeight { get; private set; } /// /// Parsed data of each frame. /// public ReadOnlyCollection frameData => Array.AsReadOnly(m_FrameData); FrameData[] m_FrameData; internal void Read(BinaryReader reader) { fileSize = reader.ReadUInt32(); var misc0 = reader.ReadUInt16(); noOfFrames = reader.ReadUInt16(); width = reader.ReadUInt16(); height = reader.ReadUInt16(); colorDepth = reader.ReadUInt16(); flags = reader.ReadUInt32(); animSpeed = reader.ReadUInt16(); var misc1 = reader.ReadUInt32(); var misc2 = reader.ReadUInt32(); alphaPaletteEntry = reader.ReadByte(); var miscByte0 = reader.ReadByte(); var miscByte1 = reader.ReadByte(); var miscByte2 = reader.ReadByte(); noOfColors = reader.ReadUInt16(); pixelWidth = reader.ReadByte(); pixelHeight = reader.ReadByte(); gridPosX = reader.ReadInt16(); gridPosY = reader.ReadInt16(); gridWidth = reader.ReadUInt16(); gridHeight = reader.ReadUInt16(); Assert.IsTrue(misc0 == 0xA5E0, "Unexpected file content. The file is most likely corrupt."); // Unused 84 bytes for (var i = 0; i < 84; ++i) reader.ReadByte(); m_FrameData = new FrameData[noOfFrames]; } internal void SetFrameData(int index, FrameData data) { if (index < 0 || index >= m_FrameData.Length) return; m_FrameData[index] = data; } public void Dispose() { for (var i = 0; i < m_FrameData.Length; ++i) m_FrameData[i].Dispose(); } } }