/* * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.IO; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Handle = Interop.ThumbnailExtractorHandle; using Native = Interop.ThumbnailExtractor; namespace Tizen.Multimedia.Util { /// /// Provides the ability to extract the thumbnail from media files. /// /// 4 public static class ThumbnailExtractor { private static Handle CreateHandle() { Native.Create(out var handle).ThrowIfError("Failed to extract."); return handle; } /// /// Extracts the thumbnail for the given media with the specified path. /// /// 4 /// A task that represents the asynchronous extracting operation. /// The size of the thumbnail will be the default size (320x240). /// The path of the media file to extract the thumbnail. /// is null. /// does not exist. /// An internal error occurs. /// The caller does not have required privilege for accessing the . /// The specified file is not supported. public static Task ExtractAsync(string path) { return RunExtractAsync(path, null, CancellationToken.None); } /// /// Extracts the thumbnail for the given media with the specified path. /// /// A task that represents the asynchronous extracting operation. /// The size of the thumbnail will be the default size(320x240). /// The path of the media file to extract the thumbnail. /// The token to stop the operation. /// is null. /// does not exist. /// An internal error occurs. /// The caller does not have required privilege for accessing the . /// The specified file is not supported. /// 4 public static Task ExtractAsync(string path, CancellationToken cancellationToken) { return RunExtractAsync(path, null, cancellationToken); } /// /// Extracts the thumbnail for the given media with the specified path and size. /// /// 4 /// A task that represents the asynchronous extracting operation. /// /// If the width is not a multiple of 8, it can be changed by the inner process.
/// The width will be a multiple of 8 greater than the set value. ///
/// The path of the media file to extract the thumbnail. /// The size of the thumbnail. /// is null. /// does not exist. /// An internal error occurs. /// The caller does not have required privilege for accessing the . /// /// The width or the height of is less than or equal to zero. /// /// The specified file is not supported. public static Task ExtractAsync(string path, Size size) { return RunExtractAsync(path, size, CancellationToken.None); } /// /// Extracts the thumbnail for the given media with the specified path and size. /// /// 4 /// A task that represents the asynchronous extracting operation. /// /// If the width is not a multiple of 8, it can be changed by the inner process.
/// The width will be a multiple of 8 greater than the set value. ///
/// The path of the media file to extract the thumbnail. /// The size of the thumbnail. /// The token to stop the operation. /// is null. /// does not exist. /// An internal error occurs. /// The caller does not have required privilege for accessing the . /// /// The width or the height of is less than or equal to zero. /// /// The specified file is not supported. public static Task ExtractAsync(string path, Size size, CancellationToken cancellationToken) { return RunExtractAsync(path, size, cancellationToken); } private static Task RunExtractAsync(string path, Size? size, CancellationToken cancellationToken) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (File.Exists(path) == false) { throw new FileNotFoundException("File does not exists.", path); } if (size.HasValue) { if (size.Value.Width <= 0) { throw new ArgumentOutOfRangeException(nameof(size), size.Value.Width, "The width must be greater than zero."); } if (size.Value.Height <= 0) { throw new ArgumentOutOfRangeException(nameof(size), size.Value.Height, "The height must be greater than zero."); } } return cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) : ExtractAsyncCore(path, size, cancellationToken); } private static async Task ExtractAsyncCore(string path, Size? size, CancellationToken cancellationToken) { using (var handle = CreateHandle()) { Native.SetPath(handle, path).ThrowIfError("Failed to extract; failed to set the path."); if (size.HasValue) { Native.SetSize(handle, size.Value.Width, size.Value.Height). ThrowIfError("Failed to extract; failed to set the size"); } var tcs = new TaskCompletionSource(); IntPtr id = IntPtr.Zero; try { var cb = GetCallback(tcs); using (var cbKeeper = ObjectKeeper.Get(cb)) { Native.Extract(handle, cb, IntPtr.Zero, out id) .ThrowIfError("Failed to extract."); using (RegisterCancellationToken(tcs, cancellationToken, handle, Marshal.PtrToStringAnsi(id))) { return await tcs.Task; } } } finally { LibcSupport.Free(id); } } } private static Native.ThumbnailExtractCallback GetCallback(TaskCompletionSource tcs) { return (error, requestId, thumbWidth, thumbHeight, thumbData, dataSize, _) => { if (error == ThumbnailExtractorError.None) { try { tcs.TrySetResult(new ThumbnailExtractionResult(thumbData, thumbWidth, thumbHeight, dataSize)); } catch (Exception e) { tcs.TrySetException(new InvalidOperationException("[" + error + "] Failed to create ThumbnailExtractionResult instance.", e)); } finally { LibcSupport.Free(thumbData); } } else { tcs.TrySetException(error.ToException("Failed to extract.")); } }; } private static IDisposable RegisterCancellationToken(TaskCompletionSource tcs, CancellationToken cancellationToken, Handle handle, string id) { if (cancellationToken.CanBeCanceled == false) { return null; } return cancellationToken.Register(() => { if (tcs.Task.IsCompleted) { return; } Native.Cancel(handle, id).ThrowIfError("Failed to cancel."); tcs.TrySetCanceled(); }); } /// /// Extracts the thumbnail for the given media with the specified path and size. /// The generated thumbnail will be returned in . /// /// /// The size of generated thumbnail will be 320x240.
/// But, if the size of has different ratio with 320x240 (approximately 1.33:1),
/// thumbnail will be generated in a way to keep the ratio of , which based on short axis of .
/// For example, if the size of is 900x500 (1.8:1), the size of generated thumbnail is 432x240(1.8:1).
/// If you want to set the size, which is different with 320x240, please use .
///
/// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.
/// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage. ///
/// http://tizen.org/privilege/mediastorage /// http://tizen.org/privilege/externalstorage /// The path of the media file to extract the thumbnail. /// is null. /// does not exist. /// An internal error occurs. /// The specified file is not supported. /// The caller has no required privilege. /// The result of extracting operation. /// 6 public static ThumbnailExtractionResult Extract(string path) { return Extract(path, new Size(320, 240)); } /// /// Extracts the thumbnail for the given media with the specified path and size. /// The generated thumbnail will be returned in . /// /// /// The size of generated thumbnail will be .
/// But, if the size of has different ratio with ,
/// thumbnail will be generated in a way to keep the ratio of , which based on short axis of .
/// For example, if the size of is 900x500 (1.8:1)) and is 320x240,
/// the size of generated thumbnail is 432x240(1.8:1).
///
/// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.
/// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage. ///
/// http://tizen.org/privilege/mediastorage /// http://tizen.org/privilege/externalstorage /// The path of the media file to extract the thumbnail. /// The size of the thumbnail. /// is null. /// does not exist. /// An internal error occurs. /// /// The width or the height of is less than or equal to zero. /// /// The specified file is not supported. /// The caller has no required privilege. /// The result of extracting operation. /// 6 public static ThumbnailExtractionResult Extract(string path, Size size) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (File.Exists(path) == false) { throw new FileNotFoundException("File does not exists.", path); } if (size.Width <= 0) { throw new ArgumentOutOfRangeException(nameof(size), size.Width, "The width must be greater than zero."); } if (size.Height <= 0) { throw new ArgumentOutOfRangeException(nameof(size), size.Height, "The height must be greater than zero."); } Native.ExtractToBuffer(path, (uint)size.Width, (uint)size.Height, out IntPtr thumbData, out int dataSize, out uint thumbWidth, out uint thumbHeight). ThrowIfError("Failed to extract thumbnail to buffer"); try { return new ThumbnailExtractionResult(thumbData, (int)thumbWidth, (int)thumbHeight, dataSize); } finally { if (thumbData != IntPtr.Zero) { LibcSupport.Free(thumbData); } } } /// /// Extracts the thumbnail for the given media with the specified path and size. /// The generated thumbnail will be saved in . /// /// /// The size of image will be 320x240.
/// But, if the size of has different ratio with 320x240 (approximately 1.33:1),
/// thumbnail will be generated in a way to keep the ratio of , which based on short axis of .
/// For example, if the size of is 900x500 (1.8:1), the size of is 432x240(1.8:1).
/// If you want to set the size, which is different with 320x240, please use .
///
/// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.
/// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage. ///
/// http://tizen.org/privilege/mediastorage /// http://tizen.org/privilege/externalstorage /// The path of the media file to extract the thumbnail. /// The path to save the generated thumbnail. /// is null. /// does not exist. /// An internal error occurs. /// The specified file is not supported. /// The caller has no required privilege. /// 6 public static void Extract(string path, string resultThumbnailPath) { Extract(path, new Size(320, 240), resultThumbnailPath); } /// /// Extracts the thumbnail for the given media with the specified path and size. /// The generated thumbnail will be saved in . /// /// /// The size of image will be .
/// But, if the size of has different ratio with ,
/// thumbnail will be generated in a way to keep the ratio of , which based on short axis of .
/// For example, if the size of is 900x500 (1.8:1) and is 320x240,
/// the size of is 432x240(1.8:1).
///
/// If you want to access internal storage, you should add privilege http://tizen.org/privilege/mediastorage.
/// If you want to access external storage, you should add privilege http://tizen.org/privilege/externalstorage. ///
/// http://tizen.org/privilege/mediastorage /// http://tizen.org/privilege/externalstorage /// The path of the media file to extract the thumbnail. /// The size of the thumbnail. /// The path to save the generated thumbnail. /// is null. /// does not exist. /// An internal error occurs. /// /// The width or the height of is less than or equal to zero. /// /// The specified file is not supported. /// The caller has no required privilege. /// 6 public static void Extract(string path, Size size, string resultThumbnailPath) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (File.Exists(path) == false) { throw new FileNotFoundException("File does not exists.", path); } if (size.Width <= 0) { throw new ArgumentOutOfRangeException(nameof(size), size.Width, "The width must be greater than zero."); } if (size.Height <= 0) { throw new ArgumentOutOfRangeException(nameof(size), size.Height, "The height must be greater than zero."); } Native.ExtractToFile(path, (uint)size.Width, (uint)size.Height, resultThumbnailPath). ThrowIfError("Failed to extract thumbnail to file."); } } }