UpdateGif.cs
//
// This code is part of GrapeCity Documents for Imaging samples.
// Copyright (c) GrapeCity, Inc. All rights reserved.
//
using System;
using System.IO;
using GrapeCity.Documents.Imaging;
using GrapeCity.Documents.Drawing;

namespace GcImagingWeb.Samples
{
    // This sample loads an existing GIF and modifies its frames.
    // Specifically, it applies a color matrix to change the colors,
    // and flips the images horizontally.
    // The GIF loaded in this sample is the one produced by IndexedGif.
    public class UpdateGif
    {
        public Stream GenerateImageStream (ImageEncoding targetEncoding, int pixelWidth = 1024, int pixelHeight = 1024, bool opaque = true, float dpiX = 96, float dpiY = 96)
        {
            if (targetEncoding != ImageEncoding.Gif)
                throw new Exception("This sample only supports GIF output format.");

            // Matrix to change colors to greenish blues:
            var colorMatrix = new ColorMatrix5x4()
            {
                M11 = 0.2f,
                M12 = 0.3f,
                M22 = 0.5f
            };

            var ms = new MemoryStream();
            // Read source GIF, write modified one (change palette and flip and rotate frames):
            using (var gr = new GcGifReader(Path.Combine("Resources", "Gifs", "goldfish-indexed.gif")))
            using (var gw = new GcGifWriter(ms))
            {
                var pal = gr.GetGlobalPalette();
                // This sample will only work with GIFs that have a global palette:
                if (pal == null)
                    throw new Exception("Source GIF does not have a global palette.");
                // Use color matrix to update the palette:
                using (var palBmp = new GcBitmap(pal, pal.Length, 1, true))
                    palBmp.ApplyColorMatrix(colorMatrix);

                // Set target paletter and other properties:
                gw.GlobalPalette = pal;
                gw.LogicalScreenWidth = gr.LogicalScreenWidth;
                gw.LogicalScreenHeight = gr.LogicalScreenHeight;
                gw.PixelAspectRatio = gr.PixelAspectRatio;
                gw.AllowAddingTransparentColor = false;
                using (var tbmp = new GcBitmap())
                    for (int i = 0; i < gr.Frames.Count; i++)
                    {
                        var frame = gr.Frames[i];
                        frame.ToGcBitmap(tbmp, i - 1);

                        // Flip the image horizontally (this will reverse the 'rotation' of the fish):
                        using (var bmp = tbmp.FlipRotate(FlipRotateAction.FlipHorizontal))
                        {
                            // Apply the color matrix and append the frame to the target GIF:
                            bmp.ApplyColorMatrix(colorMatrix);
                            gw.AppendFrame(bmp, pal, DitheringMethod.NoDithering, 0, 0, GifDisposalMethod.DoNotDispose, frame.DelayTime, false);
                        }
                    }
            }
            ms.Seek(0, SeekOrigin.Begin);
            return ms;
        }

        public ImageEncoding DefaultEncoding { get => ImageEncoding.Gif; }
    }
}