Ejemplo n.º 1
0
        void dIHDR(PNGChunk c)
        {
            IHDRChunk ic = new IHDRChunk(c);

            ind();

            wo("Width: " + ic.Width);
            wo("Height: " + ic.Height);
            wo("BitDepth: " + ic.BitDepth);
            wo("ColorType: " + ic.ColorType + " " + decodeColorType(ic));

            oud();
        }
Ejemplo n.º 2
0
        private static BitmapSource MakeFrame(IHDRChunk header, Frame rawFrame, Frame previousFrame,
                                              BitmapSource previousRenderedFrame)
        {
            var fs     = rawFrame.GetBitmapSource();
            var visual = new DrawingVisual();

            using (var context = visual.RenderOpen())
            {
                switch (rawFrame.fcTLChunk.DisposeOp)
                {
                case DisposeOps.APNGDisposeOpNone:
                    // restore previousRenderedFrame
                    //if (previousRenderedFrame != null)
                    //{
                    //    var fullRect = new Rect(0, 0, header.Width, header.Height);
                    //    context.DrawImage(previousRenderedFrame, fullRect);
                    //}
                    break;

                case DisposeOps.APNGDisposeOpPrevious:
                    // restore previousFrame
                    if (previousFrame != null)
                    {
                        var pFrameRect = new Rect(previousFrame.fcTLChunk.XOffset,
                                                  previousFrame.fcTLChunk.YOffset,
                                                  previousFrame.fcTLChunk.Width, previousFrame.fcTLChunk.Height);
                        context.DrawImage(previousFrame.GetBitmapSource(), pFrameRect);
                    }
                    break;

                case DisposeOps.APNGDisposeOpBackground:
                    // do nothing
                    break;
                }

                // draw current frame
                var frameRect = new Rect(rawFrame.fcTLChunk.XOffset, rawFrame.fcTLChunk.YOffset,
                                         rawFrame.fcTLChunk.Width, rawFrame.fcTLChunk.Height);

                context.DrawImage(fs, frameRect);
            }
            var bitmap = new RenderTargetBitmap(
                header.Width, header.Height,
                Math.Floor(fs.DpiX), Math.Floor(fs.DpiY),
                PixelFormats.Pbgra32);

            bitmap.Render(visual);
            return(bitmap);
        }
Ejemplo n.º 3
0
            public FrameInfo(IHDRChunk header, Frame frame)
            {
                FullRect  = new Rect(0, 0, header.Width, header.Height);
                FrameRect = new Rect(frame.fcTLChunk.XOffset, frame.fcTLChunk.YOffset,
                                     frame.fcTLChunk.Width, frame.fcTLChunk.Height);

                BlendOp   = frame.fcTLChunk.BlendOp;
                DisposeOp = frame.fcTLChunk.DisposeOp;

                Pixels = frame.GetBitmapSource();
                Pixels.Freeze();

                Delay = TimeSpan.FromSeconds((double)frame.fcTLChunk.DelayNum /
                                             (frame.fcTLChunk.DelayDen == 0
                                                 ? 100
                                                 : frame.fcTLChunk.DelayDen));
            }
Ejemplo n.º 4
0
        string decodeColorType(IHDRChunk ic)
        {
            List <string> ans = new List <string>();

            if (ic.HasPalette)
            {
                ans.Add("palette");
            }
            if (ic.HasColor)
            {
                ans.Add("color");
            }
            if (ic.HasAlpha)
            {
                ans.Add("alpha");
            }

            return(String.Join(",", ans.ToArray()));
        }
Ejemplo n.º 5
0
        /// <summary>
        ///     Gets the frame as PNG FileStream.
        /// </summary>
        public MemoryStream GetStream()
        {
            var ihdrChunk = new IHDRChunk(IHDRChunk);

            if (fcTLChunk != null)
            {
                // Fix frame size with fcTL data.
                ihdrChunk.ModifyChunkData(0, Helper.ConvertEndian(fcTLChunk.Width));
                ihdrChunk.ModifyChunkData(4, Helper.ConvertEndian(fcTLChunk.Height));
            }

            // Write image data
            var ms = new MemoryStream();

            ms.WriteBytes(Signature);
            ms.WriteBytes(ihdrChunk.RawData);
            otherChunks.ForEach(o => ms.WriteBytes(o.RawData));
            idatChunks.ForEach(i => ms.WriteBytes(i.RawData));
            ms.WriteBytes(IENDChunk.RawData);

            ms.Position = 0;
            return(ms);
        }
Ejemplo n.º 6
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);
            }
