@@ -35,6 +35,7 @@ public partial class ImageInpaint : UserControl, INavigatable, INotifyPropertyCh
3535 private int _selectedTabIndex ;
3636 private bool _hasInputResult ;
3737 private bool _hasInputMaskResult ;
38+ private bool _isControlsEnabled ;
3839 private ImageInput _inputImage ;
3940 private ImageResult _resultImage ;
4041 private ImageInput _inputImageMask ;
@@ -65,6 +66,7 @@ public ImageInpaint()
6566 BatchOptions = new BatchOptionsModel ( ) ;
6667 ImageResults = new ObservableCollection < ImageResult > ( ) ;
6768 ProgressMax = SchedulerOptions . InferenceSteps ;
69+ IsControlsEnabled = true ;
6870 InitializeComponent ( ) ;
6971 }
7072
@@ -167,6 +169,11 @@ public int SelectedTabIndex
167169 set { _selectedTabIndex = value ; NotifyPropertyChanged ( ) ; }
168170 }
169171
172+ public bool IsControlsEnabled
173+ {
174+ get { return _isControlsEnabled ; }
175+ set { _isControlsEnabled = value ; NotifyPropertyChanged ( ) ; }
176+ }
170177
171178
172179 /// <summary>
@@ -179,9 +186,9 @@ public Task NavigateAsync(ImageResult imageResult)
179186 Reset ( ) ;
180187 HasResult = false ;
181188 ResultImage = null ;
189+ InputImageMask = null ;
182190 HasInputResult = true ;
183191 HasInputMaskResult = false ;
184- InputImageMask = null ;
185192 if ( imageResult . Model . ModelOptions . Diffusers . Contains ( DiffuserType . ImageInpaint )
186193 || imageResult . Model . ModelOptions . Diffusers . Contains ( DiffuserType . ImageInpaintLegacy ) )
187194 {
@@ -210,24 +217,9 @@ private async Task Generate()
210217 {
211218 HasResult = false ;
212219 IsGenerating = true ;
220+ IsControlsEnabled = false ;
213221 ResultImage = null ;
214- var promptOptions = new PromptOptions
215- {
216- Prompt = PromptOptions . Prompt ,
217- NegativePrompt = PromptOptions . NegativePrompt ,
218- DiffuserType = SelectedModel . ModelOptions . Diffusers . Contains ( DiffuserType . ImageInpaint )
219- ? DiffuserType . ImageInpaint
220- : DiffuserType . ImageInpaintLegacy ,
221- InputImage = new StableDiffusion . Models . InputImage
222- {
223- ImageBytes = InputImage . Image . GetImageBytes ( )
224- } ,
225- InputImageMask = new StableDiffusion . Models . InputImage
226- {
227- ImageBytes = InputImageMask . Image . GetImageBytes ( )
228- }
229- } ;
230-
222+ var promptOptions = GetPromptOptions ( PromptOptions , InputImage , InputImageMask ) ;
231223 var batchOptions = BatchOptions . ToBatchOptions ( ) ;
232224 var schedulerOptions = SchedulerOptions . ToSchedulerOptions ( ) ;
233225 schedulerOptions . Strength = 1 ; // Make sure strength is 1 for Image Inpainting
@@ -239,8 +231,11 @@ private async Task Generate()
239231 if ( resultImage != null )
240232 {
241233 ResultImage = resultImage ;
242- ImageResults . Add ( resultImage ) ;
243234 HasResult = true ;
235+ if ( BatchOptions . IsAutomationEnabled && BatchOptions . DisableHistory )
236+ continue ;
237+
238+ ImageResults . Add ( resultImage ) ;
244239 }
245240 }
246241 }
@@ -267,8 +262,7 @@ private bool CanExecuteGenerate()
267262 {
268263 return ! IsGenerating
269264 && ! string . IsNullOrEmpty ( PromptOptions . Prompt )
270- && HasInputResult
271- && HasInputMaskResult ;
265+ && HasInputResult ;
272266 }
273267
274268
@@ -324,6 +318,7 @@ private bool CanExecuteClearHistory()
324318 private void Reset ( )
325319 {
326320 IsGenerating = false ;
321+ IsControlsEnabled = true ;
327322 ProgressValue = 0 ;
328323 }
329324
@@ -338,6 +333,9 @@ private void Reset()
338333 /// <returns></returns>
339334 private async IAsyncEnumerable < ImageResult > ExecuteStableDiffusion ( IModelOptions modelOptions , PromptOptions promptOptions , SchedulerOptions schedulerOptions , BatchOptions batchOptions )
340335 {
336+ if ( ! IsExecuteOptionsValid ( PromptOptions ) )
337+ yield break ;
338+
341339 _cancelationTokenSource = new CancellationTokenSource ( ) ;
342340 if ( ! BatchOptions . IsAutomationEnabled )
343341 {
@@ -347,15 +345,68 @@ private async IAsyncEnumerable<ImageResult> ExecuteStableDiffusion(IModelOptions
347345 }
348346 else
349347 {
350- var timestamp = Stopwatch . GetTimestamp ( ) ;
351- await foreach ( var batchResult in _stableDiffusionService . GenerateBatchAsync ( modelOptions , promptOptions , schedulerOptions , batchOptions , ProgressBatchCallback ( ) , _cancelationTokenSource . Token ) )
348+ if ( _batchOptions . BatchType != BatchOptionType . Realtime )
352349 {
353- yield return await GenerateResultAsync ( batchResult . ImageResult . ToImageBytes ( ) , promptOptions , batchResult . SchedulerOptions , timestamp ) ;
354- timestamp = Stopwatch . GetTimestamp ( ) ;
350+ var timestamp = Stopwatch . GetTimestamp ( ) ;
351+ await foreach ( var batchResult in _stableDiffusionService . GenerateBatchAsync ( modelOptions , promptOptions , schedulerOptions , batchOptions , ProgressBatchCallback ( ) , _cancelationTokenSource . Token ) )
352+ {
353+ yield return await GenerateResultAsync ( batchResult . ImageResult . ToImageBytes ( ) , promptOptions , batchResult . SchedulerOptions , timestamp ) ;
354+ timestamp = Stopwatch . GetTimestamp ( ) ;
355+ }
356+ yield break ;
357+ }
358+
359+ // Realtime Diffusion
360+ IsControlsEnabled = true ;
361+ while ( ! _cancelationTokenSource . IsCancellationRequested )
362+ {
363+ var refreshTimestamp = Stopwatch . GetTimestamp ( ) ;
364+ if ( SchedulerOptions . HasChanged || PromptOptions . HasChanged || HasInputMaskResult )
365+ {
366+ HasInputMaskResult = false ;
367+ PromptOptions . HasChanged = false ;
368+ SchedulerOptions . HasChanged = false ;
369+ var realtimePromptOptions = GetPromptOptions ( PromptOptions , InputImage , InputImageMask ) ;
370+ var realtimeSchedulerOptions = SchedulerOptions . ToSchedulerOptions ( ) ;
371+
372+ var timestamp = Stopwatch . GetTimestamp ( ) ;
373+ var result = await _stableDiffusionService . GenerateAsBytesAsync ( modelOptions , realtimePromptOptions , realtimeSchedulerOptions , RealtimeProgressCallback ( ) , _cancelationTokenSource . Token ) ;
374+ yield return await GenerateResultAsync ( result , promptOptions , schedulerOptions , timestamp ) ;
375+ }
376+ await Utils . RefreshDelay ( refreshTimestamp , BatchOptions . RealtimeRefreshRate , _cancelationTokenSource . Token ) ;
355377 }
356378 }
357379 }
358380
381+ private bool IsExecuteOptionsValid ( PromptOptionsModel prompt )
382+ {
383+ if ( string . IsNullOrEmpty ( prompt . Prompt ) )
384+ return false ;
385+
386+ return true ;
387+ }
388+
389+
390+ private PromptOptions GetPromptOptions ( PromptOptionsModel promptOptionsModel , ImageInput imageInput , ImageInput imageInputMask )
391+ {
392+ return new PromptOptions
393+ {
394+ Prompt = promptOptionsModel . Prompt ,
395+ NegativePrompt = promptOptionsModel . NegativePrompt ,
396+ DiffuserType = SelectedModel . ModelOptions . Diffusers . Contains ( DiffuserType . ImageInpaint )
397+ ? DiffuserType . ImageInpaint
398+ : DiffuserType . ImageInpaintLegacy ,
399+ InputImage = new StableDiffusion . Models . InputImage
400+ {
401+ ImageBytes = imageInput . Image . GetImageBytes ( )
402+ } ,
403+ InputImageMask = new StableDiffusion . Models . InputImage
404+ {
405+ ImageBytes = imageInputMask . Image . GetImageBytes ( )
406+ }
407+ } ;
408+ }
409+
359410
360411 /// <summary>
361412 /// Generates the result.
@@ -430,6 +481,24 @@ private Action<int, int, int, int> ProgressBatchCallback()
430481 } ;
431482 }
432483
484+ private Action < int , int > RealtimeProgressCallback ( )
485+ {
486+ return ( value , maximum ) =>
487+ {
488+ App . UIInvoke ( ( ) =>
489+ {
490+ if ( _cancelationTokenSource . IsCancellationRequested )
491+ return ;
492+
493+ if ( BatchOptions . StepValue != value )
494+ BatchOptions . StepValue = value ;
495+ if ( BatchOptions . StepsValue != maximum )
496+ BatchOptions . StepsValue = maximum ;
497+ } ) ;
498+ } ;
499+ }
500+
501+
433502 #region INotifyPropertyChanged
434503 public event PropertyChangedEventHandler PropertyChanged ;
435504 public void NotifyPropertyChanged ( [ CallerMemberName ] string property = "" )
0 commit comments