public Models(int numPipelines = 1) { NumPipelines = numPipelines; CheckDeviceCapabilities(); SharedModel = new SharedModel(); Images = new ImagesModel(SharedModel.ScaleShader); TextureCache = new TextureCache(Images); pixelValueShader = new PixelValueShader(SharedModel); polarConvertShader = new ConvertPolarShader(SharedModel.QuadShader); Export = new ExportModel(SharedModel); Filter = new FiltersModel(Images); //Gif = new GifModel(sharedModel.QuadShader); Progress = new ProgressModel(); for (int i = 0; i < numPipelines; ++i) { pipelines.Add(new ImagePipeline(i)); pipelines.Last().PropertyChanged += PipeOnPropertyChanged; } Pipelines = pipelines; stats = new StatisticsModel(SharedModel); thumbnail = new ThumbnailModel(SharedModel.QuadShader); // pipeline controller pipelineController = new PipelineController(this); }
public virtual void Dispose() { //Gif?.Dispose(); Images?.Dispose(); Filter?.Dispose(); polarConvertShader?.Dispose(); foreach (var imagePipeline in pipelines) { imagePipeline.Dispose(); } pixelValueShader?.Dispose(); SharedModel?.Dispose(); }
public void CreateGif(Config cfg, SharedModel shared) { Debug.Assert(cfg.Left != null); Debug.Assert(cfg.Right != null); Debug.Assert(cfg.Left.Size == cfg.Right.Size); Debug.Assert(!progressModel.IsProcessing); if (cfg.Overlay != null) { Debug.Assert(cfg.Left.Size == cfg.Overlay.Size); } var cts = new CancellationTokenSource(); progressModel.AddTask(CreateGifAsync(cfg, progressModel.GetProgressInterface(cts.Token), shared), cts); }
public virtual void Dispose() { Progress?.Dispose(); thumbnail?.Dispose(); stats?.Dispose(); gif?.Dispose(); Images?.Dispose(); Filter?.Dispose(); polarConvertShader?.Dispose(); foreach (var imagePipeline in pipelines) { imagePipeline.Dispose(); } pixelValueShader?.Dispose(); SharedModel?.Dispose(); }
public Models(int numPipelines = 1) { NumPipelines = numPipelines; CheckDeviceCapabilities(); SharedModel = new SharedModel(); Images = new ImagesModel(SharedModel.ScaleShader); TextureCache = new ImageModelTextureCache(Images); Filter = new FiltersModel(Images); Progress = new ProgressModel(); for (int i = 0; i < numPipelines; ++i) { pipelines.Add(new ImagePipeline(i)); pipelines.Last().PropertyChanged += PipeOnPropertyChanged; } Pipelines = pipelines; // pipeline controller pipelineController = new PipelineController(this); }
public virtual void Dispose() { Progress?.Dispose(); thumbnail?.Dispose(); stats?.Dispose(); gif?.Dispose(); scaling?.Dispose(); overlay?.Dispose(); ssim?.Dispose(); Images?.Dispose(); Filter?.Dispose(); polarConvertShader?.Dispose(); convertTo3DShader?.Dispose(); foreach (var imagePipeline in pipelines) { imagePipeline.Dispose(); } pixelValueShader?.Dispose(); SharedModel?.Dispose(); // finally, destroy directx resources Device.Get().Dispose(); }
private async Task CreateGifAsync(Config cfg, IProgress progress, SharedModel shared) { // delay in milliseconds var numFrames = cfg.FramesPerSecond * cfg.NumSeconds; var left = cfg.Left; var right = cfg.Right; var overlay = cfg.Overlay; // size compatible? bool disposeImages = false; if ((left.Size.Width % 2) != 0 || (left.Size.Height % 2) != 0) { disposeImages = true; var pad = Size3.Zero; pad.X = left.Size.Width % 2; pad.Y = left.Size.Height % 2; left = (TextureArray2D)shared.Padding.Run(left, Size3.Zero, pad, PaddingShader.FillMode.Clamp, null, shared, false); right = (TextureArray2D)shared.Padding.Run(right, Size3.Zero, pad, PaddingShader.FillMode.Clamp, null, shared, false); if (overlay != null) { overlay = (TextureArray2D)shared.Padding.Run(overlay, Size3.Zero, pad, PaddingShader.FillMode.Transparent, null, shared, false); } Debug.Assert(left.Size.Width % 2 == 0 && left.Size.Height % 2 == 0); } try { progressModel.EnableDllProgress = false; var leftView = left.GetSrView(LayerMipmapSlice.Mip0); var rightView = right.GetSrView(LayerMipmapSlice.Mip0); var overlayView = overlay?.GetSrView(LayerMipmapSlice.Mip0); var curProg = progress.CreateSubProgress(0.9f); // prepare parallel processing var numTasks = Environment.ProcessorCount; var tasks = new Task[numTasks]; var images = new DllImageData[numTasks]; for (int i = 0; i < numTasks; ++i) { images[i] = IO.CreateImage(new ImageFormat(Format.R8G8B8A8_UNorm_SRgb), left.Size, LayerMipmapCount.One); } int textSize = left.Size.Y / 18; float padding = textSize / 4.0f; // render frames into texture using (var frame = new TextureArray2D(LayerMipmapCount.One, left.Size, Format.R8G8B8A8_UNorm_SRgb, false)) { var frameView = frame.GetRtView(LayerMipmapSlice.Mip0); using (var d2d = new Direct2D(frame)) { for (int i = 0; i < numFrames; ++i) { float t = (float)i / (numFrames - 1); int borderPos = (int)(t * (frame.Size.Width - 1)); int idx = i % numTasks; // render frame shader.Run(leftView, rightView, overlayView, frameView, cfg.SliderWidth, borderPos, frame.Size.Width, frame.Size.Height, shared.QuadShader, shared.Upload); // add text using (var c = d2d.Begin()) { c.Text(new Float2(padding), new Float2(left.Size.X - padding, left.Size.Y - padding), textSize, Colors.White, cfg.Label1, TextAlignment.Leading); c.Text(new Float2(padding), new Float2(left.Size.X - padding, left.Size.Y - padding), textSize, Colors.White, cfg.Label2, TextAlignment.Trailing); } // copy frame from gpu to cpu var dstMip = images[idx].GetMipmap(LayerMipmapSlice.Mip0); var dstPtr = dstMip.Bytes; var dstSize = dstMip.ByteSize; // wait for previous task to finish before writing it to the file if (tasks[idx] != null) { await tasks[idx]; } frame.CopyPixels(LayerMipmapSlice.Mip0, dstPtr, dstSize); var filename = $"{cfg.TmpFilename}{i:D4}"; // write to file tasks[idx] = Task.Run(() => { try { IO.SaveImage(images[idx], filename, "png", GliFormat.RGBA8_SRGB); } catch (Exception) { // ignored (probably cancelled by user) } }, progress.Token); curProg.Progress = i / (float)numFrames; curProg.What = "creating frames"; progress.Token.ThrowIfCancellationRequested(); } } } // wait for tasks to finish for (var i = 0; i < tasks.Length; i++) { if (tasks[i] != null) { await tasks[i]; } tasks[i] = null; } // convert video await FFMpeg.ConvertAsync(cfg, progress.CreateSubProgress(1.0f)); } finally { progressModel.EnableDllProgress = true; if (disposeImages) { left.Dispose(); right.Dispose(); overlay?.Dispose(); } } }