Ejemplo n.º 7
0
        /// <summary>
        /// Load the specified stream.
        /// </summary>
        /// <param name="stream">Stream representation of the png file.</param>
        internal void Load(MemoryStream stream)
        {
            ms = stream;

            // check file signature.
            if (!Helper.IsBytesEqual(ms.ReadBytes(Frame.Signature.Length), Frame.Signature))
            {
                throw new Exception("File signature incorrect.");
            }

            // Read IHDR chunk.
            IHDRChunk = new IHDRChunk(ms);
            if (IHDRChunk.ChunkType != "IHDR")
            {
                throw new Exception("IHDR chunk must located before any other chunks.");
            }

            viewSize = new Size(IHDRChunk.Width, IHDRChunk.Height);

            // Now let's loop in chunks
            Chunk chunk;
            Frame frame               = null;
            var   otherChunks         = new List <OtherChunk>();
            bool  isIDATAlreadyParsed = false;

            do
            {
                if (ms.Position == ms.Length)
                {
                    throw new Exception("IEND chunk expected.");
                }

                chunk = new Chunk(ms);

                switch (chunk.ChunkType)
                {
                case "IHDR":
                    throw new Exception("Only single IHDR is allowed.");

                case "acTL":
                    if (IsSimplePNG)
                    {
                        throw new Exception("acTL chunk must located before any IDAT and fdAT");
                    }

                    acTLChunk = new acTLChunk(chunk);
                    break;

                case "IDAT":
                    // To be an APNG, acTL must located before any IDAT and fdAT.
                    if (acTLChunk == null)
                    {
                        IsSimplePNG = true;
                    }

                    // Only default image has IDAT.
                    defaultImage.IHDRChunk = IHDRChunk;
                    defaultImage.AddIDATChunk(new IDATChunk(chunk));
                    isIDATAlreadyParsed = true;
                    break;

                case "fcTL":
                    // Simple PNG should ignore this.
                    if (IsSimplePNG)
                    {
                        continue;
                    }

                    if (frame != null && frame.IDATChunks.Count == 0)
                    {
                        throw new Exception("One frame must have only one fcTL chunk.");
                    }

                    // IDAT already parsed means this fcTL is used by FRAME IMAGE.
                    if (isIDATAlreadyParsed)
                    {
                        // register current frame object and build a new frame object
                        // for next use
                        if (frame != null)
                        {
                            frames.Add(frame);
                        }
                        frame = new Frame
                        {
                            IHDRChunk = IHDRChunk,
                            fcTLChunk = new fcTLChunk(chunk)
                        };
                    }
                    // Otherwise this fcTL is used by the DEFAULT IMAGE.
                    else
                    {
                        defaultImage.fcTLChunk = new fcTLChunk(chunk);
                    }
                    break;

                case "fdAT":
                    // Simple PNG should ignore this.
                    if (IsSimplePNG)
                    {
                        continue;
                    }

                    // fdAT is only used by frame image.
                    if (frame == null || frame.fcTLChunk == null)
                    {
                        throw new Exception("fcTL chunk expected.");
                    }

                    frame.AddIDATChunk(new fdATChunk(chunk).ToIDATChunk());
                    break;

                case "IEND":
                    // register last frame object
                    if (frame != null)
                    {
                        frames.Add(frame);
                    }

                    if (DefaultImage.IDATChunks.Count != 0)
                    {
                        DefaultImage.IENDChunk = new IENDChunk(chunk);
                    }
                    foreach (Frame f in frames)
                    {
                        f.IENDChunk = new IENDChunk(chunk);
                    }
                    break;

                default:
                    otherChunks.Add(new OtherChunk(chunk));
                    break;
                }
            } while (chunk.ChunkType != "IEND");

            // We have one more thing to do:
            // If the default image is part of the animation,
            // we should insert it into frames list.
            if (defaultImage.fcTLChunk != null)
            {
                frames.Insert(0, defaultImage);
                DefaultImageIsAnimated = true;
            }
            else //If it isn't animated it still needs the other chunks.
            {
                otherChunks.ForEach(defaultImage.AddOtherChunk);
            }

            // Now we should apply every chunk in otherChunks to every frame.
            frames.ForEach(f => otherChunks.ForEach(f.AddOtherChunk));
        }
Ejemplo n.º 8
0
        private static BitmapSource MakeNextFrame(IHDRChunk header, Frame nextFrame, Frame currentFrame,
                                                  BitmapSource currentRenderedFrame, BitmapSource previousStateRenderedFrame)
        {
            var fullRect  = new Rect(0, 0, header.Width, header.Height);
            var frameRect = new Rect(nextFrame.fcTLChunk.XOffset, nextFrame.fcTLChunk.YOffset,
                                     nextFrame.fcTLChunk.Width, nextFrame.fcTLChunk.Height);

            var fs     = nextFrame.GetBitmapSource();
            var visual = new DrawingVisual();

            using (var context = visual.RenderOpen())
            {
                // protect region
                if (nextFrame.fcTLChunk.BlendOp == BlendOps.APNGBlendOpSource)
                {
                    var freeRegion = new CombinedGeometry(GeometryCombineMode.Xor,
                                                          new RectangleGeometry(fullRect),
                                                          new RectangleGeometry(frameRect));
                    context.PushOpacityMask(
                        new DrawingBrush(new GeometryDrawing(Brushes.Transparent, null, freeRegion)));
                }

                if (currentFrame != null && currentRenderedFrame != null)
                {
                    switch (currentFrame.fcTLChunk.DisposeOp)
                    {
                    case DisposeOps.APNGDisposeOpNone:
                        // restore currentRenderedFrame
                        if (currentRenderedFrame != null)
                        {
                            context.DrawImage(currentRenderedFrame, fullRect);
                        }
                        break;

                    case DisposeOps.APNGDisposeOpPrevious:
                        // restore previousStateRenderedFrame
                        if (previousStateRenderedFrame != null)
                        {
                            context.DrawImage(previousStateRenderedFrame, fullRect);
                        }
                        break;

                    case DisposeOps.APNGDisposeOpBackground:
                        // do nothing
                        break;
                    }
                }

                // unprotect region and draw the next frame
                if (nextFrame.fcTLChunk.BlendOp == BlendOps.APNGBlendOpSource)
                {
                    context.Pop();
                }
                context.DrawImage(fs, frameRect);
            }

            var bitmap = new RenderTargetBitmap(
                header.Width, header.Height,
                Math.Floor(fs.DpiX), Math.Floor(fs.DpiY),
                PixelFormats.Pbgra32);

            bitmap.Render(visual);
            return(bitmap);
        }