public static UserDataChunk Read(AsepriteStreamReader reader)
        {
            //DWORD Flags
            //  1 = Has text
            //  2 = Has color
            var flag = reader.DWORD();

            //+ If flags have bit 1
            //  STRING Text
            if (reader.FLAG(flag, 1))
            {
                return(new UserDataChunk(reader.STRING()));
            }
            //+If flags have bit 2
            //  BYTE Color Red(0 - 255)
            //  BYTE Color Green(0 - 255)
            //  BYTE Color Blue(0 - 255)
            //  BYTE Color Alpha(0 - 255)
            if (reader.FLAG(flag, 2))
            {
                return(new UserDataChunk(reader.BYTE(), reader.BYTE(), reader.BYTE(), reader.BYTE()));
            }

            return(new UserDataChunk());
        }
Example #2
0
        public static LayerChunk Read(AsepriteStreamReader reader)
        {
            // WORD Flags:
            //               1 = Visible
            //               2 = Editable
            //               4 = Lock movement
            //               8 = Background
            //               16 = Prefer linked cels
            //               32 = The layer group should be displayed collapsed
            //               64 = The layer is a reference layer
            var flags = (LayerFlags)reader.WORD();

            // WORD        Layer type
            //               0 = Normal(image) layer
            //               1 = Group
            var type = (LayerTypes)reader.WORD();
            // WORD Layer child level(see NOTE.1)
            var childLevel = reader.WORD();

            // WORD Default layer width in pixels(ignored)
            reader.WORD();
            // WORD Default layer height in pixels(ignored)
            reader.WORD();
            // WORD Blend mode(always 0 for layer set)
            //                     Normal = 0
            //               Multiply = 1
            //               Screen = 2
            //               Overlay = 3
            //               Darken = 4
            //               Lighten = 5
            //               Color Dodge = 6
            //               Color Burn = 7
            //               Hard Light = 8
            //               Soft Light = 9
            //               Difference = 10
            //               Exclusion = 11
            //               Hue = 12
            //               Saturation = 13
            //               Color = 14
            //               Luminosity = 15
            //               Addition = 16
            //               Subtract = 17
            //               Divide = 18
            var blendMode = (BlendModes)reader.WORD();
            // BYTE Opacity
            var opacity = reader.BYTE();

            //               Note: valid only if file header flags field has bit 1 set
            // BYTE[3]     For future(set to zero)
            reader.BYTES(3);
            // STRING Layer name
            var name = reader.STRING();

            return(new LayerChunk(flags, type, childLevel, blendMode, opacity, name));
        }
Example #3
0
        public static TagsChunk Read(AsepriteStreamReader reader)
        {
            //WORD Number of tags
            var tagCount = reader.WORD();

            //BYTE[8] For future(set to zero)
            reader.BYTES(8);
            //+For each tag
            var tags = new Tag[tagCount];

            for (int i = 0; i < tagCount; i++)
            {
                tags[i] = Tag.Read(reader);
            }

            return(new TagsChunk(tags));
        }
Example #4
0
        public static SliceKey Read(AsepriteStreamReader reader, int flag)
        {
            //   DWORD     Frame number(this slice is valid from
            //             this frame to the end of the animation)
            var frameNumber = reader.DWORD();
            //   LONG Slice X origin coordinate in the sprite
            var xOrigin = reader.LONG();
            //   LONG Slice Y origin coordinate in the sprite
            var yOrigin = reader.LONG();
            //   DWORD Slice width(can be 0 if this slice hidden in the
            //        animation from the given frame)
            var width = reader.DWORD();
            //   DWORD Slice height
            var height = reader.DWORD();

            long centerX = 0;
            long centerY = 0;
            long pivotX  = 0;
            long pivotY  = 0;

            uint centerWidth  = 0;
            uint centerHeight = 0;

            //     + If flags have bit 1
            if (reader.FLAG(flag, 1))
            {
                //         LONG Center X position(relative to slice bounds)
                centerX = reader.LONG();
                //         LONG Center Y position
                centerY = reader.LONG();
                //         DWORD Center width
                centerWidth = reader.DWORD();
                //         DWORD   Center height
                centerHeight = reader.DWORD();
            }
            //     + If flags have bit 2
            if (reader.FLAG(flag, 2))
            {
                //         LONG Pivot X position(relative to the slice origin)
                pivotX = reader.LONG();
                //         LONG Pivot Y position(relative to the slice origin)
                pivotY = reader.LONG();
            }

            return(new SliceKey(frameNumber, xOrigin, yOrigin, width, height, centerX, centerY, centerWidth, centerHeight, pivotX, pivotY));
        }
