Пример #1
0
        public static FrameMetadata GetFrameMetadata(BitmapDecoder decoder, GifFile gifMetadata, int frameIndex)
        {
            if (gifMetadata != null && gifMetadata.Frames.Count > frameIndex)
            {
                return(GetFrameMetadata(gifMetadata.Frames[frameIndex]));
            }

            return(GetFrameMetadata(decoder.Frames[frameIndex]));
        }
Пример #2
0
        private static Int32Size GetFullSize(BitmapDecoder decoder, GifFile gifMetadata)
        {
            if (gifMetadata == null)
            {
                return(new Int32Size(decoder.Metadata.GetQueryOrDefault <int>("/logscrdesc/Width", 0), decoder.Metadata.GetQueryOrDefault <int>("/logscrdesc/Height", 0)));
            }
            GifLogicalScreenDescriptor logicalScreenDescriptor = gifMetadata.Header.LogicalScreenDescriptor;

            return(new Int32Size(logicalScreenDescriptor.Width, logicalScreenDescriptor.Height));
        }
Пример #3
0
    public static Texture2D GenerateAtlas(GifFile gif, out SpriteImportData[] spriteData)
    {
        int spriteCount = gif.textureList.Count;

        var cols = spriteCount;
        var rows = 1;

        var divider = 2;

        Texture2D  sampleTexture = gif.textureList[0].m_texture2d;
        Vector2Int spriteSize    = new Vector2Int(sampleTexture.width, sampleTexture.height);
        var        width         = cols * spriteSize.x;
        var        height        = rows * spriteSize.y;

        while (width > height)
        {
            cols = (int)Math.Ceiling((float)spriteCount / divider);
            rows = (int)Math.Ceiling((float)spriteCount / cols);

            width  = cols * spriteSize.x;
            height = rows * spriteSize.y;

            if (cols <= 1)
            {
                break;
            }

            divider++;
        }

        if (height > width)
        {
            divider -= 2;
        }
        else
        {
            divider -= 1;
        }

        if (divider < 1)
        {
            divider = 1;
        }

        cols = (int)Math.Ceiling((float)spriteCount / divider);
        rows = (int)Math.Ceiling((float)spriteCount / cols);

        Texture2D[] textures = new Texture2D[spriteCount];
        for (int i = 0; i < gif.textureList.Count; i++)
        {
            textures[i] = gif.textureList[i].m_texture2d;
        }

        return(GenerateAtlas(textures, out spriteData, spriteSize, cols, rows));
    }
Пример #4
0
        private static Int32Size GetFullSize(BitmapDecoder decoder, GifFile gifMetadata)
        {
            if (gifMetadata != null)
            {
                var lsd = gifMetadata.Header.LogicalScreenDescriptor;
                return(new Int32Size(lsd.Width, lsd.Height));
            }
            int width  = decoder.Metadata.GetQueryOrDefault("/logscrdesc/Width", 0);
            int height = decoder.Metadata.GetQueryOrDefault("/logscrdesc/Height", 0);

            return(new Int32Size(width, height));
        }
Пример #5
0
        public GifImage Decode(BinaryReader br, double dpiX, double dpiY, int defaultDelay = 10)
        {
            var gif = new GifFile(br);

            // TODO: ratio?
            var image = new GifImage {
                File   = gif,
                Width  = gif.ScreenWidth,
                Height = gif.ScreenHeight
            };

            var globalColorTable = TransformColor(gif.GlobalColorTable?.Colors) ?? DefaultColorTable;
            var prevBm           = ImagingHelpers.DrawAndRender(image.Width, image.Height, dpiX, dpiY,
                                                                dc => {
                dc.DrawRectangle(new SolidColorBrush(globalColorTable[gif.BackgroundColorIndex]), null,
                                 new Rect(0, 0, image.Width, image.Height));
            });
            var dpiFixFactor = prevBm.Width / image.Width;

            foreach (var frame in gif.Frames)
            {
                var colorTable = TransformColor(frame.LocalColorTable?.Colors) ?? globalColorTable;
                var ctrl       = frame.ControlExtension;
                var preserved  = Colors.Transparent;
                if (ctrl?.TransparentColor ?? false)
                {
                    preserved = colorTable[ctrl.TransparentColorIndex];
                    colorTable[ctrl.TransparentColorIndex] = Colors.Transparent;
                }

                var palette = new BitmapPalette(colorTable);

                var bm = BitmapSource.Create(frame.Width, frame.Height, dpiX, dpiY, PixelFormats.Indexed8, palette,
                                             frame.Data, frame.Width);

                if (ctrl?.TransparentColor ?? false)
                {
                    colorTable[ctrl.TransparentColorIndex] = preserved;
                }

                bm = ImagingHelpers.BlendImage(prevBm, new Rect(0, 0, image.Width * dpiFixFactor, image.Height * dpiFixFactor),
                                               bm, new Rect(frame.Left * dpiFixFactor, frame.Top * dpiFixFactor, frame.Width * dpiFixFactor, frame.Height * dpiFixFactor));
                prevBm = bm;

                image.Frames.Add(new GifImageFrame {
                    Delay = (ctrl?.DelayTime ?? defaultDelay) * 10,
                    Frame = frame,
                    Image = bm
                });
            }

            return(image);
        }
Пример #6
0
 public static IBitmap GetWindowIcon()
 {
     using (Stream resourceStream = WindowIcon)
         using (MemoryStream ms = new MemoryStream())
         {
             resourceStream.CopyTo(ms);
             using (GifFile gifFile = new GifFile(ms.ToArray()))
             {
                 return(gifFile.GetBitmap());
             }
         }
 }
Пример #7
0
        public static System.Drawing.Size GetFullSize(BitmapDecoder decoder, GifFile gifMetadata)
        {
            if (gifMetadata != null)
            {
                var lsd = gifMetadata.Header.LogicalScreenDescriptor;
                return(new System.Drawing.Size(lsd.Width, lsd.Height));
            }

            var width  = decoder.Metadata.GetQueryOrDefault("/logscrdesc/Width", 0);
            var height = decoder.Metadata.GetQueryOrDefault("/logscrdesc/Height", 0);

            return(new System.Drawing.Size(width, height));
        }
Пример #8
0
        public static void LoadFrom(this MonoBehaviour mono, GifFile gif)
        {
            if (mono == null)
            {
                throw new ArgumentNullException(nameof(mono));
            }

            if (gif == null)
            {
                throw new ArgumentNullException(nameof(gif));
            }

            LoadFrom(mono, gif.path);
        }
Пример #9
0
        private static GifFile?DecodeGifFile(Uri uri)
        {
            Stream?stream = null;

            if (uri.Scheme == PackUriHelper.UriSchemePack)
            {
                StreamResourceInfo sri;
                if (uri.Authority == "siteoforigin:,,,")
                {
                    sri = Application.GetRemoteStream(uri);
                }
                else
                {
                    sri = Application.GetResourceStream(uri);
                }

                if (sri != null)
                {
                    stream = sri.Stream;
                }
                if (stream != null)
                {
                    using (stream)
                    {
                        var gif = GifFile.ReadGifFile(stream, true);
                        stream.Close();
                        return(gif);
                    }
                }
            }
            else
            {
                //using (var wc = new WebClient())
                //{
                //	stream = wc.OpenRead(uri);
                //                if (stream != null)
                //                {
                //                    using (stream)
                //                    {
                //                        var gif = GifFile.ReadGifFile(stream, true);
                //                        stream.Close();
                //                        return gif;
                //                    }
                //                }
                //            }

                // TODO: implement using HttpClient
            }
            return(null);
        }
Пример #10
0
        static void Main(string[] args)
        {
            if (args.Length == 1)
            {
                var gif = new GifFile(args[0]);
                Console.WriteLine(gif.ToString());
                foreach (var frame in gif.Frames)
                {
                    Console.WriteLine($"Frame: at ({frame.Top}, {frame.Left}) size [{frame.Width}, {frame.Height}], delay {frame.ControlExtension?.DelayTime}");
                }

                Console.WriteLine("Done");
                Console.ReadKey();
            }
        }
Пример #11
0
        private static RepeatBehavior GetActualRepeatBehavior(
            Image imageControl,
            BitmapDecoder decoder,
            GifFile gifMetadata)
        {
            RepeatBehavior repeatBehavior = ImageBehavior.GetRepeatBehavior(imageControl);

            if (repeatBehavior != new RepeatBehavior())
            {
                return(repeatBehavior);
            }
            int num = gifMetadata == null?ImageBehavior.GetRepeatCount(decoder) : (int)gifMetadata.RepeatCount;

            return(num == 0 ? RepeatBehavior.Forever : new RepeatBehavior((double)num));
        }
Пример #12
0
        private void OnKeyboardDown(object sender, KeyboardEventArgs args)
        {
            if (args[KeyModifier.Control, Key.F5])
            {
                string filename = Common.CaptureFilename;
                if (Runtime.Layers == null)
                {
                    return;
                }
                using (IBitmap bitmap = new Picture(CanvasWidth, CanvasHeight, Common.TopScreen.Palette.Copy()))
                {
                    bitmap.Palette[0] = Colour.Black;
                    if (Common.HasAttribute <Modal>(TopScreen))
                    {
                        bitmap.AddLayer(TopScreen);
                    }
                    else
                    {
                        Runtime.Layers.ToList().ForEach(x => bitmap.AddLayer(x));
                    }

                    using (GifFile file = new GifFile(bitmap))
                        using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
                        {
                            byte[] output = file.GetBytes();
                            fs.Write(output, 0, output.Length);
                            Runtime.Log($"Screenshot saved: {filename}");
                        }
                }
                return;
            }

            if (args[KeyModifier.Control, Key.F6] && Game.Started)
            {
                string filename = Common.CaptureFilename;
                using (IBitmap tilesPicture = Map.Instance[0, 0, Map.WIDTH, Map.HEIGHT].ToBitmap())
                    using (GifFile file = new GifFile(tilesPicture))
                        using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
                        {
                            byte[] output = file.GetBytes();
                            fs.Write(output, 0, output.Length);
                            Runtime.Log($"Screenshot saved: {filename}");
                        }
                return;
            }

            TopScreen?.KeyDown(args);
        }
Пример #13
0
 private static int GetRepeatCountFromMetadata(BitmapDecoder decoder, GifFile gifMetadata)
 {
     if (gifMetadata != null)
     {
         return(gifMetadata.RepeatCount);
     }
     else
     {
         var ext = GetApplicationExtension(decoder, "NETSCAPE2.0");
         if (ext != null)
         {
             byte[] bytes = ext.GetQueryOrNull <byte[]>("/Data");
             if (bytes != null && bytes.Length >= 4)
             {
                 return(BitConverter.ToUInt16(bytes, 2));
             }
         }
         return(1);
     }
 }
