From dfb1574d428d00e25ae33c30bae18bbc129bff79 Mon Sep 17 00:00:00 2001 From: Haesu Gwon Date: Tue, 20 Feb 2024 10:54:47 +0900 Subject: [PATCH] [ImageUtil] Remove deprecated API and change native pinvoke APIs (#5950) --- .../ImageUtil/ImageEncoder.cs | 87 +++++++++++++++------- src/Tizen.Multimedia.Util/ImageUtil/ImageUtil.cs | 37 --------- .../ImageUtil/ImageUtilEnums.cs | 12 +++ .../Interop/Interop.ImageUtil.Encode.cs | 64 +++++++++++----- .../Interop/Interop.ImageUtil.Transform.cs | 3 - .../Interop/Interop.ImageUtil.cs | 6 +- 6 files changed, 123 insertions(+), 86 deletions(-) diff --git a/src/Tizen.Multimedia.Util/ImageUtil/ImageEncoder.cs b/src/Tizen.Multimedia.Util/ImageUtil/ImageEncoder.cs index f9af44e..f1d5617 100644 --- a/src/Tizen.Multimedia.Util/ImageUtil/ImageEncoder.cs +++ b/src/Tizen.Multimedia.Util/ImageUtil/ImageEncoder.cs @@ -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; } /// /// Sets the color-space of the output image. /// /// The target color-space. + /// The default color space is /// is invalid. /// is not supported by the encoder. /// @@ -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 /// 4 public class GifEncoder : ImageEncoder { + private IEnumerable _frames; + /// /// Initializes a new instance of the class. /// @@ -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"); + } + } } } diff --git a/src/Tizen.Multimedia.Util/ImageUtil/ImageUtil.cs b/src/Tizen.Multimedia.Util/ImageUtil/ImageUtil.cs index f1483b2..639c46e 100644 --- a/src/Tizen.Multimedia.Util/ImageUtil/ImageUtil.cs +++ b/src/Tizen.Multimedia.Util/ImageUtil/ImageUtil.cs @@ -48,43 +48,6 @@ namespace Tizen.Multimedia.Util } /// - /// Calculates the size of the image buffer for the specified resolution and color-space. - /// - /// The resolution of the image. - /// of the image. - /// The buffer size. - /// - /// width of is less than or equal to zero.
- /// -or-
- /// height of is less than or equal to zero. - ///
- /// is invalid. - /// 4 - [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; - } - - /// /// Extracts representative color from an image buffer. /// /// Raw image buffer. diff --git a/src/Tizen.Multimedia.Util/ImageUtil/ImageUtilEnums.cs b/src/Tizen.Multimedia.Util/ImageUtil/ImageUtilEnums.cs index 37d6082..cab1521 100644 --- a/src/Tizen.Multimedia.Util/ImageUtil/ImageUtilEnums.cs +++ b/src/Tizen.Multimedia.Util/ImageUtil/ImageUtilEnums.cs @@ -91,6 +91,18 @@ namespace Tizen.Multimedia.Util Level9, } + internal enum AnimationType + { + /// + /// GIF + /// + Gif, + /// + /// WebP + /// + WebP + } + /// /// Specifies how an image is rotated or flipped. /// diff --git a/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Encode.cs b/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Encode.cs index 71e9a15..cbe4259 100644 --- a/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Encode.cs +++ b/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Encode.cs @@ -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; + } + } } diff --git a/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Transform.cs b/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Transform.cs index cc26f74..a684278 100644 --- a/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Transform.cs +++ b/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.Transform.cs @@ -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); diff --git a/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.cs b/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.cs index fd593a0..edee0de 100644 --- a/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.cs +++ b/src/Tizen.Multimedia.Util/Interop/Interop.ImageUtil.cs @@ -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); } } -- 2.7.4