Beispiel #1
0
        /// <summary>
        ///     Creates a new <see cref="AsepriteHeader"/> instance.
        /// </summary>
        /// <param name="reader">
        ///     The <see cref="AsepriteReader"/> instance being used to read the
        ///     Aseprite file.
        /// </param>
        internal AsepriteHeader(AsepriteReader reader)
        {
            //  Get the basestream position of the reader
            long headerStart = reader.BaseStream.Position;

            //  Header is 128 bytes. Calcualte the base stream position that is
            //  at the end of the header
            long headerEnd = headerStart + 128;

            //  Read but ignore the file size
            _ = reader.ReadDWORD();

            //  Read and validate the magic number
            if (reader.ReadWORD() != 0xA5E0)
            {
                throw new Exception($"File given does not appear to be a valid .ase/.aseprite file!");
            }

            FrameCount = reader.ReadWORD();
            Width      = reader.ReadWORD();
            Height     = reader.ReadWORD();
            ColorDepth = (AsepriteColorDepth)(reader.ReadWORD() / 8);
            _flags     = (AsepriteHeaderFlags)reader.ReadDWORD();

            //  Per ase file specs, the speed field is deprecated, so we'll
            //  ignroe it.
            _ = reader.ReadWORD();

            //  Per ase file specs, next two DWORDs are ignored.
            _ = reader.ReadDWORD();
            _ = reader.ReadDWORD();

            TransparentIndex = reader.ReadByte();

            //  Per ase file specs, next 3 bytes are ignored
            reader.Ignore(3);

            ColorCount = reader.ReadWORD();

            //  We're going to ignore the rest of the header as we don't need
            //  the information. For documentation though, the following is
            //  what we are skipping
            //
            //  Pixel Width
            //  Pixel Height
            //  X position of the grid
            //  Y position of the grid
            //  Grid width (zero if there is no grid, grid size is 16x16 on Aseprite default)
            //  Grid height (zero if there is no grid
            //  84 bytes which are reserved for future use.
            //
            //  Since we are skipping all this, we'll just set the reader's basestream to
            //  the end of the header position we calculated earlier
            reader.BaseStream.Position = headerEnd;
        }
        /// <summary>
        ///     Creates a new <see cref="AsepriteSliceChunk"/> instance.
        /// </summary>
        /// <param name="reader">
        ///     The <see cref="AsepriteReader"/> instance being used to read the
        ///     Aseprite file.
        /// </param>
        internal AsepriteSliceChunk(AsepriteReader reader)
        {
            TotalKeys = (int)reader.ReadDWORD();
            Flags     = (AsepriteSliceFlags)reader.ReadDWORD();

            //  Per ase file spec, ignore the next DWORD, it's "reserved"
            _ = reader.ReadDWORD();

            Name = reader.ReadString();

            Keys = new AsepriteSliceKey[TotalKeys];
            for (int i = 0; i < TotalKeys; i++)
            {
                Keys[i] = new AsepriteSliceKey(reader, Flags);
            }
        }
Beispiel #3
0
        private void ReadAsNewPalette(AsepriteReader reader)
        {
            //  Read the size value
            int size = (int)reader.ReadDWORD();

            //  Read the first index value.
            int firstIndex = (int)reader.ReadDWORD();

            //  Read the last index value.
            int lastIndex = (int)reader.ReadDWORD();

            //  Per ase file spec, ignore next 8 bytes, they are reserved for future use
            reader.Ignore(8);

            Colors = new AsepritePaletteColor[size];
            for (int i = 0; i < lastIndex - firstIndex + 1; i++)
            {
                Colors[i] = new AsepritePaletteColor(reader, true);
            }
        }
Beispiel #4
0
        /// <summary>
        ///     Creates a new <see cref="AsepriteSliceKey"/> instance.
        /// </summary>
        /// <param name="reader">
        ///     The <see cref="AsepriteReader"/> instance being used to read the
        ///     Aseprite file.
        /// </param>
        /// <param name="flags">
        ///     The <see cref="AsepriteSliceFlags"/> value of the slice this
        ///     slice key belongs to.
        /// </param>
        internal AsepriteSliceKey(AsepriteReader reader, AsepriteSliceFlags flags)
        {
            Frame  = (int)reader.ReadDWORD();
            X      = reader.ReadLONG();
            Y      = reader.ReadLONG();
            Width  = (int)reader.ReadDWORD();
            Height = (int)reader.ReadDWORD();

            if ((flags & AsepriteSliceFlags.HasNinePatch) != 0)
            {
                CenterX = reader.ReadLONG();
                CenterY = reader.ReadLONG();
                Width   = (int)reader.ReadDWORD();
                Height  = (int)reader.ReadDWORD();
            }

            if ((flags & AsepriteSliceFlags.HasPivot) != 0)
            {
                PivotX = reader.ReadLONG();
                PivotY = reader.ReadLONG();
            }
        }
