private void Grid_Loaded(object sender, RoutedEventArgs e) { SceneExtractorArguments arguments = new SceneExtractorArguments { InputFile = _video, OutputDirectory = FfmpegWrapper.CreateRandomTempDirectory() }; SceneExtractorWrapper wrapper = new SceneExtractorWrapper(arguments, _viewmodel.Settings.FfmpegPath); wrapper.Execute(); var scenes = new List <SceneViewModel>(); foreach (string imageFile in Directory.EnumerateFiles(arguments.OutputDirectory)) { string number = Path.GetFileNameWithoutExtension(imageFile); int frame = int.Parse(number); SceneFrame scene = arguments.Result.Single(w => w.Index == frame); scenes.Add(new SceneViewModel { IsSelected = false, TimeStamp = scene.TimeStamp, Duration = scene.Duration, Preview = new BitmapImage(new Uri(imageFile, UriKind.Absolute)) }); } Scenes = scenes; }
public MainForm() { InitializeComponent(); var executingAssembly = Assembly.GetExecutingAssembly(); Icon = Icon.ExtractAssociatedIcon(executingAssembly.Location); Text += $" - {executingAssembly.GetName().Version}"; AppendLog(Text); _openFileDialog = new OpenFileDialog() { CheckFileExists = true, CheckPathExists = true, }; _saveFileDialog = new SaveFileDialog() { DefaultExt = ".png", Filter = "Bitmap|*.bmp|Jpeg|*.jpg|Png|*.png|Gif|*.gif|All files|*.*", FilterIndex = 3, // 1 based OverwritePrompt = true, }; _ffmpegWrapper = new FfmpegWrapper("ffmpeg.exe"); _imageProcessor = new ImageProcessor(); _barCodeParametersValidator = new BarCodeParametersValidator(); useInputHeightForOutputCheckBox.Checked = true; generateButton.Text = GenerateButtonText; }
public void FfmpegWrapper_GetMediaDuration_Returns_Correct_Value() { CreateTestVideoIfNecessary(); var ffmpegWrapper = new FfmpegWrapper(FfmpegExecutablePath); var duration = ffmpegWrapper.GetMediaDuration(TestVideoFileName, CancellationToken.None); Assert.AreEqual(TimeSpan.FromSeconds(TestVideoDuration), duration); }
public Stream GetVideoByName(string name) //public async Task<Stream> GetVideoByName(string name) { var fileName = string.Empty; switch (name) { case "video": var outputStream = new MemoryStream(); outputStream.Write(jsmpHeader); var width = BitConverter.GetBytes((UInt16)1920); outputStream.Write(width); var height = BitConverter.GetBytes((UInt16)1080); outputStream.Write(height); var inputfileName = @"D:\Projects\Others\R-Pi\RemoteFiles\video-h264"; fileName = @"D:\Projects\Others\R-Pi\RemoteFiles\video-mp4"; using (var logFile = new StreamWriter("FFMpegLog.txt")) { using (var ffmpeg = new FfmpegWrapper()) { ffmpeg.ConvertStream(inputfileName, outputStream, logFile); //using (var inputStream = new FileStream(inputfileName, FileMode.Open)) //{ // ffmpeg.ConvertStream(inputStream, outputStream, logFile); // //ffmpeg.ConvertFile(inputfileName, fileName, logFile); } logFile.Flush(); } return(outputStream); case "nature": default: fileName = @"D:\Projects\Others\R-Pi\RemoteFiles\nature2.mp4"; var fileStream = File.OpenRead(fileName); return(fileStream); } //return await _client.GetStreamAsync(fileName); }
public void FfmpegWrapper_GetImagesFromMedia_Returns_Expected_Values(int requestedFrameCount) { CreateTestVideoIfNecessary(); var ffmpegWrapper = new FfmpegWrapper(FfmpegExecutablePath); var images = ffmpegWrapper.GetImagesFromMedia( TestVideoFileName, requestedFrameCount, CancellationToken.None) .ToList(); CollectionAssert.AllItemsAreNotNull(images); Assert.AreEqual(requestedFrameCount, images.Count); foreach (var image in images) { Assert.AreEqual(TestVideoWidth, image.Width); Assert.AreEqual(TestVideoHeight, image.Height); } }
public async Task FfmpegWrapper_GetImagesFromMedia_Returns_Expected_Values(int requestedFrameCount) { CreateTestVideoIfNecessary(); var ffmpegWrapper = new FfmpegWrapper(FfmpegExecutablePath); var images = ffmpegWrapper.GetImagesFromMedia( TestVideoFileName, requestedFrameCount, CancellationToken.None) .ToList(); CollectionAssert.AllItemsAreNotNull(images); Assert.AreEqual(requestedFrameCount, images.Count); foreach (var bitmapStream in images) { var imageInfo = await Task.Run(() => ImageFileInfo.Load(bitmapStream)); Assert.AreEqual(TestVideoWidth, imageInfo.Frames[0].Width); Assert.AreEqual(TestVideoHeight, imageInfo.Frames[0].Height); } }
protected override GeneratorResult ProcessInternal(ThumbnailBannerGeneratorSettings settings, GeneratorEntry entry) { try { entry.State = JobStates.Processing; _wrapper = new FfmpegWrapper(FfmpegExePath); var videoInfo = _wrapper.GetVideoInfo(settings.VideoFile); if (!videoInfo.IsGoodEnough()) { entry.State = JobStates.Done; entry.DoneType = JobDoneTypes.Failure; entry.Update("Failed", 1); return(GeneratorResult.Failed()); } TimeSpan duration = videoInfo.Duration; TimeSpan intervall = duration.Divide(settings.Columns * settings.Rows + 1); var frameArguments = new FrameConverterArguments { Width = 800, Intervall = intervall.TotalSeconds, StatusUpdateHandler = (progress) => { entry.Update(null, progress); }, InputFile = settings.VideoFile, OutputDirectory = FfmpegWrapper.CreateRandomTempDirectory() }; entry.Update("Extracting Frames", 0); var frames = _wrapper.ExtractFrames(frameArguments); if (_canceled) { return(GeneratorResult.Failed()); } entry.Update("Saving Thumbnails", 1); List <ThumbnailBannerGeneratorImage> images = new List <ThumbnailBannerGeneratorImage>(); foreach (var frame in frames) { images.Add(new ThumbnailBannerGeneratorImage { Image = frame.Item2, Position = frame.Item1 }); } ThumbnailBannerGeneratorData data = new ThumbnailBannerGeneratorData(); data.Settings = settings; data.Images = images.ToArray(); data.VideoName = settings.VideoFile; data.VideoInfo = videoInfo; data.FileSize = new FileInfo(settings.VideoFile).Length; var result = CreateBanner(data); JpegBitmapEncoder encoder = new JpegBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create((BitmapSource)result)); using (FileStream stream = new FileStream(settings.OutputFile, FileMode.Create)) encoder.Save(stream); Directory.Delete(frameArguments.OutputDirectory); entry.DoneType = JobDoneTypes.Success; entry.Update("Done", 1); return(GeneratorResult.Succeeded(settings.OutputFile)); } catch (Exception) { entry.Update("Failed", 1); entry.DoneType = JobDoneTypes.Failure; return(GeneratorResult.Failed()); } finally { entry.State = JobStates.Done; if (_canceled) { entry.DoneType = JobDoneTypes.Cancelled; entry.Update("Cancelled", 1); } } }
protected override GeneratorResult ProcessInternal(HeatmapGeneratorSettings settings, GeneratorEntry entry) { try { entry.State = JobStates.Processing; _wrapper = new FfmpegWrapper(FfmpegExePath); var videoInfo = _wrapper.GetVideoInfo(settings.VideoFile); if (videoInfo.Duration <= TimeSpan.Zero) { entry.State = JobStates.Done; entry.DoneType = JobDoneTypes.Failure; entry.Update("Failed", 1); return(GeneratorResult.Failed()); } TimeSpan duration = videoInfo.Duration; //TODO string script = ViewModel.GetScriptFile(settings.VideoFile); var actions = ViewModel.LoadScriptActions(script, null); if (actions == null || actions.Count == 0) { entry.State = JobStates.Done; entry.DoneType = JobDoneTypes.Failure; entry.Update("Failed", 1); return(GeneratorResult.Failed()); } List <TimedPosition> timeStamps = ViewModel.FilterDuplicates(actions.ToList()).Cast <FunScriptAction>().Select(f => new TimedPosition { Position = f.Position, TimeStamp = f.TimeStamp }).ToList(); Brush heatmap = HeatMapGenerator.Generate3(timeStamps, TimeSpan.FromSeconds(10), TimeSpan.Zero, duration, 1.0, out Geometry bounds); bounds.Transform = new ScaleTransform(settings.Width, settings.Height); var rect = new Rect(0, 0, settings.Width, settings.Height); DrawingVisual visual = new DrawingVisual(); using (DrawingContext context = visual.RenderOpen()) { if (!settings.TransparentBackground) { context.DrawRectangle(Brushes.Black, null, rect); } if (settings.MovementRange) { context.PushClip(bounds); } context.DrawRectangle(heatmap, null, rect); if (settings.AddShadow) { LinearGradientBrush shadow = new LinearGradientBrush(); shadow.StartPoint = new Point(0.5, 0); shadow.EndPoint = new Point(0.5, 1); shadow.GradientStops.Add(new GradientStop(Color.FromArgb(0xFF - 0x20, 0, 0, 0), 0)); shadow.GradientStops.Add(new GradientStop(Color.FromArgb(0xFF - 0xcc, 0, 0, 0), 0.98)); shadow.GradientStops.Add(new GradientStop(Color.FromArgb(0xFF - 0x50, 0, 0, 0), 0.98)); shadow.GradientStops.Add(new GradientStop(Color.FromArgb(0xFF - 0x50, 0, 0, 0), 1)); context.DrawRectangle(shadow, null, rect); } if (settings.MovementRange) { context.Pop(); } } RenderTargetBitmap bitmap = new RenderTargetBitmap(settings.Width, settings.Height, 96, 96, PixelFormats.Pbgra32); bitmap.Render(visual); PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bitmap)); using (FileStream stream = new FileStream(settings.OutputFile, FileMode.Create)) encoder.Save(stream); entry.DoneType = JobDoneTypes.Success; entry.Update("Done", 1); return(GeneratorResult.Succeeded(settings.OutputFile)); } catch (Exception) { entry.Update("Failed", 1); entry.DoneType = JobDoneTypes.Failure; return(GeneratorResult.Failed()); } finally { entry.State = JobStates.Done; if (_canceled) { entry.DoneType = JobDoneTypes.Cancelled; entry.Update("Cancelled", 1); } } }
protected override GeneratorResult ProcessInternal(PreviewGeneratorSettings settings, GeneratorEntry entry) { entry.State = JobStates.Processing; List <string> tempFiles = new List <string>(); try { _wrapper = new FfmpegWrapper(FfmpegExePath); List <string> sectionFileNames = new List <string>(); if (settings.TimeFrames.Any(tf => tf.IsFactor)) { VideoInfo info = _wrapper.GetVideoInfo(settings.VideoFile); if (!info.IsGoodEnough()) { entry.State = JobStates.Done; entry.DoneType = JobDoneTypes.Failure; entry.Update("Failed", 1); return(GeneratorResult.Failed()); } TimeSpan duration = info.Duration; settings.TimeFrames.ForEach(tf => tf.CalculateStart(duration)); } ClipExtractorArguments clipArguments = new ClipExtractorArguments { InputFile = settings.VideoFile, Width = settings.Width, Height = settings.Height, Framerate = settings.Framerate }; for (int i = 0; i < settings.TimeFrames.Count; i++) { string sectionFileName = Path.Combine(Path.GetTempPath(), Path.GetFileName(settings.VideoFile) + $"-clip_{i}.mkv"); sectionFileNames.Add(sectionFileName); tempFiles.Add(sectionFileName); var timeFrame = settings.TimeFrames[i]; clipArguments.Duration = timeFrame.Duration; clipArguments.StartTimeSpan = timeFrame.StartTimeSpan; clipArguments.OutputFile = sectionFileName; entry.Update($"Generating GIF (1/4): Clipping Video Section {i + 1}/{settings.TimeFrames.Count}", ((i / (double)settings.TimeFrames.Count)) / 4.0); if (!_wrapper.Execute(clipArguments)) { return(GeneratorResult.Failed()); } if (_canceled) { return(GeneratorResult.Failed()); } } entry.Update("Generating GIF (2/4): Merging Clips", 1 / 4.0); string clipFileName = ""; if (sectionFileNames.Count == 1) { clipFileName = sectionFileNames[0]; } else { ClipMergeArguments mergeArguments = new ClipMergeArguments { InputFile = settings.VideoFile, ClipFiles = sectionFileNames.ToArray(), OutputFile = Path.Combine(Path.GetTempPath(), Path.GetFileName(settings.VideoFile) + $"-clip.mkv") }; clipFileName = mergeArguments.OutputFile; tempFiles.Add(clipFileName); if (!_wrapper.Execute(mergeArguments)) { return(GeneratorResult.Failed()); } if (_canceled) { return(GeneratorResult.Failed()); } } entry.Update("Generating GIF (3/4): Extracting Palette", 2 / 4.0); string paletteFile = clipFileName + "-palette.png"; PaletteExtractorArguments paletteArguments = new PaletteExtractorArguments { InputFile = clipFileName, OutputFile = paletteFile }; tempFiles.Add(paletteFile); if (!_wrapper.Execute(paletteArguments)) { return(GeneratorResult.Failed()); } if (_canceled) { return(GeneratorResult.Failed()); } entry.Update("Generating GIF (3/4): Creating GIF", 3 / 4.0); string gifFileName = settings.OutputFile; GifCreatorArguments gifArguments = new GifCreatorArguments(); gifArguments.InputFile = clipFileName; gifArguments.PaletteFile = paletteFile; gifArguments.OutputFile = gifFileName; gifArguments.Framerate = settings.Framerate; if (!_wrapper.Execute(gifArguments)) { return(GeneratorResult.Failed()); } if (_canceled) { return(GeneratorResult.Failed()); } entry.Update("Done!", 4 / 4.0); bool success = File.Exists(gifFileName); if (success) { entry.DoneType = JobDoneTypes.Success; } else { entry.DoneType = JobDoneTypes.Failure; } OnDone(new Tuple <bool, string>(success, gifFileName)); if (success) { return(GeneratorResult.Succeeded(gifFileName)); } return(GeneratorResult.Failed()); } catch { entry.DoneType = JobDoneTypes.Failure; return(GeneratorResult.Failed()); } finally { entry.State = JobStates.Done; if (_canceled) { entry.DoneType = JobDoneTypes.Cancelled; } foreach (string tempFile in tempFiles) { if (File.Exists(tempFile)) { File.Delete(tempFile); } } } }
public FfmpegThumbnailGenerator(FfmpegWrapper ffmpeg, FileManager fileManager, string tempFileLocation) { _ffmpeg = ffmpeg; _fileManager = fileManager; _tempFileLocation = tempFileLocation; }
protected override GeneratorResult ProcessInternal(ThumbnailGeneratorSettings settings, GeneratorEntry entry) { try { entry.State = JobStates.Processing; _wrapper = new FfmpegWrapper(FfmpegExePath); double intervall = settings.Intervall; if (settings.Intervall < 1) { var info = _wrapper.GetVideoInfo(settings.VideoFile); if (!info.IsGoodEnough()) { entry.Update("Failed", 1); entry.DoneType = JobDoneTypes.Failure; return(GeneratorResult.Failed()); } const double targetFrameCount = 500.0; intervall = info.Duration.TotalSeconds / targetFrameCount; intervall = Math.Min(Math.Max(1, intervall), 10); } FrameConverterArguments arguments = new FrameConverterArguments { StatusUpdateHandler = (progress) => { entry.Update(null, progress); }, InputFile = settings.VideoFile, OutputDirectory = FfmpegWrapper.CreateRandomTempDirectory(), Intervall = intervall, Width = settings.Width, Height = settings.Height, ClipLeft = settings.ClipLeft, DeLense = settings.ClipLeft }; string thumbfile = Path.ChangeExtension(settings.VideoFile, "thumbs"); entry.Update("Extracting Frames", 0); var frames = _wrapper.ExtractFrames(arguments); if (_canceled) { return(GeneratorResult.Failed()); } entry.Update("Saving Thumbnails", 1); VideoThumbnailCollection thumbnails = new VideoThumbnailCollection(); foreach (var frame in frames) { thumbnails.Add(frame.Item1, frame.Item2); } using (FileStream stream = new FileStream(thumbfile, FileMode.Create, FileAccess.Write)) { thumbnails.Save(stream); } thumbnails.Dispose(); entry.DoneType = JobDoneTypes.Success; entry.Update("Done", 1); return(GeneratorResult.Succeeded(thumbfile)); } catch (Exception) { entry.DoneType = JobDoneTypes.Failure; return(GeneratorResult.Failed()); } finally { entry.State = JobStates.Done; if (_canceled) { entry.DoneType = JobDoneTypes.Cancelled; } } }
public void Generate_All_Barcode_Settings_Combinations() { Assert.Inconclusive("Uncomment me to run the test"); var ffmpegWrapper = new FfmpegWrapper(FfmpegExecutablePath); var streamProcessor = new ImageStreamProcessor(); var allGenerators = new List <IBarGenerator>(); // Legacy (reference) allGenerators.Add(GdiBarGenerator.CreateLegacy(false)); // Legacy (reference) smoothed allGenerators.Add(GdiBarGenerator.CreateLegacy(true)); foreach (var average in new[] { GdiAverage.No, GdiAverage.OnePass }) { foreach (var interpolationMode in new[] { InterpolationMode.HighQualityBicubic, InterpolationMode.NearestNeighbor, InterpolationMode.Bicubic }) { allGenerators.Add(new GdiBarGenerator(average: average, scalingMode: ScalingMode.Sane, interpolationMode: interpolationMode)); } } foreach (var average in new[] { false, true }) { foreach (var interpolation in new[] { InterpolationSettings.Average, InterpolationSettings.CubicSmoother, InterpolationSettings.NearestNeighbor, }) { allGenerators.Add(new MagicScalerBarGenerator("noname", average: average, interpolation: interpolation)); } } CreateTestVideoIfNecessary(); var inputPath = TestVideoFilePath; inputPath = @"G:\videos\In Bruges (2008)\In.Bruges.2008.720p.BrRip.x264.YIFY.mp4"; { var results = streamProcessor.CreateBarCodes( new BarCodeParameters { Width = 1280, BarWidth = 1, InputPath = inputPath, GeneratorOutputPaths = allGenerators.ToDictionary(x => x, x => x.Name) }, ffmpegWrapper, CancellationToken.None, progress: null, log: x => TestContext.WriteLine(x)); foreach (var result in results) { result.Value.Save($"{result.Key.Name}.png"); } } //{ // var results = streamProcessor.CreateBarCodes( // inputPath, // new BarCodeParameters { Width = 500, BarWidth = 50 }, // ffmpegWrapper, // CancellationToken.None, // progress: null, // log: x => TestContext.WriteLine(x), // allGenerators.ToArray()); // foreach (var result in results) // { // result.Value.Save($"50-{result.Key.Name}.png"); // } //} }
public VideoRecorder(string ffmpegBinPath = @"c:/Program Files (x86)/ffmpeg/bin/") { ffmpeg = new FfmpegWrapper(ffmpegBinPath); SetVideoCaptureFileName(); }
protected override GeneratorResult ProcessInternal(PreviewGeneratorSettings settings, GeneratorEntry entry) { entry.State = JobStates.Processing; List <string> tempFiles = new List <string>(); int totalSteps = settings.OverlayScriptPositions ? 5 : 4; int stepsDone = 0; try { _wrapper = new FfmpegWrapper(FfmpegExePath); List <string> sectionFileNames = new List <string>(); if (settings.TimeFrames.Any(tf => tf.IsFactor)) { VideoInfo info = _wrapper.GetVideoInfo(settings.VideoFile); if (!info.IsGoodEnough()) { entry.State = JobStates.Done; entry.DoneType = JobDoneTypes.Failure; entry.Update("Failed", 1); return(GeneratorResult.Failed()); } TimeSpan duration = info.Duration; settings.TimeFrames.ForEach(tf => tf.CalculateStart(duration)); } ClipExtractorArguments clipArguments = new ClipExtractorArguments { InputFile = settings.VideoFile, Width = settings.Width, Height = settings.Height, Framerate = settings.Framerate, ClipLeft = settings.ClipLeft, DeLense = settings.ClipLeft }; VideoInfo clipInfo = null; for (int i = 0; i < settings.TimeFrames.Count; i++) { string sectionFileName = Path.Combine(Path.GetTempPath(), Path.GetFileName(settings.VideoFile) + $"-clip_{i}.mkv"); sectionFileNames.Add(sectionFileName); tempFiles.Add(sectionFileName); var timeFrame = settings.TimeFrames[i]; clipArguments.Duration = timeFrame.Duration; clipArguments.StartTimeSpan = timeFrame.StartTimeSpan; clipArguments.OutputFile = sectionFileName; entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Clipping Video Section {i + 1}/{settings.TimeFrames.Count}", (stepsDone / (double)totalSteps) + ((i / (double)settings.TimeFrames.Count)) / totalSteps); if (!_wrapper.Execute(clipArguments)) { return(GeneratorResult.Failed()); } if (clipInfo == null) { clipInfo = _wrapper.GetVideoInfo(sectionFileName); } if (_canceled) { return(GeneratorResult.Failed()); } } stepsDone++; if (settings.OverlayScriptPositions) { string script = ViewModel.GetScriptFile(settings.VideoFile); var actions = ViewModel.LoadScriptActions(script, null)?.OfType <FunScriptAction>().ToList(); Size barSize = new Size(clipInfo.Resolution.Horizontal, 20); if (actions != null && actions.Count > 0) { PositionBar bar = new PositionBar { Width = barSize.Width, Height = barSize.Height, TotalDisplayedDuration = TimeSpan.FromSeconds(5), Background = Brushes.Black, Positions = new PositionCollection(actions.Select(a => new TimedPosition() { Position = a.Position, TimeStamp = a.TimeStamp })), DrawCircles = false, DrawLines = false, }; for (int i = 0; i < settings.TimeFrames.Count; i++) { TimeSpan start = settings.TimeFrames[i].StartTimeSpan; TimeSpan max = start + settings.TimeFrames[i].Duration; TimeSpan progress = start; string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); Directory.CreateDirectory(tempDir); string overlayFileName = Path.Combine(Path.GetTempPath(), Path.GetFileName(settings.VideoFile) + $"-overlay_{i}.mkv"); tempFiles.Add(overlayFileName); int frame = 0; entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Overlaying Positions {i + 1}/{settings.TimeFrames.Count}", (stepsDone / (double)totalSteps) + ((i / (double)settings.TimeFrames.Count)) / totalSteps); double expectedFrames = 1 + (settings.TimeFrames[i].Duration.TotalSeconds * clipInfo.FrameRate); while (progress <= max) { progress = start + TimeSpan.FromSeconds(frame / clipInfo.FrameRate); bar.Progress = progress; var bitmap = RenderToBitmap(bar, barSize); PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bitmap)); using (FileStream f = new FileStream(Path.Combine(tempDir, $"frame{frame:0000}.png"), FileMode.CreateNew)) encoder.Save(f); frame++; } FrameMergeArguments frameMergeArguments = new FrameMergeArguments { Framerate = clipInfo.FrameRate, InputFile = Path.Combine(tempDir, "frame%04d.png"), OutputFile = overlayFileName }; if (!_wrapper.Execute(frameMergeArguments)) { return(GeneratorResult.Failed()); } var clipInfo2 = _wrapper.GetVideoInfo(overlayFileName); Directory.Delete(tempDir, true); string mergeFileName = Path.Combine(Path.GetTempPath(), Path.GetFileName(settings.VideoFile) + $"-merge_{i}.mkv"); tempFiles.Add(mergeFileName); VideoOverlayArguments overlayArguments = new VideoOverlayArguments { InputFile = sectionFileNames[i], Overlay = overlayFileName, OutputFile = mergeFileName, PosX = 0, PosY = clipInfo.Resolution.Vertical - 20 }; if (!_wrapper.Execute(overlayArguments)) { return(GeneratorResult.Failed()); } sectionFileNames[i] = mergeFileName; } } stepsDone++; } entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Merging Clips", stepsDone / (double)totalSteps); string clipFileName; if (sectionFileNames.Count == 1) { clipFileName = sectionFileNames[0]; } else { ClipMergeArguments mergeArguments = new ClipMergeArguments { InputFile = settings.VideoFile, ClipFiles = sectionFileNames.ToArray(), OutputFile = Path.Combine(Path.GetTempPath(), Path.GetFileName(settings.VideoFile) + $"-clip.mkv") }; clipFileName = mergeArguments.OutputFile; tempFiles.Add(clipFileName); if (!_wrapper.Execute(mergeArguments)) { return(GeneratorResult.Failed()); } if (_canceled) { return(GeneratorResult.Failed()); } } stepsDone++; entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Extracting Palette", stepsDone / (double)totalSteps); string paletteFile = clipFileName + "-palette.png"; PaletteExtractorArguments paletteArguments = new PaletteExtractorArguments { InputFile = clipFileName, OutputFile = paletteFile }; tempFiles.Add(paletteFile); if (!_wrapper.Execute(paletteArguments)) { return(GeneratorResult.Failed()); } if (_canceled) { return(GeneratorResult.Failed()); } stepsDone++; entry.Update($"Generating GIF ({stepsDone + 1}/{totalSteps}): Creating GIF", stepsDone / (double)totalSteps); string gifFileName = settings.OutputFile; GifCreatorArguments gifArguments = new GifCreatorArguments(); gifArguments.InputFile = clipFileName; gifArguments.PaletteFile = paletteFile; gifArguments.OutputFile = gifFileName; gifArguments.Framerate = settings.Framerate; if (!_wrapper.Execute(gifArguments)) { return(GeneratorResult.Failed()); } if (_canceled) { return(GeneratorResult.Failed()); } stepsDone++; entry.Update("Done", 1.0); bool success = File.Exists(gifFileName); if (success) { entry.DoneType = JobDoneTypes.Success; } else { entry.DoneType = JobDoneTypes.Failure; } OnDone(new Tuple <bool, string>(success, gifFileName)); if (success) { return(GeneratorResult.Succeeded(gifFileName)); } return(GeneratorResult.Failed()); } catch (Exception e) { entry.DoneType = JobDoneTypes.Failure; return(GeneratorResult.Failed()); } finally { entry.State = JobStates.Done; if (_canceled) { entry.DoneType = JobDoneTypes.Cancelled; } foreach (string tempFile in tempFiles) { if (File.Exists(tempFile)) { File.Delete(tempFile); } } } }
public IReadOnlyDictionary <IBarGenerator, Bitmap> CreateBarCodes( BarCodeParameters parameters, FfmpegWrapper ffmpeg, CancellationToken cancellationToken, IProgress <double> progress = null, Action <string> log = null) { var barCount = (int)Math.Round((double)parameters.Width / parameters.BarWidth); var bitmapStreamSource = ffmpeg.GetImagesFromMedia(parameters.InputPath, barCount, cancellationToken, log); var barGenerators = parameters.GeneratorOutputPaths.Keys.ToArray(); Bitmap[] finalBitmaps = new Bitmap[barGenerators.Length]; Graphics[] finalBitmapGraphics = new Graphics[barGenerators.Length]; int actualBarHeight = 0; int x = 0; foreach (var bitmapStream in bitmapStreamSource) { if (x == 0) { var imageInfo = ImageFileInfo.Load(bitmapStream); actualBarHeight = parameters.Height ?? imageInfo.Frames.First().Height; for (int i = 0; i < barGenerators.Length; i++) { finalBitmaps[i] = new Bitmap(parameters.Width, actualBarHeight); finalBitmapGraphics[i] = Graphics.FromImage(finalBitmaps[i]); } } using (bitmapStream) { for (int i = 0; i < barGenerators.Length; i++) { bitmapStream.Position = 0; var bar = barGenerators[i].GetBar(bitmapStream, parameters.BarWidth, actualBarHeight); var srcRect = new Rectangle(0, 0, bar.Width, bar.Height); var destRect = new Rectangle(x, 0, parameters.BarWidth, actualBarHeight); finalBitmapGraphics[i].DrawImage(bar, destRect, srcRect, GraphicsUnit.Pixel); } x += parameters.BarWidth; progress?.Report((double)x / parameters.Width); } } for (int i = 0; i < barGenerators.Length; i++) { finalBitmapGraphics[i]?.Dispose(); } var result = new Dictionary <IBarGenerator, Bitmap>(); for (int i = 0; i < barGenerators.Length; i++) { result.Add(barGenerators[i], finalBitmaps[i]); } return(result); }
public MainForm() { InitializeComponent(); var executingAssembly = Assembly.GetExecutingAssembly(); Icon = Icon.ExtractAssociatedIcon(executingAssembly.Location); Text += $" - {executingAssembly.GetName().Version}"; _barGenerators = new List <BarGeneratorViewModel> { new BarGeneratorViewModel( new MagicScalerBarGenerator("Normal", average: false), "The default mode to generate barcodes.\r\nIt scales images using a resampling algorithm that takes care of gamma correction and produces correct color averages.", initialCheckState: true), new BarGeneratorViewModel( new MagicScalerBarGenerator("Normal (smoothed)", "_smoothed", average: true, InterpolationSettings.CubicSmoother), "Almost the same as the 'Normal' mode, but vertically smoothed.\r\nIt also uses a 'cubic smoother' resampling algorithm that generates images sharper than the normal algorithm.", initialCheckState: false), new BarGeneratorViewModel( GdiBarGenerator.CreateLegacy(average: false), "The mode used in previous versions.\r\nIt's relatively fast, but the algorithm used to scale images is of poor quality.\r\nThis mode is not recommended, and only here for backward-compatibility.", initialCheckState: false), new BarGeneratorViewModel( GdiBarGenerator.CreateLegacy(average: true), "Same as 'Legacy', but vertically smoothed.", initialCheckState: false), }; barGeneratorList.DisplayMember = nameof(BarGeneratorViewModel.DisplayName); barGeneratorList.Items.Clear(); foreach (var item in _barGenerators) { barGeneratorList.Items.Add(item, isChecked: item.Checked); } barGeneratorList.SelectedItem = _barGenerators.First(x => x.Checked); // So that the right panel displays something. barGeneratorList.SelectedItem = null; // Unselect so a click on the line will not uncheck the item. AppendLog(Text); _openFileDialog = new OpenFileDialog() { CheckFileExists = true, CheckPathExists = true, }; _saveFileDialog = new SaveFileDialog() { DefaultExt = ".png", Filter = "Bitmap|*.bmp|Jpeg|*.jpg|Png|*.png|Gif|*.gif|All files|*.*", FilterIndex = 3, // 1 based OverwritePrompt = true, }; _ffmpegWrapper = new FfmpegWrapper("ffmpeg.exe"); _imageProcessor = new ImageStreamProcessor(); _barCodeParametersValidator = new BarCodeParametersValidator(); useInputHeightForOutputCheckBox.Checked = true; generateButton.Text = GenerateButtonText; }