[ImageUtil] Remove deprecated API and change native pinvoke APIs (#5950)
authorHaesu Gwon <haesu.gwon@samsung.com>
Tue, 20 Feb 2024 01:54:47 +0000 (10:54 +0900)
committerGitHub <noreply@github.com>
Tue, 20 Feb 2024 01:54:47 +0000 (10:54 +0900)
src/Tizen.Multimedia.Util/ImageUtil/ImageEncoder.cs
src/Tizen.Multimedia.Util/ImageUtil/ImageUtil.cs
src/Tizen.Multimedia.Util/ImageUtil/ImageUtilEnums.cs
src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Encode.cs
src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Transform.cs
src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.cs

index f9af44e..f1d5617 100644 (file)
@@ -24,6 +24,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using static Interop;
 using NativeEncoder = Interop.ImageUtil.Encode;
+using NativeUtil = Interop.ImageUtil;
 
 namespace Tizen.Multimedia.Util
 {
@@ -34,8 +35,11 @@ namespace Tizen.Multimedia.Util
     public abstract class ImageEncoder : IDisposable
     {
         private ImageEncoderHandle _handle;
+        internal IntPtr _imageUtilHandle;
+        internal IntPtr _animationHandle;
 
-        private bool _hasResolution;
+        internal Size? _resolution;
+        internal ColorSpace? _colorSpace;
 
         internal ImageEncoder(ImageFormat format)
         {
@@ -88,16 +92,14 @@ namespace Tizen.Multimedia.Util
                     "The height of resolution can't be less than or equal to zero.");
             }
 
-            NativeEncoder.SetResolution(Handle, (uint)resolution.Width, (uint)resolution.Height).
-                ThrowIfFailed("Failed to set the resolution");
-
-            _hasResolution = true;
+            _resolution = resolution;
         }
 
         /// <summary>
         /// Sets the color-space of the output image.
         /// </summary>
         /// <param name="colorSpace">The target color-space.</param>
+        /// <value>The default color space is <see cref="ColorSpace.Rgba8888"/>
         /// <exception cref="ArgumentException"><paramref name="colorSpace"/> is invalid.</exception>
         /// <exception cref="NotSupportedException"><paramref name="colorSpace"/> is not supported by the encoder.</exception>
         /// <seealso cref="ImageUtil.GetSupportedColorSpaces(ImageFormat)"/>
@@ -111,19 +113,18 @@ namespace Tizen.Multimedia.Util
                 throw new NotSupportedException($"{colorSpace.ToString()} is not supported for {OutputFormat}.");
             }
 
-            NativeEncoder.SetColorspace(Handle, colorSpace.ToImageColorSpace()).
-                ThrowIfFailed("Failed to set the color space");
+            _colorSpace = colorSpace;
         }
 
-        private void RunEncoding(object outStream)
+        internal virtual void RunEncoding(object outStream)
         {
             IntPtr outBuffer = IntPtr.Zero;
+            int size = 0;
 
             try
             {
-                NativeEncoder.SetOutputBuffer(Handle, out outBuffer).ThrowIfFailed("Failed to initialize encoder");
-
-                NativeEncoder.Run(Handle, out var size).ThrowIfFailed("Failed to encode given image");
+                NativeEncoder.RunToBuffer(Handle, _imageUtilHandle, out outBuffer, out size).
+                    ThrowIfFailed("Failed to encode given image");
 
                 byte[] buf = new byte[size];
                 Marshal.Copy(outBuffer, buf, 0, (int)size);
@@ -132,6 +133,7 @@ namespace Tizen.Multimedia.Util
             finally
             {
                 Marshal.FreeHGlobal(outBuffer);
+                NativeUtil.Destroy(_imageUtilHandle).ThrowIfFailed("Failed to destroy ImageUtil handle");
             }
         }
 
@@ -195,10 +197,9 @@ namespace Tizen.Multimedia.Util
                 throw new ArgumentException("buffer is empty.", nameof(inputBuffer));
             }
 
