예제 #1
0
            public void Load(Stream stream)
            {
                chunks = new List <APNGChunk>();
                pngs   = new List <PNG>();

                // Create a new header (should be 1 per file) and
                // read it from the stream
                var header = new APNGHeader();

                try
                {
                    header.Read(stream);
                }
                catch (Exception)
                {
                    stream.Close();
                    throw;
                }

                APNGChunk chunk;
                PNG       png = null;

                // Read chunks from the stream until we reach the MEND chunk
                do
                {
                    // Read a generic Chunk
                    chunk = new APNGChunk();
                    try
                    {
                        chunk.Read(stream);
                    }
                    catch (Exception)
                    {
                        stream.Close();
                        throw;
                    }

                    // Take a look at the chunk type and decide what derived class to
                    // use to create a specific chunk
                    switch (chunk.ChunkType)
                    {
                    case acTLChunk.NAME:
                        if (headerChunk != null)
                        {
                            throw new ApplicationException(String.Format(
                                                               "Only one chunk of type {0} is allowed", chunk.ChunkType));
                        }
                        chunk = headerChunk = new acTLChunk(chunk);
                        break;

                    case MENDChunk.NAME:
                        chunk = new MENDChunk(chunk);
                        break;

                    case TERMChunk.NAME:
                        chunk = new TERMChunk(chunk);
                        break;

                    case BACKChunk.NAME:
                        chunk = new BACKChunk(chunk);
                        break;

                    case BKGDChunk.NAME:
                        chunk = new BKGDChunk(chunk);
                        break;

                    case fcTLChunk.NAME:
                        // This is the beginning of a new embedded PNG
                        chunk = new fcTLChunk(chunk);
                        png   = new PNG {
                            FCTL = chunk as fcTLChunk, IHDR = ihdrChunk
                        };
                        pngs.Add(png);
                        break;

                    case IHDRChunk.NAME:
                        chunk     = new IHDRChunk(chunk);
                        ihdrChunk = chunk as IHDRChunk;
                        break;

                    case IDATChunk.NAME:
                        chunk = new IDATChunk(chunk);
                        if (png != null)
                        {
                            png.IDAT = chunk as IDATChunk;
                        }
                        break;

                    case fdATChunk.NAME:
                        chunk = new fdATChunk(chunk);
                        if (png != null)
                        {
                            chunk.ChunkType = IDATChunk.NAME;
                            png.IDAT        = new IDATChunk(chunk);
                        }
                        break;

                    case IENDChunk.NAME:
                        chunk = new IENDChunk(chunk);
                        for (var i = 0; i < pngs.Count; i++)
                        {
                            pngs[i].IEND = chunk as IENDChunk;
                        }
                        break;

                    default:
                        break;
                    }
                    // Add the chunk to our list of chunks
                    chunks.Add(chunk);
                }while (chunk.ChunkType != IENDChunk.NAME);
            }
예제 #2
0
        /// <summary>
        /// Adds an image as the next frame.
        /// </summary>
        /// <param name="image">Png frame.</param>
        public void AddFrame(Image image)
        {
            //TODO: Handle different sizes
            //Temporarily reject improper sizes.
            if (IHDRChunk != null && (image.Width > IHDRChunk.Width || image.Height > IHDRChunk.Height))
            {
                throw new InvalidDataException("Frame must be less than or equal to the size of the other frames.");
            }

            APNG apng = APNG.FromImage(image);

            if (IHDRChunk == null)
            {
                IHDRChunk = apng.IHDRChunk;
            }

            //Create acTL Chunk.
            if (acTLChunk == null)
            {
                acTLChunk           = new acTLChunk();
                acTLChunk.PlayCount = 0;
            }

            uint sequenceNumber = (frames.Count == 0) ? 0 : (uint)(frames[frames.Count - 1].fcTLChunk.SequenceNumber + frames[frames.Count - 1].IDATChunks.Count);
            //Create fcTL Chunk
            fcTLChunk fctl = new fcTLChunk
            {
                SequenceNumber   = sequenceNumber,
                Width            = (uint)image.Width,
                Height           = (uint)image.Height,
                XOffset          = 0,
                YOffset          = 0,
                DelayNumerator   = 100,
                DelayDenominator = 1000,
                DisposeOp        = DisposeOps.APNGDisposeOpNone,
                BlendOp          = BlendOps.APNGBlendOpSource
            };

            //Set the default image if needed.
            if (defaultImage.IDATChunks.Count == 0)
            {
                defaultImage           = apng.DefaultImage;
                defaultImage.fcTLChunk = fctl;
                DefaultImageIsAnimated = true;
            }

            //Add all the frames from the png.
            if (apng.IsSimplePNG)
            {
                Frame frame = apng.DefaultImage;
                frame.fcTLChunk = fctl;

                foreach (OtherChunk chunk in frame.OtherChunks)
                {
                    if (!defaultImage.OtherChunks.Contains(chunk))
                    {
                        defaultImage.OtherChunks.Add(chunk);
                    }
                }
                frame.OtherChunks.Clear();
                frames.Add(frame);
            }
            else
            {
                for (int i = 0; i < apng.FrameCount; ++i)
                {
                    Frame frame = apng.Frames[i];
                    frame.fcTLChunk.SequenceNumber = sequenceNumber;
                    foreach (OtherChunk chunk in frame.OtherChunks)
                    {
                        if (!defaultImage.OtherChunks.Contains(chunk))
                        {
                            defaultImage.OtherChunks.Add(chunk);
                        }
                    }
                    frame.OtherChunks.Clear();
                    frames.Add(frame);
                }
            }
            List <OtherChunk> otherChunks = defaultImage.OtherChunks;

            // Now we should apply every chunk in otherChunks to every frame.
            if (defaultImage != frames[0])
            {
                frames.ForEach(f => otherChunks.ForEach(f.AddOtherChunk));
            }
            else
            {
                for (int i = 1; i < frames.Count; ++i)
                {
                    otherChunks.ForEach(frames[i].AddOtherChunk);
                }
            }

            acTLChunk.FrameCount = (uint)frames.Count;
        }