77using System . Threading . Tasks ;
88using System . Windows ;
99using System . Windows . Controls ;
10+ using System . Windows . Ink ;
11+ using System . Windows . Media ;
12+ using System . Windows . Media . Imaging ;
1013
1114namespace OnnxStack . UI . UserControls
1215{
1316 public partial class ImageInputControl : UserControl , INotifyPropertyChanged
1417 {
1518 private readonly IDialogService _dialogService ;
1619
17- /// <summary>Initializes a new instance of the <see cref="ImageInputControl" /> class.</summary>
20+ private int _maskDrawSize = 20 ;
21+ private bool _isMaskEraserEnabled ;
22+ private DrawingAttributes _maskAttributes ;
23+ private InkCanvasEditingMode _maskEditingMode = InkCanvasEditingMode . Ink ;
24+
25+ /// <summary>
26+ /// Initializes a new instance of the <see cref="ImageInputControl" /> class.
27+ /// </summary>
1828 public ImageInputControl ( )
1929 {
2030 if ( ! DesignerProperties . GetIsInDesignMode ( this ) )
2131 _dialogService = App . GetService < IDialogService > ( ) ;
2232
2333 LoadImageCommand = new AsyncRelayCommand ( LoadImage ) ;
2434 ClearImageCommand = new AsyncRelayCommand ( ClearImage ) ;
35+ MaskModeCommand = new AsyncRelayCommand ( MaskMode ) ;
36+ SaveMaskCommand = new AsyncRelayCommand ( SaveMask ) ;
2537 InitializeComponent ( ) ;
2638 }
2739
2840 public AsyncRelayCommand LoadImageCommand { get ; }
2941 public AsyncRelayCommand ClearImageCommand { get ; }
42+ public AsyncRelayCommand MaskModeCommand { get ; }
43+ public AsyncRelayCommand SaveMaskCommand { get ; }
3044
3145 public ImageInput Result
3246 {
@@ -37,6 +51,14 @@ public ImageInput Result
3751 public static readonly DependencyProperty ResultProperty =
3852 DependencyProperty . Register ( "Result" , typeof ( ImageInput ) , typeof ( ImageInputControl ) ) ;
3953
54+ public ImageInput MaskResult
55+ {
56+ get { return ( ImageInput ) GetValue ( MaskResultProperty ) ; }
57+ set { SetValue ( MaskResultProperty , value ) ; }
58+ }
59+
60+ public static readonly DependencyProperty MaskResultProperty =
61+ DependencyProperty . Register ( "MaskResult" , typeof ( ImageInput ) , typeof ( ImageInputControl ) ) ;
4062
4163 public SchedulerOptionsModel SchedulerOptions
4264 {
@@ -47,7 +69,6 @@ public SchedulerOptionsModel SchedulerOptions
4769 public static readonly DependencyProperty SchedulerOptionsProperty =
4870 DependencyProperty . Register ( "SchedulerOptions" , typeof ( SchedulerOptionsModel ) , typeof ( ImageInputControl ) ) ;
4971
50-
5172 public bool HasResult
5273 {
5374 get { return ( bool ) GetValue ( HasResultProperty ) ; }
@@ -57,7 +78,60 @@ public bool HasResult
5778 public static readonly DependencyProperty HasResultProperty =
5879 DependencyProperty . Register ( "HasResult" , typeof ( bool ) , typeof ( ImageInputControl ) ) ;
5980
81+ public bool HasMaskResult
82+ {
83+ get { return ( bool ) GetValue ( HasMaskResultProperty ) ; }
84+ set { SetValue ( HasMaskResultProperty , value ) ; }
85+ }
86+
87+ public static readonly DependencyProperty HasMaskResultProperty =
88+ DependencyProperty . Register ( "HasMaskResult" , typeof ( bool ) , typeof ( ImageInputControl ) ) ;
89+
90+ public bool IsMaskEnabled
91+ {
92+ get { return ( bool ) GetValue ( IsMaskEnabledProperty ) ; }
93+ set { SetValue ( IsMaskEnabledProperty , value ) ; }
94+ }
95+
96+ // Using a DependencyProperty as the backing store for IsMaskEnabled. This enables animation, styling, binding, etc...
97+ public static readonly DependencyProperty IsMaskEnabledProperty =
98+ DependencyProperty . Register ( "IsMaskEnabled" , typeof ( bool ) , typeof ( ImageInputControl ) ) ;
99+
100+
101+ public InkCanvasEditingMode MaskEditingMode
102+ {
103+ get { return _maskEditingMode ; }
104+ set { _maskEditingMode = value ; NotifyPropertyChanged ( ) ; }
105+ }
106+
107+ public DrawingAttributes MaskAttributes
108+ {
109+ get { return _maskAttributes ; }
110+ set { _maskAttributes = value ; NotifyPropertyChanged ( ) ; }
111+ }
112+
113+ public bool IsMaskEraserEnabled
114+ {
115+ get { return _isMaskEraserEnabled ; }
116+ set { _isMaskEraserEnabled = value ; NotifyPropertyChanged ( ) ; }
117+ }
118+
119+ public int MaskDrawSize
120+ {
121+ get { return _maskDrawSize ; }
122+ set
123+ {
124+ _maskDrawSize = value ;
125+ NotifyPropertyChanged ( ) ;
126+ UpdateMaskAttributes ( ) ;
127+ }
128+ }
129+
60130
131+ /// <summary>
132+ /// Loads the image.
133+ /// </summary>
134+ /// <returns></returns>
61135 private Task LoadImage ( )
62136 {
63137 var loadImageDialog = _dialogService . GetDialog < CropImageDialog > ( ) ;
@@ -75,13 +149,93 @@ private Task LoadImage()
75149 }
76150
77151
152+ /// <summary>
153+ /// Clears the image.
154+ /// </summary>
155+ /// <returns></returns>
78156 private Task ClearImage ( )
79157 {
80158 Result = null ;
159+ MaskResult = null ;
81160 HasResult = false ;
161+ HasMaskResult = false ;
162+ MaskCanvas . Strokes . Clear ( ) ;
163+ IsMaskEraserEnabled = false ;
164+ MaskEditingMode = InkCanvasEditingMode . Ink ;
82165 return Task . CompletedTask ;
83166 }
84167
168+
169+ /// <summary>
170+ /// Saves the mask.
171+ /// </summary>
172+ /// <returns></returns>
173+ private Task SaveMask ( )
174+ {
175+ MaskResult = new ImageInput
176+ {
177+ Image = CreateMaskImage ( ) ,
178+ FileName = "OnnxStack Generated Mask" ,
179+ } ;
180+ HasMaskResult = true ;
181+ return Task . CompletedTask ;
182+ }
183+
184+
185+ /// <summary>
186+ /// Change Masks mode.
187+ /// </summary>
188+ /// <returns></returns>
189+ private Task MaskMode ( )
190+ {
191+ if ( _isMaskEraserEnabled )
192+ {
193+ IsMaskEraserEnabled = false ;
194+ MaskEditingMode = InkCanvasEditingMode . Ink ;
195+ }
196+ else
197+ {
198+ IsMaskEraserEnabled = true ;
199+ MaskEditingMode = InkCanvasEditingMode . EraseByPoint ;
200+ }
201+ return Task . CompletedTask ;
202+ }
203+
204+
205+ /// <summary>
206+ /// Updates the mask attributes.
207+ /// </summary>
208+ private void UpdateMaskAttributes ( )
209+ {
210+ MaskAttributes = new DrawingAttributes
211+ {
212+ Color = Colors . Black ,
213+ Height = _maskDrawSize ,
214+ Width = _maskDrawSize ,
215+ } ;
216+ }
217+
218+
219+ /// <summary>
220+ /// Creates the mask image.
221+ /// </summary>
222+ /// <returns></returns>
223+ public BitmapSource CreateMaskImage ( )
224+ {
225+ // Create a RenderTargetBitmap to render the Canvas content.
226+ var renderBitmap = new RenderTargetBitmap ( ( int ) MaskCanvas . ActualWidth , ( int ) MaskCanvas . ActualHeight , 96 , 96 , PixelFormats . Pbgra32 ) ;
227+
228+ // Make a drawing visual to render.
229+ var visual = new DrawingVisual ( ) ;
230+ using ( DrawingContext context = visual . RenderOpen ( ) )
231+ {
232+ VisualBrush brush = new VisualBrush ( MaskCanvas ) ;
233+ context . DrawRectangle ( brush , null , new Rect ( new Point ( 0 , 0 ) , new Point ( MaskCanvas . ActualWidth , MaskCanvas . ActualHeight ) ) ) ;
234+ }
235+ renderBitmap . Render ( visual ) ;
236+ return renderBitmap ;
237+ }
238+
85239 #region INotifyPropertyChanged
86240 public event PropertyChangedEventHandler PropertyChanged ;
87241 public void NotifyPropertyChanged ( [ CallerMemberName ] string property = "" )
0 commit comments