Example #5
0
        public static CellExtraChunk Read(AsepriteStreamReader reader)
        {
            // DWORD Flags(set to zero)
            //   1 = Precise bounds are set
            var preciesBoundsAreSet = reader.DWORD() == 1;
            // FIXED       Precise X position
            var preciseXPosition = reader.FIXED();
            // FIXED       Precise Y position
            var preciseYPosition = reader.FIXED();
            // FIXED       Width of the cel in the sprite(scaled in real-time)
            var widthOfTheCellInTheSprite = reader.FIXED();
            // FIXED Height of the cel in the sprite
            var heightOfTheCellInTheSprite = reader.FIXED();

            // BYTE[16]    For future use(set to zero)
            reader.BYTES(16);

            return(new CellExtraChunk(preciesBoundsAreSet, preciseXPosition, preciseYPosition, widthOfTheCellInTheSprite, heightOfTheCellInTheSprite));
        }
Example #6
0
        public static PaletteChunk Read(AsepriteStreamReader reader)
        {
            // DWORD New palette size(total number of entries)
            var entryCount = reader.DWORD();
            // DWORD First color index to change
            var from = reader.DWORD();
            // DWORD Last color index to change
            var to = reader.DWORD();

            // BYTE[8]     For future(set to zero)
            reader.BYTES(8);
            // +For each palette entry in [from, to] range(to - from + 1 entries)
            var entries = new PaletteEntry[entryCount];

            for (int i = 0; i < (to - from) + 1; i++)
            {
                entries[i] = PaletteEntry.Read(reader, $"Color {i}");
            }

            return(new PaletteChunk(entries));
        }
Example #7
0
        public static PaletteEntry Read(AsepriteStreamReader reader, string defaultName)
        {
            //   WORD Entry flags:
            //             1 = Has name
            bool hasName = reader.FLAG(reader.WORD(), 1);
            //   BYTE      Red(0 - 255)
            var r = reader.BYTE();
            //   BYTE Green(0 - 255)
            var g = reader.BYTE();
            //   BYTE Blue(0 - 255)
            var b = reader.BYTE();
            //   BYTE Alpha(0 - 255)
            var a = reader.BYTE();
            //   +If has name bit in entry flags
            //     STRING Color name
            var name = hasName
                ? reader.STRING()
                : defaultName;

            return(new PaletteEntry(r, g, b, a, name));
        }
Example #8
0
        public static SliceChunk Read(AsepriteStreamReader reader)
        {
            // DWORD Number of "slice keys"
            var keyCount = reader.DWORD();
            // DWORD Flags
            //               1 = It's a 9-patches slice
            //               2 = Has pivot information
            var flag = reader.DWORD();

            // DWORD Reserved
            reader.DWORD();
            // STRING Name
            var name = reader.STRING();
            // + For each slice key
            var keys = new SliceKey[keyCount];

            for (int i = 0; i < keyCount; i++)
            {
                keys[i] = SliceKey.Read(reader, (int)flag);
            }

            return(new SliceChunk(name, keys));
        }
Example #9
0
        public static Tag Read(AsepriteStreamReader reader)
        {
            //WORD From frame
            var fromFrame = reader.WORD();
            //WORD To frame
            var toFrame = reader.WORD();
            //BYTE Loop animation direction
            //            0 = Forward
            //            1 = Reverse
            //            2 = Ping - pong
            var loopDirection = (LoopDirections)reader.BYTE();

            //BYTE[8]   For future(set to zero)
            reader.BYTES(8);
            //BYTE[3]   RGB values of the tag color
            var color = reader.BYTES(3);

            //BYTE Extra byte(zero)
            reader.BYTE();
            //STRING Tag name
            var name = reader.STRING();

            return(new Tag(fromFrame, toFrame, loopDirection, color, name));
        }