-            return EncodeAsync(handle =>
-            {
-                NativeEncoder.SetInputBuffer(handle, inputBuffer).
-                        ThrowIfFailed("Failed to configure encoder; InputBuffer");
+            return EncodeAsync(handle => {
+                NativeUtil.Create((uint)_resolution.Value.Width, (uint)_resolution.Value.Height, _colorSpace.Value.ToImageColorSpace(),
+                    inputBuffer, inputBuffer.Length, out _imageUtilHandle).ThrowIfFailed("Failed to create ImageUtil handle");
             }, outStream);
         }
 
@@ -206,10 +207,15 @@ namespace Tizen.Multimedia.Util
         {
             Configure(Handle);
 
-            if (_hasResolution == false)
+            if (!_resolution.HasValue)
             {
                 throw new InvalidOperationException("Resolution is not set.");
             }
+            if (!_colorSpace.HasValue)
+            {
+                _colorSpace = ColorSpace.Rgba8888;
+                Log.Info("Tizen.Multimedia.Util", "ColorSpace was set to default value(Rgba8888).");
+            }
         }
 
         internal abstract void Configure(ImageEncoderHandle handle);
@@ -413,6 +419,8 @@ namespace Tizen.Multimedia.Util
     /// <since_tizen> 4 </since_tizen>
     public class GifEncoder : ImageEncoder
     {
+        private IEnumerable<GifFrame> _frames;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="GifEncoder"/> class.
         /// </summary>
@@ -453,26 +461,55 @@ namespace Tizen.Multimedia.Util
                 throw new ArgumentNullException(nameof(frames));
             }
 
-            if (frames.Count() == 0)
+            if (!frames.Any())
             {
                 throw new ArgumentException("frames is a empty collection", nameof(frames));
             }
 
-            return EncodeAsync(handle =>
+            _frames = frames;
+
+            return EncodeAsync(handle => {}, outStream);
+        }
+
+        internal override void RunEncoding(object outStream)
+        {
+            IntPtr outBuffer = IntPtr.Zero;
+
+            NativeEncoder.AnimationCreate(AnimationType.Gif, out _animationHandle).
+                ThrowIfFailed("Failed to create animation handle");
+
+            try
             {
-                foreach (GifFrame frame in frames)
+                foreach (GifFrame frame in _frames)
                 {
                     if (frame == null)
                     {
-                        throw new ArgumentNullException(nameof(frames));
+                        throw new ArgumentNullException(nameof(frame));
                     }
-                    NativeEncoder.SetInputBuffer(handle, frame.Buffer).
-                        ThrowIfFailed("Failed to configure encoder; Buffer");
 
-                    NativeEncoder.SetGifFrameDelayTime(handle, (ulong)frame.Delay).
-                        ThrowIfFailed("Failed to configure encoder; Delay");
+                    NativeUtil.Create((uint)_resolution.Value.Width, (uint)_resolution.Value.Height, _colorSpace.Value.ToImageColorSpace(),
+                        frame.Buffer, frame.Buffer.Length, out _imageUtilHandle).ThrowIfFailed("Failed to create ImageUtil handle");
+                    NativeEncoder.AnimationAddFrame(_animationHandle, _imageUtilHandle, frame.Delay).
+                        ThrowIfFailed("Failed to add frame");
+
+                    NativeUtil.Destroy(_imageUtilHandle).ThrowIfFailed("Failed to destroy ImageUtil handle");
                 }
-            }, outStream);
+
+                NativeEncoder.AnimationSaveToBuffer(_animationHandle, out outBuffer, out ulong size).
+                    ThrowIfFailed("Failed to encode given image");
+
+                byte[] buf = new byte[size];
+                Marshal.Copy(outBuffer, buf, 0, (int)size);
+                (outStream as Stream).Write(buf, 0, (int)size);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(outBuffer);
+                if (_animationHandle != IntPtr.Zero)
+                {
+                    NativeEncoder.AnimationDestroy(_animationHandle).ThrowIfFailed("Failed to destroy animation handle");
+                }
+            }
         }
     }
 
