Ejemplo n.º 1
0
        /// <summary>
        /// Creates an FDAT Chunk from an IDAT Chunk.
        /// </summary>
        /// <returns>The FDAT chunk.</returns>
        /// <param name="idatChunk">IDAT chunk.</param>
        /// <param name="sequenceNumber">Sequence number.</param>
        public static fdATChunk FromIDATChunk(IDATChunk idatChunk, uint sequenceNumber)
        {
            uint newCrc;

            byte[]    frameData;
            fdATChunk fdat = null;

            using (var msCrc = new MemoryStream())
            {
                msCrc.WriteBytes(new[] { (byte)'f', (byte)'d', (byte)'A', (byte)'T' });
                byte[] seqNum = BitConverter.GetBytes(Helper.ConvertEndian(sequenceNumber));
                frameData = new byte[seqNum.Length + idatChunk.ChunkData.Length];
                Buffer.BlockCopy(seqNum, 0, frameData, 0, seqNum.Length);
                Buffer.BlockCopy(idatChunk.ChunkData, 0, frameData, seqNum.Length, idatChunk.ChunkData.Length);
                msCrc.WriteBytes(frameData);

                newCrc = CrcHelper.Calculate(msCrc.ToArray());
            }

            using (var ms = new MemoryStream())
            {
                ms.WriteUInt32((uint)Helper.ConvertEndian(idatChunk.ChunkData.Length + 4));
                ms.WriteBytes(new[] { (byte)'f', (byte)'d', (byte)'A', (byte)'T' });
                ms.WriteBytes(frameData);
                ms.WriteUInt32(Helper.ConvertEndian(newCrc));
                ms.Position = 0;

                fdat = new fdATChunk(ms);
            }

            return(fdat);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Save the APNG to file.
        /// </summary>
        /// <param name="filename">The filename to output to.</param>
        public void Save(string filename)
        {
            using (BinaryWriter writer = new BinaryWriter(new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write)))
            {
                int frameWriteStartIndex = 0;

                //Write signature
                writer.Write(Frame.Signature);

                //Write header
                writer.Write(this.IHDRChunk.RawData);

                //If acTL exists
                if (acTLChunk != null)
                {
                    //write actl.
                    writer.Write(acTLChunk.RawData);
                }

                //Write all other chunks. (NOTE: These should be consistently the same for all frames)
                foreach (OtherChunk otherChunk in defaultImage.OtherChunks)
                {
                    writer.Write(otherChunk.RawData);
                }

                uint sequenceNumber = 0;
                //If Default Image is not animated
                if (!DefaultImageIsAnimated)
                {
                    //write IDAT
                    defaultImage.IDATChunks.ForEach(i => writer.Write(i.RawData));
                }
                else
                {
                    frames[0].fcTLChunk.SequenceNumber = sequenceNumber++;
                    //Write fcTL
                    writer.Write(frames[0].fcTLChunk.RawData);
                    //Write IDAT of first frame.
                    frames[0].IDATChunks.ForEach(i => writer.Write(i.RawData));
                    //Set start frame indes to 1
                    frameWriteStartIndex = 1;
                }

                //Foreach frame
                for (int i = frameWriteStartIndex; i < frames.Count; ++i)
                {
                    frames[i].fcTLChunk.SequenceNumber = sequenceNumber++;
                    //write fcTL
                    writer.Write(frames[i].fcTLChunk.RawData);

                    //Write fDAT
                    for (int j = 0; j < frames[i].IDATChunks.Count; ++j)
                    {
                        fdATChunk fdat = fdATChunk.FromIDATChunk(frames[i].IDATChunks[j], sequenceNumber++);

                        writer.Write(fdat.RawData);
                    }
                }

                //Write IEnd
                writer.Write(defaultImage.IENDChunk.RawData);

                writer.Close();
            }
        }