2 * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
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.
19 using System.Threading;
20 using System.Threading.Tasks;
21 using Native = Interop.ThumbnailExtractor;
23 namespace Tizen.Multimedia.Util
26 /// Provides the ability to extract the thumbnail from media files.
28 /// <since_tizen> 4 </since_tizen>
29 public static class ThumbnailExtractor
32 /// Extracts the thumbnail for the given media with the specified path.
34 /// <since_tizen> 4 </since_tizen>
35 /// <returns>A task that represents the asynchronous extracting operation.</returns>
36 /// <remarks>The size of the thumbnail will be the default size (320x240).</remarks>
37 /// <param name="path">The path of the media file to extract the thumbnail.</param>
38 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
39 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
40 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
41 /// <exception cref="UnauthorizedAccessException">The caller does not have required privilege for accessing the <paramref name="path"/>.</exception>
42 /// <exception cref="FileFormatException">The specified file is not supported.</exception>
43 public static Task<ThumbnailExtractionResult> ExtractAsync(string path)
45 return RunExtractAsync(path, null, CancellationToken.None);
49 /// Extracts the thumbnail for the given media with the specified path.
51 /// <returns>A task that represents the asynchronous extracting operation.</returns>
52 /// <remarks>The size of the thumbnail will be the default size(320x240).</remarks>
53 /// <param name="path">The path of the media file to extract the thumbnail.</param>
54 /// <param name="cancellationToken">The token to stop the operation.</param>
55 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
56 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
57 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
58 /// <exception cref="UnauthorizedAccessException">The caller does not have required privilege for accessing the <paramref name="path"/>.</exception>
59 /// <exception cref="FileFormatException">The specified file is not supported.</exception>
60 /// <since_tizen> 4 </since_tizen>
61 public static Task<ThumbnailExtractionResult> ExtractAsync(string path, CancellationToken cancellationToken)
63 return RunExtractAsync(path, null, cancellationToken);
67 /// Extracts the thumbnail for the given media with the specified path and size.
69 /// <since_tizen> 4 </since_tizen>
70 /// <returns>A task that represents the asynchronous extracting operation.</returns>
72 /// If the width is not a multiple of 8, it can be changed by the inner process.<br/>
73 /// The width will be a multiple of 8 greater than the set value.
75 /// <param name="path">The path of the media file to extract the thumbnail.</param>
76 /// <param name="size">The size of the thumbnail.</param>
77 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
78 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
79 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
80 /// <exception cref="UnauthorizedAccessException">The caller does not have required privilege for accessing the <paramref name="path"/>.</exception>
81 /// <exception cref="ArgumentOutOfRangeException">
82 /// The width or the height of <paramref name="size"/> is less than or equal to zero.
84 /// <exception cref="FileFormatException">The specified file is not supported.</exception>
85 public static Task<ThumbnailExtractionResult> ExtractAsync(string path, Size size)
87 return RunExtractAsync(path, size, CancellationToken.None);
91 /// Extracts the thumbnail for the given media with the specified path and size.
93 /// <since_tizen> 4 </since_tizen>
94 /// <returns>A task that represents the asynchronous extracting operation.</returns>
96 /// If the width is not a multiple of 8, it can be changed by the inner process.<br/>
97 /// The width will be a multiple of 8 greater than the set value.
99 /// <param name="path">The path of the media file to extract the thumbnail.</param>
100 /// <param name="size">The size of the thumbnail.</param>
101 /// <param name="cancellationToken">The token to stop the operation.</param>
102 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
103 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
104 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
105 /// <exception cref="UnauthorizedAccessException">The caller does not have required privilege for accessing the <paramref name="path"/>.</exception>
106 /// <exception cref="ArgumentOutOfRangeException">
107 /// The width or the height of <paramref name="size"/> is less than or equal to zero.
109 /// <exception cref="FileFormatException">The specified file is not supported.</exception>
110 public static Task<ThumbnailExtractionResult> ExtractAsync(string path, Size size,
111 CancellationToken cancellationToken)
113 return RunExtractAsync(path, size, cancellationToken);
116 private static Task<ThumbnailExtractionResult> RunExtractAsync(string path, Size? size,
117 CancellationToken cancellationToken)
121 throw new ArgumentNullException(nameof(path));
124 if (!File.Exists(path))
126 throw new FileNotFoundException("File does not exists.", path);
131 if (size.Value.Width <= 0)
133 throw new ArgumentOutOfRangeException(nameof(size), size.Value.Width,
134 "The width must be greater than zero.");
137 if (size.Value.Height <= 0)
139 throw new ArgumentOutOfRangeException(nameof(size), size.Value.Height,
140 "The height must be greater than zero.");
144 return cancellationToken.IsCancellationRequested ?
145 Task.FromCanceled<ThumbnailExtractionResult>(cancellationToken) :
146 ExtractAsyncCore(path, size, cancellationToken);
149 private static async Task<ThumbnailExtractionResult> ExtractAsyncCore(string path, Size? size,
150 CancellationToken cancellationToken)
152 var tcs = new TaskCompletionSource<ThumbnailExtractionResult>();
154 Task thumbTask = null;
156 if (cancellationToken.CanBeCanceled)
158 cancellationToken.Register(() =>
160 if (tcs.Task.IsCompleted)
165 tcs.TrySetCanceled();
169 thumbTask = Task.Factory.StartNew( () =>
173 var result = Extract(path, size.HasValue ? size.Value : new Size(320, 240));
176 tcs.TrySetResult(result);
180 tcs.TrySetException(new InvalidOperationException("Failed to extract thumbnail"));
185 Log.Error("Tizen.Multimedia.Util", e.ToString());
186 tcs.TrySetException(e);
188 }, cancellationToken,
189 TaskCreationOptions.DenyChildAttach | TaskCreationOptions.LongRunning,
190 TaskScheduler.Default);
192 return await tcs.Task;
196 /// Extracts the thumbnail for the given media with the specified path and size.
197 /// The generated thumbnail will be returned in <see cref="ThumbnailExtractionResult"/>.
200 /// The size of generated thumbnail will be 320x240.<br/>
201 /// If the size of <paramref name="path"/> has different ratio from 320x240 (approximately 1.33:1),<br/>
202 /// thumbnail is generated in a way to keep the ratio of <paramref name="path"/>, which is based on short axis of <paramref name="path"/>.<br/>
203 /// For example, if the size of <paramref name="path"/> is 900x500 (1.8:1), the size of generated thumbnail is 432x240(1.8:1).<br/>
204 /// To set the size different from 320x240, please use <see cref="Extract(string, Size)"/>.<br/>
206 /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage. <br/>
207 /// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage.
209 /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
210 /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
211 /// <param name="path">The path of the media file to extract the thumbnail.</param>
212 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
213 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
214 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
215 /// <exception cref="FileFormatException">The specified file is not supported.</exception>
216 /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
217 /// <returns>The result of extracting operation.</returns>
218 /// <since_tizen> 6 </since_tizen>
219 public static ThumbnailExtractionResult Extract(string path)
221 return Extract(path, new Size(320, 240));
225 /// Extracts the thumbnail for the given media with the specified path and size.
226 /// The generated thumbnail will be returned in <see cref="ThumbnailExtractionResult"/>.
229 /// The size of generated thumbnail will be <paramref name="size"/>.<br/>
230 /// But, if the size of <paramref name="path"/> has different ratio with <paramref name="size"/>,<br/>
231 /// thumbnail will be generated in a way to keep the ratio of <paramref name="path"/>, which based on short axis of <paramref name="path"/>.<br/>
232 /// For example, if the size of <paramref name="path"/> is 900x500 (1.8:1)) and <paramref name="size"/> is 320x240,<br/>
233 /// the size of generated thumbnail is 432x240(1.8:1).<br/>
235 /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage. <br/>
236 /// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage.
238 /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
239 /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
240 /// <param name="path">The path of the media file to extract the thumbnail.</param>
241 /// <param name="size">The size of the thumbnail.</param>
242 /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception>
243 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
244 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
245 /// <exception cref="ArgumentOutOfRangeException">
246 /// The width or the height of <paramref name="size"/> is less than or equal to zero.
248 /// <exception cref="FileFormatException">The specified file is not supported.</exception>
249 /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
250 /// <returns>The result of extracting operation.</returns>
251 /// <since_tizen> 6 </since_tizen>
252 public static ThumbnailExtractionResult Extract(string path, Size size)
256 throw new ArgumentNullException(nameof(path));
259 if (File.Exists(path) == false)
261 throw new FileNotFoundException("File does not exists.", path);
266 throw new ArgumentOutOfRangeException(nameof(size), size.Width,
267 "The width must be greater than zero.");
270 if (size.Height <= 0)
272 throw new ArgumentOutOfRangeException(nameof(size), size.Height,
273 "The height must be greater than zero.");
276 Native.ExtractToBuffer(path, (uint)size.Width, (uint)size.Height, out IntPtr thumbData,
277 out int dataSize, out uint thumbWidth, out uint thumbHeight).
278 ThrowIfError("Failed to extract thumbnail to buffer");
282 return new ThumbnailExtractionResult(thumbData, (int)thumbWidth, (int)thumbHeight,
287 if (thumbData != IntPtr.Zero)
289 LibcSupport.Free(thumbData);
295 /// Extracts the thumbnail for the given media with the specified path and size.
296 /// The generated thumbnail will be saved in <paramref name="resultThumbnailPath"/>.
299 /// The size of <paramref name="resultThumbnailPath"/> image will be 320x240.<br/>
300 /// If the size of <paramref name="path"/> has different ratio with 320x240 (approximately 1.33:1),<br/>
301 /// thumbnail is generated in a way to keep the ratio of <paramref name="path"/>, which is based on short axis of <paramref name="path"/>.<br/>
302 /// For example, if the size of <paramref name="path"/> is 900x500 (1.8:1), the size of <paramref name="resultThumbnailPath"/> is 432x240(1.8:1).<br/>
303 /// To set the size different from 320x240, please use <see cref="Extract(string, Size, string)"/>.<br/>
305 /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage. <br/>
306 /// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage.
308 /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
309 /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
310 /// <param name="path">The path of the media file to extract the thumbnail.</param>
311 /// <param name="resultThumbnailPath">The path to save the generated thumbnail.</param>
312 /// <exception cref="ArgumentException"><paramref name="path"/> or <paramref name="resultThumbnailPath"/> is invalid.</exception>
313 /// <exception cref="ArgumentNullException"><paramref name="path"/> or <paramref name="resultThumbnailPath"/> is null.</exception>
314 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
315 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
316 /// <exception cref="FileFormatException">The specified file is not supported.</exception>
317 /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
318 /// <since_tizen> 6 </since_tizen>
319 public static void Extract(string path, string resultThumbnailPath)
321 Extract(path, new Size(320, 240), resultThumbnailPath);
325 /// Extracts the thumbnail for the given media with the specified path and size.
326 /// The generated thumbnail will be saved in <paramref name="resultThumbnailPath"/>.
329 /// The size of <paramref name="resultThumbnailPath"/> image will be <paramref name="size"/>.<br/>
330 /// But, if the size of <paramref name="path"/> has different ratio with <paramref name="size"/>,<br/>
331 /// thumbnail will be generated in a way to keep the ratio of <paramref name="path"/>, which based on short axis of <paramref name="path"/>.<br/>
332 /// For example, if the size of <paramref name="path"/> is 900x500 (1.8:1) and <paramref name="size"/> is 320x240,<br/>
333 /// the size of <paramref name="resultThumbnailPath"/> is 432x240(1.8:1).<br/>
335 /// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage. <br/>
336 /// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage.
338 /// <privilege>http://tizen.org/privilege/mediastorage</privilege>
339 /// <privilege>http://tizen.org/privilege/externalstorage</privilege>
340 /// <param name="path">The path of the media file to extract the thumbnail.</param>
341 /// <param name="size">The size of the thumbnail.</param>
342 /// <param name="resultThumbnailPath">The path to save the generated thumbnail.</param>
343 /// <exception cref="ArgumentException"><paramref name="path"/> or <paramref name="resultThumbnailPath"/> is invalid.</exception>
344 /// <exception cref="ArgumentNullException"><paramref name="path"/> or <paramref name="resultThumbnailPath"/> is null.</exception>
345 /// <exception cref="FileNotFoundException"><paramref name="path"/> does not exist.</exception>
346 /// <exception cref="InvalidOperationException">An internal error occurs.</exception>
347 /// <exception cref="ArgumentOutOfRangeException">
348 /// The width or the height of <paramref name="size"/> is less than or equal to zero.
350 /// <exception cref="FileFormatException">The specified file is not supported.</exception>
351 /// <exception cref="UnauthorizedAccessException">The caller has no required privilege.</exception>
352 /// <since_tizen> 6 </since_tizen>
353 public static void Extract(string path, Size size, string resultThumbnailPath)
355 ValidationUtil.ValidateIsNullOrEmpty(path, nameof(path));
356 ValidationUtil.ValidateIsNullOrEmpty(resultThumbnailPath, nameof(resultThumbnailPath));
358 if (File.Exists(path) == false)
360 throw new FileNotFoundException("File does not exists.", path);
365 throw new ArgumentOutOfRangeException(nameof(size), size.Width,
366 "The width must be greater than zero.");
369 if (size.Height <= 0)
371 throw new ArgumentOutOfRangeException(nameof(size), size.Height,
372 "The height must be greater than zero.");
375 Native.ExtractToFile(path, (uint)size.Width, (uint)size.Height, resultThumbnailPath).
376 ThrowIfError("Failed to extract thumbnail to file.");