Пример #14
0
        public static BitmapDecoder GetDecoder(string fileName, out GifFile gifFile)
        {
            gifFile = null;
            BitmapDecoder decoder = null;

            using (var stream = new FileStream(fileName, FileMode.Open))
            {
                stream.Position = 0;
                decoder         = BitmapDecoder.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);

                if (decoder is GifBitmapDecoder)// && !CanReadNativeMetadata(decoder))
                {
                    stream.Position = 0;
                    gifFile         = GifFile.ReadGifFile(stream, true);
                }

                //if (decoder == null)
                //    throw new InvalidOperationException("Can't get a decoder from the source.");
            }

            return(decoder);
        }
Пример #15
0
        public ImpImage(GifBitmapDecoder decoder, GifFile gifFile)
        {
            this.GifFile = gifFile;
            var animation = ImageBehavior.CreateGifAnimation(decoder, gifFile);
            var list      = new List <BitmapSource>();

            foreach (ObjectKeyFrame animationKeyFrame in animation.KeyFrames)
            {
                list.Add((BitmapSource)animationKeyFrame.Value);
            }

            if (animation.Duration.HasTimeSpan)
            {
                this.Duration = animation.Duration.TimeSpan;
            }
            else
            {
                this.Duration = TimeSpan.FromSeconds(this.Frames.Count / 10.0);
            }

            this.Frames   = new ReadOnlyCollection <BitmapSource>(list);
            this.Animated = this.Frames.Count > 1;
        }
Пример #16
0
        private static async Task <GifFile> DecodeGifFile(Uri uri)
        {
            Stream stream = null;

            if (uri.Scheme == PackUriHelper.UriSchemePack)
            {
                StreamResourceInfo sri;
                if (uri.Authority == "siteoforigin:,,,")
                {
                    sri = Application.GetRemoteStream(uri);
                }
                else
                {
                    sri = Application.GetResourceStream(uri);
                }

                if (sri != null)
                {
                    stream = sri.Stream;
                }
            }
            else
            {
                using (var wc = new HttpClient())
                {
                    stream = await wc.GetStreamAsync(uri);
                }
            }
            if (stream != null)
            {
                using (stream)
                {
                    return(GifFile.ReadGifFile(stream, true));
                }
            }
            return(null);
        }
Пример #17
0
        private static GifFile DecodeGifFile(Uri uri)
        {
            Stream stream = (Stream)null;

            if (uri.Scheme == PackUriHelper.UriSchemePack)
            {
                StreamResourceInfo streamResourceInfo = !(uri.Authority == "siteoforigin:,,,") ? Application.GetResourceStream(uri) : Application.GetRemoteStream(uri);
                if (streamResourceInfo != null)
                {
                    stream = streamResourceInfo.Stream;
                }
            }
            else
            {
                using (WebClient webClient = new WebClient())
                    stream = webClient.OpenRead(uri);
            }
            if (stream == null)
            {
                return((GifFile)null);
            }
            using (stream)
                return(GifFile.ReadGifFile(stream, true));
        }
Пример #18
0
        private static BitmapDecoder GetDecoder(BitmapSource image, Image imageControl, out GifFile gifFile)
        {
            gifFile = null;
            BitmapDecoder       decoder       = null;
            Stream              stream        = null;
            Uri                 uri           = null;
            BitmapCreateOptions createOptions = BitmapCreateOptions.None;

            var bmp = image as BitmapImage;

            if (bmp != null)
            {
                createOptions = bmp.CreateOptions;
                if (bmp.StreamSource != null)
                {
                    stream = bmp.StreamSource;
                }
                else if (bmp.UriSource != null)
                {
                    uri = bmp.UriSource;
                    if (!uri.IsAbsoluteUri)
                    {
                        var baseUri = bmp.BaseUri ?? (imageControl as IUriContext)?.BaseUri;
                        if (baseUri != null)
                        {
                            uri = new Uri(baseUri, uri);
                        }
                    }
                }
            }
            else
            {
                BitmapFrame frame = image as BitmapFrame;
                if (frame != null)
                {
                    decoder = frame.Decoder;
                    Uri.TryCreate(frame.BaseUri, frame.ToString(), out uri);
                }
            }

            if (decoder == null)
            {
                if (stream != null)
                {
                    stream.Position = 0;
                    decoder         = BitmapDecoder.Create(stream, createOptions, BitmapCacheOption.OnLoad);
                }
                else if (uri != null && uri.IsAbsoluteUri)
                {
                    decoder = BitmapDecoder.Create(uri, createOptions, BitmapCacheOption.OnLoad);
                }
            }

            if (decoder is GifBitmapDecoder && !CanReadNativeMetadata(decoder))
            {
                if (stream != null)
                {
                    stream.Position = 0;
                    gifFile         = GifFile.ReadGifFile(stream, true);
                }
                else if (uri != null)
                {
                    gifFile = DecodeGifFile(uri);
                }
                else
                {
                    throw new InvalidOperationException("Can't get URI or Stream from the source. AnimatedSource should be either a BitmapImage, or a BitmapFrame constructed from a URI.");
                }
            }
            if (decoder == null)
            {
                throw new InvalidOperationException("Can't get a decoder from the source. AnimatedSource should be either a BitmapImage or a BitmapFrame.");
            }
            return(decoder);
        }
Пример #19
0
        private static RepeatBehavior GetActualRepeatBehavior(Image imageControl, BitmapDecoder decoder, GifFile gifMetadata)
        {
            RepeatBehavior repeatBehavior = GetRepeatBehavior(imageControl);
            RepeatBehavior behavior2      = new RepeatBehavior();

            if (repeatBehavior != behavior2)
            {
                return(repeatBehavior);
            }
            int num = (gifMetadata == null) ? GetRepeatCount(decoder) : gifMetadata.RepeatCount;

            return((num != 0) ? new RepeatBehavior((double)num) : RepeatBehavior.Forever);
        }