index f1483b2..639c46e 100644 (file)
@@ -48,43 +48,6 @@ namespace Tizen.Multimedia.Util
         }
 
         /// <summary>
-        /// Calculates the size of the image buffer for the specified resolution and color-space.
-        /// </summary>
-        /// <param name="resolution">The resolution of the image.</param>
-        /// <param name="colorSpace"><see cref="ColorSpace"/> of the image.</param>
-        /// <returns>The buffer size.</returns>
-        /// <exception cref="ArgumentOutOfRangeException">
-        ///     width of <paramref name="resolution"/> is less than or equal to zero.<br/>
-        ///     -or-<br/>
-        ///     height of <paramref name="resolution"/> is less than or equal to zero.
-        /// </exception>
-        /// <exception cref="ArgumentException"><paramref name="colorSpace"/> is invalid.</exception>
-        /// <since_tizen> 4 </since_tizen>
-        [Obsolete("Please do not use! This will be deprecated in level 6.")]
-        public static int CalculateBufferSize(Size resolution, ColorSpace colorSpace)
-        {
-            if (resolution.Width <= 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(resolution), resolution.Width,
-                    "width can't be less than or equal to zero.");
-            }
-            if (resolution.Height <= 0)
-            {
-                throw new ArgumentOutOfRangeException(nameof(resolution), resolution.Height,
-                    "height can't be less than or equal to zero.");
-            }
-
-            ValidationUtil.ValidateEnum(typeof(ColorSpace), colorSpace, nameof(colorSpace));
-
-            uint bufferSize;
-            global::Interop.ImageUtil.CalculateBufferSize(resolution.Width, resolution.Height,
-                colorSpace.ToImageColorSpace(), out bufferSize)
-                .ThrowIfFailed("Failed to calculate buffer size for given parameter");
-
-            return (int)bufferSize;
-        }
-
-        /// <summary>
         /// Extracts representative color from an image buffer.
         /// </summary>
         /// <param name="buffer">Raw image buffer.</param>
index 37d6082..cab1521 100644 (file)
@@ -91,6 +91,18 @@ namespace Tizen.Multimedia.Util
         Level9,
     }
 
+    internal enum AnimationType
+    {
+        /// <summary>
+        /// GIF
+        /// </summary>
+        Gif,
+        /// <summary>
+        /// WebP
+        /// </summary>
+        WebP
+    }
+
     /// <summary>
     /// Specifies how an image is rotated or flipped.
     /// </summary>