Example #10
0
        public static CellChunk Read(AsepriteStreamReader reader, ColorDepth colorDepth)
        {
            // WORD Layer index(see NOTE.2)
            var layerIndex = reader.WORD();
            // SHORT X position
            var xPosition = reader.SHORT();
            // SHORT       Y position
            var yPosition = reader.SHORT();
            // BYTE Opacity level
            var opacityLevel = reader.BYTE();
            // WORD        Cel type
            var cellType = reader.WORD();

            // BYTE[7]     For future(set to zero)
            reader.BYTES(7);
            // +For cel type = 0(Raw Cel)
            if (cellType == 0)
            {
                //   WORD Width in pixels
                var width = reader.WORD();
                //   WORD Height in pixels
                var height = reader.WORD();
                //   PIXEL[]   Raw pixel data: row by row from top to bottom,
                //             for each scanline read pixels from left to right.
                var depthModifier = 0;
                if (colorDepth == ColorDepth.RGBA)
                {
                    depthModifier = 4;
                }
                else if (colorDepth == ColorDepth.Grayscale)
                {
                    depthModifier = 2;
                }
                else if (colorDepth == ColorDepth.Indexed)
                {
                    depthModifier = 1;
                }

                var pixels = reader.BYTES(width * height * depthModifier);

                return(new CellChunk(layerIndex, xPosition, yPosition, opacityLevel, cellType,
                                     width, height, pixels));
            }
            // + For cel type = 1(Linked Cel)
            else if (cellType == 1)
            {
                //   WORD      Frame position to link with
                var linkedFramePosition = reader.WORD();
                return(new CellChunk(layerIndex, xPosition, yPosition, opacityLevel, cellType,
                                     linkedFramePosition));
            }
            // + For cel type = 2(Compressed Image)
            else if (cellType == 2)
            {
                //   WORD      Width in pixels
                var width = reader.WORD();
                //   WORD      Height in pixels
                var height = reader.WORD();
                //   BYTE[]    "Raw Cel" data compressed with ZLIB method
                var depthModifier = 0;
                if (colorDepth == ColorDepth.RGBA)
                {
                    depthModifier = 4;
                }
                else if (colorDepth == ColorDepth.Grayscale)
                {
                    depthModifier = 2;
                }
                else if (colorDepth == ColorDepth.Indexed)
                {
                    depthModifier = 1;
                }

                var count  = width * height * depthModifier;
                var pixels = new byte[count];
                reader.DEFLATE(pixels);

                return(new CellChunk(layerIndex, xPosition, yPosition, opacityLevel, cellType, width, height, pixels));
            }
            else
            {
                return(new CellChunk(layerIndex, xPosition, yPosition, opacityLevel, cellType));
            }
        }