Beispiel #5
0
        /// <summary>
        ///     Reads the userdata values for this chunk from the provided
        ///     reader.
        /// </summary>
        /// <param name="reader">
        ///     The <see cref="AsepriteReader"/> instance being used to read the
        ///     Aseprite file.
        /// </param>
        internal void ReadUserData(AsepriteReader reader)
        {
            AsepriteUserDataFlags flags = (AsepriteUserDataFlags)reader.ReadDWORD();

            if ((flags & AsepriteUserDataFlags.HasText) != 0)
            {
                UserDataText = reader.ReadString();
            }

            if ((flags & AsepriteUserDataFlags.HasColor) != 0)
            {
                UserDataColor    = new byte[4];
                UserDataColor[0] = reader.ReadByte();
                UserDataColor[1] = reader.ReadByte();
                UserDataColor[2] = reader.ReadByte();
                UserDataColor[3] = reader.ReadByte();
            }
        }
        /// <summary>
        ///     Creates a new <see cref="AsepriteFrame"/> instance.
        /// </summary>
        /// <param name="file">
        ///     The <see cref="AsepriteDocument"/> instance this frame belongs to.
        /// </param>
        /// <param name="reader">
        ///     The <see cref="AsepriteReader"/> instance being used to read the
        ///     Aseprite file.
        /// </param>
        internal AsepriteFrame(AsepriteDocument file, AsepriteReader reader)
        {
            Cels = new List <AsepriteCelChunk>();

            File = file;

            //  Ignore the total bytes in frame value, we don't need it
            _ = reader.ReadDWORD();

            //  Read and validate the magic number
            if (reader.ReadWORD() != 0xF1FA)
            {
                throw new Exception($"Invalid frame header, please ensure the .ase/.aseprite file is valid");
            }

            //  The next field contains the chunk count, but this is the old chunk count field
            int oldChunkCount = reader.ReadWORD();

            //  Aseprite stores the frame duration value as milliseconds
            Duration = reader.ReadWORD();

            //  Per ase file spec, the next two bytes are reserved for future use
            reader.Ignore(2);

            //  This field contains the chunk count, but is the new chunk count field.
            uint newChunkCount = reader.ReadDWORD();

            //  Per ase file spec, if the new chunk count filed is 0, then we use the old field
            //  value instad.
            int totalChunks = newChunkCount == 0 ? oldChunkCount : (int)newChunkCount;

            //  A value indicating if the new palette chunk was found. When it is found
            //  then we can skip reading the old palette chunk.
            bool newPaletteChunkFound = false;

            for (int i = 0; i < totalChunks; i++)
            {
                long chunkStart = reader.BaseStream.Position;
                uint chunkSize  = reader.ReadDWORD();
                long chunkEnd   = chunkStart + chunkSize;

                AsepriteChunkType chunkType = (AsepriteChunkType)reader.ReadWORD();
                System.Diagnostics.Debug.WriteLine($"Chunk Type: {chunkType}");

                switch (chunkType)
                {
                case AsepriteChunkType.Layer:
                    ReadLayerChunk(reader);
                    break;

                case AsepriteChunkType.Cel:
                    ReadCelChunk(reader, (int)chunkSize - 6);
                    break;

                case AsepriteChunkType.Tags:
                    ReadTagChunk(reader);
                    break;

                case AsepriteChunkType.OldPaletteA:
                    if (newPaletteChunkFound)
                    {
                        reader.BaseStream.Position = chunkEnd;
                    }
                    else
                    {
                        ReadOldPalleteAChunk(reader);
                    }
                    break;

                case AsepriteChunkType.Palette:
                    ReadPaletteChunk(reader);
                    newPaletteChunkFound = true;
                    break;

                case AsepriteChunkType.UserData:
                    ReadUserDataChunk(reader);
                    break;

                case AsepriteChunkType.Slice:
                    ReadSliceChunk(reader);
                    break;

                case AsepriteChunkType.OldPaletteB:         //  Ignore
                case AsepriteChunkType.CelExtra:            //  Ignore
                case AsepriteChunkType.ColorProfile:        //  Ignore
                case AsepriteChunkType.Mask:                //  Ignore
                case AsepriteChunkType.Path:                //  Ignore
                    //  Since we are ignoreing these chunk types, we need to ensure that the
                    //  reader's basestream position is set to where the end of the ignored
                    //  chunk would be.
                    reader.BaseStream.Position = chunkEnd;
                    break;

                default:
                    throw new Exception("Invalid chunk type detected");
                }
            }
        }