using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using Imazen.WebP.Extern; using Microsoft.CodeAnalysis; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("imazen;lilith")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright 2017-2026 Imazen LLC")] [assembly: AssemblyDescription(".NET bindings for libwebp. Provides WebP encoding and decoding via both System.Drawing (Bitmap) and raw pixel buffer APIs. Requires a platform-specific Imazen.WebP.NativeRuntime package or Imazen.WebP.AllPlatforms.")] [assembly: AssemblyFileVersion("11.0.0.0")] [assembly: AssemblyInformationalVersion("11.0.0+a2d53ed552b46e7f3a9a1a1f8ccd23e19f6f1595")] [assembly: AssemblyProduct("Imazen.WebP")] [assembly: AssemblyTitle("Imazen.WebP")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/imazen/libwebp-net")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("11.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Imazen.WebP { public static class AbiVersionCheck { private static volatile bool _validated; public static void ValidateOrThrow() { if (!_validated) { int num = NativeMethods.WebPGetDecoderVersion(); int num2 = NativeMethods.WebPGetEncoderVersion(); int num3 = (num >> 16) & 0xFF; int num4 = (num2 >> 16) & 0xFF; if (num3 != 1 || num4 != 1) { throw new NotSupportedException("Incompatible libwebp version. Expected 1.x, got decoder=" + FormatVersion(num) + ", encoder=" + FormatVersion(num2)); } _validated = true; } } public static string GetVersionString() { int version = NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPGetDecoderVersion()); int version2 = NativeMethods.WebPGetEncoderVersion(); return "decoder=" + FormatVersion(version) + ", encoder=" + FormatVersion(version2); } private static string FormatVersion(int version) { int num = (version >> 16) & 0xFF; int num2 = (version >> 8) & 0xFF; int num3 = version & 0xFF; return $"{num}.{num2}.{num3}"; } } public class AnimInfo { public int Width { get; } public int Height { get; } public int FrameCount { get; } public int LoopCount { get; } public uint BackgroundColor { get; } internal AnimInfo(int width, int height, int frameCount, int loopCount, uint bgColor) { Width = width; Height = height; FrameCount = frameCount; LoopCount = loopCount; BackgroundColor = bgColor; } } public class AnimDecoder : IDisposable { private IntPtr _decoder; private GCHandle _dataHandle; private bool _disposed; private readonly AnimInfo _info; private int _prevEndTimestamp; public AnimInfo Info => _info; public AnimDecoder(byte[] webpData, bool useThreads = false) { AnimDecoder animDecoder = this; if (webpData == null) { throw new ArgumentNullException("webpData"); } _dataHandle = GCHandle.Alloc(webpData, GCHandleType.Pinned); WebPData data = new WebPData { bytes = _dataHandle.AddrOfPinnedObject(), size = (UIntPtr)(ulong)webpData.Length }; WebPAnimDecoderOptions options = default(WebPAnimDecoderOptions); NativeLibraryLoader.FixDllNotFoundException("webpdemux", delegate { if (NativeMethods.WebPAnimDecoderOptionsInit(ref options) == 0) { throw new Exception("Failed to initialize animation decoder options (version mismatch)"); } return 0; }); options.color_mode = WEBP_CSP_MODE.MODE_BGRA; options.use_threads = (useThreads ? 1 : 0); _decoder = NativeLibraryLoader.FixDllNotFoundException("webpdemux", () => NativeMethods.WebPAnimDecoderNew(ref data, ref options)); if (_decoder == IntPtr.Zero) { throw new Exception("Failed to create animation decoder. Data may not be a valid animated WebP."); } WebPAnimInfo animInfo = default(WebPAnimInfo); if (NativeLibraryLoader.FixDllNotFoundException("webpdemux", () => NativeMethods.WebPAnimDecoderGetInfo(animDecoder._decoder, ref animInfo)) == 0) { throw new Exception("Failed to get animation info"); } _info = new AnimInfo((int)animInfo.canvas_width, (int)animInfo.canvas_height, (int)animInfo.frame_count, (int)animInfo.loop_count, animInfo.bgcolor); } public AnimDecoder(Stream stream, bool useThreads = false) : this(ReadStreamFully(stream), useThreads) { } public List DecodeAllFrames() { ThrowIfDisposed(); Reset(); List list = new List(); AnimFrame nextFrame; while ((nextFrame = GetNextFrame()) != null) { list.Add(nextFrame); } return list; } public AnimFrame? GetNextFrame() { ThrowIfDisposed(); if (!HasMoreFrames()) { return null; } IntPtr buf = IntPtr.Zero; int endTimestamp = 0; if (NativeLibraryLoader.FixDllNotFoundException("webpdemux", () => NativeMethods.WebPAnimDecoderGetNext(_decoder, ref buf, ref endTimestamp)) == 0) { return null; } int num = _info.Width * _info.Height * 4; byte[] array = new byte[num]; Marshal.Copy(buf, array, 0, num); int prevEndTimestamp = _prevEndTimestamp; AnimFrame result = new AnimFrame(array, _info.Width, _info.Height, prevEndTimestamp) { DurationMs = endTimestamp - prevEndTimestamp }; _prevEndTimestamp = endTimestamp; return result; } public bool HasMoreFrames() { ThrowIfDisposed(); return NativeLibraryLoader.FixDllNotFoundException("webpdemux", () => NativeMethods.WebPAnimDecoderHasMoreFrames(_decoder)) != 0; } public void Reset() { ThrowIfDisposed(); NativeLibraryLoader.FixDllNotFoundException("webpdemux", delegate { NativeMethods.WebPAnimDecoderReset(_decoder); return 0; }); _prevEndTimestamp = 0; } private void ThrowIfDisposed() { if (_disposed) { throw new ObjectDisposedException("AnimDecoder"); } } private static byte[] ReadStreamFully(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } if (stream is MemoryStream { Position: 0L } memoryStream) { return memoryStream.ToArray(); } using MemoryStream memoryStream2 = new MemoryStream(); byte[] array = new byte[8192]; int count; while ((count = stream.Read(array, 0, array.Length)) > 0) { memoryStream2.Write(array, 0, count); } return memoryStream2.ToArray(); } public void Dispose() { if (_disposed) { return; } if (_decoder != IntPtr.Zero) { NativeLibraryLoader.FixDllNotFoundException("webpdemux", delegate { NativeMethods.WebPAnimDecoderDelete(_decoder); return 0; }); _decoder = IntPtr.Zero; } if (_dataHandle.IsAllocated) { _dataHandle.Free(); } _disposed = true; } } public class AnimEncoder : IDisposable { private IntPtr _encoder; private readonly int _width; private readonly int _height; private bool _disposed; private int _lastTimestamp; private int _lastDuration = 100; private bool _hasFrames; public AnimEncoder(int width, int height) { if (width <= 0) { throw new ArgumentOutOfRangeException("width"); } if (height <= 0) { throw new ArgumentOutOfRangeException("height"); } _width = width; _height = height; WebPAnimEncoderOptions options = default(WebPAnimEncoderOptions); NativeLibraryLoader.FixDllNotFoundException("webpmux", delegate { if (NativeMethods.WebPAnimEncoderOptionsInit(ref options) == 0) { throw new Exception("Failed to initialize animation encoder options (version mismatch)"); } return 0; }); _encoder = NativeLibraryLoader.FixDllNotFoundException("webpmux", () => NativeMethods.WebPAnimEncoderNew(width, height, ref options)); if (_encoder == IntPtr.Zero) { throw new Exception("Failed to create animation encoder"); } } public AnimEncoder(int width, int height, int loopCount = 0, uint backgroundColor = 0u, bool allowMixed = false, bool minimizeSize = false) { if (width <= 0) { throw new ArgumentOutOfRangeException("width"); } if (height <= 0) { throw new ArgumentOutOfRangeException("height"); } _width = width; _height = height; WebPAnimEncoderOptions options = default(WebPAnimEncoderOptions); NativeLibraryLoader.FixDllNotFoundException("webpmux", delegate { if (NativeMethods.WebPAnimEncoderOptionsInit(ref options) == 0) { throw new Exception("Failed to initialize animation encoder options (version mismatch)"); } return 0; }); options.anim_params.loop_count = loopCount; options.anim_params.bgcolor = backgroundColor; options.allow_mixed = (allowMixed ? 1 : 0); options.minimize_size = (minimizeSize ? 1 : 0); _encoder = NativeLibraryLoader.FixDllNotFoundException("webpmux", () => NativeMethods.WebPAnimEncoderNew(width, height, ref options)); if (_encoder == IntPtr.Zero) { throw new Exception("Failed to create animation encoder"); } } public void AddFrame(byte[] bgraPixels, int timestampMs, float quality = -1f) { if (bgraPixels == null) { throw new ArgumentNullException("bgraPixels"); } AddFrameInternal(bgraPixels, _width * 4, WebPPixelFormat.Bgra, timestampMs, quality); } public void AddFrame(byte[] pixels, int stride, WebPPixelFormat format, int timestampMs, float quality = -1f) { if (pixels == null) { throw new ArgumentNullException("pixels"); } AddFrameInternal(pixels, stride, format, timestampMs, quality); } public void AddFrame(byte[] pixels, int stride, WebPPixelFormat format, int timestampMs, WebPEncoderConfig config) { if (pixels == null) { throw new ArgumentNullException("pixels"); } if (config == null) { throw new ArgumentNullException("config"); } ThrowIfDisposed(); if (!config.Validate()) { throw new ArgumentException("Invalid encoder configuration", "config"); } WebPConfig config2 = config.GetNativeConfig(); AddFrameWithConfig(pixels, stride, format, timestampMs, ref config2); } private void AddFrameInternal(byte[] pixels, int stride, WebPPixelFormat format, int timestampMs, float quality) { ThrowIfDisposed(); WebPConfig config = default(WebPConfig); NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPConfigInitInternal(ref config, WebPPreset.WEBP_PRESET_DEFAULT, (quality >= 0f) ? quality : 75f, 528)); if (quality < 0f) { config.lossless = 1; config.quality = 75f; } else { config.lossless = 0; config.quality = Math.Max(0f, Math.Min(100f, quality)); } AddFrameWithConfig(pixels, stride, format, timestampMs, ref config); } private void AddFrameWithConfig(byte[] pixels, int stride, WebPPixelFormat format, int timestampMs, ref WebPConfig config) { WebPConfig localConfig = config; WebPPicture picture = default(WebPPicture); NativeLibraryLoader.FixDllNotFoundException("webp", delegate { if (NativeMethods.WebPPictureInitInternal(ref picture, 528) == 0) { throw new Exception("Failed to initialize WebPPicture (version mismatch)"); } return 0; }); picture.width = _width; picture.height = _height; picture.use_argb = 1; GCHandle gCHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned); try { IntPtr pixelPtr = gCHandle.AddrOfPinnedObject(); if (format switch { WebPPixelFormat.Bgra => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPPictureImportBGRA(ref picture, pixelPtr, stride)), WebPPixelFormat.Rgba => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPPictureImportRGBA(ref picture, pixelPtr, stride)), WebPPixelFormat.Bgr => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPPictureImportBGR(ref picture, pixelPtr, stride)), WebPPixelFormat.Rgb => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPPictureImportRGB(ref picture, pixelPtr, stride)), _ => throw new ArgumentOutOfRangeException("format"), } == 0) { throw new Exception("Failed to import pixel data into WebPPicture"); } if (NativeLibraryLoader.FixDllNotFoundException("webpmux", () => NativeMethods.WebPAnimEncoderAdd(_encoder, ref picture, timestampMs, ref localConfig)) == 0) { IntPtr intPtr = NativeMethods.WebPAnimEncoderGetError(_encoder); string text = ((intPtr != IntPtr.Zero) ? (Marshal.PtrToStringAnsi(intPtr) ?? "Unknown error") : "Unknown error"); throw new Exception("Failed to add animation frame: " + text); } if (_hasFrames) { _lastDuration = Math.Max(timestampMs - _lastTimestamp, 1); } _lastTimestamp = timestampMs; _hasFrames = true; } finally { NativeLibraryLoader.FixDllNotFoundException("webp", delegate { NativeMethods.WebPPictureFree(ref picture); return 0; }); gCHandle.Free(); } } public byte[] Assemble() { ThrowIfDisposed(); int endTimestamp = _lastTimestamp + Math.Max(_lastDuration, 1); NativeLibraryLoader.FixDllNotFoundException("webpmux", () => NativeMethods.WebPAnimEncoderAddNull(_encoder, IntPtr.Zero, endTimestamp, IntPtr.Zero)); WebPData webpData = default(WebPData); if (NativeLibraryLoader.FixDllNotFoundException("webpmux", () => NativeMethods.WebPAnimEncoderAssemble(_encoder, ref webpData)) == 0) { IntPtr intPtr = NativeMethods.WebPAnimEncoderGetError(_encoder); string text = ((intPtr != IntPtr.Zero) ? (Marshal.PtrToStringAnsi(intPtr) ?? "Unknown error") : "Unknown error"); throw new Exception("Failed to assemble animation: " + text); } int num = (int)(ulong)webpData.size; byte[] array = new byte[num]; Marshal.Copy(webpData.bytes, array, 0, num); return array; } public void Assemble(Stream outputStream) { if (outputStream == null) { throw new ArgumentNullException("outputStream"); } byte[] array = Assemble(); outputStream.Write(array, 0, array.Length); } private void ThrowIfDisposed() { if (_disposed) { throw new ObjectDisposedException("AnimEncoder"); } } public void Dispose() { if (!_disposed && _encoder != IntPtr.Zero) { NativeLibraryLoader.FixDllNotFoundException("webpmux", delegate { NativeMethods.WebPAnimEncoderDelete(_encoder); return 0; }); _encoder = IntPtr.Zero; _disposed = true; } } } public class AnimFrame { public byte[] Pixels { get; } public int TimestampMs { get; } public int Width { get; } public int Height { get; } public int DurationMs { get; internal set; } public AnimFrame(byte[] pixels, int width, int height, int timestampMs) { Pixels = pixels ?? throw new ArgumentNullException("pixels"); Width = width; Height = height; TimestampMs = timestampMs; DurationMs = -1; } } internal class LoadLogger : ILibraryLoadLogger { private struct LogEntry { internal string Basename; internal string? FullPath; internal bool FileExists; internal bool PreviouslyLoaded; internal int? LoadErrorCode; } internal string Verb = "loaded"; internal string Filename = RuntimeFileLocator.SharedLibraryPrefix.Value + "webp." + RuntimeFileLocator.SharedLibraryExtension.Value; internal Exception? FirstException; internal Exception? LastException; private readonly List _log = new List(7); public void NotifyAttempt(string basename, string? fullPath, bool fileExists, bool previouslyLoaded, int? loadErrorCode) { _log.Add(new LogEntry { Basename = basename, FullPath = fullPath, FileExists = fileExists, PreviouslyLoaded = previouslyLoaded, LoadErrorCode = loadErrorCode }); } internal void RaiseException() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "Looking for \"{0}\" RID=\"{1}-{2}\", IsUnix={3}, IsDotNetCore={4} RelativeSearchPath=\"{5}\"\n", Filename, RuntimeFileLocator.PlatformRuntimePrefix.Value, RuntimeFileLocator.ArchitectureSubdir.Value, RuntimeFileLocator.IsUnix, RuntimeFileLocator.IsDotNetCore.Value, AppDomain.CurrentDomain.RelativeSearchPath); if (FirstException != null) { stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "Before searching: {0}\n", FirstException.Message); } foreach (LogEntry item in _log) { if (item.PreviouslyLoaded) { stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\" is already {1}", item.Basename, Verb); } else if (!item.FileExists) { stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "File not found: {0}", item.FullPath); } else if (item.LoadErrorCode.HasValue) { string text = ((item.LoadErrorCode.Value < 0) ? string.Format(CultureInfo.InvariantCulture, "0x{0:X8}", item.LoadErrorCode.Value) : item.LoadErrorCode.Value.ToString(CultureInfo.InvariantCulture)); stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "Error \"{0}\" ({1}) loading {2} from {3}", new Win32Exception(item.LoadErrorCode.Value).Message, text, item.Basename, item.FullPath); if (item.LoadErrorCode.Value == 193 && RuntimeFileLocator.PlatformRuntimePrefix.Value == "win") { string arg = (Environment.Is64BitProcess ? "32-bit (x86)" : "64-bit (x86_64)"); string arg2 = (Environment.Is64BitProcess ? "64-bit (x86_64)" : "32-bit (x86)"); stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "\n> You have installed a {0} copy of libwebp but need the {1} version", arg, arg2); } if (item.LoadErrorCode.Value == 126 && RuntimeFileLocator.PlatformRuntimePrefix.Value == "win") { string arg3 = "https://aka.ms/vs/17/release/vc_redist." + (Environment.Is64BitProcess ? "x64.exe" : "x86.exe"); stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "\n> You may need to install the C Runtime from {0}", arg3); } } else { stringBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0} {1} in {2}", Verb, item.Basename, item.FullPath); } stringBuilder.Append('\n'); } if (LastException != null) { stringBuilder.AppendLine(LastException.Message); } string text2 = (FirstException ?? LastException)?.StackTrace; if (text2 != null) { stringBuilder.AppendLine(text2); } throw new DllNotFoundException(stringBuilder.ToString()); } } internal static class RuntimeFileLocator { internal static readonly Lazy SharedLibraryPrefix = new Lazy(() => (!IsUnix) ? "" : "lib", LazyThreadSafetyMode.PublicationOnly); internal static readonly Lazy IsDotNetCore = new Lazy(delegate { try { return typeof(GCSettings).GetTypeInfo().Assembly.CodeBase.Contains("Microsoft.NETCore.App"); } catch { return false; } }, LazyThreadSafetyMode.PublicationOnly); internal static readonly Lazy PlatformRuntimePrefix = new Lazy(delegate { if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return "osx"; } return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux" : "win"; }, LazyThreadSafetyMode.PublicationOnly); internal static readonly Lazy SharedLibraryExtension = new Lazy(delegate { if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return "dylib"; } return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "so" : "dll"; }, LazyThreadSafetyMode.PublicationOnly); internal static readonly Lazy ArchitectureSubdir = new Lazy(delegate { switch (RuntimeInformation.ProcessArchitecture) { case Architecture.X86: return "x86"; case Architecture.X64: return "x64"; case Architecture.Arm: return "arm"; case Architecture.Arm64: return "arm64"; default: { string environmentVariable = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); if (environmentVariable != null) { switch (environmentVariable.ToUpperInvariant()) { case "AMD64": return "x64"; case "IA64": return "ia64"; case "ARM64": return "arm64"; case "EM64T": return "x64"; case "X86": return "x86"; } } if (!Environment.Is64BitProcess) { return "x86"; } return "x64"; } } }, LazyThreadSafetyMode.PublicationOnly); internal static bool IsUnix { get { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return RuntimeInformation.IsOSPlatform(OSPlatform.OSX); } return true; } } private static IEnumerable> BaseFolders(IEnumerable? customSearchDirectories = null) { if (customSearchDirectories != null) { foreach (string customSearchDirectory in customSearchDirectories) { yield return Tuple.Create(item1: true, customSearchDirectory); } } if (!string.IsNullOrEmpty(AppDomain.CurrentDomain.RelativeSearchPath) && AppDomain.CurrentDomain.RelativeSearchPath.StartsWith(AppDomain.CurrentDomain.BaseDirectory)) { yield return Tuple.Create(item1: true, AppDomain.CurrentDomain.RelativeSearchPath); } if (!string.IsNullOrEmpty(AppContext.BaseDirectory)) { yield return Tuple.Create(item1: true, AppContext.BaseDirectory); } yield return Tuple.Create(item1: true, AppDomain.CurrentDomain.BaseDirectory); if (AppDomain.CurrentDomain.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar).EndsWith("bin")) { DirectoryInfo parent = Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory); if (parent != null) { yield return Tuple.Create(item1: false, Path.Combine(parent.FullName, "runtimes", PlatformRuntimePrefix.Value + "-" + ArchitectureSubdir.Value, "native")); } } string text = null; try { text = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } catch (NotImplementedException) { } if (!string.IsNullOrEmpty(text)) { yield return Tuple.Create(item1: true, text); } } internal static IEnumerable SearchPossibilitiesForFile(string filename, IEnumerable? customSearchDirectories = null) { HashSet attemptedPaths = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (Tuple item in BaseFolders(customSearchDirectories)) { if (string.IsNullOrEmpty(item.Item2)) { continue; } string directory = Path.GetFullPath(item.Item2); bool searchSubDirs = item.Item1; string text; if (searchSubDirs) { text = Path.Combine(directory, "runtimes", PlatformRuntimePrefix.Value + "-" + ArchitectureSubdir.Value, "native", filename); if (attemptedPaths.Add(text)) { yield return text; } } if (searchSubDirs) { text = Path.Combine(directory, ArchitectureSubdir.Value, filename); if (attemptedPaths.Add(text)) { yield return text; } } text = Path.Combine(directory, filename); if (attemptedPaths.Add(text)) { yield return text; } } } } internal interface ILibraryLoadLogger { void NotifyAttempt(string basename, string? fullPath, bool fileExists, bool previouslyLoaded, int? loadErrorCode); } internal static class NativeLibraryLoader { private static readonly Lazy> LibraryHandlesByBasename = new Lazy>(() => new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase), LazyThreadSafetyMode.PublicationOnly); internal static string GetFilenameWithoutDirectory(string basename) { return RuntimeFileLocator.SharedLibraryPrefix.Value + basename + "." + RuntimeFileLocator.SharedLibraryExtension.Value; } public static T? FixDllNotFoundException(string basename, Func invokingOperation, IEnumerable? customSearchDirectories = null) { Exception firstException; try { return invokingOperation(); } catch (BadImageFormatException ex) { firstException = ex; } catch (DllNotFoundException ex2) { firstException = ex2; } LoadLogger loadLogger = new LoadLogger { FirstException = firstException, Filename = GetFilenameWithoutDirectory(basename) }; if (TryLoadByBasename(basename, loadLogger, out var _, customSearchDirectories)) { try { return invokingOperation(); } catch (DllNotFoundException lastException) { loadLogger.LastException = lastException; } } loadLogger.RaiseException(); return default(T); } public static bool TryLoadByBasename(string basename, ILibraryLoadLogger log, out IntPtr handle, IEnumerable? customSearchDirectories = null) { if (string.IsNullOrEmpty(basename)) { throw new ArgumentNullException("basename"); } if (LibraryHandlesByBasename.Value.TryGetValue(basename, out handle)) { log.NotifyAttempt(basename, null, fileExists: true, previouslyLoaded: true, 0); return true; } lock (LibraryHandlesByBasename) { if (LibraryHandlesByBasename.Value.TryGetValue(basename, out handle)) { log.NotifyAttempt(basename, null, fileExists: true, previouslyLoaded: true, 0); return true; } bool num = TryLoadByBasenameInternal(basename, log, out handle, customSearchDirectories); if (num) { LibraryHandlesByBasename.Value[basename] = handle; if (string.Equals(basename, "webp", StringComparison.OrdinalIgnoreCase)) { AbiVersionCheck.ValidateOrThrow(); } } return num; } } private static bool TryLoadByBasenameInternal(string basename, ILibraryLoadLogger log, out IntPtr handle, IEnumerable? customSearchDirectories = null) { string filenameWithoutDirectory = GetFilenameWithoutDirectory(basename); List list = new List { filenameWithoutDirectory }; if (!RuntimeFileLocator.IsUnix) { string text = "lib" + basename + "." + RuntimeFileLocator.SharedLibraryExtension.Value; if (!string.Equals(filenameWithoutDirectory, text, StringComparison.OrdinalIgnoreCase)) { list.Add(text); } } foreach (string item in list) { foreach (string item2 in RuntimeFileLocator.SearchPossibilitiesForFile(item, customSearchDirectories)) { if (!File.Exists(item2)) { log.NotifyAttempt(basename, item2, fileExists: false, previouslyLoaded: false, 0); continue; } int? errorCode; bool num = LoadLibrary(item2, out handle, out errorCode); log.NotifyAttempt(basename, item2, fileExists: true, previouslyLoaded: false, errorCode); if (!num) { continue; } return true; } } handle = IntPtr.Zero; return false; } private static bool LoadLibrary(string fullPath, out IntPtr handle, out int? errorCode) { handle = (RuntimeFileLocator.IsUnix ? UnixLoadLibrary.Execute(fullPath) : WindowsLoadLibrary.Execute(fullPath)); if (handle == IntPtr.Zero) { errorCode = Marshal.GetLastWin32Error(); return false; } errorCode = null; return true; } } [SuppressUnmanagedCodeSecurity] [SecurityCritical] internal static class WindowsLoadLibrary { [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)] private static extern IntPtr LoadLibraryEx(string fileName, IntPtr reservedNull, uint flags); public static IntPtr Execute(string fileName) { return LoadLibraryEx(fileName, IntPtr.Zero, 8u); } } [SuppressUnmanagedCodeSecurity] [SecurityCritical] internal static class UnixLoadLibrary { private static volatile bool _preferLibdl2 = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); [DllImport("libdl.so.2", CharSet = CharSet.Ansi, EntryPoint = "dlopen", SetLastError = true)] private static extern IntPtr dlopen_libdl2(string fileName, int flags); [DllImport("libdl", CharSet = CharSet.Ansi, EntryPoint = "dlopen", SetLastError = true)] private static extern IntPtr dlopen_libdl(string fileName, int flags); public static IntPtr Execute(string fileName) { if (_preferLibdl2) { try { return dlopen_libdl2(fileName, 2); } catch (DllNotFoundException) { _preferLibdl2 = false; } } return dlopen_libdl(fileName, 2); } } public class SimpleDecoder { public static string GetDecoderVersion() { int num = NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPGetDecoderVersion()); uint num2 = (uint)num % 256u; uint num3 = (uint)(num >>> 8) % 256u; uint num4 = (uint)(num >>> 16) % 256u; return num4 + "." + num3 + "." + num2; } public unsafe Bitmap DecodeFromBytes(byte[] data, long length) { fixed (byte* ptr = data) { return DecodeFromPointer((IntPtr)ptr, length); } } public Bitmap DecodeFromPointer(IntPtr data, long length) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown int w = 0; int h = 0; if (NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPGetInfo(data, (UIntPtr)(ulong)length, ref w, ref h)) == 0) { throw new Exception("Invalid WebP header detected"); } bool flag = false; Bitmap val = null; BitmapData bd = null; try { val = new Bitmap(w, h, (PixelFormat)2498570); bd = val.LockBits(new Rectangle(0, 0, w, h), (ImageLockMode)3, (PixelFormat)2498570); IntPtr intPtr = NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPDecodeBGRAInto(data, (UIntPtr)(ulong)length, bd.Scan0, (UIntPtr)(ulong)(bd.Stride * bd.Height), bd.Stride)); if (bd.Scan0 != intPtr) { throw new Exception("Failed to decode WebP image with error " + (long)intPtr); } flag = true; } finally { if (bd != null && val != null) { val.UnlockBits(bd); } if (!flag && val != null) { ((Image)val).Dispose(); } } return val; } public Bitmap DecodeFromStream(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } byte[] array = ReadStreamFully(stream); return DecodeFromBytes(array, array.LongLength); } private static byte[] ReadStreamFully(Stream stream) { if (stream is MemoryStream { Position: 0L } memoryStream) { return memoryStream.ToArray(); } using MemoryStream memoryStream2 = new MemoryStream(); byte[] array = new byte[8192]; int count; while ((count = stream.Read(array, 0, array.Length)) > 0) { memoryStream2.Write(array, 0, count); } return memoryStream2.ToArray(); } } public class SimpleEncoder { public static string GetEncoderVersion() { int num = NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPGetEncoderVersion()); uint num2 = (uint)num % 256u; uint num3 = (uint)(num >>> 8) % 256u; uint num4 = (uint)(num >>> 16) % 256u; return num4 + "." + num3 + "." + num2; } [Obsolete("Use Encode(Bitmap, Stream, float) instead")] public void Encode(Bitmap from, Stream to, float quality, bool noAlpha) { Encode(from, to, quality); } public void Encode(Bitmap from, Stream to, float quality) { Encode(from, quality, out var result, out var length); try { byte[] array = new byte[4096]; for (int i = 0; i < length; i += array.Length) { int num = (int)Math.Min(array.Length, length - i); Marshal.Copy((IntPtr)((long)result + i), array, 0, num); to.Write(array, 0, num); } } finally { NativeMethods.WebPSafeFree(result); } } [Obsolete("Use Encode(Bitmap, float, out IntPtr, out long) instead")] public void Encode(Bitmap b, float quality, bool noAlpha, out IntPtr result, out long length) { Encode(b, quality, out result, out length); } public void Encode(Bitmap b, float quality, out IntPtr result, out long length) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Invalid comparison between Unknown and I4 //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Invalid comparison between Unknown and I4 if (quality < -1f) { quality = -1f; } if (quality > 100f) { quality = 100f; } int w = ((Image)b).Width; int h = ((Image)b).Height; BitmapData val = b.LockBits(new Rectangle(0, 0, w, h), (ImageLockMode)1, ((Image)b).PixelFormat); try { result = IntPtr.Zero; IntPtr scan0 = val.Scan0; int stride = val.Stride; if ((int)((Image)b).PixelFormat == 2498570) { IntPtr res = IntPtr.Zero; if (quality == -1f) { length = (long)(ulong)NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeLosslessBGRA(scan0, w, h, stride, ref res)); } else { length = (long)(ulong)NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeBGRA(scan0, w, h, stride, quality, ref res)); } result = res; } else if ((int)((Image)b).PixelFormat == 137224) { IntPtr res2 = IntPtr.Zero; if (quality == -1f) { length = (long)(ulong)NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeLosslessBGR(scan0, w, h, stride, ref res2)); } else { length = (long)(ulong)NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeBGR(scan0, w, h, stride, quality, ref res2)); } result = res2; } else { Bitmap val2 = b.Clone(new Rectangle(0, 0, ((Image)b).Width, ((Image)b).Height), (PixelFormat)2498570); try { Encode(val2, quality, out result, out length); } finally { ((IDisposable)val2)?.Dispose(); } } if (length == 0L) { throw new Exception("WebP encode failed!"); } } finally { b.UnlockBits(val); } } public void Encode(Bitmap b, Stream to, WebPEncoderConfig config) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Invalid comparison between Unknown and I4 //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Invalid comparison between Unknown and I4 if (b == null) { throw new ArgumentNullException("b"); } if (to == null) { throw new ArgumentNullException("to"); } if (config == null) { throw new ArgumentNullException("config"); } int width = ((Image)b).Width; int height = ((Image)b).Height; Bitmap val = b; bool flag = false; if ((int)((Image)b).PixelFormat != 2498570 && (int)((Image)b).PixelFormat != 137224) { val = b.Clone(new Rectangle(0, 0, ((Image)b).Width, ((Image)b).Height), (PixelFormat)2498570); flag = true; } try { BitmapData val2 = val.LockBits(new Rectangle(0, 0, width, height), (ImageLockMode)1, ((Image)val).PixelFormat); try { _ = ((Image)val).PixelFormat; _ = 137224; int stride = val2.Stride; byte[] array = new byte[Math.Abs(stride) * height]; Marshal.Copy(val2.Scan0, array, 0, array.Length); WebPPixelFormat format = (((int)((Image)val).PixelFormat == 137224) ? WebPPixelFormat.Bgr : WebPPixelFormat.Bgra); WebPEncoder.Encode(array, width, height, Math.Abs(stride), format, config, to); } finally { val.UnlockBits(val2); } } finally { if (flag) { ((Image)val).Dispose(); } } } } public enum WebPPixelFormat { Bgra, Rgba, Bgr, Rgb } public static class WebPDecoder { public static byte[] Decode(byte[] data, out int width, out int height) { return Decode(data, out width, out height, WebPPixelFormat.Bgra); } public static byte[] Decode(byte[] data, out int width, out int height, WebPPixelFormat format) { if (data == null) { throw new ArgumentNullException("data"); } GCHandle gCHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { IntPtr dataPtr = gCHandle.AddrOfPinnedObject(); UIntPtr dataSize = (UIntPtr)(ulong)data.Length; int w = 0; int h = 0; if (NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPGetInfo(dataPtr, dataSize, ref w, ref h)) == 0) { throw new Exception("Invalid WebP header detected"); } width = w; height = h; int num = ((format == WebPPixelFormat.Bgr || format == WebPPixelFormat.Rgb) ? 3 : 4); int num2 = w * num; byte[] array = new byte[num2 * h]; GCHandle gCHandle2 = GCHandle.Alloc(array, GCHandleType.Pinned); try { IntPtr intPtr = gCHandle2.AddrOfPinnedObject(); UIntPtr outSize = (UIntPtr)(ulong)array.Length; IntPtr intPtr2 = DecodeInto(dataPtr, dataSize, intPtr, outSize, num2, format); if (intPtr != intPtr2) { throw new Exception("Failed to decode WebP image"); } } finally { gCHandle2.Free(); } return array; } finally { gCHandle.Free(); } } public static void Decode(byte[] data, byte[] output, int stride, WebPPixelFormat format) { if (data == null) { throw new ArgumentNullException("data"); } if (output == null) { throw new ArgumentNullException("output"); } GCHandle gCHandle = GCHandle.Alloc(data, GCHandleType.Pinned); GCHandle gCHandle2 = GCHandle.Alloc(output, GCHandleType.Pinned); try { IntPtr dataPtr = gCHandle.AddrOfPinnedObject(); IntPtr intPtr = gCHandle2.AddrOfPinnedObject(); UIntPtr dataSize = (UIntPtr)(ulong)data.Length; UIntPtr outSize = (UIntPtr)(ulong)output.Length; IntPtr intPtr2 = DecodeInto(dataPtr, dataSize, intPtr, outSize, stride, format); if (intPtr != intPtr2) { throw new Exception("Failed to decode WebP image"); } } finally { gCHandle2.Free(); gCHandle.Free(); } } public static byte[] DecodeFromStream(Stream stream, out int width, out int height) { return DecodeFromStream(stream, out width, out height, WebPPixelFormat.Bgra); } public static byte[] DecodeFromStream(Stream stream, out int width, out int height, WebPPixelFormat format) { if (stream == null) { throw new ArgumentNullException("stream"); } return Decode(ReadStreamFully(stream), out width, out height, format); } public static bool IsWebP(byte[] data) { if (data == null || data.Length < 12) { return false; } if (data[0] == 82 && data[1] == 73 && data[2] == 70 && data[3] == 70 && data[8] == 87 && data[9] == 69 && data[10] == 66) { return data[11] == 80; } return false; } public static bool IsWebP(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanSeek) { throw new ArgumentException("Stream must be seekable", "stream"); } long position = stream.Position; try { byte[] array = new byte[12]; int num; for (int i = 0; i < 12; i += num) { num = stream.Read(array, i, 12 - i); if (num == 0) { return false; } } return IsWebP(array); } finally { stream.Position = position; } } private static byte[] ReadStreamFully(Stream stream) { if (stream is MemoryStream { Position: 0L } memoryStream) { return memoryStream.ToArray(); } using MemoryStream memoryStream2 = new MemoryStream(); byte[] array = new byte[8192]; int count; while ((count = stream.Read(array, 0, array.Length)) > 0) { memoryStream2.Write(array, 0, count); } return memoryStream2.ToArray(); } private static IntPtr DecodeInto(IntPtr dataPtr, UIntPtr dataSize, IntPtr outPtr, UIntPtr outSize, int stride, WebPPixelFormat format) { return format switch { WebPPixelFormat.Bgra => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPDecodeBGRAInto(dataPtr, dataSize, outPtr, outSize, stride)), WebPPixelFormat.Rgba => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPDecodeRGBAInto(dataPtr, dataSize, outPtr, outSize, stride)), WebPPixelFormat.Bgr => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPDecodeBGRInto(dataPtr, dataSize, outPtr, outSize, stride)), WebPPixelFormat.Rgb => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPDecodeRGBInto(dataPtr, dataSize, outPtr, outSize, stride)), _ => throw new ArgumentOutOfRangeException("format"), }; } } public static class WebPEncoder { private class EncodeOutput { public MemoryStream Stream = new MemoryStream(); } [ThreadStatic] private static WebPWriterFunction? _writerDelegate; private static int ManagedWriter(IntPtr data, UIntPtr dataSize, ref WebPPicture picture) { int num = (int)(uint)dataSize; if (num <= 0) { return 1; } byte[] array = new byte[num]; Marshal.Copy(data, array, 0, num); ((EncodeOutput)GCHandle.FromIntPtr(picture.custom_ptr).Target).Stream.Write(array, 0, num); return 1; } public static byte[] Encode(byte[] pixels, int width, int height, int stride, WebPPixelFormat format, float quality) { if (pixels == null) { throw new ArgumentNullException("pixels"); } if (width <= 0) { throw new ArgumentOutOfRangeException("width"); } if (height <= 0) { throw new ArgumentOutOfRangeException("height"); } GCHandle gCHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned); try { IntPtr data = gCHandle.AddrOfPinnedObject(); IntPtr result = IntPtr.Zero; UIntPtr uIntPtr; if (quality < 0f) { uIntPtr = EncodeLossless(data, width, height, stride, format, ref result); } else { if (quality > 100f) { quality = 100f; } uIntPtr = EncodeLossy(data, width, height, stride, format, quality, ref result); } if ((ulong)uIntPtr == 0L || result == IntPtr.Zero) { throw new Exception("WebP encode failed!"); } try { byte[] array = new byte[(uint)(ulong)uIntPtr]; Marshal.Copy(result, array, 0, array.Length); return array; } finally { NativeMethods.WebPSafeFree(result); } } finally { gCHandle.Free(); } } public static void Encode(byte[] pixels, int width, int height, int stride, WebPPixelFormat format, float quality, Stream output) { if (output == null) { throw new ArgumentNullException("output"); } byte[] array = Encode(pixels, width, height, stride, format, quality); output.Write(array, 0, array.Length); } private static UIntPtr EncodeLossy(IntPtr data, int width, int height, int stride, WebPPixelFormat format, float quality, ref IntPtr result) { IntPtr res = result; UIntPtr result2 = format switch { WebPPixelFormat.Bgra => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeBGRA(data, width, height, stride, quality, ref res)), WebPPixelFormat.Rgba => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeRGBA(data, width, height, stride, quality, ref res)), WebPPixelFormat.Bgr => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeBGR(data, width, height, stride, quality, ref res)), WebPPixelFormat.Rgb => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeRGB(data, width, height, stride, quality, ref res)), _ => throw new ArgumentOutOfRangeException("format"), }; result = res; return result2; } private static UIntPtr EncodeLossless(IntPtr data, int width, int height, int stride, WebPPixelFormat format, ref IntPtr result) { IntPtr res = result; UIntPtr result2 = format switch { WebPPixelFormat.Bgra => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeLosslessBGRA(data, width, height, stride, ref res)), WebPPixelFormat.Rgba => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeLosslessRGBA(data, width, height, stride, ref res)), WebPPixelFormat.Bgr => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeLosslessBGR(data, width, height, stride, ref res)), WebPPixelFormat.Rgb => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncodeLosslessRGB(data, width, height, stride, ref res)), _ => throw new ArgumentOutOfRangeException("format"), }; result = res; return result2; } public static byte[] Encode(byte[] pixels, int width, int height, int stride, WebPPixelFormat format, WebPEncoderConfig config) { if (pixels == null) { throw new ArgumentNullException("pixels"); } if (config == null) { throw new ArgumentNullException("config"); } if (width <= 0) { throw new ArgumentOutOfRangeException("width"); } if (height <= 0) { throw new ArgumentOutOfRangeException("height"); } if (!config.Validate()) { throw new ArgumentException("Invalid WebP encoder configuration", "config"); } WebPConfig nativeConfig = config.GetNativeConfig(); WebPPicture picture = default(WebPPicture); NativeLibraryLoader.FixDllNotFoundException("webp", delegate { if (NativeMethods.WebPPictureInitInternal(ref picture, 528) == 0) { throw new Exception("WebP version mismatch: failed to initialize picture"); } return 0; }); picture.width = width; picture.height = height; picture.use_argb = 1; GCHandle gCHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned); EncodeOutput encodeOutput = new EncodeOutput(); GCHandle value = GCHandle.Alloc(encodeOutput); _writerDelegate = ManagedWriter; try { IntPtr pixelPtr = gCHandle.AddrOfPinnedObject(); if (format switch { WebPPixelFormat.Bgra => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPPictureImportBGRA(ref picture, pixelPtr, stride)), WebPPixelFormat.Rgba => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPPictureImportRGBA(ref picture, pixelPtr, stride)), WebPPixelFormat.Bgr => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPPictureImportBGR(ref picture, pixelPtr, stride)), WebPPixelFormat.Rgb => NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPPictureImportRGB(ref picture, pixelPtr, stride)), _ => throw new ArgumentOutOfRangeException("format"), } == 0) { throw new Exception("Failed to import pixel data into WebPPicture"); } picture.writer = _writerDelegate; picture.custom_ptr = GCHandle.ToIntPtr(value); if (NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPEncode(ref nativeConfig, ref picture)) == 0) { throw new Exception($"WebP encode failed with error: {picture.error_code}"); } return encodeOutput.Stream.ToArray(); } finally { NativeLibraryLoader.FixDllNotFoundException("webp", delegate { NativeMethods.WebPPictureFree(ref picture); return 0; }); gCHandle.Free(); value.Free(); _writerDelegate = null; } } public static void Encode(byte[] pixels, int width, int height, int stride, WebPPixelFormat format, WebPEncoderConfig config, Stream outputStream) { if (outputStream == null) { throw new ArgumentNullException("outputStream"); } byte[] array = Encode(pixels, width, height, stride, format, config); outputStream.Write(array, 0, array.Length); } } public class WebPEncoderConfig { private WebPConfig _config; private bool _initialized; public WebPEncoderConfig() { _config = default(WebPConfig); if (NativeMethods.WebPConfigInit(ref _config) == 0) { throw new Exception("WebP version mismatch: failed to initialize config"); } _initialized = true; } public WebPEncoderConfig(WebPPreset preset, float quality) { _config = default(WebPConfig); if (NativeMethods.WebPConfigPreset(ref _config, preset, quality) == 0) { throw new Exception("WebP version mismatch: failed to initialize config with preset"); } _initialized = true; } public WebPEncoderConfig SetQuality(float quality) { EnsureInitialized(); _config.quality = Math.Max(0f, Math.Min(100f, quality)); _config.lossless = 0; return this; } public WebPEncoderConfig SetLossless(bool lossless = true) { EnsureInitialized(); _config.lossless = (lossless ? 1 : 0); return this; } public WebPEncoderConfig SetLosslessPreset(int level) { EnsureInitialized(); _config.lossless = 1; NativeMethods.WebPConfigLosslessPreset(ref _config, level); return this; } public WebPEncoderConfig SetMethod(int method) { EnsureInitialized(); _config.method = Math.Max(0, Math.Min(6, method)); return this; } public WebPEncoderConfig SetNearLossless(int level) { EnsureInitialized(); _config.near_lossless = Math.Max(0, Math.Min(100, level)); return this; } public WebPEncoderConfig SetTargetSize(int bytes) { EnsureInitialized(); _config.target_size = bytes; return this; } public WebPEncoderConfig SetTargetPSNR(float psnr) { EnsureInitialized(); _config.target_PSNR = psnr; return this; } public WebPEncoderConfig SetMultiThreaded(bool enabled = true) { EnsureInitialized(); _config.thread_level = (enabled ? 1 : 0); return this; } public WebPEncoderConfig SetSnsStrength(int strength) { EnsureInitialized(); _config.sns_strength = Math.Max(0, Math.Min(100, strength)); return this; } public WebPEncoderConfig SetFilterStrength(int strength) { EnsureInitialized(); _config.filter_strength = Math.Max(0, Math.Min(100, strength)); return this; } public WebPEncoderConfig SetAlphaQuality(int quality) { EnsureInitialized(); _config.alpha_quality = Math.Max(0, Math.Min(100, quality)); return this; } public WebPEncoderConfig SetImageHint(WebPImageHint hint) { EnsureInitialized(); _config.image_hint = hint; return this; } public WebPEncoderConfig SetExact(bool exact = true) { EnsureInitialized(); _config.exact = (exact ? 1 : 0); return this; } public WebPEncoderConfig SetSharpYuv(bool enabled = true) { EnsureInitialized(); _config.use_sharp_yuv = (enabled ? 1 : 0); return this; } public bool Validate() { EnsureInitialized(); return NativeMethods.WebPValidateConfig(ref _config) != 0; } public WebPConfig GetNativeConfig() { EnsureInitialized(); return _config; } private void EnsureInitialized() { if (!_initialized) { throw new InvalidOperationException("Config not initialized"); } } } public class WebPImageInfo { public int Width { get; } public int Height { get; } public bool HasAlpha { get; } public bool HasAnimation { get; } public int Format { get; } internal WebPImageInfo(int width, int height, bool hasAlpha, bool hasAnimation, int format) { Width = width; Height = height; HasAlpha = hasAlpha; HasAnimation = hasAnimation; Format = format; } } public static class WebPInfo { public static bool TryGetSize(byte[] data, out int width, out int height) { width = 0; height = 0; if (data == null || data.Length < 12) { return false; } GCHandle gCHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { IntPtr ptr = gCHandle.AddrOfPinnedObject(); UIntPtr size = (UIntPtr)(ulong)data.Length; int w = 0; int h = 0; int num = NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPGetInfo(ptr, size, ref w, ref h)); width = w; height = h; return num != 0; } finally { gCHandle.Free(); } } public static WebPImageInfo GetImageInfo(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length < 12) { throw new ArgumentException("Data too short to be a valid WebP file", "data"); } GCHandle gCHandle = GCHandle.Alloc(data, GCHandleType.Pinned); try { return GetImageInfo(gCHandle.AddrOfPinnedObject(), data.Length); } finally { gCHandle.Free(); } } public static WebPImageInfo GetImageInfo(IntPtr data, long length) { if (data == IntPtr.Zero) { throw new ArgumentNullException("data"); } if (length < 12) { throw new ArgumentException("Data too short to be a valid WebP file", "length"); } WebPBitstreamFeatures features = default(WebPBitstreamFeatures); VP8StatusCode vP8StatusCode = NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPGetFeatures(data, (UIntPtr)(ulong)length, ref features)); if (vP8StatusCode != VP8StatusCode.VP8_STATUS_OK) { throw new Exception($"Failed to get WebP features: {vP8StatusCode}"); } return new WebPImageInfo(features.width, features.height, features.has_alpha != 0, features.has_animation != 0, features.format); } } } namespace Imazen.WebP.Extern { public class NativeMethods { public const int WEBP_DECODER_ABI_VERSION = 528; public const int WEBP_ENCODER_ABI_VERSION = 528; public const int WEBP_MAX_DIMENSION = 16383; public const int WEBP_DEMUX_ABI_VERSION = 263; public const int WEBP_MUX_ABI_VERSION = 265; [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPGetDecoderVersion(); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPGetInfo([In] IntPtr data, UIntPtr data_size, ref int width, ref int height); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeRGBA([In] IntPtr data, UIntPtr data_size, ref int width, ref int height); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeARGB([In] IntPtr data, UIntPtr data_size, ref int width, ref int height); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeBGRA([In] IntPtr data, UIntPtr data_size, ref int width, ref int height); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeRGB([In] IntPtr data, UIntPtr data_size, ref int width, ref int height); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeBGR([In] IntPtr data, UIntPtr data_size, ref int width, ref int height); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeYUV([In] IntPtr data, UIntPtr data_size, ref int width, ref int height, ref IntPtr u, ref IntPtr v, ref int stride, ref int uv_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeRGBAInto([In] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeARGBInto([In] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeBGRAInto([In] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeRGBInto([In] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeBGRInto([In] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPDecodeYUVInto([In] IntPtr data, UIntPtr data_size, IntPtr luma, UIntPtr luma_size, int luma_stride, IntPtr u, UIntPtr u_size, int u_stride, IntPtr v, UIntPtr v_size, int v_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPInitDecBufferInternal(ref WebPDecBuffer param0, int param1); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPFreeDecBuffer(ref WebPDecBuffer buffer); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPINewDecoder(ref WebPDecBuffer output_buffer); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPINewRGB(WEBP_CSP_MODE csp, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPINewYUVA(IntPtr luma, UIntPtr luma_size, int luma_stride, IntPtr u, UIntPtr u_size, int u_stride, IntPtr v, UIntPtr v_size, int v_stride, IntPtr a, UIntPtr a_size, int a_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPINewYUV(IntPtr luma, UIntPtr luma_size, int luma_stride, IntPtr u, UIntPtr u_size, int u_stride, IntPtr v, UIntPtr v_size, int v_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPIDelete(ref WebPIDecoder idec); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern VP8StatusCode WebPIAppend(ref WebPIDecoder idec, [In] IntPtr data, UIntPtr data_size); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern VP8StatusCode WebPIUpdate(ref WebPIDecoder idec, [In] IntPtr data, UIntPtr data_size); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPIDecGetRGB(ref WebPIDecoder idec, ref int last_y, ref int width, ref int height, ref int stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPIDecGetYUVA(ref WebPIDecoder idec, ref int last_y, ref IntPtr u, ref IntPtr v, ref IntPtr a, ref int width, ref int height, ref int stride, ref int uv_stride, ref int a_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPIDecodedArea(ref WebPIDecoder idec, ref int left, ref int top, ref int width, ref int height); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern VP8StatusCode WebPGetFeaturesInternal([In] IntPtr param0, UIntPtr param1, ref WebPBitstreamFeatures param2, int param3); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPInitDecoderConfigInternal(ref WebPDecoderConfig param0, int param1); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPIDecode([In] IntPtr data, UIntPtr data_size, ref WebPDecoderConfig config); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern VP8StatusCode WebPDecode([In] IntPtr data, UIntPtr data_size, ref WebPDecoderConfig config); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPValidateDecoderConfig(ref WebPDecoderConfig config); public static bool WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { if (mode != WEBP_CSP_MODE.MODE_rgbA && mode != WEBP_CSP_MODE.MODE_bgrA && mode != WEBP_CSP_MODE.MODE_Argb) { return mode == WEBP_CSP_MODE.MODE_rgbA_4444; } return true; } public static bool WebPIsRGBMode(WEBP_CSP_MODE mode) { return mode < WEBP_CSP_MODE.MODE_YUV; } public static bool WebPIsAlphaMode(WEBP_CSP_MODE mode) { if (mode != WEBP_CSP_MODE.MODE_RGBA && mode != WEBP_CSP_MODE.MODE_BGRA && mode != WEBP_CSP_MODE.MODE_ARGB && mode != WEBP_CSP_MODE.MODE_RGBA_4444 && mode != WEBP_CSP_MODE.MODE_YUVA) { return WebPIsPremultipliedMode(mode); } return true; } public static VP8StatusCode WebPGetFeatures(IntPtr data, UIntPtr data_size, ref WebPBitstreamFeatures features) { return WebPGetFeaturesInternal(data, data_size, ref features, 528); } public static int WebPInitDecoderConfig(ref WebPDecoderConfig config) { return WebPInitDecoderConfigInternal(ref config, 528); } public static int WebPInitDecBuffer(ref WebPDecBuffer buffer) { return WebPInitDecBufferInternal(ref buffer, 528); } [DllImport("libwebpdemux", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPAnimDecoderOptionsInitInternal(ref WebPAnimDecoderOptions dec_options, int abi_version); [DllImport("libwebpdemux", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPAnimDecoderNewInternal(ref WebPData webp_data, ref WebPAnimDecoderOptions dec_options, int abi_version); [DllImport("libwebpdemux", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPAnimDecoderNewInternal")] public static extern IntPtr WebPAnimDecoderNewInternalDefault(ref WebPData webp_data, IntPtr dec_options, int abi_version); [DllImport("libwebpdemux", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPAnimDecoderGetInfo(IntPtr dec, ref WebPAnimInfo info); [DllImport("libwebpdemux", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPAnimDecoderGetNext(IntPtr dec, ref IntPtr buf, ref int timestamp); [DllImport("libwebpdemux", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPAnimDecoderHasMoreFrames(IntPtr dec); [DllImport("libwebpdemux", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPAnimDecoderReset(IntPtr dec); [DllImport("libwebpdemux", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPAnimDecoderDelete(IntPtr dec); public static int WebPAnimDecoderOptionsInit(ref WebPAnimDecoderOptions dec_options) { return WebPAnimDecoderOptionsInitInternal(ref dec_options, 263); } public static IntPtr WebPAnimDecoderNew(ref WebPData webp_data, ref WebPAnimDecoderOptions dec_options) { return WebPAnimDecoderNewInternal(ref webp_data, ref dec_options, 263); } public static IntPtr WebPAnimDecoderNewDefault(ref WebPData webp_data) { return WebPAnimDecoderNewInternalDefault(ref webp_data, IntPtr.Zero, 263); } [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPGetEncoderVersion(); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr WebPEncodeRGB([In] IntPtr rgb, int width, int height, int stride, float quality_factor, ref IntPtr output); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr WebPEncodeBGR([In] IntPtr bgr, int width, int height, int stride, float quality_factor, ref IntPtr output); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr WebPEncodeRGBA([In] IntPtr rgba, int width, int height, int stride, float quality_factor, ref IntPtr output); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr WebPEncodeBGRA([In] IntPtr bgra, int width, int height, int stride, float quality_factor, ref IntPtr output); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr WebPEncodeLosslessRGB([In] IntPtr rgb, int width, int height, int stride, ref IntPtr output); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr WebPEncodeLosslessBGR([In] IntPtr bgr, int width, int height, int stride, ref IntPtr output); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr WebPEncodeLosslessRGBA([In] IntPtr rgba, int width, int height, int stride, ref IntPtr output); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern UIntPtr WebPEncodeLosslessBGRA([In] IntPtr bgra, int width, int height, int stride, ref IntPtr output); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPConfigInitInternal(ref WebPConfig param0, WebPPreset param1, float param2, int param3); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPConfigLosslessPreset(ref WebPConfig config, int level); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPValidateConfig(ref WebPConfig config); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPMemoryWriterInit(ref WebPMemoryWriter writer); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPMemoryWriterClear(ref WebPMemoryWriter writer); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPMemoryWrite([In] IntPtr data, UIntPtr data_size, ref WebPPicture picture); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureInitInternal(ref WebPPicture param0, int param1); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureAlloc(ref WebPPicture picture); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPPictureFree(ref WebPPicture picture); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureCopy(ref WebPPicture src, ref WebPPicture dst); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureDistortion(ref WebPPicture src, ref WebPPicture reference, int metric_type, ref float result); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureCrop(ref WebPPicture picture, int left, int top, int width, int height); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureView(ref WebPPicture src, int left, int top, int width, int height, ref WebPPicture dst); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureIsView(ref WebPPicture picture); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureRescale(ref WebPPicture pic, int width, int height); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureImportRGB(ref WebPPicture picture, [In] IntPtr rgb, int rgb_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureImportRGBA(ref WebPPicture picture, [In] IntPtr rgba, int rgba_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureSmartARGBToYUVA(ref WebPPicture picture); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureImportRGBX(ref WebPPicture picture, [In] IntPtr rgbx, int rgbx_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureImportBGR(ref WebPPicture picture, [In] IntPtr bgr, int bgr_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureImportBGRA(ref WebPPicture picture, [In] IntPtr bgra, int bgra_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureImportBGRX(ref WebPPicture picture, [In] IntPtr bgrx, int bgrx_stride); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureARGBToYUVA(ref WebPPicture picture, WebPEncCSP colorspace); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureYUVAToARGB(ref WebPPicture picture); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPCleanupTransparentArea(ref WebPPicture picture); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureHasTransparency(ref WebPPicture picture); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureARGBToYUVADithered(ref WebPPicture picture, WebPEncCSP colorspace, float dithering); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPictureSharpARGBToYUVA(ref WebPPicture picture); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPPlaneDistortion([In] IntPtr src, UIntPtr src_stride, [In] IntPtr reference, UIntPtr ref_stride, int width, int height, UIntPtr x_step, int type, ref float distortion, ref float result); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPBlendAlpha(ref WebPPicture picture, uint background_rgb); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPEncode(ref WebPConfig config, ref WebPPicture picture); public static int WebPConfigInit(ref WebPConfig config) { return WebPConfigInitInternal(ref config, WebPPreset.WEBP_PRESET_DEFAULT, 75f, 528); } public static int WebPConfigPreset(ref WebPConfig config, WebPPreset preset, float quality) { return WebPConfigInitInternal(ref config, preset, quality, 528); } public static int WebPPictureInit(ref WebPPicture picture) { return WebPPictureInitInternal(ref picture, 528); } public static void WebPSafeFree(IntPtr toDeallocate) { NativeLibraryLoader.FixDllNotFoundException("webp", delegate { WebPFree(toDeallocate); return 0; }); } [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPFree(IntPtr toDeallocate); [DllImport("libwebp", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPMalloc(UIntPtr size); [DllImport("libwebpmux", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPAnimEncoderOptionsInitInternal(ref WebPAnimEncoderOptions enc_options, int abi_version); [DllImport("libwebpmux", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPAnimEncoderNewInternal(int width, int height, ref WebPAnimEncoderOptions enc_options, int abi_version); [DllImport("libwebpmux", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPAnimEncoderNewInternal")] public static extern IntPtr WebPAnimEncoderNewInternalDefault(int width, int height, IntPtr enc_options, int abi_version); [DllImport("libwebpmux", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPAnimEncoderAdd(IntPtr enc, ref WebPPicture frame, int timestamp_ms, ref WebPConfig config); [DllImport("libwebpmux", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPAnimEncoderAdd")] public static extern int WebPAnimEncoderAddDefaultConfig(IntPtr enc, ref WebPPicture frame, int timestamp_ms, IntPtr config); [DllImport("libwebpmux", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPAnimEncoderAdd")] public static extern int WebPAnimEncoderAddNull(IntPtr enc, IntPtr frame, int timestamp_ms, IntPtr config); [DllImport("libwebpmux", CallingConvention = CallingConvention.Cdecl)] public static extern int WebPAnimEncoderAssemble(IntPtr enc, ref WebPData webp_data); [DllImport("libwebpmux", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr WebPAnimEncoderGetError(IntPtr enc); [DllImport("libwebpmux", CallingConvention = CallingConvention.Cdecl)] public static extern void WebPAnimEncoderDelete(IntPtr enc); public static int WebPAnimEncoderOptionsInit(ref WebPAnimEncoderOptions enc_options) { return WebPAnimEncoderOptionsInitInternal(ref enc_options, 265); } public static IntPtr WebPAnimEncoderNew(int width, int height, ref WebPAnimEncoderOptions enc_options) { return WebPAnimEncoderNewInternal(width, height, ref enc_options, 265); } public static IntPtr WebPAnimEncoderNewDefault(int width, int height) { return WebPAnimEncoderNewInternalDefault(width, height, IntPtr.Zero, 265); } } public struct WebPIDecoder { } public enum WEBP_CSP_MODE { MODE_RGB, MODE_RGBA, MODE_BGR, MODE_BGRA, MODE_ARGB, MODE_RGBA_4444, MODE_RGB_565, MODE_rgbA, MODE_bgrA, MODE_Argb, MODE_rgbA_4444, MODE_YUV, MODE_YUVA, MODE_LAST } public struct WebPRGBABuffer { public IntPtr rgba; public int stride; public UIntPtr size; } public struct WebPYUVABuffer { public IntPtr y; public IntPtr u; public IntPtr v; public IntPtr a; public int y_stride; public int u_stride; public int v_stride; public int a_stride; public UIntPtr y_size; public UIntPtr u_size; public UIntPtr v_size; public UIntPtr a_size; } [StructLayout(LayoutKind.Explicit)] public struct Anonymous_690ed5ec_4c3d_40c6_9bd0_0747b5a28b54 { [FieldOffset(0)] public WebPRGBABuffer RGBA; [FieldOffset(0)] public WebPYUVABuffer YUVA; } public struct WebPDecBuffer { public WEBP_CSP_MODE colorspace; public int width; public int height; public int is_external_memory; public Anonymous_690ed5ec_4c3d_40c6_9bd0_0747b5a28b54 u; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U4)] public uint[] pad; public IntPtr private_memory; } public enum VP8StatusCode { VP8_STATUS_OK, VP8_STATUS_OUT_OF_MEMORY, VP8_STATUS_INVALID_PARAM, VP8_STATUS_BITSTREAM_ERROR, VP8_STATUS_UNSUPPORTED_FEATURE, VP8_STATUS_SUSPENDED, VP8_STATUS_USER_ABORT, VP8_STATUS_NOT_ENOUGH_DATA } public struct WebPBitstreamFeatures { public int width; public int height; public int has_alpha; public int has_animation; public int format; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.U4)] public uint[] pad; } public struct WebPDecoderOptions { public int bypass_filtering; public int no_fancy_upsampling; public int use_cropping; public int crop_left; public int crop_top; public int crop_width; public int crop_height; public int use_scaling; public int scaled_width; public int scaled_height; public int use_threads; public int dithering_strength; public int flip; public int alpha_dithering_strength; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.U4)] public uint[] pad; } public struct WebPDecoderConfig { public WebPBitstreamFeatures input; public WebPDecBuffer output; public WebPDecoderOptions options; } public struct WebPAnimDecoderOptions { public WEBP_CSP_MODE color_mode; public int use_threads; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7, ArraySubType = UnmanagedType.U4)] public uint[] padding; } public struct WebPAnimInfo { public uint canvas_width; public uint canvas_height; public uint loop_count; public uint bgcolor; public uint frame_count; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U4)] public uint[] pad; } public enum WebPImageHint { WEBP_HINT_DEFAULT, WEBP_HINT_PICTURE, WEBP_HINT_PHOTO, WEBP_HINT_GRAPH, WEBP_HINT_LAST } public struct WebPConfig { public int lossless; public float quality; public int method; public WebPImageHint image_hint; public int target_size; public float target_PSNR; public int segments; public int sns_strength; public int filter_strength; public int filter_sharpness; public int filter_type; public int autofilter; public int alpha_compression; public int alpha_filtering; public int alpha_quality; public int pass; public int show_compressed; public int preprocessing; public int partitions; public int partition_limit; public int emulate_jpeg_size; public int thread_level; public int low_memory; public int near_lossless; public int exact; public int use_delta_palette; public int use_sharp_yuv; public int qmin; public int qmax; } public enum WebPPreset { WEBP_PRESET_DEFAULT, WEBP_PRESET_PICTURE, WEBP_PRESET_PHOTO, WEBP_PRESET_DRAWING, WEBP_PRESET_ICON, WEBP_PRESET_TEXT } public struct WebPAuxStats { public int coded_size; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.R4)] public float[] PSNR; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I4)] public int[] block_count; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I4)] public int[] header_bytes; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12, ArraySubType = UnmanagedType.I4)] public int[] residual_bytes; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)] public int[] segment_size; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)] public int[] segment_quant; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)] public int[] segment_level; public int alpha_data_size; public int layer_data_size; public uint lossless_features; public int histogram_bits; public int transform_bits; public int cache_bits; public int palette_size; public int lossless_size; public int lossless_hdr_size; public int lossless_data_size; public int cross_color_transform_bits; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1, ArraySubType = UnmanagedType.U4)] public uint[] pad; } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int WebPWriterFunction([In] IntPtr data, UIntPtr data_size, ref WebPPicture picture); public struct WebPMemoryWriter { public IntPtr mem; public UIntPtr size; public UIntPtr max_size; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1, ArraySubType = UnmanagedType.U4)] public uint[] pad; } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int WebPProgressHook(int percent, ref WebPPicture picture); public enum WebPEncCSP { WEBP_YUV420 = 0, WEBP_CSP_UV_MASK = 3, WEBP_YUV420A = 4, WEBP_CSP_ALPHA_BIT = 4 } public enum WebPEncodingError { VP8_ENC_OK, VP8_ENC_ERROR_OUT_OF_MEMORY, VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, VP8_ENC_ERROR_NULL_PARAMETER, VP8_ENC_ERROR_INVALID_CONFIGURATION, VP8_ENC_ERROR_BAD_DIMENSION, VP8_ENC_ERROR_PARTITION0_OVERFLOW, VP8_ENC_ERROR_PARTITION_OVERFLOW, VP8_ENC_ERROR_BAD_WRITE, VP8_ENC_ERROR_FILE_TOO_BIG, VP8_ENC_ERROR_USER_ABORT, VP8_ENC_ERROR_LAST } public struct WebPPicture { public int use_argb; public WebPEncCSP colorspace; public int width; public int height; public IntPtr y; public IntPtr u; public IntPtr v; public int y_stride; public int uv_stride; public IntPtr a; public int a_stride; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)] public uint[] pad1; public IntPtr argb; public int argb_stride; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U4)] public uint[] pad2; public WebPWriterFunction writer; public IntPtr custom_ptr; public int extra_info_type; public IntPtr extra_info; public IntPtr stats; public WebPEncodingError error_code; public WebPProgressHook progress_hook; public IntPtr user_data; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U4)] public uint[] pad3; public IntPtr pad4; public IntPtr pad5; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.U4)] public uint[] pad6; public IntPtr memory_; public IntPtr memory_argb_; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.SysUInt)] public IntPtr[] pad7; } [Obsolete("Use NativeLibraryLoader.FixDllNotFoundException instead. Library loading is now automatic.")] public static class LoadLibrary { public static void LoadWebPOrFail() { NativeLibraryLoader.FixDllNotFoundException("webp", () => NativeMethods.WebPGetDecoderVersion()); } [Obsolete] public static bool AutoLoadNearby(string name, bool throwFailure) { LoadWebPOrFail(); return true; } } public struct WebPMuxAnimParams { public uint bgcolor; public int loop_count; } public struct WebPAnimEncoderOptions { public WebPMuxAnimParams anim_params; public int minimize_size; public int kmin; public int kmax; public int allow_mixed; public int verbose; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U4)] public uint[] padding; } public struct WebPData { public IntPtr bytes; public UIntPtr size; } public enum WebPMuxAnimDispose { WEBP_MUX_DISPOSE_NONE, WEBP_MUX_DISPOSE_BACKGROUND } public enum WebPMuxAnimBlend { WEBP_MUX_BLEND, WEBP_MUX_NO_BLEND } [Flags] public enum WebPFeatureFlags : uint { ANIMATION_FLAG = 2u, XMP_FLAG = 4u, EXIF_FLAG = 8u, ALPHA_FLAG = 0x10u, ICCP_FLAG = 0x20u, ALL_VALID_FLAGS = 0x3Eu } }