2 * Copyright(c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Diagnostics;
25 using global::System.ComponentModel;
26 using global::System.Runtime.InteropServices;
27 using Tizen.NUI.BaseComponents;
30 /// Capture snapshots the current scene and save as a file.
31 /// Applications should follow the example below to create capture :
33 /// Capture capture = new Capture();
35 /// If required, you can also subscribe Finished event :
37 /// capture.Finished += onCaptureFinished;
39 /// At the subcribed event handler, user can know whether capture finish succeeded state.
41 /// private void onCaptureFinished(object sender, CaptureFinishedEventArgs e)
43 /// if(e.Success) { //capture success, do something. }
44 /// else { //capture failure, do something. }
47 /// suppose that we want to capture View 'A'. And, the View 'A' is overlapped by another View 'B' that is not a child of 'A'.
48 /// in this case, if source is root of scene, the captured image includes a part of View 'B' on the 'A'.
49 /// however, if source is just View 'A', the result includes only 'A'.
51 [EditorBrowsable(EditorBrowsableState.Never)]
52 public class Capture : BaseHandle
55 /// Create an Capture.
57 [EditorBrowsable(EditorBrowsableState.Never)]
58 public Capture() : this(Interop.Capture.New(), true)
60 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
63 internal Capture(IntPtr cPtr, bool cMemoryOwn) : base(Interop.Capture.Upcast(cPtr), cMemoryOwn)
70 /// <param name="type"></param>
71 [EditorBrowsable(EditorBrowsableState.Never)]
72 protected override void Dispose(DisposeTypes type)
79 if (type == DisposeTypes.Explicit)
82 //Release your own managed resources here.
83 //You should release all of your own disposable objects here.
89 /// This will not be public opened.
90 [EditorBrowsable(EditorBrowsableState.Never)]
91 protected override void ReleaseSwigCPtr(HandleRef swigCPtr)
93 Interop.Capture.Delete(swigCPtr);
97 /// Start capture and save the image as a file.
99 /// <param name="source">source View or Layer to be used for capture.
100 /// This source must be added on the window in advance.</param>
101 /// <param name="position">top-left position of area to be captured.
102 /// this position is defined in the window.</param>
103 /// <param name="size">captured size.</param>
104 /// <param name="path">image file path to be saved as a file.
105 /// If path is empty string, the captured result is not be saved as a file.</param>
106 /// <param name="color">background color of captured scene.</param>
107 /// <exception cref="InvalidOperationException">This exception can be due to the invalid size values, of when width or height is lower than zero.</exception>
108 /// <exception cref="ArgumentNullException">This exception is thrown when size or path or position or color is null.</exception>
109 [EditorBrowsable(EditorBrowsableState.Never)]
110 public void Start(Container source, Position position, Size size, string path, Color color)
114 throw new ArgumentNullException(nameof(size));
116 else if (size.Width <= 0 || size.Height <= 0)
118 throw new InvalidOperationException("size should larger than zero");
120 else if (null == path)
122 throw new ArgumentNullException("path should not be null");
124 else if (null == position)
126 throw new ArgumentNullException(nameof(position));
128 else if (null == color)
130 throw new ArgumentNullException(nameof(color));
133 if (source is View || source is Layer)
135 Interop.Capture.Start4(swigCPtr, source.SwigCPtr, new Vector2(position.X, position.Y).SwigCPtr, new Vector2(size.Width, size.Height).SwigCPtr, path, new Vector4(color.R, color.G, color.B, color.A).SwigCPtr);
137 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
142 /// Start capture and save the image as a file.
144 /// <param name="source">source View or Layer to be used for capture.
145 /// This source must be added on the window in advance.</param>
146 /// <param name="size">captured size.</param>
147 /// <param name="path">image file path to be saved as a file.
148 /// If path is empty string, the captured result is not be saved as a file.</param>
149 /// <param name="color">background color of captured scene.</param>
150 /// <param name="quality">The value to control image quality for jpeg file format in the range [1, 100].</param>
151 /// <exception cref="InvalidOperationException">This exception can be due to the invalid size values, of when width or height is lower than zero.</exception>
152 /// <exception cref="ArgumentNullException">This exception is thrown when size or path or color is null.</exception>
153 [EditorBrowsable(EditorBrowsableState.Never)]
154 public void Start(Container source, Size size, string path, Color color, uint quality)
158 throw new ArgumentNullException(nameof(size));
160 else if (size.Width <= 0 || size.Height <= 0)
162 throw new InvalidOperationException("size should larger than zero");
164 else if (null == path)
166 throw new ArgumentNullException("path should not be null");
168 else if (quality > 100)
170 throw new InvalidOperationException("quality should between 0 to 100");
172 else if (null == color)
174 throw new ArgumentNullException(nameof(color));
177 if (source is View || source is Layer)
179 Interop.Capture.Start3(swigCPtr, source.SwigCPtr, new Vector2(size.Width, size.Height).SwigCPtr, path, new Vector4(color.R, color.G, color.B, color.A).SwigCPtr, quality);
181 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
186 /// Start capture and save the image as a file.
188 /// <param name="source">source View or Layer to be used for capture.
189 /// This source must be added on the window in advance.</param>
190 /// <param name="size">captured size.</param>
191 /// <param name="path">image file path to be saved as a file.
192 /// If path is empty string, the captured result is not be saved as a file.</param>
193 /// <param name="color">background color of captured scene.</param>
194 /// <exception cref="InvalidOperationException">This exception can be due to the invalid size values, of when width or height is lower than zero.</exception>
195 /// <exception cref="ArgumentNullException">This exception is thrown when size or path or color is null.</exception>
196 [EditorBrowsable(EditorBrowsableState.Never)]
197 public void Start(Container source, Size size, string path, Color color)
201 throw new ArgumentNullException(nameof(size));
203 else if (size.Width <= 0 || size.Height <= 0)
205 throw new InvalidOperationException("size should larger than zero");
207 else if (null == path)
209 throw new ArgumentNullException("path should not be null");
211 else if (null == color)
213 throw new ArgumentNullException(nameof(color));
216 if (source is View || source is Layer)
218 Interop.Capture.Start1(swigCPtr, source.SwigCPtr, new Vector2(size.Width, size.Height).SwigCPtr, path, new Vector4(color.R, color.G, color.B, color.A).SwigCPtr);
220 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
225 /// Start capture and save the image as a file.
228 /// Background color of captured scene is transparent.
230 /// <param name="source">source View or Layer to be used for capture.
231 /// This source must be added on the window in advance.</param>
232 /// <param name="size">captured size.</param>
233 /// <param name="path">image file path to be saved as a file.
234 /// If path is empty string, the captured result is not be saved as a file.</param>
235 /// <exception cref="InvalidOperationException">This exception can be due to the invalid size values, of when width or height is lower than zero.</exception>
236 /// <exception cref="ArgumentNullException">This exception is thrown when size or path is null.</exception>
237 [EditorBrowsable(EditorBrowsableState.Never)]
238 public void Start(Container source, Size size, string path)
242 throw new ArgumentNullException(nameof(size));
244 else if (size.Width <= 0 || size.Height <= 0)
246 throw new InvalidOperationException("size should larger than zero");
248 else if (null == path)
250 throw new ArgumentNullException("path should not be null");
253 if (source is View || source is Layer)
255 Interop.Capture.Start2(swigCPtr, source.SwigCPtr, new Vector2(size.Width, size.Height).SwigCPtr, path);
257 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
262 /// Set result image quality in case of jpeg.
264 /// <param name="quality">quality The value to control image quality for jpeg file format in the range [1, 100]</param>
265 /// <exception cref="InvalidOperationException">This exception can be due to the invalid size values, of when quality is lower than zero or over than 100.</exception>
266 [EditorBrowsable(EditorBrowsableState.Never)]
267 public void SetImageQuality(uint quality)
269 if (quality < 0 || quality > 100)
271 throw new InvalidOperationException("quality should between zero to 100");
274 Interop.Capture.SetImageQuality(swigCPtr, quality);
277 private void onFinished(IntPtr data, int state)
279 if (data != IntPtr.Zero)
281 var arg = new CaptureFinishedEventArgs();
282 // dali native definition :
283 // enum class FinishState
285 // SUCCEEDED, ///< Succeeded in saving the result after capture
286 // FAILED ///< Failed to capture by time out or to save the result
288 arg.Success = (state == 0) ? true : false;
289 finishedEventHandler?.Invoke(this, arg);
293 private CaptureSignal finishedSignal;
294 private delegate void finishedCallbackType(IntPtr data, int state);
295 private finishedCallbackType finishedCallback;
296 private EventHandler<CaptureFinishedEventArgs> finishedEventHandler;
299 /// For subscribing Finished event sent by this class.
301 [EditorBrowsable(EditorBrowsableState.Never)]
302 public event EventHandler<CaptureFinishedEventArgs> Finished
306 if (finishedEventHandler == null && disposed == false)
308 finishedSignal = new CaptureSignal(Interop.Capture.Get(swigCPtr), false);
309 finishedCallback = onFinished;
310 finishedSignal.Connect(finishedCallback);
312 finishedEventHandler += value;
316 finishedEventHandler -= value;
318 if (finishedEventHandler == null && finishedSignal?.Empty() == false)
320 finishedCallback = onFinished;
321 finishedSignal.Disconnect(finishedCallback);
327 /// Get NativeImageSource that is saved captured image.
329 /// <returns>NativeImageSource that is saved captured image.</returns>
330 [EditorBrowsable(EditorBrowsableState.Never)]
331 public NativeImageSource GetNativeImageSource()
333 Tizen.Log.Debug("NUI", $"GetNativeImageSource()");
334 return new NativeImageSource(Interop.Capture.GetNativeImageSourcePtr(swigCPtr), true);
339 /// CaptureFinishedEventArgs
341 [EditorBrowsable(EditorBrowsableState.Never)]
342 public class CaptureFinishedEventArgs : EventArgs
345 /// Status of saving the result after capture.
348 /// true when succeeded in saving the result after capture.
349 /// false when failed to capture by time out or to save the result.
351 public bool Success { get; internal set; }
354 internal class CaptureSignal : Disposable
356 internal CaptureSignal(IntPtr cPtr, bool cMemoryOwn) : base(cPtr, cMemoryOwn)
360 protected override void ReleaseSwigCPtr(HandleRef swigCPtr)
364 Interop.Capture.DeleteSignal(swigCPtr);
370 bool ret = Interop.Capture.SignalEmpty(swigCPtr);
371 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
375 public uint GetConnectionCount()
377 uint ret = Interop.Capture.SignalGetConnectionCount(swigCPtr);
378 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
382 public void Connect(Delegate func)
384 IntPtr ip = Marshal.GetFunctionPointerForDelegate<Delegate>(func);
386 Interop.Capture.SignalConnect(swigCPtr, new HandleRef(this, ip));
387 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
391 public void Disconnect(Delegate func)
393 IntPtr ip = Marshal.GetFunctionPointerForDelegate<Delegate>(func);
395 Interop.Capture.SignalDisconnect(swigCPtr, new HandleRef(this, ip));
396 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();
400 public void Emit(Capture src, bool success)
402 Interop.Capture.SignalEmit(swigCPtr, src.SwigCPtr, (success ? 0 : 1));
403 if (NDalicPINVOKE.SWIGPendingException.Pending) throw NDalicPINVOKE.SWIGPendingException.Retrieve();