index 71e9a15..cbe4259 100644 (file)
@@ -38,35 +38,41 @@ internal static partial class Interop
             [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_destroy")]
             internal static extern ImageUtilError Destroy(IntPtr handle);
 
-            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_resolution")]
-            internal static extern ImageUtilError SetResolution(ImageEncoderHandle handle, uint width, uint height);
-
-            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_colorspace")]
-            internal static extern ImageUtilError SetColorspace(ImageEncoderHandle handle, ImageColorSpace colorspace);
-
             [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_quality")]
             internal static extern ImageUtilError SetQuality(ImageEncoderHandle handle, int quality);
 
             [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_png_compression")]
             internal static extern ImageUtilError SetPngCompression(ImageEncoderHandle handle, PngCompression compression);
 
-            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_gif_frame_delay_time")]
-            internal static extern ImageUtilError SetGifFrameDelayTime(ImageEncoderHandle handle, ulong delayTime);
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_run_to_buffer")]
+            internal static extern ImageUtilError RunToBuffer(ImageEncoderHandle handle, IntPtr imageUtilHandle, out IntPtr buffer, out int size);
+
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_lossless")]
+            internal static extern ImageUtilError SetLossless(ImageEncoderHandle handle, bool lossless);
+
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_anim_encode_create")]
+            internal static extern ImageUtilError AnimationCreate(AnimationType type, out IntPtr animHandle);
 
-            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_output_path")]
-            internal static extern ImageUtilError SetOutputPath(ImageEncoderHandle handle, string path);
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_anim_encode_set_loop_count")]
+            internal static extern ImageUtilError AnimationSetLoopCount(IntPtr animHandle, uint count);
 
-            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_input_buffer")]
-            internal static extern ImageUtilError SetInputBuffer(ImageEncoderHandle handle, byte[] srcBuffer);
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_anim_encode_set_background_color")]
+            internal static extern ImageUtilError AnimationSetBackgroundColor(IntPtr animHandle, byte r, byte g, byte b, byte a);
 
-            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_output_buffer")]
-            internal static extern ImageUtilError SetOutputBuffer(ImageEncoderHandle handle, out IntPtr dstBuffer);
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_anim_encode_set_lossless")]
+            internal static extern ImageUtilError AnimationSetLossless(IntPtr animHandle, bool isLossless);
 
-            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_run")]
-            internal static extern ImageUtilError Run(ImageEncoderHandle handle, out ulong size);
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_anim_encode_add_frame")]
+            internal static extern ImageUtilError AnimationAddFrame(IntPtr animHandle, IntPtr utilHandle, uint delayTime);
 
-            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_encode_set_lossless")]
-            internal static extern ImageUtilError SetLossless(ImageEncoderHandle handle, bool lossless);
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_anim_encode_save_to_file")]
+            internal static extern ImageUtilError AnimationSaveToFile(IntPtr animHandle, string path);
+
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_anim_encode_save_to_buffer")]
+            internal static extern ImageUtilError AnimationSaveToBuffer(IntPtr animHandle, out IntPtr dstBuffer, out ulong size);
+
+            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_anim_encode_destroy")]
+            internal static extern ImageUtilError AnimationDestroy(IntPtr animHandle);
         }
     }
 
@@ -91,4 +97,26 @@ internal static partial class Interop
             return true;
         }
     }
+
+    internal class AgifImageEncoderHandle : SafeHandle
+    {
+        protected AgifImageEncoderHandle() : base(IntPtr.Zero, true)
+        {
+        }
+
+        public override bool IsInvalid => handle == IntPtr.Zero;
+
+
+        protected override bool ReleaseHandle()
+        {
+            var ret = ImageUtil.Encode.Destroy(handle);
+            if (ret != ImageUtilError.None)
+            {
+                Log.Debug(GetType().FullName, $"Failed to release native {GetType().Name}");
+                return false;
+            }
+
+            return true;
+        }
+    }
 }
index cc26f74..a684278 100644 (file)
@@ -45,9 +45,6 @@ internal static partial class Interop
             [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_transform_set_colorspace")]
             internal static extern ImageUtilError SetColorspace(TransformHandle handle, ImageColorSpace colorspace);
 
-            [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_transform_set_hardware_acceleration")]
-            internal static extern ImageUtilError SetHardwareAcceleration(TransformHandle handle, bool mode);
-
             [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_transform_set_rotation")]
             internal static extern ImageUtilError SetRotation(TransformHandle handle, ImageRotation rotation);
 
index fd593a0..edee0de 100644 (file)
@@ -30,9 +30,6 @@ internal static partial class Interop
         internal static extern ImageUtilError ForeachSupportedColorspace(ImageFormat type, SupportedColorspaceCallback callback,
             IntPtr userData = default(IntPtr));
 
-        [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_calculate_buffer_size")]
-        internal static extern ImageUtilError CalculateBufferSize(int width, int height, ImageColorSpace colorspace, out uint size);
-
         [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_extract_color_from_memory")]
         internal static extern ImageUtilError ExtractColorFromMemory(byte[] buffer, int width, int height, out byte rgbR, out byte rgbG, out byte rgbB);
 
@@ -42,5 +39,8 @@ internal static partial class Interop
 
         [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_destroy_image")]
         internal static extern ImageUtilError Destroy(IntPtr handle);
+
+        [DllImport(Libraries.ImageUtil, EntryPoint = "image_util_create_image")]
+        internal static extern ImageUtilError Create(uint width, uint height, ImageColorSpace colorSpace, byte[] srcBuffer, int size, out IntPtr handle);
     }
 }