Пример #20
0
        private async void Encode(List <FrameInfo> listFrames, int id, Parameters param, CancellationTokenSource tokenSource)
        {
            var processing = this.DispatcherStringResource("Encoder.Processing");

            try
            {
                switch (param.Type)
                {
                case Export.Gif:

                    #region Gif

                    #region Cut/Paint Unchanged Pixels

                    if (param.EncoderType == GifEncoderType.Legacy || param.EncoderType == GifEncoderType.ScreenToGif)
                    {
                        if (param.DetectUnchangedPixels)
                        {
                            Update(id, 0, FindResource("Encoder.Analyzing").ToString());

                            if (param.DummyColor.HasValue)
                            {
                                var color = Color.FromArgb(param.DummyColor.Value.R, param.DummyColor.Value.G, param.DummyColor.Value.B);

                                listFrames = ImageMethods.PaintTransparentAndCut(listFrames, color, id, tokenSource);
                            }
                            else
                            {
                                listFrames = ImageMethods.CutUnchanged(listFrames, id, tokenSource);
                            }
                        }
                        else
                        {
                            var size = listFrames[0].Path.ScaledSize();
                            listFrames.ForEach(x => x.Rect = new Int32Rect(0, 0, (int)size.Width, (int)size.Height));
                        }
                    }

                    #endregion

                    switch (param.EncoderType)
                    {
                    case GifEncoderType.ScreenToGif:

                        #region Improved encoding

                        using (var stream = new MemoryStream())
                        {
                            using (var encoder = new GifFile(stream, param.RepeatCount))
                            {
                                encoder.UseGlobalColorTable = param.UseGlobalColorTable;
                                encoder.TransparentColor    = param.DummyColor;
                                encoder.MaximumNumberColor  = param.MaximumNumberColors;

                                for (var i = 0; i < listFrames.Count; i++)
                                {
                                    if (!listFrames[i].HasArea && param.DetectUnchangedPixels)
                                    {
                                        continue;
                                    }

                                    if (listFrames[i].Delay == 0)
                                    {
                                        listFrames[i].Delay = 10;
                                    }

                                    encoder.AddFrame(listFrames[i].Path, listFrames[i].Rect, listFrames[i].Delay);

                                    Update(id, i, string.Format(processing, i));

                                    #region Cancellation

                                    if (tokenSource.Token.IsCancellationRequested)
                                    {
                                        SetStatus(Status.Canceled, id);
                                        break;
                                    }

                                    #endregion
                                }
                            }

                            try
                            {
                                using (var fileStream = new FileStream(param.Filename, FileMode.Create, FileAccess.Write, FileShare.None, 4096))
                                    stream.WriteTo(fileStream);
                            }
                            catch (Exception ex)
                            {
                                SetStatus(Status.Error, id);
                                LogWriter.Log(ex, "Improved Encoding");
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.Legacy:

                        #region Legacy Encoding

                        using (var encoder = new AnimatedGifEncoder())
                        {
                            if (param.DummyColor.HasValue)
                            {
                                var color = Color.FromArgb(param.DummyColor.Value.R,
                                                           param.DummyColor.Value.G, param.DummyColor.Value.B);

                                encoder.SetTransparent(color);
                                encoder.SetDispose(1);         //Undraw Method, "Leave".
                            }

                            encoder.Start(param.Filename);
                            encoder.SetQuality(param.Quality);
                            encoder.SetRepeat(param.RepeatCount);

                            var numImage = 0;
                            foreach (var frame in listFrames)
                            {
                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion

                                if (!frame.HasArea && param.DetectUnchangedPixels)
                                {
                                    continue;
                                }

                                var bitmapAux = new Bitmap(frame.Path);

                                encoder.SetDelay(frame.Delay);
                                encoder.AddFrame(bitmapAux, frame.Rect.X, frame.Rect.Y);

                                bitmapAux.Dispose();

                                Update(id, numImage, string.Format(processing, numImage));
                                numImage++;
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.PaintNet:

                        #region paint.NET encoding

                        using (var stream = new MemoryStream())
                        {
                            using (var encoder = new GifEncoder(stream, null, null, param.RepeatCount))
                            {
                                for (var i = 0; i < listFrames.Count; i++)
                                {
                                    var bitmapAux = new Bitmap(listFrames[i].Path);
                                    encoder.AddFrame(bitmapAux, 0, 0, TimeSpan.FromMilliseconds(listFrames[i].Delay));
                                    bitmapAux.Dispose();

                                    Update(id, i, string.Format(processing, i));

                                    #region Cancellation

                                    if (tokenSource.Token.IsCancellationRequested)
                                    {
                                        SetStatus(Status.Canceled, id);

                                        break;
                                    }

                                    #endregion
                                }
                            }

                            stream.Position = 0;

                            try
                            {
                                using (var fileStream = new FileStream(param.Filename, FileMode.Create, FileAccess.Write, FileShare.None, Constants.BufferSize, false))
                                    stream.WriteTo(fileStream);
                            }
                            catch (Exception ex)
                            {
                                SetStatus(Status.Error, id);
                                LogWriter.Log(ex, "Encoding with paint.Net.");
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.FFmpeg:

                        #region FFmpeg encoding

                        SetStatus(Status.Processing, id, null, true);

                        if (!Util.Other.IsFfmpegPresent())
                        {
                            throw new ApplicationException("FFmpeg not present.");
                        }

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        #region Generate concat

                        var concat = new StringBuilder();
                        foreach (var frame in listFrames)
                        {
                            concat.AppendLine("file '" + frame.Path + "'");
                            concat.AppendLine("duration " + (frame.Delay / 1000d).ToString(CultureInfo.InvariantCulture));
                        }

                        var concatPath = Path.GetDirectoryName(listFrames[0].Path) ?? Path.GetTempPath();
                        var concatFile = Path.Combine(concatPath, "concat.txt");

                        if (!Directory.Exists(concatPath))
                        {
                            Directory.CreateDirectory(concatPath);
                        }

                        if (File.Exists(concatFile))
                        {
                            File.Delete(concatFile);
                        }

                        File.WriteAllText(concatFile, concat.ToString());

                        #endregion

                        param.Command = string.Format(param.Command, concatFile, param.ExtraParameters.Replace("{H}", param.Height.ToString()).Replace("{W}", param.Width.ToString()), param.Filename);

                        var process = new ProcessStartInfo(UserSettings.All.FfmpegLocation)
                        {
                            Arguments             = param.Command,
                            CreateNoWindow        = true,
                            ErrorDialog           = false,
                            UseShellExecute       = false,
                            RedirectStandardError = true
                        };

                        var pro = Process.Start(process);

                        var str = pro.StandardError.ReadToEnd();

                        var fileInfo = new FileInfo(param.Filename);

                        if (!fileInfo.Exists || fileInfo.Length == 0)
                        {
                            throw new Exception("Error while encoding the gif with FFmpeg.")
                                  {
                                      HelpLink = $"Command:\n\r{param.Command}\n\rResult:\n\r{str}"
                                  }
                        }
                        ;

                        #endregion

                        break;

                    case GifEncoderType.Gifski:

                        #region Gifski encoding

                        SetStatus(Status.Processing, id, null, true);

                        if (!Util.Other.IsGifskiPresent())
                        {
                            throw new ApplicationException("Gifski not present.");
                        }

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        var gifski = new GifskiInterop();
                        var handle = gifski.Start(UserSettings.All.GifskiQuality, UserSettings.All.Looped);

                        ThreadPool.QueueUserWorkItem(delegate
                        {
                            Thread.Sleep(500);
                            SetStatus(Status.Processing, id, null, false);

                            for (var i = 0; i < listFrames.Count; i++)
                            {
                                Update(id, i, string.Format(processing, i));
                                gifski.AddFrame(handle, (uint)i, listFrames[i].Path, listFrames[i].Delay);
                            }

                            gifski.EndAdding(handle);
                        }, null);

                        gifski.End(handle, param.Filename);

                        var fileInfo2 = new FileInfo(param.Filename);

                        if (!fileInfo2.Exists || fileInfo2.Length == 0)
                        {
                            throw new Exception("Error while encoding the gif with Gifski.", new Win32Exception())
                                  {
                                      HelpLink = $"Command:\n\r{param.Command}\n\rResult:\n\r{Marshal.GetLastWin32Error()}"
                                  }
                        }
                        ;

                        #endregion

                        break;

                    default:
                        throw new Exception("Undefined Gif encoder type");
                    }

                    #endregion

                    break;

                case Export.Apng:

                    #region Apng

                    #region Cut/Paint Unchanged Pixels

                    if (param.DetectUnchangedPixels)
                    {
                        Update(id, 0, FindResource("Encoder.Analyzing").ToString());

                        if (param.DummyColor.HasValue)
                        {
                            var color = Color.FromArgb(param.DummyColor.Value.A, param.DummyColor.Value.R, param.DummyColor.Value.G, param.DummyColor.Value.B);
                            listFrames = ImageMethods.PaintTransparentAndCut(listFrames, color, id, tokenSource);
                        }
                        else
                        {
                            listFrames = ImageMethods.CutUnchanged(listFrames, id, tokenSource);
                        }
                    }
                    else
                    {
                        var size = listFrames[0].Path.ScaledSize();
                        listFrames.ForEach(x => x.Rect = new Int32Rect(0, 0, (int)size.Width, (int)size.Height));
                    }

                    #endregion

                    #region Encoding

                    using (var stream = new MemoryStream())
                    {
                        var frameCount = listFrames.Count(x => x.HasArea);

                        using (var encoder = new Apng(stream, frameCount, param.RepeatCount))
                        {
                            for (var i = 0; i < listFrames.Count; i++)
                            {
                                if (!listFrames[i].HasArea && param.DetectUnchangedPixels)
                                {
                                    continue;
                                }

                                if (listFrames[i].Delay == 0)
                                {
                                    listFrames[i].Delay = 10;
                                }

                                encoder.AddFrame(listFrames[i].Path, listFrames[i].Rect, listFrames[i].Delay);

                                Update(id, i, string.Format(processing, i));

                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion
                            }
                        }

                        try
                        {
                            using (var fileStream = new FileStream(param.Filename, FileMode.Create, FileAccess.Write, FileShare.None, 4096))
                                stream.WriteTo(fileStream);
                        }
                        catch (Exception ex)
                        {
                            SetStatus(Status.Error, id);
                            LogWriter.Log(ex, "Apng Encoding");
                        }
                    }

                    #endregion

                    #endregion

                    break;

                case Export.Video:

                    #region Video

                    switch (param.VideoEncoder)
                    {
                    case VideoEncoderType.AviStandalone:

                        #region Avi Standalone

                        var image = listFrames[0].Path.SourceFrom();

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        //1000 / listFrames[0].Delay
                        using (var aviWriter = new AviWriter(param.Filename, param.Framerate, image.PixelWidth, image.PixelHeight, param.VideoQuality))
                        {
                            var numImage = 0;
                            foreach (var frame in listFrames)
                            {
                                using (var outStream = new MemoryStream())
                                {
                                    var bitImage = frame.Path.SourceFrom();

                                    var enc = new BmpBitmapEncoder();
                                    enc.Frames.Add(BitmapFrame.Create(bitImage));
                                    enc.Save(outStream);

                                    outStream.Flush();

                                    using (var bitmap = new Bitmap(outStream))
                                        aviWriter.AddFrame(bitmap, param.FlipVideo);
                                }

                                Update(id, numImage, string.Format(processing, numImage));
                                numImage++;

                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion
                            }
                        }

                        #endregion

                        break;

                    case VideoEncoderType.Ffmpg:

                        #region Video using FFmpeg

                        SetStatus(Status.Processing, id, null, true);

                        if (!Util.Other.IsFfmpegPresent())
                        {
                            throw new ApplicationException("FFmpeg not present.");
                        }

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        #region Generate concat

                        var concat = new StringBuilder();
                        foreach (var frame in listFrames)
                        {
                            concat.AppendLine("file '" + frame.Path + "'");
                            concat.AppendLine("duration " + (frame.Delay / 1000d).ToString(CultureInfo.InvariantCulture));
                        }

                        var concatPath = Path.GetDirectoryName(listFrames[0].Path) ?? Path.GetTempPath();
                        var concatFile = Path.Combine(concatPath, "concat.txt");

                        if (!Directory.Exists(concatPath))
                        {
                            Directory.CreateDirectory(concatPath);
                        }

                        if (File.Exists(concatFile))
                        {
                            File.Delete(concatFile);
                        }

                        File.WriteAllText(concatFile, concat.ToString());

                        #endregion

                        param.Command = string.Format(param.Command, concatFile, param.ExtraParameters.Replace("{H}", param.Height.ToString()).Replace("{W}", param.Width.ToString()), param.Filename);

                        var process = new ProcessStartInfo(UserSettings.All.FfmpegLocation)
                        {
                            Arguments             = param.Command,
                            CreateNoWindow        = true,
                            ErrorDialog           = false,
                            UseShellExecute       = false,
                            RedirectStandardError = true
                        };

                        var pro = Process.Start(process);

                        var str = pro.StandardError.ReadToEnd();

                        var fileInfo = new FileInfo(param.Filename);

                        if (!fileInfo.Exists || fileInfo.Length == 0)
                        {
                            throw new Exception("Error while encoding with FFmpeg.")
                                  {
                                      HelpLink = str
                                  }
                        }
                        ;

                        #endregion

                        break;

                    default:
                        throw new Exception("Undefined video encoder");
                    }

                    #endregion

                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(param));
                }

                //If it was canceled, try deleting the file.
                if (tokenSource.Token.IsCancellationRequested)
                {
                    if (File.Exists(param.Filename))
                    {
                        File.Delete(param.Filename);
                    }

                    SetStatus(Status.Canceled, id);
                    return;
                }

                #region Upload

                if (param.Upload && File.Exists(param.Filename))
                {
                    InternalUpdate(id, "Encoder.Uploading", true, true);

                    try
                    {
                        ICloud cloud = CloudFactory.CreateCloud(param.UploadDestinationIndex);

                        var uploadedFile = await cloud.UploadFileAsync(param.Filename, CancellationToken.None);

                        InternalSetUpload(id, true, uploadedFile.Link, uploadedFile.DeleteLink);
                    }
                    catch (Exception e)
                    {
                        LogWriter.Log(e, "It was not possible to run the post encoding command.");
                        InternalSetUpload(id, false, null, null, e);
                    }
                }

                #endregion

                #region Copy to clipboard

                if (param.CopyToClipboard && File.Exists(param.Filename))
                {
                    Dispatcher.Invoke(() =>
                    {
                        try
                        {
                            var data = new DataObject();

                            switch (param.CopyType)
                            {
                            case CopyType.File:
                                if (param.Type != Export.Video)
                                {
                                    data.SetImage(param.Filename.SourceFrom());
                                }

                                data.SetText(param.Filename, TextDataFormat.Text);
                                data.SetFileDropList(new StringCollection {
                                    param.Filename
                                });
                                break;

                            case CopyType.FolderPath:
                                data.SetText(Path.GetDirectoryName(param.Filename) ?? param.Filename, TextDataFormat.Text);
                                break;

                            case CopyType.Link:
                                var link = InternalGetUpload(id);

                                data.SetText(string.IsNullOrEmpty(link) ? param.Filename : link, TextDataFormat.Text);
                                break;

                            default:
                                data.SetText(param.Filename, TextDataFormat.Text);
                                break;
                            }

                            //It tries to set the data to the clipboard 10 times before failing it to do so.
                            //This issue may happen if the clipboard is opened by any clipboard manager.
                            for (var i = 0; i < 10; i++)
                            {
                                try
                                {
                                    Clipboard.SetDataObject(data, true);
                                    break;
                                }
                                catch (COMException ex)
                                {
                                    if ((uint)ex.ErrorCode != 0x800401D0) //CLIPBRD_E_CANT_OPEN
                                    {
                                        throw;
                                    }
                                }

                                Thread.Sleep(100);
                            }

                            InternalSetCopy(id, true);
                        }
                        catch (Exception e)
                        {
                            LogWriter.Log(e, "It was not possible to copy the file.");
                            InternalSetCopy(id, false, e);
                        }
                    });
                }

                #endregion

                #region Execute commands

                if (param.ExecuteCommands && !string.IsNullOrWhiteSpace(param.PostCommands))
                {
                    InternalUpdate(id, "Encoder.Executing", true, true);

                    var command = param.PostCommands.Replace("{p}", "\"" + param.Filename + "\"").Replace("{f}", "\"" + Path.GetDirectoryName(param.Filename) + "\"");
                    var output  = "";

                    try
                    {
                        foreach (var com in command.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            var procStartInfo = new ProcessStartInfo("cmd", "/c " + com)
                            {
                                RedirectStandardOutput = true,
                                RedirectStandardError  = true,
                                UseShellExecute        = false,
                                CreateNoWindow         = true
                            };

                            using (var process = new Process())
                            {
                                process.StartInfo = procStartInfo;
                                process.Start();

                                var message = process.StandardOutput.ReadToEnd();
                                var error   = process.StandardError.ReadToEnd();

                                if (!string.IsNullOrWhiteSpace(message))
                                {
                                    output += message + Environment.NewLine;
                                }

                                if (!string.IsNullOrWhiteSpace(message))
                                {
                                    output += message + Environment.NewLine;
                                }

                                if (!string.IsNullOrWhiteSpace(error))
                                {
                                    throw new Exception(error);
                                }

                                process.WaitForExit(1000);
                            }
                        }

                        InternalSetCommand(id, true, command, output);
                    }
                    catch (Exception e)
                    {
                        LogWriter.Log(e, "It was not possible to run the post encoding command.");
                        InternalSetCommand(id, false, command, output, e);
                    }
                }

                #endregion

                if (!tokenSource.Token.IsCancellationRequested)
                {
                    SetStatus(Status.Completed, id, param.Filename);
                }
            }
            catch (Exception ex)
            {
                LogWriter.Log(ex, "Encode");

                SetStatus(Status.Error, id, null, false, ex);
            }
            finally
            {
                #region Delete Encoder Folder

                try
                {
                    var encoderFolder = Path.GetDirectoryName(listFrames[0].Path);

                    if (!string.IsNullOrEmpty(encoderFolder))
                    {
                        if (Directory.Exists(encoderFolder))
                        {
                            Directory.Delete(encoderFolder, true);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogWriter.Log(ex, "Cleaning the Encode folder");
                }

                #endregion

                GC.Collect();
            }
        }
Пример #21
0
        private static BitmapDecoder GetDecoder(BitmapSource image, out GifFile gifFile)
        {
            gifFile = null;
            BitmapDecoder       decoder       = null;
            Stream              stream        = null;
            Uri                 uri           = null;
            BitmapCreateOptions createOptions = BitmapCreateOptions.None;

            var bmp = image as BitmapImage;

            if (bmp != null)
            {
                createOptions = bmp.CreateOptions;
                if (bmp.StreamSource != null)
                {
                    stream = bmp.StreamSource;
                }
                else if (bmp.UriSource != null)
                {
                    uri = bmp.UriSource;
                    if (bmp.BaseUri != null && !uri.IsAbsoluteUri)
                    {
                        uri = new Uri(bmp.BaseUri, uri);
                    }
                }
            }
            else
            {
                BitmapFrame frame = image as BitmapFrame;
                if (frame != null)
                {
                    decoder = frame.Decoder;
                    Uri.TryCreate(frame.BaseUri, frame.ToString(), out uri);
                }
            }

            if (decoder == null)
            {
                if (stream != null)
                {
                    stream.Position = 0;
                    decoder         = BitmapDecoder.Create(stream, createOptions, BitmapCacheOption.OnLoad);
                }
                else if (uri != null && uri.IsAbsoluteUri)
                {
                    decoder = BitmapDecoder.Create(uri, createOptions, BitmapCacheOption.OnLoad);
                }
            }

            if (decoder is GifBitmapDecoder && !CanReadNativeMetadata(decoder))
            {
                if (stream != null)
                {
                    stream.Position = 0;
                    gifFile         = GifFile.ReadGifFile(stream, true);
                }
                else if (uri != null)
                {
                    gifFile = DecodeGifFile(uri);
                }
            }
            return(decoder);
        }
Пример #22
0
    //生成动画
    static void GenerateAnimation(string name, GifFile gif, string path, ref AnimationInfo info)
    {
        AnimationClip clip = new AnimationClip();

        clip.name      = name;
        clip.frameRate = 25;

        //创建动画文件
        string asset = string.Format("{0}/{1}.anim", path, name);

        AssetDatabase.CreateAsset(clip, asset);

        SpriteImportData[] spriteImportData = new SpriteImportData[0];
        Texture2D          atlas            = AtlasGenerator.GenerateAtlas(gif, out spriteImportData);

        atlas.filterMode = FilterMode.Point;
        atlas.name       = name;
        //AssetDatabase.AddObjectToAsset(atlas, clip);

        byte[] pngBytes  = atlas.EncodeToPNG();
        string atlasPath = string.Format("{0}/{1}.png", path, name);

        File.WriteAllBytes(atlasPath, pngBytes);
        AssetDatabase.Refresh();

        //生成的贴图
        Texture2D atlasObject = (Texture2D)AssetDatabase.LoadAssetAtPath(atlasPath, typeof(Texture2D));

        atlasObject.filterMode = FilterMode.Point;

        //生成贴图
        List <Sprite> sprites = GenerateSprites(atlasObject, spriteImportData, clip);

        //帧数
        int length = sprites.Count;

        EditorCurveBinding spriteBinding = new EditorCurveBinding();

        spriteBinding.type         = typeof(SpriteRenderer);
        spriteBinding.path         = "";
        spriteBinding.propertyName = "m_Sprite";

        //设置帧信息
        ObjectReferenceKeyframe[] spriteKeyFrames = new ObjectReferenceKeyframe[length + 1];

        float time = 0;

        for (int i = 0; i < length; i++)
        {
            ObjectReferenceKeyframe frame = new ObjectReferenceKeyframe();
            frame.time  = time;
            frame.value = sprites[i];
            time       += gif.textureList[i].m_delaySec;

            spriteKeyFrames[i] = frame;
        }

        //单独设置最后一帧
        float frameTime = 1f / clip.frameRate;
        ObjectReferenceKeyframe lastFrame = new ObjectReferenceKeyframe();

        lastFrame.time  = time - frameTime;
        lastFrame.value = sprites[length - 1];
        spriteKeyFrames[spriteKeyFrames.Length - 1] = lastFrame;

        AnimationUtility.SetObjectReferenceCurve(clip, spriteBinding, spriteKeyFrames);

        //循环设置
        AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(clip);

        //循环设置
        //if (animationSetting.loop) {
        //    settings.loopTime = true;
        //    clip.wrapMode = WrapMode.Loop;
        //} else {
        //    settings.loopTime = false;
        //    clip.wrapMode = WrapMode.Once;
        //}

        AnimationUtility.SetAnimationClipSettings(clip, settings);

        info.animationClip = clip;
        info.texture       = atlasObject;
    }
Пример #23
0
        public static ObjectAnimationUsingKeyFrames CreateGifAnimation(GifBitmapDecoder decoder, GifFile gifMetadata)
        {
            ObjectAnimationUsingKeyFrames animation;
            var fullSize = GetFullSize(decoder, gifMetadata);
            int index    = 0;

            animation = new ObjectAnimationUsingKeyFrames();
            var          totalDuration = TimeSpan.Zero;
            BitmapSource baseFrame     = null;

            foreach (var rawFrame in decoder.Frames)
            {
                var metadata = GetFrameMetadata(decoder, gifMetadata, index);

                var frame    = MakeFrame(fullSize, rawFrame, metadata, baseFrame);
                var keyFrame = new DiscreteObjectKeyFrame(frame, totalDuration);
                animation.KeyFrames.Add(keyFrame);

                totalDuration += metadata.Delay;

                switch (metadata.DisposalMethod)
                {
                case FrameDisposalMethod.None:
                case FrameDisposalMethod.DoNotDispose:
                    baseFrame = frame;
                    break;

                case FrameDisposalMethod.RestoreBackground:
                    if (IsFullFrame(metadata, fullSize))
                    {
                        baseFrame = null;
                    }
                    else
                    {
                        baseFrame = ClearArea(frame, metadata);
                    }

                    break;

                case FrameDisposalMethod.RestorePrevious:
                    // Reuse same base frame
                    break;
                }

                index++;
            }

            animation.Duration = totalDuration;


            return(animation);
        }
Пример #24
0
        protected override ImpImage Load(string path, out ImpError error)
        {
            error = null;
            var myUri = new Uri(path, UriKind.RelativeOrAbsolute);
            var type  = GetType(path);

            BitmapDecoder decoder = null;

            try
            {
                switch (type)
                {
                case ImageType.Jpg:
                    try
                    {
                        decoder = new JpegBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
                                                        BitmapCacheOption.OnLoad);
                    }
                    catch (Exception)
                    {
                        var impJpgDecoder = new ImpJpgDecoder(myUri);
                        return(new ImpImage(impJpgDecoder.Source));
                    }
                    break;

                case ImageType.Png:
                    try
                    {
                        decoder = new PngBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
                                                       BitmapCacheOption.OnLoad);
                    }
                    catch (Exception)
                    {
                        var impPngDecoder = new ImpPngDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
                                                              BitmapCacheOption.OnLoad);
                        return(new ImpImage(impPngDecoder.Source));
                    }
                    break;

                case ImageType.Gif:
                    decoder = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
                                                   BitmapCacheOption.OnLoad);

                    if (decoder.Frames.Count > 1)
                    {
                        using (var stream = new FileStream(myUri.AbsolutePath, FileMode.Open))
                        {
                            var gifFile = GifFile.ReadGifFile(stream, true);
                            return(new ImpImage((GifBitmapDecoder)decoder, gifFile));
                        }
                    }
                    break;

                case ImageType.Bmp:
                    decoder = new BmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
                                                   BitmapCacheOption.OnLoad);
                    break;

                case ImageType.Tiff:
                    decoder = new TiffBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
                                                    BitmapCacheOption.OnLoad);
                    break;

                case ImageType.Tga:
                    error = new ImpError(ErrorType.NotSupportedFile);
                    break;

                case ImageType.Icon:
                    decoder = new IconBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
                                                    BitmapCacheOption.OnLoad);
                    break;

                case ImageType.WindowsMediaPhoto:
                    decoder = new WmpBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat,
                                                   BitmapCacheOption.OnLoad);
                    break;

                default:
                    error = new ImpError(ErrorType.UnknownFileType);
                    break;
                }
            }
            catch (Exception)
            {
                error = new ImpError(ErrorType.FailedToOpenFile);
            }

            if (error != null)
            {
                return(null);
            }

            return(new ImpImage(decoder));
        }
