public bool SaveAsGif(string path) { Error = ""; AnimatedGifEncoder encoder = new AnimatedGifEncoder(); if (!encoder.Start(path)) { Error = "Failed to start the GIF encoder :("; return(false); } encoder.SetTransparent(Color.Black); encoder.SetDelay(100); encoder.SetRepeat(0); // -1:no repeat, 0:always repeat foreach (Bitmap bmp in Frames) { if (!encoder.AddFrame(bmp)) { Error = "Failed to add frame to GIF encoder :("; return(false); } } if (!encoder.Finish()) { Error = "GIF encoder failed to finish :("; return(false); } return(true); }
public byte[] GetWaitShot() { GifDecoder gifDecoder = new GifDecoder(); AnimatedGifEncoder gifEncoder = new AnimatedGifEncoder(); MemoryStream outStream = new MemoryStream(); gifEncoder.SetFrameRate(10); gifEncoder.SetDelay(100); gifEncoder.SetRepeat(0); gifEncoder.SetTransparent(Color.Black); gifEncoder.Start(outStream); ResourceManager rm = new ResourceManager("webshot.serv.Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly()); gifDecoder.Read(rm.GetStream("ajax_loader")); for (int i = 0, count = gifDecoder.GetFrameCount(); i < count; i++) { gifEncoder.AddFrame(gifDecoder.GetFrame(i), thumbwidth, thumbheight); } gifEncoder.Finish(); byte[] buffer = outStream.ToArray(); outStream.Close(); return(buffer); }
public static void WriteGif(string path, Image[] array, Color transparent, int delay = 75) { var encoder = new AnimatedGifEncoder(); encoder.Start(); encoder.SetDelay(75); encoder.SetTransparent(transparent); for (var i = 0; i < array.Length; i++) { encoder.AddFrame(array[i]); } encoder.Finish(); encoder.Output(path); }
public static void WriteGif(string path, Image[] array, Color transparent, int delay = 75) { var encoder = new AnimatedGifEncoder(); encoder.Start(); encoder.SetDelay(75); encoder.SetTransparent(transparent); foreach (var a in array) { encoder.AddFrame(a); } encoder.Finish(); encoder.Output(path); }
void gifGeneratorWorker_DoWork(object sender, DoWorkEventArgs e) { var frames = e.Argument as List <WriteableBitmap>; AnimatedGifEncoder encoder = new AnimatedGifEncoder(); encoder.SetDelay(1000); encoder.SetRepeat(0); encoder.SetTransparent(Colors.Transparent); foreach (var frame in frames) { encoder.AddFrame(frame); } }
public static string BuildAnimation(List <Bitmap> bmps, int repeat, HttpContext http) { string guid = Guid.NewGuid().ToString(); string final = http.Server.MapPath("~/tempfiles/") + "anim" + guid + ".gif"; AnimatedGifEncoder e = new AnimatedGifEncoder(); using (MemoryStream m = new MemoryStream()) { using (FileStream fs = new FileStream(final, FileMode.Create)) { e.Start(m); e.SetTransparent(Color.Black); e.SetDelay(10); int width = 0; int height = 0; foreach (var b in bmps) { if (b.Width > width) { width = b.Width; } if (b.Height > height) { height = b.Height; } } e.SetRepeat(repeat); e.SetSize(width, height); foreach (var b in bmps) { e.AddFrame(b); b.Dispose(); } e.Finish(); m.WriteTo(fs); } } return(final); }
private void btnGetGif_Click(object sender, EventArgs e) { if (gifBases.Length == 0) { MessageBox.Show("文件不存在"); return; } string gifFile = "location.gif"; AnimatedGifEncoder gifEncoder = new AnimatedGifEncoder(); gifEncoder.Start(gifFile); gifEncoder.SetDelay(500); gifEncoder.SetRepeat(999); gifEncoder.SetSize(40, 40); gifEncoder.SetTransparent(Color.Transparent); for (int i = 0; i < gifBases.Length; i++) { gifEncoder.AddFrame(Image.FromFile(gifBases[i])); } gifEncoder.Finish(); pbGif.Image = Image.FromFile(gifFile); }
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(); } }
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(); } }
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(); } }
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(); } }
private void Encode(List <FrameInfo> listFrames, int id, string fileName, Export type, CancellationTokenSource tokenSource) { if (type == Export.Gif) { #region Gif if (Settings.Default.CustomEncoding) { #region Custom Gif Encoding using (var encoder = new AnimatedGifEncoder()) { string cutFolder = null; #region Cut/Paint Unchanged Pixels if (Settings.Default.DetectUnchanged) { Update(id, 0, "Analizing Unchanged Pixels"); if (Settings.Default.PaintTransparent) { var color = Color.FromArgb(Settings.Default.TransparentColor.R, Settings.Default.TransparentColor.G, Settings.Default.TransparentColor.B); listFrames = ImageMethods.PaintTransparentAndCut(listFrames, color, id, tokenSource); //TODO: Use System.Windows.Media.Color inside the AnimatedGifEncoder. encoder.SetTransparent(color); encoder.SetDispose(1); //Undraw Method, "Leave". } else { listFrames = ImageMethods.CutUnchanged(listFrames, id, tokenSource); } } #endregion encoder.Start(fileName); encoder.SetQuality(Settings.Default.Quality); encoder.SetRepeat(Settings.Default.Looped ? (Settings.Default.RepeatForever ? 0 : Settings.Default.RepeatCount) : -1); // 0 = Always, -1 once int numImage = 0; foreach (FrameInfo image in listFrames) { #region Cancellation if (tokenSource.Token.IsCancellationRequested) { SetStatus(Status.Cancelled, id); break; } #endregion var bitmapAux = new Bitmap(image.ImageLocation); encoder.SetDelay(image.Delay); encoder.AddFrame(bitmapAux, image.PositionTopLeft.X, image.PositionTopLeft.Y); bitmapAux.Dispose(); Update(id, numImage, "Processing " + numImage); numImage++; } #region Specific Clear try { if (!String.IsNullOrEmpty(cutFolder)) { if (Directory.Exists(cutFolder)) { Directory.Delete(cutFolder, true); } } } catch (Exception ex) { LogWriter.Log(ex, "Errow while Deleting and Cleaning Specific Variables"); } #endregion } #endregion } else { #region paint.NET encoding //0 = Always, -1 = no repeat, n = repeat number (first shown + repeat number = total number of iterations) var repeat = (Settings.Default.Looped ? (Settings.Default.RepeatForever ? 0 : Settings.Default.RepeatCount) : -1); using (var stream = new MemoryStream()) { using (var encoderNet = new GifEncoder(stream, null, null, repeat)) { for (int i = 0; i < listFrames.Count; i++) { var bitmapAux = new Bitmap(listFrames[i].ImageLocation); encoderNet.AddFrame(bitmapAux, 0, 0, TimeSpan.FromMilliseconds(listFrames[i].Delay)); bitmapAux.Dispose(); Update(id, i, "Processing " + i); #region Cancellation if (tokenSource.Token.IsCancellationRequested) { SetStatus(Status.Cancelled, id); break; } #endregion } } stream.Position = 0; try { using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None, Constants.BufferSize, false)) { stream.WriteTo(fileStream); } } catch (Exception ex) { SetStatus(Status.Error, id); LogWriter.Log(ex, "Error while writing to disk."); } } #endregion } #endregion } else { #region Avi var image = listFrames[0].ImageLocation.SourceFrom(); using (var aviWriter = new AviWriter(fileName, 1000 / listFrames[0].Delay, (int)image.PixelWidth, (int)image.PixelHeight, 5000)) { int numImage = 0; foreach (FrameInfo frame in listFrames) { using (MemoryStream 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, "Processing " + numImage); numImage++; #region Cancellation if (tokenSource.Token.IsCancellationRequested) { SetStatus(Status.Cancelled, id); break; } #endregion } } #endregion } #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, "Errow while deleting and cleaning the Encode folder"); } #endregion GC.Collect(); if (!tokenSource.Token.IsCancellationRequested) { SetStatus(Status.Completed, id, fileName); } }
// 感谢ok群群友 yuanyilvhua(QQ:4570848**)提供测试电脑,以修复之前存在的高分屏下的bug :-) private void button2_Click(object sender, EventArgs e) { PowerPoint.Selection sel = app.ActiveWindow.Selection; if (sel.Type == PowerPoint.PpSelectionType.ppSelectionSlides && sel.SlideRange.Count > 1) { PowerPoint.Slides slides = app.ActivePresentation.Slides; PowerPoint.SlideRange srange = sel.SlideRange; int scount = srange.Count; float wp = app.ActivePresentation.PageSetup.SlideWidth; float hp = app.ActivePresentation.PageSetup.SlideHeight; int pw = Properties.Settings.Default.pwidth; int h2 = (int)(pw * hp / wp); string name = app.ActivePresentation.Name; if (name.Contains(".pptx")) { name = name.Replace(".pptx", ""); } if (name.Contains(".ppt")) { name = name.Replace(".ppt", ""); } string cPath = app.ActivePresentation.Path + @"\" + name + @" 的GIF图\"; if (!Directory.Exists(cPath)) { Directory.CreateDirectory(cPath); } System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(cPath); int k = dir.GetFiles().Length + 1; string gpath = cPath + name + "_" + k + ".gif"; int time = int.Parse(textBox1.Text.Trim()); int[] index = new int[srange.Count]; for (int i = 1; i <= srange.Count; i++) { index[i - 1] = srange[i].SlideIndex; } if (index[0] > index[1]) { Array.Sort(index); } sel.Unselect(); slides.Range(index).Select(); List <string> path = new List <string>(); for (int i = 1; i <= scount; i++) { PowerPoint.Slide nslide = slides[index[i - 1]]; string cPath2 = cPath + name + "_" + k + ".jpg"; nslide.Export(cPath2, "jpg"); path.Add(cPath2); k = k + 1; } AnimatedGifEncoder gif = new AnimatedGifEncoder(); gif.Start(gpath); gif.SetDelay(time); if (checkBox1.Checked) { gif.SetRepeat(0); } else { gif.SetRepeat(-1); } Bitmap bmp = null; Graphics g = null; for (int j = 0; j < scount; j++) { Image spic = Image.FromFile(path[j]); if (j == 0) { bmp = new Bitmap(spic.Width, spic.Height); bmp.SetResolution(spic.HorizontalResolution, spic.VerticalResolution); g = Graphics.FromImage(bmp); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; } g.Clear(panel1.BackColor); g.DrawImage(spic, 0, 0); gif.AddFrame(bmp); spic.Dispose(); File.Delete(path[j]); } gif.Finish(); g.Dispose(); bmp.Dispose(); if (!checkBox2.Checked) { System.Diagnostics.Process.Start("Explorer.exe", cPath); } else { int n = srange[1].SlideNumber; PowerPoint.Shape nshape = slides[n].Shapes.AddPicture(gpath, Office.MsoTriState.msoFalse, Office.MsoTriState.msoTrue, -pw, 0, pw, h2); if (pw > app.ActivePresentation.PageSetup.SlideWidth) { nshape.LockAspectRatio = Office.MsoTriState.msoTrue; nshape.Width = app.ActivePresentation.PageSetup.SlideWidth; nshape.Left = 0; nshape.Top = 0; } nshape.Select(); File.Delete(gpath); if (dir.GetFiles().Length == 0) { Directory.Delete(cPath, true); } } } else if (sel.Type == PowerPoint.PpSelectionType.ppSelectionShapes) { PowerPoint.Slide slide = app.ActiveWindow.View.Slide; PowerPoint.ShapeRange range = sel.ShapeRange; if (sel.HasChildShapeRange) { range = sel.ChildShapeRange; } int count = range.Count; if (count > 1) { string name = app.ActivePresentation.Name; if (name.Contains(".pptx")) { name = name.Replace(".pptx", ""); } if (name.Contains(".ppt")) { name = name.Replace(".ppt", ""); } string cPath = app.ActivePresentation.Path + @"\" + name + @" 的GIF图\"; if (!Directory.Exists(cPath)) { Directory.CreateDirectory(cPath); } System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(cPath); int k = dir.GetFiles().Length + 1; int time = int.Parse(textBox1.Text.Trim()); string gpath = cPath + name + "_" + k + ".gif"; List <int> w = new List <int>(); List <int> h = new List <int>(); List <string> path = new List <string>(); Bitmap spic = null; float xs = 0; float ys = 0; for (int i = 1; i <= count; i++) { PowerPoint.Shape pic = range[i]; pic.Export(cPath + name + "_" + k + ".png", PowerPoint.PpShapeFormat.ppShapeFormatPNG); spic = new Bitmap(cPath + name + "_" + k + ".png"); w.Add(spic.Width); h.Add(spic.Height); if (xs == 0) { xs = spic.HorizontalResolution; ys = spic.VerticalResolution; } spic.Dispose(); path.Add(cPath + name + "_" + k + ".png"); k = k + 1; } int wmax = w.Max(); int hmax = h.Max(); Bitmap bmp = new Bitmap(wmax, hmax); bmp.SetResolution(xs, ys); Graphics g = Graphics.FromImage(bmp); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; AnimatedGifEncoder gif = new AnimatedGifEncoder(); gif.Start(gpath); gif.SetDelay(time); if (checkBox1.Checked) { gif.SetRepeat(0); } else { gif.SetRepeat(-1); } if (checkBox4.Checked) { gif.SetQuality(300); gif.SetTransparent(panel1.BackColor); } for (int j = 0; j < count; j++) { spic = new Bitmap(path[j]); g.Clear(panel1.BackColor); g.DrawImage(spic, (bmp.Width - spic.Width) / 2, (bmp.Height - spic.Height) / 2); gif.AddFrame(bmp); spic.Dispose(); File.Delete(path[j]); } gif.Finish(); g.Dispose(); bmp.Dispose(); if (!checkBox2.Checked) { System.Diagnostics.Process.Start("Explorer.exe", cPath); } else { PowerPoint.Shape nshape = slide.Shapes.AddPicture(gpath, Office.MsoTriState.msoFalse, Office.MsoTriState.msoTrue, -wmax, 0, wmax, hmax); nshape.Select(); //File.Delete(cPath + name + "_" + k + ".gif"); //if (dir.GetFiles().Length == 0) //{ // Directory.Delete(cPath, true); //} } } else { MessageBox.Show("请选中多张图片"); } } else { MessageBox.Show("请选中多张图片或幻灯片页面"); } }
public void Execute(object data) { try { lock (thisLock) { Bitmap clipImage = (Bitmap)data; ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); string strCodecToUse = null; ImageCodecInfo codecToUse = null; EncoderParameters encParams = null; switch (int.Parse(myOptions["SelectedFormat"])) { case 0: anigifTotalFrameNum = int.Parse(myOptions["AniGIFNumFrames"]); strCodecToUse = "AniGIF"; break; case 1: strCodecToUse = "BMP"; break; case 2: encParams = new EncoderParameters(2); encParams.Param[0] = new EncoderParameter(Encoder.Quality, long.Parse(myOptions["JPEGQuality"])); if (bool.Parse(myOptions["JPEGEncoding"])) { encParams.Param[1] = new EncoderParameter(Encoder.RenderMethod, (long)EncoderValue.RenderProgressive); } else { encParams.Param[1] = new EncoderParameter(Encoder.RenderMethod, (long)EncoderValue.RenderNonProgressive); } strCodecToUse = "JPEG"; break; case 3: strCodecToUse = "GIF"; break; case 4: switch (int.Parse(myOptions["TIFFCompression"])) { case 0: encParams = new EncoderParameters(1); encParams.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionNone); break; case 1: encParams = new EncoderParameters(2); encParams.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionCCITT3); encParams.Param[1] = new EncoderParameter(Encoder.ColorDepth, 1L); break; case 2: encParams = new EncoderParameters(2); encParams.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionCCITT4); encParams.Param[1] = new EncoderParameter(Encoder.ColorDepth, 1L); break; case 3: encParams = new EncoderParameters(1); encParams.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionLZW); break; case 4: encParams = new EncoderParameters(2); encParams.Param[0] = new EncoderParameter(Encoder.Compression, (long)EncoderValue.CompressionRle); encParams.Param[1] = new EncoderParameter(Encoder.ColorDepth, 1L); break; } strCodecToUse = "TIFF"; break; case 5: encParams = new EncoderParameters(1); if (bool.Parse(myOptions["PNGEncoding"])) { encParams.Param[0] = new EncoderParameter(Encoder.ScanMethod, (long)EncoderValue.ScanMethodInterlaced); } else { encParams.Param[0] = new EncoderParameter(Encoder.ScanMethod, (long)EncoderValue.ScanMethodNonInterlaced); } strCodecToUse = "PNG"; break; } if (!strCodecToUse.Equals("AniGIF")) { foreach (ImageCodecInfo codec in codecs) { if (codec.FormatDescription.Equals(strCodecToUse)) { codecToUse = codec; break; } } if (codecToUse != null) { string filename = myOptions["PrefixOutputName"] + fileNum + myOptions["SuffixOutputName"] + (codecToUse.FilenameExtension.Split(new char[] { ';' }))[0].Substring(1); clipImage.Save(filename, codecToUse, encParams); fileNum++; } } else { if (!aniGifEnc.IsStarted) { anigifFrameNum = 0; aniGifEnc.Start(myOptions["PrefixOutputName"] + fileNum + myOptions["SuffixOutputName"] + ".gif"); aniGifEnc.SetFrameRate(float.Parse(myOptions["AniGIFFrameRate"])); aniGifEnc.SetRepeat(int.Parse(myOptions["AniGIFRepeat"])); aniGifEnc.SetQuality(int.Parse(myOptions["AniGIFQuality"])); if (!myOptions["AniGIFTrasparent"].Equals("NULL")) { aniGifEnc.SetTransparent(Color.FromArgb(int.Parse(myOptions["AniGIFTrasparent"]))); } } aniGifEnc.AddFrame((Image)clipImage); anigifFrameNum++; MessageBox.Show("Frame " + anigifFrameNum.ToString() + " of " + anigifTotalFrameNum + " added.", "AniGIF Creation", MessageBoxButtons.OK, MessageBoxIcon.Information); if (anigifFrameNum >= anigifTotalFrameNum) { aniGifEnc.Finish(); fileNum++; } } } } catch (System.Runtime.InteropServices.ExternalException ee) { MessageBox.Show("Error writing file.\n" + ee.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (FormatException fe) { MessageBox.Show("Error parsing the configuration file.\n" + fe.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
public async Task Custom(string name, string fontName, string color, string fontSize, [Remainder] string text) { if (!Program.Owners.Contains(Context.User.Id)) { await Utility.SendEmbedMessage(Context, "이 커맨드를 실행할 권한이 없습니다."); return; } name = new string(name.Where(c => alpha.Contains(c.ToString())).ToArray()); if (name.Length == 1) { await Utility.SendEmbedMessage(Context, "이름이 한 글자 이하인 이모지를 만들 수 없습니다."); return; } FontFamily font = new FontFamily(fontName == "_" ? "NanumGothic" : fontName); Bitmap img = new Bitmap(512, 512); Graphics graphic = Graphics.FromImage(img); graphic.Clear(System.Drawing.Color.Transparent); graphic.InterpolationMode = InterpolationMode.High; graphic.SmoothingMode = SmoothingMode.HighQuality; graphic.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; graphic.CompositingQuality = CompositingQuality.HighQuality; int len = text.Length; float size = fontSize == "_" ? (len == 1 ? 300 : len <= 4 ? 225 : 175) : int.Parse(fontSize); GraphicsPath path = new GraphicsPath(); path.AddString(text, font, style, size, rect, format); graphic.DrawPath(pen, path); graphic.FillPath(new SolidBrush(System.Drawing.Color.FromName(color == "_" ? "White" : color)), path); graphic.Dispose(); SocketGuild guild = GetChoGuild(text[0]); if (guild == null) { await Utility.SendEmbedMessage(Context, "남은 이모지 슬롯이 없습니다."); return; } if (GetChoGuilds(text[0]).Where(g => g.Emotes.Where(e => e.Name == name).Count() != 0).Count() == 0) { if (guild.Emotes.Where(e => !e.Animated).Count() < 50) { img.Save($"img/{name}.png"); img.Dispose(); GuildEmote emote = await guild.CreateEmoteAsync(name, new Discord.Image($"img/{name}.png")); await ReplyAsync(emote.ToString()); } else { AnimatedGifEncoder e = new AnimatedGifEncoder(); e.SetTransparent(System.Drawing.Color.Black); e.Start($"img/{name}.gif"); e.SetDelay(1); e.SetRepeat(-1); e.AddFrame(img); e.AddFrame(img); e.Finish(); img.Dispose(); GuildEmote emote = await guild.CreateEmoteAsync(name, new Discord.Image($"img/{name}.gif")); await ReplyAsync(emote.ToString()); } } else { await Utility.SendEmbedMessage(Context, "이미 존재하는 이모지입니다."); } }
private 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 = 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 outputPath = Path.GetDirectoryName(listFrames[0].Path); var fps = !param.ExtraParameters.Contains("--fps") ? "--fps " + (int)(1000d / listFrames.Average(x => x.Delay)) : ""; param.Command = $"{param.ExtraParameters} {fps} -o \"{param.Filename}\" \"{Path.Combine(outputPath, "*.png")}\""; var process2 = new ProcessStartInfo(UserSettings.All.GifskiLocation) { Arguments = param.Command, CreateNoWindow = true, ErrorDialog = false, UseShellExecute = false, RedirectStandardError = true }; var pro2 = Process.Start(process2); var str2 = pro2.StandardError.ReadToEnd(); var fileInfo2 = new FileInfo(param.Filename); if (!fileInfo2.Exists || fileInfo2.Length == 0) { throw new Exception("Error while encoding the gif with Gifski.") { HelpLink = str2 } } ; #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 { //TODO: Make it less hardcoded. switch (param.UploadDestinationIndex) { case 0: //Imgur. using (var w = new WebClient()) { w.Headers.Add("Authorization", "Client-ID " + Secret.ImgurId); var values = new NameValueCollection { { "image", Convert.ToBase64String(File.ReadAllBytes(param.Filename)) } }; var response = w.UploadValues("https://api.imgur.com/3/upload.xml", values); var x = XDocument.Load(new MemoryStream(response)); var node = x.Descendants().FirstOrDefault(n => n.Name == "link"); var nodeHash = x.Descendants().FirstOrDefault(n => n.Name == "deletehash"); if (node == null) { throw new Exception("No link was provided by Imgur", new Exception(x.Document?.ToString() ?? "The document was null. :/")); } InternalSetUpload(id, true, node.Value, "https://imgur.com/delete/" + nodeHash?.Value); } break; case 1: //Gfycat. using (var client = new HttpClient()) { using (var res = client.PostAsync(@"https://api.gfycat.com/v1/gfycats", null).Result) { var result = res.Content.ReadAsStringAsync().Result; //{"isOk":true,"gfyname":"ThreeWordCode","secret":"15alphanumerics","uploadType":"filedrop.gfycat.com"} var ser = new JavaScriptSerializer(); if (!(ser.DeserializeObject(result) is Dictionary <string, object> thing)) { throw new Exception("It was not possible to get the gfycat name: " + res); } var name = thing["gfyname"] as string; using (var content = new MultipartFormDataContent()) { content.Add(new StringContent(name), "key"); content.Add(new ByteArrayContent(File.ReadAllBytes(param.Filename)), "file", name); using (var res2 = client.PostAsync("https://filedrop.gfycat.com", content).Result) { if (!res2.IsSuccessStatusCode) { throw new Exception("It was not possible to get the gfycat upload result: " + res2); } //{"task": "complete", "gfyname": "ThreeWordCode"} //{"progress": "0.03", "task": "encoding", "time": 10} //If the task is not yet completed, try waiting. var input2 = ""; while (!input2.Contains("complete")) { using (var res3 = client.GetAsync("https://api.gfycat.com/v1/gfycats/fetch/status/" + name).Result) { input2 = res3.Content.ReadAsStringAsync().Result; if (!res3.IsSuccessStatusCode) { throw new Exception("It was not possible to get the gfycat upload status: " + res3); } } if (!input2.Contains("complete")) { Thread.Sleep(1000); } } if (res2.IsSuccessStatusCode) { InternalSetUpload(id, true, "https://gfycat.com/" + name); } } } } } break; } } 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: 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)) { 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(); } }