Example #11
0
        public static FrameData Read(AsepriteStreamReader reader, ColorDepth colorDepth)
        {
            // DWORD Bytes in this frame
            var bytesInFrame = reader.DWORD();
            // WORD        Magic number(always 0xF1FA)
            var magicNumber = reader.WORD();

            if (magicNumber != 0xF1FA)
            {
                throw new System.Exception("Invalid Format");
            }

            // WORD Old field which specifies the number of "chunks"
            //             in this frame.If this value is 0xFFFF, we might
            //             have more chunks to read in this frame
            //             (so we have to use the new field)
            var oldNumberOfChunks = reader.WORD();
            // WORD Frame duration(in milliseconds)
            var frameDuration = reader.WORD();

            // BYTE[2]     For future(set to zero)
            reader.BYTES(2);
            // DWORD New field which specifies the number of "chunks"
            //             in this frame(if this is 0, use the old field)
            var newNumberOfChunks = reader.DWORD();
            var numberOfChunks    = newNumberOfChunks > 0 ? newNumberOfChunks : oldNumberOfChunks;

            var chunks = new IChunk[numberOfChunks];

            for (int i = 0; i < numberOfChunks; i++)
            {
                // DWORD Chunk size
                var startPos = reader.POS;
                var size     = reader.DWORD();
                // WORD Chunk type
                var type = reader.WORD();
                // BYTE[] Chunk data
                Console.WriteLine($"Reading Chunk Type: {type:X}");
                switch (type)
                {
                case 0x2004:
                    chunks[i] = LayerChunk.Read(reader);
                    break;

                case 0x2005:
                    chunks[i] = CellChunk.Read(reader, colorDepth);
                    break;

                case 0x2006:
                    chunks[i] = CellExtraChunk.Read(reader);
                    break;

                case 0x2018:
                    chunks[i] = TagsChunk.Read(reader);
                    break;

                case 0x2019:
                    chunks[i] = PaletteChunk.Read(reader);
                    break;

                case 0x2020:
                    chunks[i] = UserDataChunk.Read(reader);
                    break;

                case 0x2022:
                    chunks[i] = SliceChunk.Read(reader);
                    break;

                default:
                    // ingoring data
                    reader.BYTES((int)size);
                    break;
                }

                reader.POS = startPos + size;
            }

            return(new FrameData(bytesInFrame, frameDuration, chunks));
        }
Example #12
0
        public static Header Read(AsepriteStreamReader reader)
        {
            // DWORD       File size
            var fileSize = reader.DWORD();
            // WORD        Magic number (0xA5E0)
            var magicNumber = reader.WORD();

            if (magicNumber != 0xA5E0)
            {
                throw new System.Exception("Invalid Format");
            }
            // WORD        Frames
            var frames = reader.WORD();
            // WORD        Width in pixels
            var width = reader.WORD();
            // WORD        Height in pixels
            var height = reader.WORD();
            // WORD        Color depth (bits per pixel)
            //               32 bpp = RGBA
            //               16 bpp = Grayscale
            //               8 bpp = Indexed
            var colorDepth = (ColorDepth)reader.WORD();
            // DWORD       Flags:
            //               1 = Layer opacity has valid value
            var layerOpacityHasValidValue = reader.FLAG(reader.DWORD(), 1);

            // WORD        Speed (milliseconds between frame, like in FLC files)
            //             DEPRECATED: You should use the frame duration field
            //             from each frame header
            reader.WORD();
            // DWORD       Set be 0
            reader.DWORD();
            // DWORD       Set be 0
            reader.DWORD();
            // BYTE        Palette entry (index) which represent transparent color
            //             in all non-background layers (only for Indexed sprites).
            var transparentIndex = reader.BYTE();

            // BYTE[3]     Ignore these bytes
            reader.BYTES(3);
            // WORD        Number of colors (0 means 256 for old sprites)
            reader.WORD();
            // BYTE        Pixel width (pixel ratio is "pixel width/pixel height").
            //             If this or pixel height field is zero, pixel ratio is 1:1
            var pixelWidth = reader.BYTE();
            // BYTE        Pixel height
            var  pixelHeight = reader.BYTE();
            byte pixelRatio  = 1;

            if (pixelHeight > 0 && pixelWidth > 0)
            {
                pixelRatio = (byte)(pixelWidth / pixelHeight);
            }
            // SHORT       X position of the grid
            var xPos = reader.SHORT();
            // SHORT       Y position of the grid
            var yPos = reader.SHORT();
            // WORD        Grid width (zero if there is no grid, grid size
            //             is 16x16 on Aseprite by default)
            var gridWidth = reader.WORD();
            // WORD        Grid height (zero if there is no grid)
            var gridHeight = reader.WORD();

            // BYTE[84]    For future (set to zero)
            reader.BYTES(84);

            return(new Header(
                       fileSize,
                       frames,
                       width,
                       height,
                       colorDepth,
                       layerOpacityHasValidValue,
                       transparentIndex,
                       pixelWidth,
                       pixelHeight,
                       pixelRatio,
                       xPos,
                       yPos,
                       gridWidth,
                       gridHeight));
        }