Пример #25
0
        private static BitmapDecoder GetDecoder(BitmapSource image, out GifFile gifFile)
        {
            gifFile = (GifFile)null;
            BitmapDecoder       decoder       = (BitmapDecoder)null;
            Stream              stream        = (Stream)null;
            Uri                 result        = (Uri)null;
            BitmapCreateOptions createOptions = BitmapCreateOptions.None;

            if (image is BitmapImage bitmapImage)
            {
                createOptions = bitmapImage.CreateOptions;
                if (bitmapImage.StreamSource != null)
                {
                    stream = bitmapImage.StreamSource;
                }
                else if (bitmapImage.UriSource != (Uri)null)
                {
                    result = bitmapImage.UriSource;
                    if (bitmapImage.BaseUri != (Uri)null && !result.IsAbsoluteUri)
                    {
                        result = new Uri(bitmapImage.BaseUri, result);
                    }
                }
            }
            else if (image is BitmapFrame bitmapFrame)
            {
                decoder = bitmapFrame.Decoder;
                Uri.TryCreate(bitmapFrame.BaseUri, bitmapFrame.ToString((IFormatProvider)CultureInfo.InvariantCulture), out result);
            }
            if (decoder == null)
            {
                if (stream != null)
                {
                    stream.Position = 0L;
                    decoder         = BitmapDecoder.Create(stream, createOptions, BitmapCacheOption.OnLoad);
                }
                else if (result != (Uri)null && result.IsAbsoluteUri)
                {
                    decoder = BitmapDecoder.Create(result, createOptions, BitmapCacheOption.OnLoad);
                }
            }
            if (decoder is GifBitmapDecoder && !ImageBehavior.CanReadNativeMetadata(decoder))
            {
                if (stream != null)
                {
                    stream.Position = 0L;
                    gifFile         = GifFile.ReadGifFile(stream, true);
                }
                else
                {
                    if (!(result != (Uri)null))
                    {
                        throw new InvalidOperationException("Can't get URI or Stream from the source. AnimatedSource should be either a BitmapImage, or a BitmapFrame constructed from a URI.");
                    }
                    gifFile = ImageBehavior.DecodeGifFile(result);
                }
            }
            if (decoder == null)
            {
                throw new InvalidOperationException("Can't get a decoder from the source. AnimatedSource should be either a BitmapImage or a BitmapFrame.");
            }
            return(decoder);
        }
Пример #26
0
        private static RepeatBehavior GetActualRepeatBehavior(Image imageControl, BitmapDecoder decoder, GifFile gifMetadata)
        {
            // If specified explicitly, use this value
            var repeatBehavior = GetRepeatBehavior(imageControl);

            if (repeatBehavior != default(RepeatBehavior))
            {
                return(repeatBehavior);
            }

            int repeatCount;

            if (gifMetadata != null)
            {
                repeatCount = gifMetadata.RepeatCount;
            }
            else
            {
                repeatCount = GetRepeatCount(decoder);
            }
            if (repeatCount == 0)
            {
                return(RepeatBehavior.Forever);
            }
            return(new RepeatBehavior(repeatCount));
        }
Пример #27
0
        private void Encode(List <FrameInfo> listFrames, int id, Parameters param, CancellationTokenSource tokenSource)
        {
            var processing = FindResource("Encoder.Processing").ToString();

            try
            {
                switch (param.Type)
                {
                case Export.Gif:

                    #region Gif

                    var gifParam = (GifParameters)param;

                    #region Cut/Paint Unchanged Pixels

                    if (gifParam.DetectUnchangedPixels && (gifParam.EncoderType == GifEncoderType.Legacy || gifParam.EncoderType == GifEncoderType.ScreenToGif))
                    {
                        Update(id, 0, FindResource("Encoder.Analyzing").ToString());

                        if (gifParam.DummyColor.HasValue)
                        {
                            var color = Color.FromArgb(gifParam.DummyColor.Value.R, gifParam.DummyColor.Value.G, gifParam.DummyColor.Value.B);

                            listFrames = ImageMethods.PaintTransparentAndCut(listFrames, color, id, tokenSource);
                        }
                        else
                        {
                            listFrames = ImageMethods.CutUnchanged(listFrames, id, tokenSource);
                        }
                    }

                    #endregion

                    switch (gifParam.EncoderType)
                    {
                    case GifEncoderType.ScreenToGif:

                        #region Improved encoding

                        using (var stream = new MemoryStream())
                        {
                            using (var encoder = new GifFile(stream, gifParam.RepeatCount))
                            {
                                encoder.UseGlobalColorTable = gifParam.UseGlobalColorTable;
                                encoder.TransparentColor    = gifParam.DummyColor;
                                encoder.MaximumNumberColor  = gifParam.MaximumNumberColors;

                                for (var i = 0; i < listFrames.Count; i++)
                                {
                                    if (!listFrames[i].HasArea)
                                    {
                                        continue;
                                    }

                                    if (listFrames[i].Delay == 0)
                                    {
                                        listFrames[i].Delay = 10;
                                    }

                                    encoder.AddFrame(listFrames[i].ImageLocation, listFrames[i].Rect, listFrames[i].Delay);

                                    Update(id, i, string.Format(processing, i));

                                    #region Cancellation

                                    if (tokenSource.Token.IsCancellationRequested)
                                    {
                                        SetStatus(Status.Canceled, id);

                                        break;
                                    }

                                    #endregion
                                }
                            }

                            try
                            {
                                using (var fileStream = new FileStream(gifParam.Filename, FileMode.Create, FileAccess.Write, FileShare.None, 4096))
                                {
                                    stream.WriteTo(fileStream);
                                }
                            }
                            catch (Exception ex)
                            {
                                SetStatus(Status.Error, id);
                                LogWriter.Log(ex, "Improved Encoding");
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.Legacy:

                        #region Legacy Encoding

                        using (var encoder = new AnimatedGifEncoder())
                        {
                            if (gifParam.DummyColor.HasValue)
                            {
                                var color = Color.FromArgb(gifParam.DummyColor.Value.R,
                                                           gifParam.DummyColor.Value.G, gifParam.DummyColor.Value.B);

                                encoder.SetTransparent(color);
                                encoder.SetDispose(1);         //Undraw Method, "Leave".
                            }

                            encoder.Start(gifParam.Filename);
                            encoder.SetQuality(gifParam.Quality);
                            encoder.SetRepeat(gifParam.RepeatCount);

                            var numImage = 0;
                            foreach (var frame in listFrames)
                            {
                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion

                                if (!frame.HasArea && gifParam.DetectUnchangedPixels)
                                {
                                    continue;
                                }

                                var bitmapAux = new Bitmap(frame.ImageLocation);

                                encoder.SetDelay(frame.Delay);
                                encoder.AddFrame(bitmapAux, frame.Rect.X, frame.Rect.Y);

                                bitmapAux.Dispose();

                                Update(id, numImage, string.Format(processing, numImage));
                                numImage++;
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.PaintNet:

                        #region paint.NET encoding

                        using (var stream = new MemoryStream())
                        {
                            using (var encoder = new GifEncoder(stream, null, null, gifParam.RepeatCount))
                            {
                                for (var i = 0; i < listFrames.Count; i++)
                                {
                                    var bitmapAux = new Bitmap(listFrames[i].ImageLocation);
                                    encoder.AddFrame(bitmapAux, 0, 0, TimeSpan.FromMilliseconds(listFrames[i].Delay));
                                    bitmapAux.Dispose();

                                    Update(id, i, string.Format(processing, i));

                                    #region Cancellation

                                    if (tokenSource.Token.IsCancellationRequested)
                                    {
                                        SetStatus(Status.Canceled, id);

                                        break;
                                    }

                                    #endregion
                                }
                            }

                            stream.Position = 0;

                            try
                            {
                                using (var fileStream = new FileStream(gifParam.Filename, FileMode.Create, FileAccess.Write, FileShare.None, Constants.BufferSize, false))
                                {
                                    stream.WriteTo(fileStream);
                                }
                            }
                            catch (Exception ex)
                            {
                                SetStatus(Status.Error, id);
                                LogWriter.Log(ex, "Encoding with paint.Net.");
                            }
                        }

                        #endregion

                        break;

                    default:
                        throw new Exception("Undefined Gif encoder type");
                    }

                    #endregion

                    break;

                case Export.Video:

                    #region Video

                    var videoParam = (VideoParameters)param;

                    switch (videoParam.VideoEncoder)
                    {
                    case VideoEncoderType.AviStandalone:

                        #region Avi Standalone

                        var image = listFrames[0].ImageLocation.SourceFrom();

                        using (var aviWriter = new AviWriter(videoParam.Filename, 1000 / listFrames[0].Delay, image.PixelWidth, image.PixelHeight, videoParam.Quality))
                        {
                            var numImage = 0;
                            foreach (var frame in listFrames)
                            {
                                using (var outStream = new MemoryStream())
                                {
                                    var bitImage = frame.ImageLocation.SourceFrom();

                                    var enc = new BmpBitmapEncoder();
                                    enc.Frames.Add(BitmapFrame.Create(bitImage));
                                    enc.Save(outStream);

                                    outStream.Flush();

                                    using (var bitmap = new Bitmap(outStream))
                                    {
                                        aviWriter.AddFrame(bitmap);
                                    }
                                }

                                //aviWriter.AddFrame(new BitmapImage(new Uri(frame.ImageLocation)));

                                Update(id, numImage, string.Format(processing, numImage));
                                numImage++;

                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion
                            }
                        }

                        #endregion

                        break;

                    case VideoEncoderType.Ffmpg:

                        #region Video using FFmpeg

                        SetStatus(Status.Encoding, id, null, true);

                        if (!Util.Other.IsFfmpegPresent())
                        {
                            throw new ApplicationException("FFmpeg not present.");
                        }

                        videoParam.Command = string.Format(videoParam.Command,
                                                           Path.Combine(Path.GetDirectoryName(listFrames[0].ImageLocation), "%d.png"),
                                                           videoParam.ExtraParameters, videoParam.Framerate,
                                                           param.Filename);

                        var process = new ProcessStartInfo(Settings.Default.FfmpegLocation)
                        {
                            Arguments             = videoParam.Command,
                            CreateNoWindow        = true,
                            ErrorDialog           = false,
                            UseShellExecute       = false,
                            RedirectStandardError = true
                        };

                        var pro = Process.Start(process);

                        var str = pro.StandardError.ReadToEnd();

                        var fileInfo = new FileInfo(param.Filename);

                        if (!fileInfo.Exists || fileInfo.Length == 0)
                        {
                            throw new Exception("Error while encoding with FFmpeg.", new Exception(str));
                        }

                        #endregion

                        break;

                    default:
                        throw new Exception("Undefined video encoder");
                    }

                    #endregion

                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(param));
                }

                if (!tokenSource.Token.IsCancellationRequested)
                {
                    SetStatus(Status.Completed, id, param.Filename);
                }
            }
            catch (Exception ex)
            {
                LogWriter.Log(ex, "Encode");

                SetStatus(Status.Error, id, null, false, ex.Message);
            }
            finally
            {
                #region Delete Encoder Folder

                try
                {
                    var encoderFolder = Path.GetDirectoryName(listFrames[0].ImageLocation);

                    if (!string.IsNullOrEmpty(encoderFolder))
                    {
                        if (Directory.Exists(encoderFolder))
                        {
                            Directory.Delete(encoderFolder, true);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogWriter.Log(ex, "Cleaning the Encode folder");
                }

                #endregion

                GC.Collect();
            }
        }
Пример #28
0
        private async void Encode(ProjectInfo project, int id, Parameters param, CancellationTokenSource tokenSource)
        {
            var processing = this.DispatcherStringResource("Encoder.Processing");

            var listFrames = project.Frames;

            try
            {
                switch (param.Type)
                {
                case Export.Gif:

                    #region Gif

                    switch (param.EncoderType)
                    {
                    case GifEncoderType.ScreenToGif:

                        #region Improved encoding

                        using (var stream = new MemoryStream())
                        {
                            using (var encoder = new GifFile(stream, param.RepeatCount))
                            {
                                encoder.UseGlobalColorTable = param.UseGlobalColorTable;
                                encoder.TransparentColor    = param.DummyColor;
                                encoder.MaximumNumberColor  = param.MaximumNumberColors;

                                for (var i = 0; i < listFrames.Count; i++)
                                {
                                    encoder.AddFrame(listFrames[i].FullPath, project.FrameSize, listFrames[i].Delay);

                                    Update(id, i, string.Format(processing, i));

                                    #region Cancellation

                                    if (tokenSource.Token.IsCancellationRequested)
                                    {
                                        SetStatus(Status.Canceled, id);
                                        break;
                                    }

                                    #endregion
                                }
                            }

                            try
                            {
                                using (var fileStream = new FileStream(param.Filename, FileMode.Create, FileAccess.Write, FileShare.None, 4096))
                                    stream.WriteTo(fileStream);
                            }
                            catch (Exception ex)
                            {
                                SetStatus(Status.Error, id);
                                LogWriter.Log(ex, "Improved Encoding");
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.Legacy:

                        #region Legacy Encoding

                        using (var encoder = new AnimatedGifEncoder())
                        {
                            if (param.DummyColor.HasValue)
                            {
                                encoder.SetTransparent(param.DummyColor.Value);
                                encoder.SetDispose(1);         //Undraw Method, "Leave".
                            }

                            encoder.Start(param.Filename);
                            encoder.SetQuality(param.Quality);
                            encoder.SetRepeat(param.RepeatCount);

                            var numImage = 0;
                            foreach (var frame in listFrames)
                            {
                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion


                                var bitmapAux = new Bitmap(frame.FullPath);

                                encoder.SetDelay(frame.Delay);
                                encoder.AddFrame(bitmapAux, project.FrameSize.X, project.FrameSize.Y);

                                bitmapAux.Dispose();

                                Update(id, numImage, string.Format(processing, numImage));
                                numImage++;
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.PaintNet:

                        #region paint.NET encoding

                        using (var stream = new MemoryStream())
                        {
                            using (var encoder = new GifEncoder(stream, null, null, param.RepeatCount))
                            {
                                for (var i = 0; i < listFrames.Count; i++)
                                {
                                    var bitmapAux = new Bitmap(listFrames[i].FullPath);
                                    encoder.AddFrame(bitmapAux, 0, 0, TimeSpan.FromMilliseconds(listFrames[i].Delay));
                                    bitmapAux.Dispose();

                                    Update(id, i, string.Format(processing, i));

                                    #region Cancellation

                                    if (tokenSource.Token.IsCancellationRequested)
                                    {
                                        SetStatus(Status.Canceled, id);

                                        break;
                                    }

                                    #endregion
                                }
                            }

                            stream.Position = 0;

                            try
                            {
                                using (var fileStream = new FileStream(param.Filename, FileMode.Create, FileAccess.Write, FileShare.None, Constants.BufferSize, false))
                                    stream.WriteTo(fileStream);
                            }
                            catch (Exception ex)
                            {
                                SetStatus(Status.Error, id);
                                LogWriter.Log(ex, "Encoding with paint.Net.");
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.FFmpeg:

                        #region FFmpeg encoding

                        SetStatus(Status.Processing, id, null, true);

                        if (!Util.Other.IsFfmpegPresent())
                        {
                            throw new ApplicationException("FFmpeg not present.");
                        }

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        #region Generate concat

                        var concat = new StringBuilder();
                        foreach (var frame in listFrames)
                        {
                            concat.AppendLine("file '" + frame.FullPath + "'");
                            concat.AppendLine("duration " + (frame.Delay / 1000d).ToString(CultureInfo.InvariantCulture));
                        }

                        var concatPath = Path.GetDirectoryName(listFrames[0].FullPath) ?? Path.GetTempPath();
                        var concatFile = Path.Combine(concatPath, "concat.txt");

                        if (!Directory.Exists(concatPath))
                        {
                            Directory.CreateDirectory(concatPath);
                        }

                        if (File.Exists(concatFile))
                        {
                            File.Delete(concatFile);
                        }

                        File.WriteAllText(concatFile, concat.ToString());

                        #endregion

                        param.Command = string.Format(param.Command, concatFile, param.ExtraParameters.Replace("{H}", param.Height.ToString()).Replace("{W}", param.Width.ToString()), param.Filename);

                        var process = new ProcessStartInfo(UserSettings.All.FfmpegLocation)
                        {
                            Arguments             = param.Command,
                            CreateNoWindow        = true,
                            ErrorDialog           = false,
                            UseShellExecute       = false,
                            RedirectStandardError = true
                        };

                        var pro = Process.Start(process);

                        var str = pro.StandardError.ReadToEnd();

                        var fileInfo = new FileInfo(param.Filename);

                        if (!fileInfo.Exists || fileInfo.Length == 0)
                        {
                            throw new Exception("Error while encoding the gif with FFmpeg.")
                                  {
                                      HelpLink = $"Command:\n\r{param.Command}\n\rResult:\n\r{str}"
                                  }
                        }
                        ;

                        #endregion

                        break;

                    case GifEncoderType.Gifski:

                        #region Gifski encoding

                        SetStatus(Status.Processing, id, null, true);

                        if (!Util.Other.IsGifskiPresent())
                        {
                            throw new ApplicationException("Gifski not present.");
                        }

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        var gifski = new GifskiInterop();
                        var handle = gifski.Start(UserSettings.All.GifskiQuality, UserSettings.All.Looped);

                        ThreadPool.QueueUserWorkItem(delegate
                        {
                            Thread.Sleep(500);
                            SetStatus(Status.Processing, id, null, false);

                            for (var i = 0; i < listFrames.Count; i++)
                            {
                                Update(id, i, string.Format(processing, i));
                                gifski.AddFrame(handle, (uint)i, listFrames[i].FullPath, listFrames[i].Delay);
                            }

                            gifski.EndAdding(handle);
                        }, null);

                        gifski.End(handle, param.Filename);

                        var fileInfo2 = new FileInfo(param.Filename);

                        if (!fileInfo2.Exists || fileInfo2.Length == 0)
                        {
                            throw new Exception("Error while encoding the gif with Gifski.", new Win32Exception())
                                  {
                                      HelpLink = $"Result:\n\r{Marshal.GetLastWin32Error()}"
                                  }
                        }
                        ;

                        #endregion

                        break;

                    default:
                        throw new Exception("Undefined Gif encoder type");
                    }

                    #endregion

                    break;

                case Export.Apng:

                    #region Apng

                    switch (param.ApngEncoder)
                    {
                    case ApngEncoderType.ScreenToGif:
                    {
                        #region Encoding

                        using (var stream = new MemoryStream())
                        {
                            var frameCount = listFrames.Count;

                            using (var encoder = new Apng(stream, frameCount, param.RepeatCount))
                            {
                                for (var i = 0; i < listFrames.Count; i++)
                                {
                                    encoder.AddFrame(listFrames[i].FullPath, project.FrameSize, listFrames[i].Delay);

                                    Update(id, i, string.Format(processing, i));

                                    #region Cancellation

                                    if (tokenSource.Token.IsCancellationRequested)
                                    {
                                        SetStatus(Status.Canceled, id);
                                        break;
                                    }

                                    #endregion
                                }
                            }

                            try
                            {
                                using (var fileStream = new FileStream(param.Filename, FileMode.Create, FileAccess.Write, FileShare.None, 4096))
                                    stream.WriteTo(fileStream);
                            }
                            catch (Exception ex)
                            {
                                SetStatus(Status.Error, id);
                                LogWriter.Log(ex, "Apng Encoding");
                            }
                        }

                        #endregion
                        break;
                    }

                    case ApngEncoderType.FFmpeg:
                    {
                        #region FFmpeg encoding

                        SetStatus(Status.Processing, id, null, true);

                        if (!Util.Other.IsFfmpegPresent())
                        {
                            throw new ApplicationException("FFmpeg not present.");
                        }

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        #region Generate concat

                        var concat = new StringBuilder();
                        foreach (var frame in listFrames)
                        {
                            concat.AppendLine("file '" + frame.FullPath + "'");
                            concat.AppendLine("duration " + (frame.Delay / 1000d).ToString(CultureInfo.InvariantCulture));
                        }

                        var concatPath = Path.GetDirectoryName(listFrames[0].FullPath) ?? Path.GetTempPath();
                        var concatFile = Path.Combine(concatPath, "concat.txt");

                        if (!Directory.Exists(concatPath))
                        {
                            Directory.CreateDirectory(concatPath);
                        }

                        if (File.Exists(concatFile))
                        {
                            File.Delete(concatFile);
                        }

                        File.WriteAllText(concatFile, concat.ToString());

                        #endregion

                        param.Command = string.Format(param.Command, concatFile, param.ExtraParameters.Replace("{H}", param.Height.ToString()).Replace("{W}", param.Width.ToString()), param.RepeatCount, param.Filename);

                        var process = new ProcessStartInfo(UserSettings.All.FfmpegLocation)
                        {
                            Arguments             = param.Command,
                            CreateNoWindow        = true,
                            ErrorDialog           = false,
                            UseShellExecute       = false,
                            RedirectStandardError = true
                        };

                        var pro = Process.Start(process);

                        var str = pro.StandardError.ReadToEnd();

                        var fileInfo = new FileInfo(param.Filename);

                        if (!fileInfo.Exists || fileInfo.Length == 0)
                        {
                            throw new Exception("Error while encoding the apng with FFmpeg.")
                                  {
                                      HelpLink = $"Command:\n\r{param.Command}\n\rResult:\n\r{str}"
                                  }
                        }
                        ;

                        #endregion

                        break;
                    }
                    }

                    #endregion

                    break;

                case Export.Video:

                    #region Video

                    switch (param.VideoEncoder)
                    {
                    case VideoEncoderType.AviStandalone:

                        #region Avi Standalone

                        var image = listFrames[0].FullPath.SourceFrom();

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        //1000 / listFrames[0].Delay
                        using (var aviWriter = new AviWriter(param.Filename, param.Framerate, image.PixelWidth, image.PixelHeight, param.VideoQuality))
                        {
                            var numImage = 0;
                            foreach (var frame in listFrames)
                            {
                                using (var outStream = new MemoryStream())
                                {
                                    var bitImage = frame.FullPath.SourceFrom();

                                    var enc = new BmpBitmapEncoder();
                                    enc.Frames.Add(BitmapFrame.Create(bitImage));
                                    enc.Save(outStream);

                                    outStream.Flush();

                                    using (var bitmap = new Bitmap(outStream))
                                        aviWriter.AddFrame(bitmap, param.FlipVideo);
                                }

                                Update(id, numImage, string.Format(processing, numImage));
                                numImage++;

                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion
                            }
                        }

                        #endregion

                        break;

                    case VideoEncoderType.Ffmpg:

                        #region Video using FFmpeg

                        SetStatus(Status.Processing, id, null, true);

                        if (!Util.Other.IsFfmpegPresent())
                        {
                            throw new ApplicationException("FFmpeg not present.");
                        }

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        #region Generate concat

                        var concat = new StringBuilder();
                        foreach (var frame in listFrames)
                        {
                            concat.AppendLine("file '" + frame.FullPath + "'");
                            concat.AppendLine("duration " + (frame.Delay / 1000d).ToString(CultureInfo.InvariantCulture));
                        }

                        var concatPath = Path.GetDirectoryName(listFrames[0].FullPath) ?? Path.GetTempPath();
                        var concatFile = Path.Combine(concatPath, "concat.txt");

                        if (!Directory.Exists(concatPath))
                        {
                            Directory.CreateDirectory(concatPath);
                        }

                        if (File.Exists(concatFile))
                        {
                            File.Delete(concatFile);
                        }

                        File.WriteAllText(concatFile, concat.ToString());

                        #endregion

                        param.Command = string.Format(param.Command, concatFile, param.ExtraParameters.Replace("{H}", param.Height.ToString()).Replace("{W}", param.Width.ToString()), param.Filename);

                        var process = new ProcessStartInfo(UserSettings.All.FfmpegLocation)
                        {
                            Arguments             = param.Command,
                            CreateNoWindow        = true,
                            ErrorDialog           = false,
                            UseShellExecute       = false,
                            RedirectStandardError = true
                        };

                        var pro = Process.Start(process);

                        var str = pro.StandardError.ReadToEnd();

                        var fileInfo = new FileInfo(param.Filename);

                        if (!fileInfo.Exists || fileInfo.Length == 0)
                        {
                            throw new Exception("Error while encoding with FFmpeg.")
                                  {
                                      HelpLink = str
                                  }
                        }
                        ;

                        #endregion

                        break;

                    default:
                        throw new Exception("Undefined video encoder");
                    }

                    #endregion

                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(param));
                }

                //If it was canceled, try deleting the file.
                if (tokenSource.Token.IsCancellationRequested)
                {
                    if (File.Exists(param.Filename))
                    {
                        File.Delete(param.Filename);
                    }

                    SetStatus(Status.Canceled, id);
                    return;
                }

                #region Execute commands

#if !UWP
                if (param.ExecuteCommands && !string.IsNullOrWhiteSpace(param.PostCommands))
                {
                    InternalUpdate(id, "Encoder.Executing", true, true);

                    var command = param.PostCommands.Replace("{p}", "\"" + param.Filename + "\"").Replace("{f}", "\"" + Path.GetDirectoryName(param.Filename) + "\"");
                    var output  = "";

                    try
                    {
                        foreach (var com in command.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            var procStartInfo = new ProcessStartInfo("cmd", "/c " + com)
                            {
                                RedirectStandardOutput = true,
                                RedirectStandardError  = true,
                                UseShellExecute        = false,
                                CreateNoWindow         = true
                            };

                            using (var process = new Process())
                            {
                                process.StartInfo = procStartInfo;
                                process.Start();

                                var message = process.StandardOutput.ReadToEnd();
                                var error   = process.StandardError.ReadToEnd();

                                if (!string.IsNullOrWhiteSpace(message))
                                {
                                    output += message + Environment.NewLine;
                                }

                                if (!string.IsNullOrWhiteSpace(message))
                                {
                                    output += message + Environment.NewLine;
                                }

                                if (!string.IsNullOrWhiteSpace(error))
                                {
                                    throw new Exception(error);
                                }

                                process.WaitForExit(1000);
                            }
                        }

                        InternalSetCommand(id, true, command, output);
                    }
                    catch (Exception e)
                    {
                        LogWriter.Log(e, "It was not possible to run the post encoding command.");
                        InternalSetCommand(id, false, command, output, e);
                    }
                }
#endif

                #endregion

                if (!tokenSource.Token.IsCancellationRequested)
                {
                    SetStatus(Status.Completed, id, param.Filename);
                }
            }
            catch (Exception ex)
            {
                LogWriter.Log(ex, "Encode");

                SetStatus(Status.Error, id, null, false, ex);
            }
            finally
            {
                #region Delete Encoder Folder

                try
                {
                    var encoderFolder = Path.GetDirectoryName(listFrames[0].FullPath);

                    if (!string.IsNullOrEmpty(encoderFolder))
                    {
                        if (Directory.Exists(encoderFolder))
                        {
                            Directory.Delete(encoderFolder, true);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogWriter.Log(ex, "Cleaning the Encode folder");
                }

                #endregion

                GC.Collect();
            }
        }
Пример #29
0
        private void Encode(List <FrameInfo> listFrames, int id, Parameters param, CancellationTokenSource tokenSource)
        {
            var processing = FindResource("Encoder.Processing").ToString();

            try
            {
                switch (param.Type)
                {
                case Export.Gif:

                    #region Gif

                    #region Cut/Paint Unchanged Pixels

                    if (param.EncoderType == GifEncoderType.Legacy || param.EncoderType == GifEncoderType.ScreenToGif)
                    {
                        if (param.DetectUnchangedPixels)
                        {
                            Update(id, 0, FindResource("Encoder.Analyzing").ToString());

                            if (param.DummyColor.HasValue)
                            {
                                var color = Color.FromArgb(param.DummyColor.Value.R, param.DummyColor.Value.G, param.DummyColor.Value.B);

                                listFrames = ImageMethods.PaintTransparentAndCut(listFrames, color, id, tokenSource);
                            }
                            else
                            {
                                listFrames = ImageMethods.CutUnchanged(listFrames, id, tokenSource);
                            }
                        }
                        else
                        {
                            var size = listFrames[0].Path.ScaledSize();
                            listFrames.ForEach(x => x.Rect = new Int32Rect(0, 0, (int)size.Width, (int)size.Height));
                        }
                    }

                    #endregion

                    switch (param.EncoderType)
                    {
                    case GifEncoderType.ScreenToGif:

                        #region Improved encoding

                        using (var stream = new MemoryStream())
                        {
                            using (var encoder = new GifFile(stream, param.RepeatCount))
                            {
                                encoder.UseGlobalColorTable = param.UseGlobalColorTable;
                                encoder.TransparentColor    = param.DummyColor;
                                encoder.MaximumNumberColor  = param.MaximumNumberColors;

                                for (var i = 0; i < listFrames.Count; i++)
                                {
                                    if (!listFrames[i].HasArea && param.DetectUnchangedPixels)
                                    {
                                        continue;
                                    }

                                    if (listFrames[i].Delay == 0)
                                    {
                                        listFrames[i].Delay = 10;
                                    }

                                    encoder.AddFrame(listFrames[i].Path, listFrames[i].Rect, listFrames[i].Delay);

                                    Update(id, i, string.Format(processing, i));

                                    #region Cancellation

                                    if (tokenSource.Token.IsCancellationRequested)
                                    {
                                        SetStatus(Status.Canceled, id);
                                        break;
                                    }

                                    #endregion
                                }
                            }

                            try
                            {
                                using (var fileStream = new FileStream(param.Filename, FileMode.Create, FileAccess.Write, FileShare.None, 4096))
                                    stream.WriteTo(fileStream);
                            }
                            catch (Exception ex)
                            {
                                SetStatus(Status.Error, id);
                                LogWriter.Log(ex, "Improved Encoding");
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.Legacy:

                        #region Legacy Encoding

                        using (var encoder = new AnimatedGifEncoder())
                        {
                            if (param.DummyColor.HasValue)
                            {
                                var color = Color.FromArgb(param.DummyColor.Value.R,
                                                           param.DummyColor.Value.G, param.DummyColor.Value.B);

                                encoder.SetTransparent(color);
                                encoder.SetDispose(1);         //Undraw Method, "Leave".
                            }

                            encoder.Start(param.Filename);
                            encoder.SetQuality(param.Quality);
                            encoder.SetRepeat(param.RepeatCount);

                            var numImage = 0;
                            foreach (var frame in listFrames)
                            {
                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion

                                if (!frame.HasArea && param.DetectUnchangedPixels)
                                {
                                    continue;
                                }

                                var bitmapAux = new Bitmap(frame.Path);

                                encoder.SetDelay(frame.Delay);
                                encoder.AddFrame(bitmapAux, frame.Rect.X, frame.Rect.Y);

                                bitmapAux.Dispose();

                                Update(id, numImage, string.Format(processing, numImage));
                                numImage++;
                            }
                        }

                        #endregion

                        break;

                    case GifEncoderType.PaintNet:

                        #region paint.NET encoding

                        using (var stream = new MemoryStream())
                        {
                            using (var encoder = new GifEncoder(stream, null, null, param.RepeatCount))
                            {
                                for (var i = 0; i < listFrames.Count; i++)
                                {
                                    var bitmapAux = new Bitmap(listFrames[i].Path);
                                    encoder.AddFrame(bitmapAux, 0, 0, TimeSpan.FromMilliseconds(listFrames[i].Delay));
                                    bitmapAux.Dispose();

                                    Update(id, i, string.Format(processing, i));

                                    #region Cancellation

                                    if (tokenSource.Token.IsCancellationRequested)
                                    {
                                        SetStatus(Status.Canceled, id);

                                        break;
                                    }

                                    #endregion
                                }
                            }

                            stream.Position = 0;

                            try
                            {
                                using (var fileStream = new FileStream(param.Filename, FileMode.Create, FileAccess.Write, FileShare.None, Constants.BufferSize, false))
                                    stream.WriteTo(fileStream);
                            }
                            catch (Exception ex)
                            {
                                SetStatus(Status.Error, id);
                                LogWriter.Log(ex, "Encoding with paint.Net.");
                            }
                        }

                        #endregion

                        break;

                    default:
                        throw new Exception("Undefined Gif encoder type");
                    }

                    #endregion

                    break;

                case Export.Apng:

                    #region Apng

                    #region Cut/Paint Unchanged Pixels

                    if (param.DetectUnchangedPixels)
                    {
                        Update(id, 0, FindResource("Encoder.Analyzing").ToString());

                        if (param.DummyColor.HasValue)
                        {
                            var color = Color.FromArgb(param.DummyColor.Value.A, param.DummyColor.Value.R, param.DummyColor.Value.G, param.DummyColor.Value.B);
                            listFrames = ImageMethods.PaintTransparentAndCut(listFrames, color, id, tokenSource);
                        }
                        else
                        {
                            listFrames = ImageMethods.CutUnchanged(listFrames, id, tokenSource);
                        }
                    }
                    else
                    {
                        var size = listFrames[0].Path.ScaledSize();
                        listFrames.ForEach(x => x.Rect = new Int32Rect(0, 0, (int)size.Width, (int)size.Height));
                    }

                    #endregion

                    #region Encoding

                    using (var stream = new MemoryStream())
                    {
                        var frameCount = listFrames.Count(x => x.HasArea);

                        using (var encoder = new Apng(stream, frameCount, param.RepeatCount))
                        {
                            for (var i = 0; i < listFrames.Count; i++)
                            {
                                if (!listFrames[i].HasArea && param.DetectUnchangedPixels)
                                {
                                    continue;
                                }

                                if (listFrames[i].Delay == 0)
                                {
                                    listFrames[i].Delay = 10;
                                }

                                encoder.AddFrame(listFrames[i].Path, listFrames[i].Rect, listFrames[i].Delay);

                                Update(id, i, string.Format(processing, i));

                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion
                            }
                        }

                        try
                        {
                            using (var fileStream = new FileStream(param.Filename, FileMode.Create, FileAccess.Write, FileShare.None, 4096))
                                stream.WriteTo(fileStream);
                        }
                        catch (Exception ex)
                        {
                            SetStatus(Status.Error, id);
                            LogWriter.Log(ex, "Apng Encoding");
                        }
                    }

                    #endregion

                    #endregion

                    break;

                case Export.Video:

                    #region Video

                    switch (param.VideoEncoder)
                    {
                    case VideoEncoderType.AviStandalone:

                        #region Avi Standalone

                        var image = listFrames[0].Path.SourceFrom();

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        //1000 / listFrames[0].Delay
                        using (var aviWriter = new AviWriter(param.Filename, param.Framerate, image.PixelWidth, image.PixelHeight, param.VideoQuality))
                        {
                            var numImage = 0;
                            foreach (var frame in listFrames)
                            {
                                using (var outStream = new MemoryStream())
                                {
                                    var bitImage = frame.Path.SourceFrom();

                                    var enc = new BmpBitmapEncoder();
                                    enc.Frames.Add(BitmapFrame.Create(bitImage));
                                    enc.Save(outStream);

                                    outStream.Flush();

                                    using (var bitmap = new Bitmap(outStream))
                                        aviWriter.AddFrame(bitmap, param.FlipVideo);
                                }

                                Update(id, numImage, string.Format(processing, numImage));
                                numImage++;

                                #region Cancellation

                                if (tokenSource.Token.IsCancellationRequested)
                                {
                                    SetStatus(Status.Canceled, id);
                                    break;
                                }

                                #endregion
                            }
                        }

                        #endregion

                        break;

                    case VideoEncoderType.Ffmpg:

                        #region Video using FFmpeg

                        SetStatus(Status.Encoding, id, null, true);

                        if (!Util.Other.IsFfmpegPresent())
                        {
                            throw new ApplicationException("FFmpeg not present.");
                        }

                        if (File.Exists(param.Filename))
                        {
                            File.Delete(param.Filename);
                        }

                        #region Generate concat

                        var concat = new StringBuilder();
                        foreach (var frame in listFrames)
                        {
                            concat.AppendLine("file '" + frame.Path + "'");
                            concat.AppendLine("duration " + (frame.Delay / 1000d).ToString(CultureInfo.InvariantCulture));
                        }

                        var concatPath = Path.GetDirectoryName(listFrames[0].Path) ?? Path.GetTempPath();
                        var concatFile = Path.Combine(concatPath, "concat.txt");

                        if (!Directory.Exists(concatPath))
                        {
                            Directory.CreateDirectory(concatPath);
                        }

                        if (File.Exists(concatFile))
                        {
                            File.Delete(concatFile);
                        }

                        File.WriteAllText(concatFile, concat.ToString());

                        #endregion

                        param.Command = string.Format(param.Command, concatFile, param.ExtraParameters.Replace("{H}", param.Height.ToString()).Replace("{W}", param.Width.ToString()), param.Filename);

                        var process = new ProcessStartInfo(UserSettings.All.FfmpegLocation)
                        {
                            Arguments             = param.Command,
                            CreateNoWindow        = true,
                            ErrorDialog           = false,
                            UseShellExecute       = false,
                            RedirectStandardError = true
                        };

                        var pro = Process.Start(process);

                        var str = pro.StandardError.ReadToEnd();

                        var fileInfo = new FileInfo(param.Filename);

                        if (!fileInfo.Exists || fileInfo.Length == 0)
                        {
                            throw new Exception("Error while encoding with FFmpeg.")
                                  {
                                      HelpLink = str
                                  }
                        }
                        ;

                        #endregion

                        break;

                    default:
                        throw new Exception("Undefined video encoder");
                    }

                    #endregion

                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(param));
                }

                if (!tokenSource.Token.IsCancellationRequested)
                {
                    SetStatus(Status.Completed, id, param.Filename);
                }

                #region Upload

                if (param.Upload && File.Exists(param.Filename))
                {
                    /*
                     * using (var w = new WebClient())
                     * {
                     *  var clientID = "15 digit key";
                     *  w.Headers.Add("Authorization", "Client-ID " + clientID);
                     *  var values = new NameValueCollection { { "image", Convert.ToBase64String(File.ReadAllBytes(@""+filename)) }};
                     *  var response = w.UploadValues("https://api.imgur.com/3/upload.xml", values);
                     *  var x = XDocument.Load(new MemoryStream(response));
                     *  var link = x.Descendants().Where(n => n.Name == "link").FirstOrDefault();
                     *  string href = link.Value;
                     * }
                     */
                }

                #endregion

                #region Copy to clipboard

                if (param.CopyToClipboard && File.Exists(param.Filename))
                {
                    Dispatcher.Invoke(() =>
                    {
                        try
                        {
                            var data = new DataObject();

                            switch (param.CopyType)
                            {
                            case CopyType.File:
                                if (param.Type != Export.Video)
                                {
                                    data.SetImage(param.Filename.SourceFrom());
                                }

                                data.SetText(param.Filename, TextDataFormat.Text);
                                data.SetFileDropList(new StringCollection {
                                    param.Filename
                                });
                                break;

                            case CopyType.FolderPath:
                                data.SetText(Path.GetDirectoryName(param.Filename) ?? param.Filename, TextDataFormat.Text);
                                break;

                            case CopyType.Link:
                                data.SetText(param.Filename, TextDataFormat.Text);     //TODO: Link.
                                break;

                            default:
                                data.SetText(param.Filename, TextDataFormat.Text);
                                break;
                            }

                            Clipboard.SetDataObject(data, true);
                            InternalSetCopy(id, true);
                        }
                        catch (Exception e)
                        {
                            LogWriter.Log(e, "It was not possible to copy the file.");
                            InternalSetCopy(id, false, e);
                        }
                    });
                }

                #endregion

                #region Execute commands

                if (param.ExecuteCommands && !string.IsNullOrWhiteSpace(param.PostCommands))
                {
                    var command = param.PostCommands.Replace("{p}", "\"" + param.Filename + "\"").Replace("{f}", "\"" + Path.GetDirectoryName(param.Filename) + "\"");
                    var output  = "";

                    try
                    {
                        foreach (var com in command.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
                        {
                            var procStartInfo = new ProcessStartInfo("cmd", "/c " + com)
                            {
                                RedirectStandardOutput = true,
                                RedirectStandardError  = true,
                                UseShellExecute        = false,
                                CreateNoWindow         = true
                            };

                            using (var process = new Process())
                            {
                                process.StartInfo = procStartInfo;
                                process.Start();

                                var message = process.StandardOutput.ReadToEnd();
                                var error   = process.StandardError.ReadToEnd();

                                if (!string.IsNullOrWhiteSpace(message))
                                {
                                    output += message + Environment.NewLine;
                                }

                                if (!string.IsNullOrWhiteSpace(message))
                                {
                                    output += message + Environment.NewLine;
                                }

                                if (!string.IsNullOrWhiteSpace(error))
                                {
                                    throw new Exception(error);
                                }

                                process.WaitForExit(1000);
                            }
                        }

                        InternalSetCommand(id, true, output);
                    }
                    catch (Exception e)
                    {
                        LogWriter.Log(e, "It was not possible to run the post encoding command.");
                        InternalSetCommand(id, false, output, e);
                    }
                }

                #endregion
            }
            catch (Exception ex)
            {
                LogWriter.Log(ex, "Encode");

                SetStatus(Status.Error, id, null, false, ex);
            }
            finally
            {
                #region Delete Encoder Folder

                try
                {
                    var encoderFolder = Path.GetDirectoryName(listFrames[0].Path);

                    if (!string.IsNullOrEmpty(encoderFolder))
                    {
                        if (Directory.Exists(encoderFolder))
                        {
                            Directory.Delete(encoderFolder, true);
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogWriter.Log(ex, "Cleaning the Encode folder");
                }

                #endregion

                GC.Collect();
            }
        }
Пример #30
0
 private static FrameMetadata GetFrameMetadata(BitmapDecoder decoder, GifFile gifMetadata, int frameIndex) =>
 (((gifMetadata == null) || (gifMetadata.Frames.Count <= frameIndex)) ? GetFrameMetadata(decoder.Frames[frameIndex]) : GetFrameMetadata(gifMetadata.Frames[frameIndex]));