├── WebPTest ├── WildCherry.png ├── YellowRose.png ├── libwebp_x64.dll ├── libwebp_x86.dll ├── bin │ └── Release │ │ ├── WebPTest.exe │ │ ├── WebPTest.pdb │ │ ├── WildCherry.png │ │ ├── YellowRose.png │ │ ├── libwebp_x64.dll │ │ └── libwebp_x86.dll ├── app.config ├── Properties │ ├── Settings.settings │ ├── Settings.Designer.cs │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ └── Resources.resx ├── Program.cs ├── WebPTest.csproj.user ├── WebPExample.resx ├── WebPTest.csproj ├── WebPExample.Designer.cs ├── WebPExample.cs └── WebPWrapper.cs ├── Compile dll.txt ├── BUILDING.md ├── LICENSE ├── WebPTest.sln └── README.md /WebPTest/WildCherry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/WildCherry.png -------------------------------------------------------------------------------- /WebPTest/YellowRose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/YellowRose.png -------------------------------------------------------------------------------- /WebPTest/libwebp_x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/libwebp_x64.dll -------------------------------------------------------------------------------- /WebPTest/libwebp_x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/libwebp_x86.dll -------------------------------------------------------------------------------- /WebPTest/bin/Release/WebPTest.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/bin/Release/WebPTest.exe -------------------------------------------------------------------------------- /WebPTest/bin/Release/WebPTest.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/bin/Release/WebPTest.pdb -------------------------------------------------------------------------------- /WebPTest/bin/Release/WildCherry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/bin/Release/WildCherry.png -------------------------------------------------------------------------------- /WebPTest/bin/Release/YellowRose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/bin/Release/YellowRose.png -------------------------------------------------------------------------------- /WebPTest/bin/Release/libwebp_x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/bin/Release/libwebp_x64.dll -------------------------------------------------------------------------------- /WebPTest/bin/Release/libwebp_x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePineiro/WebP-wrapper/HEAD/WebPTest/bin/Release/libwebp_x86.dll -------------------------------------------------------------------------------- /WebPTest/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /WebPTest/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WebPTest/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace WebPTest 5 | { 6 | static class Program 7 | { 8 | /// 9 | /// The main entry point for the application. 10 | /// 11 | [STAThread] 12 | static void Main() 13 | { 14 | Application.EnableVisualStyles(); 15 | Application.SetCompatibleTextRenderingDefault(false); 16 | Application.Run(new WebPExample()); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /WebPTest/WebPTest.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | publicar\ 5 | 6 | 7 | 8 | 9 | 10 | es-ES 11 | false 12 | 13 | -------------------------------------------------------------------------------- /Compile dll.txt: -------------------------------------------------------------------------------- 1 | Build instructions for libwebp.dll 2 | ================================== 3 | 4 | Current version : 1.2.1 5 | 6 | Download libwebp-{version}.tar.gz from the downloads list at http://downloads.webmproject.org/releases/webp 7 | and extract its contents. 8 | 9 | Run "x86 Native Tools Command Prompt for VS2019" 10 | 11 | Change to the libwebp-{version} directory, run: 12 | 13 | nmake /f Makefile.vc CFG=release-dynamic RTLIBCFG=static OBJDIR=output 14 | 15 | Run "x64 Native Tools Command Prompt for VS2019" 16 | 17 | Change to the libwebp-{version} directory, run: 18 | 19 | nmake /f Makefile.vc CFG=release-dynamic RTLIBCFG=static OBJDIR=output 20 | 21 | Copy to x86 and x64 directories from /output/bin/ -------------------------------------------------------------------------------- /BUILDING.md: -------------------------------------------------------------------------------- 1 | # Building libwebp as a windows native library (.dll) 2 | 3 | 1. Get the latest [source code release from libwebp repo](https://github.com/webmproject/libwebp/releases). 4 | 2. Extract the archive to a new folder. 5 | 3. Launch `Command Prompt` with `Native Tools Command Prompt` which is come from C++ BuildTools (Get it from ["Tools for Visual Studio" section here](https://visualstudio.microsoft.com/downloads/)). 6 | 4. Change the `Current Directory` to the directory, which you created at Step 2, using this command: 7 | ```batch 8 | cd /d "F:\Path\To\Directory" 9 | ``` 10 | 5. Start compiling the source with nmake: 11 | ```batch 12 | nmake /f Makefile.vc CFG=release-dynamic RTLIBCFG=dynamic OBJDIR=output 13 | ``` 14 | 15 | ## Notes 16 | * Depend on which `Native Tools Command Prompt` (x86 or x64), the compiled binaries will match the architecture with the `Command Prompt`'s environment. 17 | * You **may** need to manually add some directory to `PATH` environment so that the build tool can find the external tools. 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jose M. Piñeiro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /WebPTest/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Este código fue generado por una herramienta. 4 | // Versión de runtime:4.0.30319.42000 5 | // 6 | // Los cambios en este archivo podrían causar un comportamiento incorrecto y se perderán si 7 | // se vuelve a generar el código. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WebPTest.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WebPTest.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.852 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebPTest", "WebPTest\WebPTest.csproj", "{38700B2B-939E-439F-A975-E6FA91703BDB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|x86 = Debug|x86 12 | Release|Any CPU = Release|Any CPU 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {38700B2B-939E-439F-A975-E6FA91703BDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {38700B2B-939E-439F-A975-E6FA91703BDB}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {38700B2B-939E-439F-A975-E6FA91703BDB}.Debug|x86.ActiveCfg = Debug|x86 19 | {38700B2B-939E-439F-A975-E6FA91703BDB}.Debug|x86.Build.0 = Debug|x86 20 | {38700B2B-939E-439F-A975-E6FA91703BDB}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {38700B2B-939E-439F-A975-E6FA91703BDB}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {38700B2B-939E-439F-A975-E6FA91703BDB}.Release|x86.ActiveCfg = Release|x86 23 | {38700B2B-939E-439F-A975-E6FA91703BDB}.Release|x86.Build.0 = Release|x86 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {7BC2E19C-309E-4FD2-AD7A-8DB0B02759C6} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /WebPTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WebPTest")] 9 | [assembly: AssemblyDescription("Demo for WebP Wapper")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Jose M. Piñeiro")] 12 | [assembly: AssemblyProduct("WebPTest")] 13 | [assembly: AssemblyCopyright("© 2012-2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("e404c2ee-f609-411c-b2ba-3598e0f43608")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.1.0")] 36 | [assembly: AssemblyFileVersion("1.0.1.0")] 37 | -------------------------------------------------------------------------------- /WebPTest/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // Este código fue generado por una herramienta. 4 | // Versión de runtime:4.0.30319.42000 5 | // 6 | // Los cambios en este archivo podrían causar un comportamiento incorrecto y se perderán si 7 | // se vuelve a generar el código. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace WebPTest.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// Clase de recurso fuertemente tipado, para buscar cadenas traducidas, etc. 17 | /// 18 | // StronglyTypedResourceBuilder generó automáticamente esta clase 19 | // a través de una herramienta como ResGen o Visual Studio. 20 | // Para agregar o quitar un miembro, edite el archivo .ResX y, a continuación, vuelva a ejecutar ResGen 21 | // con la opción /str o recompile su proyecto de VS. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Devuelve la instancia de ResourceManager almacenada en caché utilizada por esta clase. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WebPTest.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Reemplaza la propiedad CurrentUICulture del subproceso actual para todas las 51 | /// búsquedas de recursos mediante esta clase de recurso fuertemente tipado. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebP-wrapper 2 | Wrapper for libwebp in C#. The most complete wrapper in pure managed C#. 3 | 4 | Exposes Simple Decoding and Encoding API, Advanced Decoding and Encoding API (with statistics of compression), Get version library and WebPGetFeatures (info of any WebP file). Exposed get PSNR, SSIM or LSIM distortion metrics. 5 | 6 | The wrapper is in safe managed code in one class. No need for external dll except libwebp_x86.dll (included v0.4.4) and libwebp_x64.dll (included v1.2.1). The wrapper works in 32, 64 bit or ANY (auto swith to the appropriate library). 7 | 8 | The code is commented and includes simple examples for using the wrapper. 9 | 10 | ## Decompress Functions: 11 | Load WebP image for WebP file 12 | ```C# 13 | using (WebP webp = new WebP()) 14 | Bitmap bmp = webp.Load("test.webp"); 15 | ``` 16 | 17 | Decode WebP filename to bitmap and load in PictureBox container 18 | ```C# 19 | byte[] rawWebP = File.ReadAllBytes("test.webp"); 20 | using (WebP webp = new WebP()) 21 | this.pictureBox.Image = webp.Decode(rawWebP); 22 | ``` 23 | 24 | Advanced decode WebP filename to bitmap and load in PictureBox container 25 | ```C# 26 | byte[] rawWebP = File.ReadAllBytes("test.webp"); 27 | WebPDecoderOptions decoderOptions = new WebPDecoderOptions(); 28 | decoderOptions.use_threads = 1; //Use multhreading 29 | decoderOptions.flip = 1; //Flip the image 30 | using (WebP webp = new WebP()) 31 | this.pictureBox.Image = webp.Decode(rawWebP, decoderOptions); 32 | ``` 33 | 34 | Get thumbnail with 200x150 pixels in fast/low quality mode 35 | ```C# 36 | using (WebP webp = new WebP()) 37 | this.pictureBox.Image = webp.GetThumbnailFast(rawWebP, 200, 150); 38 | ``` 39 | 40 | Get thumbnail with 200x150 pixels in slow/high quality mode 41 | ```C# 42 | using (WebP webp = new WebP()) 43 | this.pictureBox.Image = webp.GetThumbnailQuality(rawWebP, 200, 150); 44 | ``` 45 | 46 | 47 | ## Compress Functions: 48 | Save bitmap to WebP file 49 | ```C# 50 | Bitmap bmp = new Bitmap("test.jpg"); 51 | using (WebP webp = new WebP()) 52 | webp.Save(bmp, 80, "test.webp"); 53 | ``` 54 | 55 | Encode to memory buffer in lossy mode with quality 75 and save to file 56 | ```C# 57 | byte[] rawWebP = File.ReadAllBytes("test.jpg"); 58 | using (WebP webp = new WebP()) 59 | rawWebP = webp.EncodeLossy(bmp, 75); 60 | File.WriteAllBytes("test.webp", rawWebP); 61 | ``` 62 | 63 | Encode to memory buffer in lossy mode with quality 75 and speed 9. Save to file 64 | ```C# 65 | byte[] rawWebP = File.ReadAllBytes("test.jpg"); 66 | using (WebP webp = new WebP()) 67 | rawWebP = webp.EncodeLossy(bmp, 75, 9); 68 | File.WriteAllBytes("test.webp", rawWebP); 69 | ``` 70 | 71 | Encode to memory buffer in lossy mode with quality 75, speed 9 and get information. Save to file 72 | ```C# 73 | byte[] rawWebP = File.ReadAllBytes("test.jpg"); 74 | using (WebP webp = new WebP()) 75 | rawWebP = webp.EncodeLossy(bmp, 75, 9, true); 76 | File.WriteAllBytes("test.webp", rawWebP); 77 | ``` 78 | 79 | Encode to memory buffer in lossless mode and save to file 80 | ```C# 81 | byte[] rawWebP = File.ReadAllBytes("test.jpg"); 82 | using (WebP webp = new WebP()) 83 | rawWebP = webp.EncodeLossless(bmp); 84 | File.WriteAllBytes("test.webp", rawWebP); 85 | ``` 86 | 87 | Encode to memory buffer in lossless mode with speed 9 and save to file 88 | ```C# 89 | byte[] rawWebP = File.ReadAllBytes("test.jpg"); 90 | using (WebP webp = new WebP()) 91 | rawWebP = webp.EncodeLossless(bmp, 9); 92 | File.WriteAllBytes("test.webp", rawWebP); 93 | ``` 94 | 95 | Encode to memory buffer in near lossless mode with quality 40 and speed 9 and save to file 96 | ```C# 97 | byte[] rawWebP = File.ReadAllBytes("test.jpg"); 98 | using (WebP webp = new WebP()) 99 | rawWebP = webp.EncodeNearLossless(bmp, 40, 9); 100 | File.WriteAllBytes("test.webp", rawWebP); 101 | ``` 102 | 103 | ## Another Functions: 104 | Get version of libwebp.dll 105 | ```C# 106 | using (WebP webp = new WebP()) 107 | string version = "libwebp.dll v" + webp.GetVersion(); 108 | ``` 109 | 110 | Get info from WebP file 111 | ```C# 112 | byte[] rawWebp = File.ReadAllBytes(pathFileName); 113 | using (WebP webp = new WebP()) 114 | webp.GetInfo(rawWebp, out width, out height, out has_alpha, out has_animation, out format); 115 | MessageBox.Show("Width: " + width + "\n" + 116 | "Height: " + height + "\n" + 117 | "Has alpha: " + has_alpha + "\n" + 118 | "Is animation: " + has_animation + "\n" + 119 | "Format: " + format); 120 | ``` 121 | 122 | Get PSNR, SSIM or LSIM distortion metric between two pictures 123 | ```C# 124 | int metric = 0; //0 = PSNR, 1= SSIM, 2=LSIM 125 | Bitmap bmp1 = Bitmap.FromFile("image1.png"); 126 | Bitmap bmp2 = Bitmap.FromFile("image2.png"); 127 | using (WebP webp = new WebP()) 128 | result = webp.GetPictureDistortion(source, reference, metric); 129 | MessageBox.Show("Red: " + result[0] + "dB.\nGreen: " + result[1] + "dB.\nBlue: " + result[2] + "dB.\nAlpha: " + result[3] + "dB.\nAll: " + result[4] + "dB.", "PSNR"); 130 | 131 | MessageBox.Show("Red: " + result[0] + dB\n" + 132 | "Green: " + result[1] + "dB\n" + 133 | "Blue: " + result[2] + "dB\n" + 134 | "Alpha: " + result[3] + "dB\n" + 135 | "All: " + result[4] + "dB\n"); 136 | ``` 137 | 138 | 139 | ## Thanks to jzern@google.com 140 | Without their help this wrapper would not have been possible. 141 | -------------------------------------------------------------------------------- /WebPTest/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /WebPTest/WebPExample.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /WebPTest/WebPTest.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | x86 6 | 8.0.30703 7 | 2.0 8 | {38700B2B-939E-439F-A975-E6FA91703BDB} 9 | WinExe 10 | Properties 11 | WebPTest 12 | WebPTest 13 | v4.6.2 14 | 15 | 16 | 512 17 | false 18 | publicar\ 19 | true 20 | Disk 21 | false 22 | Foreground 23 | 7 24 | Days 25 | false 26 | false 27 | true 28 | 4 29 | 1.0.0.%2a 30 | false 31 | true 32 | 33 | 34 | AnyCPU 35 | true 36 | full 37 | false 38 | bin\Debug\ 39 | DEBUG;TRACE 40 | prompt 41 | 4 42 | false 43 | 44 | 45 | x86 46 | pdbonly 47 | true 48 | bin\Release\ 49 | TRACE 50 | prompt 51 | 4 52 | false 53 | true 54 | false 55 | 56 | 57 | true 58 | bin\Debug\ 59 | DEBUG;TRACE 60 | full 61 | AnyCPU 62 | prompt 63 | MinimumRecommendedRules.ruleset 64 | false 65 | 66 | 67 | bin\Release\ 68 | TRACE 69 | true 70 | pdbonly 71 | AnyCPU 72 | prompt 73 | MinimumRecommendedRules.ruleset 74 | false 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Form 88 | 89 | 90 | WebPExample.cs 91 | 92 | 93 | 94 | 95 | WebPExample.cs 96 | 97 | 98 | ResXFileCodeGenerator 99 | Resources.Designer.cs 100 | Designer 101 | 102 | 103 | True 104 | Resources.resx 105 | True 106 | 107 | 108 | 109 | SettingsSingleFileGenerator 110 | Settings.Designer.cs 111 | 112 | 113 | True 114 | Settings.settings 115 | True 116 | 117 | 118 | 119 | 120 | Always 121 | 122 | 123 | Always 124 | 125 | 126 | Always 127 | 128 | 129 | Always 130 | 131 | 132 | 133 | 134 | False 135 | .NET Framework 3.5 SP1 Client Profile 136 | false 137 | 138 | 139 | False 140 | .NET Framework 3.5 SP1 141 | true 142 | 143 | 144 | 145 | 152 | -------------------------------------------------------------------------------- /WebPTest/WebPExample.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace WebPTest 2 | { 3 | partial class WebPExample 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.pictureBox = new System.Windows.Forms.PictureBox(); 32 | this.buttonLoad = new System.Windows.Forms.Button(); 33 | this.buttonSave = new System.Windows.Forms.Button(); 34 | this.buttonInfo = new System.Windows.Forms.Button(); 35 | this.buttonMeasure = new System.Windows.Forms.Button(); 36 | this.buttonThumbnail = new System.Windows.Forms.Button(); 37 | this.buttonCropFlip = new System.Windows.Forms.Button(); 38 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); 39 | this.SuspendLayout(); 40 | // 41 | // pictureBox 42 | // 43 | this.pictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 44 | | System.Windows.Forms.AnchorStyles.Left) 45 | | System.Windows.Forms.AnchorStyles.Right))); 46 | this.pictureBox.Location = new System.Drawing.Point(0, 0); 47 | this.pictureBox.Name = "pictureBox"; 48 | this.pictureBox.Size = new System.Drawing.Size(586, 490); 49 | this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; 50 | this.pictureBox.TabIndex = 0; 51 | this.pictureBox.TabStop = false; 52 | // 53 | // buttonLoad 54 | // 55 | this.buttonLoad.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 56 | this.buttonLoad.Location = new System.Drawing.Point(12, 496); 57 | this.buttonLoad.Name = "buttonLoad"; 58 | this.buttonLoad.Size = new System.Drawing.Size(81, 30); 59 | this.buttonLoad.TabIndex = 1; 60 | this.buttonLoad.Text = "Load image"; 61 | this.buttonLoad.UseVisualStyleBackColor = true; 62 | this.buttonLoad.Click += new System.EventHandler(this.ButtonLoad_Click); 63 | // 64 | // buttonSave 65 | // 66 | this.buttonSave.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 67 | this.buttonSave.Enabled = false; 68 | this.buttonSave.Location = new System.Drawing.Point(99, 496); 69 | this.buttonSave.Name = "buttonSave"; 70 | this.buttonSave.Size = new System.Drawing.Size(81, 30); 71 | this.buttonSave.TabIndex = 2; 72 | this.buttonSave.Text = "Save WEBP"; 73 | this.buttonSave.UseVisualStyleBackColor = true; 74 | this.buttonSave.Click += new System.EventHandler(this.ButtonSave_Click); 75 | // 76 | // buttonInfo 77 | // 78 | this.buttonInfo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 79 | this.buttonInfo.Location = new System.Drawing.Point(493, 496); 80 | this.buttonInfo.Name = "buttonInfo"; 81 | this.buttonInfo.Size = new System.Drawing.Size(81, 30); 82 | this.buttonInfo.TabIndex = 3; 83 | this.buttonInfo.Text = "Info WEBP"; 84 | this.buttonInfo.UseVisualStyleBackColor = true; 85 | this.buttonInfo.Click += new System.EventHandler(this.ButtonInfo_Click); 86 | // 87 | // buttonMeasure 88 | // 89 | this.buttonMeasure.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 90 | this.buttonMeasure.Location = new System.Drawing.Point(394, 496); 91 | this.buttonMeasure.Name = "buttonMeasure"; 92 | this.buttonMeasure.Size = new System.Drawing.Size(93, 30); 93 | this.buttonMeasure.TabIndex = 4; 94 | this.buttonMeasure.Text = "Measure WEBP"; 95 | this.buttonMeasure.UseVisualStyleBackColor = true; 96 | this.buttonMeasure.Click += new System.EventHandler(this.ButtonMeasure_Click); 97 | // 98 | // buttonThumbnail 99 | // 100 | this.buttonThumbnail.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 101 | this.buttonThumbnail.Location = new System.Drawing.Point(288, 496); 102 | this.buttonThumbnail.Name = "buttonThumbnail"; 103 | this.buttonThumbnail.Size = new System.Drawing.Size(100, 30); 104 | this.buttonThumbnail.TabIndex = 5; 105 | this.buttonThumbnail.Text = "Load Thumbnail"; 106 | this.buttonThumbnail.UseVisualStyleBackColor = true; 107 | this.buttonThumbnail.Click += new System.EventHandler(this.ButtonThumbnail_Click); 108 | // 109 | // buttonCropFlip 110 | // 111 | this.buttonCropFlip.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 112 | this.buttonCropFlip.Location = new System.Drawing.Point(186, 496); 113 | this.buttonCropFlip.Name = "buttonCropFlip"; 114 | this.buttonCropFlip.Size = new System.Drawing.Size(96, 30); 115 | this.buttonCropFlip.TabIndex = 6; 116 | this.buttonCropFlip.Text = "Load (Crop && flip)"; 117 | this.buttonCropFlip.UseVisualStyleBackColor = true; 118 | this.buttonCropFlip.Click += new System.EventHandler(this.ButtonCropFlip_Click); 119 | // 120 | // WebPExample 121 | // 122 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 123 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 124 | this.ClientSize = new System.Drawing.Size(586, 538); 125 | this.Controls.Add(this.buttonCropFlip); 126 | this.Controls.Add(this.buttonThumbnail); 127 | this.Controls.Add(this.buttonMeasure); 128 | this.Controls.Add(this.buttonInfo); 129 | this.Controls.Add(this.buttonSave); 130 | this.Controls.Add(this.buttonLoad); 131 | this.Controls.Add(this.pictureBox); 132 | this.Name = "WebPExample"; 133 | this.Text = "WebP test"; 134 | this.Load += new System.EventHandler(this.WebPExample_Load); 135 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); 136 | this.ResumeLayout(false); 137 | 138 | } 139 | 140 | #endregion 141 | 142 | private System.Windows.Forms.PictureBox pictureBox; 143 | private System.Windows.Forms.Button buttonLoad; 144 | private System.Windows.Forms.Button buttonSave; 145 | private System.Windows.Forms.Button buttonInfo; 146 | private System.Windows.Forms.Button buttonMeasure; 147 | private System.Windows.Forms.Button buttonThumbnail; 148 | private System.Windows.Forms.Button buttonCropFlip; 149 | } 150 | } 151 | 152 | -------------------------------------------------------------------------------- /WebPTest/WebPExample.cs: -------------------------------------------------------------------------------- 1 | // clsWebP, by Jose M. Piñeiro 2 | // Website: https://github.com/JosePineiro/WebP-wapper 3 | // Version: 1.0.0.9 (May 23, 2020) 4 | 5 | using System; 6 | using System.Drawing; 7 | using System.IO; 8 | using System.Windows.Forms; 9 | using WebPWrapper; 10 | 11 | 12 | namespace WebPTest 13 | { 14 | public partial class WebPExample : Form 15 | { 16 | #region | Constructors | 17 | public WebPExample() 18 | { 19 | InitializeComponent(); 20 | } 21 | 22 | private void WebPExample_Load(object sender, EventArgs e) 23 | { 24 | try 25 | { 26 | //Inform of execution mode 27 | if (IntPtr.Size == 8) 28 | this.Text = Application.ProductName + " x64 v" + Application.ProductVersion; 29 | else 30 | this.Text = Application.ProductName + " x86 v" + Application.ProductVersion; 31 | 32 | //Inform of libWebP version 33 | using (WebP webp = new WebP()) 34 | this.Text += " (libwebp v" + webp.GetVersion() + ")"; 35 | } 36 | catch (Exception ex) 37 | { 38 | MessageBox.Show(ex.Message + "\r\nIn WebPExample.WebPExample_Load", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 39 | } 40 | } 41 | #endregion 42 | 43 | #region << Events >> 44 | /// 45 | /// Test for load from file function 46 | /// 47 | private void ButtonLoad_Click(object sender, EventArgs e) 48 | { 49 | try 50 | { 51 | using (OpenFileDialog openFileDialog = new OpenFileDialog()) 52 | { 53 | openFileDialog.Filter = "Image files (*.webp, *.png, *.tif, *.tiff)|*.webp;*.png;*.tif;*.tiff"; 54 | openFileDialog.FileName = ""; 55 | if (openFileDialog.ShowDialog() == DialogResult.OK) 56 | { 57 | this.buttonSave.Enabled = true; 58 | this.buttonSave.Enabled = true; 59 | string pathFileName = openFileDialog.FileName; 60 | 61 | if (Path.GetExtension(pathFileName) == ".webp") 62 | { 63 | using (WebP webp = new WebP()) 64 | pictureBox.Image = webp.Load(pathFileName); 65 | } 66 | else 67 | pictureBox.Image = Image.FromFile(pathFileName); 68 | } 69 | } 70 | } 71 | catch (Exception ex) 72 | { 73 | MessageBox.Show(ex.Message + "\r\nIn WebPExample.buttonLoad_Click", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 74 | } 75 | } 76 | 77 | /// 78 | /// Test for load thumbnail function 79 | /// 80 | private void ButtonThumbnail_Click(object sender, EventArgs e) 81 | { 82 | try 83 | { 84 | using (OpenFileDialog openFileDialog = new OpenFileDialog()) 85 | { 86 | openFileDialog.Filter = "WebP files (*.webp)|*.webp"; 87 | openFileDialog.FileName = ""; 88 | if (openFileDialog.ShowDialog() == DialogResult.OK) 89 | { 90 | string pathFileName = openFileDialog.FileName; 91 | 92 | byte[] rawWebP = File.ReadAllBytes(pathFileName); 93 | using (WebP webp = new WebP()) 94 | this.pictureBox.Image = webp.GetThumbnailQuality(rawWebP, 200, 150); 95 | } 96 | } 97 | } 98 | catch (Exception ex) 99 | { 100 | MessageBox.Show(ex.Message + "\r\nIn WebPExample.buttonThumbnail_Click", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 101 | } 102 | } 103 | 104 | /// 105 | /// Test for advanced decode function 106 | /// 107 | private void ButtonCropFlip_Click(object sender, EventArgs e) 108 | { 109 | try 110 | { 111 | using (OpenFileDialog openFileDialog = new OpenFileDialog()) 112 | { 113 | openFileDialog.Filter = "WebP files (*.webp)|*.webp"; 114 | openFileDialog.FileName = ""; 115 | if (openFileDialog.ShowDialog() == DialogResult.OK) 116 | { 117 | string pathFileName = openFileDialog.FileName; 118 | 119 | byte[] rawWebP = File.ReadAllBytes(pathFileName); 120 | WebPDecoderOptions decoderOptions = new WebPDecoderOptions 121 | { 122 | use_cropping = 1, 123 | crop_top = 10, //Top beginning of crop area 124 | crop_left = 10, //Left beginning of crop area 125 | crop_height = 250, //Height of crop area 126 | crop_width = 300, //Width of crop area 127 | use_threads = 1, //Use multi-threading 128 | flip = 1 //Flip the image 129 | }; 130 | using (WebP webp = new WebP()) 131 | this.pictureBox.Image = webp.Decode(rawWebP, decoderOptions); 132 | } 133 | } 134 | } 135 | catch (Exception ex) 136 | { 137 | MessageBox.Show(ex.Message + "\r\nIn WebPExample.buttonCrop_Click", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 138 | } 139 | } 140 | 141 | /// 142 | /// Test encode functions 143 | /// 144 | private void ButtonSave_Click(object sender, EventArgs e) 145 | { 146 | Control.CheckForIllegalCrossThreadCalls = false; 147 | byte[] rawWebP; 148 | 149 | try 150 | { 151 | if (this.pictureBox.Image == null) 152 | MessageBox.Show("Please, load an image first"); 153 | 154 | //get the picture box image 155 | Bitmap bmp = (Bitmap)pictureBox.Image; 156 | 157 | //Test simple encode in lossly mode in memory with quality 75 158 | string lossyFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SimpleLossy.webp"); 159 | using (WebP webp = new WebP()) 160 | rawWebP = webp.EncodeLossy(bmp, 75); 161 | File.WriteAllBytes(lossyFileName, rawWebP); 162 | MessageBox.Show("Made " + lossyFileName, "Simple lossy"); 163 | 164 | //Test simple encode in lossless mode in memory 165 | string simpleLosslessFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SimpleLossless.webp"); 166 | using (WebP webp = new WebP()) 167 | rawWebP = webp.EncodeLossless(bmp); 168 | File.WriteAllBytes(simpleLosslessFileName, rawWebP); 169 | MessageBox.Show("Made " + simpleLosslessFileName, "Simple lossless"); 170 | 171 | //Test encode in lossly mode in memory with quality 75 and speed 9 172 | string advanceLossyFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AdvanceLossy.webp"); 173 | using (WebP webp = new WebP()) 174 | rawWebP = webp.EncodeLossy(bmp, 71, 9, true); 175 | File.WriteAllBytes(advanceLossyFileName, rawWebP); 176 | MessageBox.Show("Made " + advanceLossyFileName, "Advance lossy"); 177 | 178 | //Test advance encode lossless mode in memory with speed 9 179 | string losslessFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AdvanceLossless.webp"); 180 | using (WebP webp = new WebP()) 181 | rawWebP = webp.EncodeLossless(bmp, 9); 182 | File.WriteAllBytes(losslessFileName, rawWebP); 183 | MessageBox.Show("Made " + losslessFileName, "Advance lossless"); 184 | 185 | //Test encode near lossless mode in memory with quality 40 and speed 9 186 | // quality 100: No-loss (bit-stream same as -lossless). 187 | // quality 80: Very very high PSNR (around 54dB) and gets an additional 5-10% size reduction over WebP-lossless image. 188 | // quality 60: Very high PSNR (around 48dB) and gets an additional 20%-25% size reduction over WebP-lossless image. 189 | // quality 40: High PSNR (around 42dB) and gets an additional 30-35% size reduction over WebP-lossless image. 190 | // quality 20 (and below): Moderate PSNR (around 36dB) and gets an additional 40-50% size reduction over WebP-lossless image. 191 | string nearLosslessFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NearLossless.webp"); 192 | using (WebP webp = new WebP()) 193 | rawWebP = webp.EncodeNearLossless(bmp, 40, 9); 194 | File.WriteAllBytes(nearLosslessFileName, rawWebP); 195 | MessageBox.Show("Made " + nearLosslessFileName, "Near lossless"); 196 | 197 | MessageBox.Show("End of Test"); 198 | } 199 | catch (Exception ex) 200 | { 201 | MessageBox.Show(ex.Message + "\r\nIn WebPExample.buttonSave_Click", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 202 | } 203 | } 204 | 205 | /// 206 | /// Test GetPictureDistortion function 207 | /// 208 | private void ButtonMeasure_Click(object sender, EventArgs e) 209 | { 210 | try 211 | { 212 | if (this.pictureBox.Image == null) 213 | MessageBox.Show("Please, load an reference image first"); 214 | 215 | using (OpenFileDialog openFileDialog = new OpenFileDialog()) 216 | { 217 | openFileDialog.Filter = "WebP images (*.webp)|*.webp"; 218 | openFileDialog.FileName = ""; 219 | if (openFileDialog.ShowDialog() == DialogResult.OK) 220 | { 221 | Bitmap source; 222 | Bitmap reference; 223 | float[] result; 224 | 225 | //Load Bitmaps 226 | source = (Bitmap)this.pictureBox.Image; 227 | using (WebP webp = new WebP()) 228 | reference = webp.Load(openFileDialog.FileName); 229 | 230 | //Measure PSNR 231 | using (WebP webp = new WebP()) 232 | result = webp.GetPictureDistortion(source, reference, 0); 233 | MessageBox.Show("Red: " + result[0] + "dB.\nGreen: " + result[1] + "dB.\nBlue: " + result[2] + "dB.\nAlpha: " + result[3] + "dB.\nAll: " + result[4] + "dB.", "PSNR"); 234 | 235 | //Measure SSIM 236 | using (WebP webp = new WebP()) 237 | result = webp.GetPictureDistortion(source, reference, 1); 238 | MessageBox.Show("Red: " + result[0] + "dB.\nGreen: " + result[1] + "dB.\nBlue: " + result[2] + "dB.\nAlpha: " + result[3] + "dB.\nAll: " + result[4] + "dB.", "SSIM"); 239 | 240 | //Measure LSIM 241 | using (WebP webp = new WebP()) 242 | result = webp.GetPictureDistortion(source, reference, 2); 243 | MessageBox.Show("Red: " + result[0] + "dB.\nGreen: " + result[1] + "dB.\nBlue: " + result[2] + "dB.\nAlpha: " + result[3] + "dB.\nAll: " + result[4] + "dB.", "LSIM"); 244 | } 245 | } 246 | } 247 | catch (Exception ex) 248 | { 249 | MessageBox.Show(ex.Message + "\r\nIn WebPExample.buttonMeasure_Click", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 250 | } 251 | } 252 | 253 | /// 254 | /// Test GetInfo function 255 | /// 256 | private void ButtonInfo_Click(object sender, EventArgs e) 257 | { 258 | int width; 259 | int height; 260 | bool has_alpha; 261 | bool has_animation; 262 | string format; 263 | 264 | try 265 | { 266 | using (OpenFileDialog openFileDialog = new OpenFileDialog()) 267 | { 268 | openFileDialog.Filter = "WebP images (*.webp)|*.webp"; 269 | openFileDialog.FileName = ""; 270 | if (openFileDialog.ShowDialog() == DialogResult.OK) 271 | { 272 | string pathFileName = openFileDialog.FileName; 273 | 274 | byte[] rawWebp = File.ReadAllBytes(pathFileName); 275 | using (WebP webp = new WebP()) 276 | webp.GetInfo(rawWebp, out width, out height, out has_alpha, out has_animation, out format); 277 | MessageBox.Show("Width: " + width + "\n" + 278 | "Height: " + height + "\n" + 279 | "Has alpha: " + has_alpha + "\n" + 280 | "Is animation: " + has_animation + "\n" + 281 | "Format: " + format, "Information"); 282 | } 283 | } 284 | } 285 | catch (Exception ex) 286 | { 287 | MessageBox.Show(ex.Message + "\r\nIn WebPExample.buttonInfo_Click", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); 288 | } 289 | } 290 | #endregion 291 | } 292 | } -------------------------------------------------------------------------------- /WebPTest/WebPWrapper.cs: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 2 | /// Wrapper for WebP format in C#. (MIT) Jose M. Piñeiro 3 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 4 | /// Decode Functions: 5 | /// Bitmap Load(string pathFileName) - Load a WebP file in bitmap. 6 | /// Bitmap Decode(byte[] rawWebP) - Decode WebP data (rawWebP) to bitmap. 7 | /// Bitmap Decode(byte[] rawWebP, WebPDecoderOptions options) - Decode WebP data (rawWebP) to bitmap using 'options'. 8 | /// Bitmap GetThumbnailFast(byte[] rawWebP, int width, int height) - Get a thumbnail from WebP data (rawWebP) with dimensions 'width x height'. Fast mode. 9 | /// Bitmap GetThumbnailQuality(byte[] rawWebP, int width, int height) - Fast get a thumbnail from WebP data (rawWebP) with dimensions 'width x height'. Quality mode. 10 | /// 11 | /// Encode Functions: 12 | /// Save(Bitmap bmp, string pathFileName, int quality) - Save bitmap with quality lost to WebP file. Opcionally select 'quality'. 13 | /// byte[] EncodeLossy(Bitmap bmp, int quality) - Encode bitmap with quality lost to WebP byte array. Opcionally select 'quality'. 14 | /// byte[] EncodeLossy(Bitmap bmp, int quality, int speed, bool info) - Encode bitmap with quality lost to WebP byte array. Select 'quality', 'speed' and optionally select 'info'. 15 | /// byte[] EncodeLossless(Bitmap bmp) - Encode bitmap without quality lost to WebP byte array. 16 | /// byte[] EncodeLossless(Bitmap bmp, int speed, bool info = false) - Encode bitmap without quality lost to WebP byte array. Select 'speed'. 17 | /// byte[] EncodeNearLossless(Bitmap bmp, int quality, int speed = 9, bool info = false) - Encode bitmap with a near lossless method to WebP byte array. Select 'quality', 'speed' and optionally select 'info'. 18 | /// 19 | /// Another functions: 20 | /// string GetVersion() - Get the library version 21 | /// GetInfo(byte[] rawWebP, out int width, out int height, out bool has_alpha, out bool has_animation, out string format) - Get information of WEBP data 22 | /// float[] PictureDistortion(Bitmap source, Bitmap reference, int metric_type) - Get PSNR, SSIM or LSIM distortion metric between two pictures 23 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | using System; 25 | using System.Drawing; 26 | using System.Drawing.Imaging; 27 | using System.IO; 28 | using System.Runtime.InteropServices; 29 | using System.Security; 30 | using System.Windows.Forms; 31 | 32 | namespace WebPWrapper 33 | { 34 | public sealed class WebP : IDisposable 35 | { 36 | private const int WEBP_MAX_DIMENSION = 16383; 37 | private UnsafeNativeMethods.WebPMemoryWrite _myWriterDelegate; 38 | 39 | #region | Public Decode Functions | 40 | /// Read a WebP file 41 | /// WebP file to load 42 | /// Bitmap with the WebP image 43 | public Bitmap Load(string pathFileName) 44 | { 45 | try 46 | { 47 | byte[] rawWebP = File.ReadAllBytes(pathFileName); 48 | 49 | return Decode(rawWebP); 50 | } 51 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.Load"); } 52 | } 53 | 54 | /// Decode a WebP image 55 | /// The data to uncompress 56 | /// Bitmap with the WebP image 57 | public Bitmap Decode(byte[] rawWebP) 58 | { 59 | Bitmap bmp = null; 60 | BitmapData bmpData = null; 61 | GCHandle pinnedWebP = GCHandle.Alloc(rawWebP, GCHandleType.Pinned); 62 | 63 | try 64 | { 65 | //Get image width and height 66 | GetInfo(rawWebP, out int imgWidth, out int imgHeight, out bool hasAlpha, out bool hasAnimation, out string format); 67 | 68 | //Create a BitmapData and Lock all pixels to be written 69 | if (hasAlpha) 70 | bmp = new Bitmap(imgWidth, imgHeight, PixelFormat.Format32bppArgb); 71 | else 72 | bmp = new Bitmap(imgWidth, imgHeight, PixelFormat.Format24bppRgb); 73 | bmpData = bmp.LockBits(new Rectangle(0, 0, imgWidth, imgHeight), ImageLockMode.WriteOnly, bmp.PixelFormat); 74 | 75 | //Uncompress the image 76 | int outputSize = bmpData.Stride * imgHeight; 77 | IntPtr ptrData = pinnedWebP.AddrOfPinnedObject(); 78 | if (bmp.PixelFormat == PixelFormat.Format24bppRgb) 79 | UnsafeNativeMethods.WebPDecodeBGRInto(ptrData, rawWebP.Length, bmpData.Scan0, outputSize, bmpData.Stride); 80 | else 81 | UnsafeNativeMethods.WebPDecodeBGRAInto(ptrData, rawWebP.Length, bmpData.Scan0, outputSize, bmpData.Stride); 82 | 83 | return bmp; 84 | } 85 | catch (Exception) { throw; } 86 | finally 87 | { 88 | //Unlock the pixels 89 | if (bmpData != null) 90 | bmp.UnlockBits(bmpData); 91 | 92 | //Free memory 93 | if (pinnedWebP.IsAllocated) 94 | pinnedWebP.Free(); 95 | } 96 | } 97 | 98 | /// Decode a WebP image 99 | /// the data to uncompress 100 | /// Options for advanced decode 101 | /// Bitmap with the WebP image 102 | public Bitmap Decode(byte[] rawWebP, WebPDecoderOptions options, PixelFormat pixelFormat = PixelFormat.DontCare) 103 | { 104 | GCHandle pinnedWebP = GCHandle.Alloc(rawWebP, GCHandleType.Pinned); 105 | Bitmap bmp = null; 106 | BitmapData bmpData = null; 107 | VP8StatusCode result; 108 | try 109 | { 110 | WebPDecoderConfig config = new WebPDecoderConfig(); 111 | if (UnsafeNativeMethods.WebPInitDecoderConfig(ref config) == 0) 112 | { 113 | throw new Exception("WebPInitDecoderConfig failed. Wrong version?"); 114 | } 115 | // Read the .webp input file information 116 | IntPtr ptrRawWebP = pinnedWebP.AddrOfPinnedObject(); 117 | int height; 118 | int width; 119 | if (options.use_scaling == 0) 120 | { 121 | result = UnsafeNativeMethods.WebPGetFeatures(ptrRawWebP, rawWebP.Length, ref config.input); 122 | if (result != VP8StatusCode.VP8_STATUS_OK) 123 | throw new Exception("Failed WebPGetFeatures with error " + result); 124 | 125 | //Test cropping values 126 | if (options.use_cropping == 1) 127 | { 128 | if (options.crop_left + options.crop_width > config.input.Width || options.crop_top + options.crop_height > config.input.Height) 129 | throw new Exception("Crop options exceeded WebP image dimensions"); 130 | width = options.crop_width; 131 | height = options.crop_height; 132 | } 133 | } 134 | else 135 | { 136 | width = options.scaled_width; 137 | height = options.scaled_height; 138 | } 139 | 140 | config.options.bypass_filtering = options.bypass_filtering; 141 | config.options.no_fancy_upsampling = options.no_fancy_upsampling; 142 | config.options.use_cropping = options.use_cropping; 143 | config.options.crop_left = options.crop_left; 144 | config.options.crop_top = options.crop_top; 145 | config.options.crop_width = options.crop_width; 146 | config.options.crop_height = options.crop_height; 147 | config.options.use_scaling = options.use_scaling; 148 | config.options.scaled_width = options.scaled_width; 149 | config.options.scaled_height = options.scaled_height; 150 | config.options.use_threads = options.use_threads; 151 | config.options.dithering_strength = options.dithering_strength; 152 | config.options.flip = options.flip; 153 | config.options.alpha_dithering_strength = options.alpha_dithering_strength; 154 | 155 | //Create a BitmapData and Lock all pixels to be written 156 | if (config.input.Has_alpha == 1) 157 | { 158 | config.output.colorspace = WEBP_CSP_MODE.MODE_bgrA; 159 | bmp = new Bitmap(config.input.Width, config.input.Height, PixelFormat.Format32bppArgb); 160 | } 161 | else 162 | { 163 | config.output.colorspace = WEBP_CSP_MODE.MODE_BGR; 164 | bmp = new Bitmap(config.input.Width, config.input.Height, PixelFormat.Format24bppRgb); 165 | } 166 | bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat); 167 | 168 | // Specify the output format 169 | config.output.u.RGBA.rgba = bmpData.Scan0; 170 | config.output.u.RGBA.stride = bmpData.Stride; 171 | config.output.u.RGBA.size = (UIntPtr)(bmp.Height * bmpData.Stride); 172 | config.output.height = bmp.Height; 173 | config.output.width = bmp.Width; 174 | config.output.is_external_memory = 1; 175 | 176 | // Decode 177 | result = UnsafeNativeMethods.WebPDecode(ptrRawWebP, rawWebP.Length, ref config); 178 | if (result != VP8StatusCode.VP8_STATUS_OK) 179 | { 180 | throw new Exception("Failed WebPDecode with error " + result); 181 | } 182 | UnsafeNativeMethods.WebPFreeDecBuffer(ref config.output); 183 | 184 | return bmp; 185 | } 186 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.Decode"); } 187 | finally 188 | { 189 | //Unlock the pixels 190 | if (bmpData != null) 191 | bmp.UnlockBits(bmpData); 192 | 193 | //Free memory 194 | if (pinnedWebP.IsAllocated) 195 | pinnedWebP.Free(); 196 | } 197 | } 198 | 199 | /// Get Thumbnail from webP in mode faster/low quality 200 | /// The data to uncompress 201 | /// Wanted width of thumbnail 202 | /// Wanted height of thumbnail 203 | /// Bitmap with the WebP thumbnail in 24bpp 204 | public Bitmap GetThumbnailFast(byte[] rawWebP, int width, int height) 205 | { 206 | GCHandle pinnedWebP = GCHandle.Alloc(rawWebP, GCHandleType.Pinned); 207 | Bitmap bmp = null; 208 | BitmapData bmpData = null; 209 | 210 | try 211 | { 212 | WebPDecoderConfig config = new WebPDecoderConfig(); 213 | if (UnsafeNativeMethods.WebPInitDecoderConfig(ref config) == 0) 214 | throw new Exception("WebPInitDecoderConfig failed. Wrong version?"); 215 | 216 | // Set up decode options 217 | config.options.bypass_filtering = 1; 218 | config.options.no_fancy_upsampling = 1; 219 | config.options.use_threads = 1; 220 | config.options.use_scaling = 1; 221 | config.options.scaled_width = width; 222 | config.options.scaled_height = height; 223 | 224 | // Create a BitmapData and Lock all pixels to be written 225 | bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); 226 | bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat); 227 | 228 | // Specify the output format 229 | config.output.colorspace = WEBP_CSP_MODE.MODE_BGR; 230 | config.output.u.RGBA.rgba = bmpData.Scan0; 231 | config.output.u.RGBA.stride = bmpData.Stride; 232 | config.output.u.RGBA.size = (UIntPtr)(height * bmpData.Stride); 233 | config.output.height = height; 234 | config.output.width = width; 235 | config.output.is_external_memory = 1; 236 | 237 | // Decode 238 | IntPtr ptrRawWebP = pinnedWebP.AddrOfPinnedObject(); 239 | VP8StatusCode result = UnsafeNativeMethods.WebPDecode(ptrRawWebP, rawWebP.Length, ref config); 240 | if (result != VP8StatusCode.VP8_STATUS_OK) 241 | throw new Exception("Failed WebPDecode with error " + result); 242 | 243 | UnsafeNativeMethods.WebPFreeDecBuffer(ref config.output); 244 | 245 | return bmp; 246 | } 247 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.Thumbnail"); } 248 | finally 249 | { 250 | //Unlock the pixels 251 | if (bmpData != null) 252 | bmp.UnlockBits(bmpData); 253 | 254 | //Free memory 255 | if (pinnedWebP.IsAllocated) 256 | pinnedWebP.Free(); 257 | } 258 | } 259 | 260 | /// Thumbnail from webP in mode slow/high quality 261 | /// The data to uncompress 262 | /// Wanted width of thumbnail 263 | /// Wanted height of thumbnail 264 | /// Bitmap with the WebP thumbnail 265 | public Bitmap GetThumbnailQuality(byte[] rawWebP, int width, int height) 266 | { 267 | GCHandle pinnedWebP = GCHandle.Alloc(rawWebP, GCHandleType.Pinned); 268 | Bitmap bmp = null; 269 | BitmapData bmpData = null; 270 | 271 | try 272 | { 273 | WebPDecoderConfig config = new WebPDecoderConfig(); 274 | if (UnsafeNativeMethods.WebPInitDecoderConfig(ref config) == 0) 275 | throw new Exception("WebPInitDecoderConfig failed. Wrong version?"); 276 | 277 | IntPtr ptrRawWebP = pinnedWebP.AddrOfPinnedObject(); 278 | VP8StatusCode result = UnsafeNativeMethods.WebPGetFeatures(ptrRawWebP, rawWebP.Length, ref config.input); 279 | if (result != VP8StatusCode.VP8_STATUS_OK) 280 | throw new Exception("Failed WebPGetFeatures with error " + result); 281 | 282 | // Set up decode options 283 | config.options.bypass_filtering = 0; 284 | config.options.no_fancy_upsampling = 0; 285 | config.options.use_threads = 1; 286 | config.options.use_scaling = 1; 287 | config.options.scaled_width = width; 288 | config.options.scaled_height = height; 289 | 290 | //Create a BitmapData and Lock all pixels to be written 291 | if (config.input.Has_alpha == 1) 292 | { 293 | config.output.colorspace = WEBP_CSP_MODE.MODE_bgrA; 294 | bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb); 295 | } 296 | else 297 | { 298 | config.output.colorspace = WEBP_CSP_MODE.MODE_BGR; 299 | bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); 300 | } 301 | bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat); 302 | 303 | // Specify the output format 304 | config.output.u.RGBA.rgba = bmpData.Scan0; 305 | config.output.u.RGBA.stride = bmpData.Stride; 306 | config.output.u.RGBA.size = (UIntPtr)(height * bmpData.Stride); 307 | config.output.height = height; 308 | config.output.width = width; 309 | config.output.is_external_memory = 1; 310 | 311 | // Decode 312 | result = UnsafeNativeMethods.WebPDecode(ptrRawWebP, rawWebP.Length, ref config); 313 | if (result != VP8StatusCode.VP8_STATUS_OK) 314 | throw new Exception("Failed WebPDecode with error " + result); 315 | 316 | UnsafeNativeMethods.WebPFreeDecBuffer(ref config.output); 317 | 318 | return bmp; 319 | } 320 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.Thumbnail"); } 321 | finally 322 | { 323 | //Unlock the pixels 324 | if (bmpData != null) 325 | bmp.UnlockBits(bmpData); 326 | 327 | //Free memory 328 | if (pinnedWebP.IsAllocated) 329 | pinnedWebP.Free(); 330 | } 331 | } 332 | #endregion 333 | 334 | #region | Public Encode Functions | 335 | /// Save bitmap to file in WebP format 336 | /// Bitmap with the WebP image 337 | /// The file to write 338 | /// Between 0 (lower quality, lowest file size) and 100 (highest quality, higher file size) 339 | public void Save(Bitmap bmp, string pathFileName, int quality = 75) 340 | { 341 | byte[] rawWebP; 342 | 343 | try 344 | { 345 | //Encode in webP format 346 | rawWebP = EncodeLossy(bmp, quality); 347 | 348 | //Write webP file 349 | File.WriteAllBytes(pathFileName, rawWebP); 350 | } 351 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.Save"); } 352 | } 353 | 354 | /// Lossy encoding bitmap to WebP (Simple encoding API) 355 | /// Bitmap with the image 356 | /// Between 0 (lower quality, lowest file size) and 100 (highest quality, higher file size) 357 | /// Compressed data 358 | public byte[] EncodeLossy(Bitmap bmp, int quality = 75) 359 | { 360 | //test bmp 361 | if (bmp.Width == 0 || bmp.Height == 0) 362 | throw new ArgumentException("Bitmap contains no data.", "bmp"); 363 | if (bmp.Width > WEBP_MAX_DIMENSION || bmp.Height > WEBP_MAX_DIMENSION) 364 | throw new NotSupportedException("Bitmap's dimension is too large. Max is " + WEBP_MAX_DIMENSION + "x" + WEBP_MAX_DIMENSION + " pixels."); 365 | if (bmp.PixelFormat != PixelFormat.Format24bppRgb && bmp.PixelFormat != PixelFormat.Format32bppArgb) 366 | throw new NotSupportedException("Only support Format24bppRgb and Format32bppArgb pixelFormat."); 367 | 368 | BitmapData bmpData = null; 369 | IntPtr unmanagedData = IntPtr.Zero; 370 | 371 | try 372 | { 373 | int size; 374 | 375 | //Get bmp data 376 | bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); 377 | 378 | //Compress the bmp data 379 | if (bmp.PixelFormat == PixelFormat.Format24bppRgb) 380 | size = UnsafeNativeMethods.WebPEncodeBGR(bmpData.Scan0, bmp.Width, bmp.Height, bmpData.Stride, quality, out unmanagedData); 381 | else 382 | size = UnsafeNativeMethods.WebPEncodeBGRA(bmpData.Scan0, bmp.Width, bmp.Height, bmpData.Stride, quality, out unmanagedData); 383 | if (size == 0) 384 | throw new Exception("Can´t encode WebP"); 385 | 386 | //Copy image compress data to output array 387 | byte[] rawWebP = new byte[size]; 388 | Marshal.Copy(unmanagedData, rawWebP, 0, size); 389 | 390 | return rawWebP; 391 | } 392 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.EncodeLossly"); } 393 | finally 394 | { 395 | //Unlock the pixels 396 | if (bmpData != null) 397 | bmp.UnlockBits(bmpData); 398 | 399 | //Free memory 400 | if (unmanagedData != IntPtr.Zero) 401 | UnsafeNativeMethods.WebPFree(unmanagedData); 402 | } 403 | } 404 | 405 | /// Lossy encoding bitmap to WebP (Advanced encoding API) 406 | /// Bitmap with the image 407 | /// Between 0 (lower quality, lowest file size) and 100 (highest quality, higher file size) 408 | /// Between 0 (fastest, lowest compression) and 9 (slower, best compression) 409 | /// Compressed data 410 | public byte[] EncodeLossy(Bitmap bmp, int quality, int speed, bool info = false) 411 | { 412 | //Initialize configuration structure 413 | WebPConfig config = new WebPConfig(); 414 | 415 | //Set compression parameters 416 | if (UnsafeNativeMethods.WebPConfigInit(ref config, WebPPreset.WEBP_PRESET_DEFAULT, 75) == 0) 417 | throw new Exception("Can´t configure preset"); 418 | 419 | // Add additional tuning: 420 | config.method = speed; 421 | if (config.method > 6) 422 | config.method = 6; 423 | config.quality = quality; 424 | config.autofilter = 1; 425 | config.pass = speed + 1; 426 | config.segments = 4; 427 | config.partitions = 3; 428 | config.thread_level = 1; 429 | config.alpha_quality = quality; 430 | config.alpha_filtering = 2; 431 | config.use_sharp_yuv = 1; 432 | 433 | if (UnsafeNativeMethods.WebPGetDecoderVersion() > 1082) //Old version does not support preprocessing 4 434 | { 435 | config.preprocessing = 4; 436 | config.use_sharp_yuv = 1; 437 | } 438 | else 439 | config.preprocessing = 3; 440 | 441 | return AdvancedEncode(bmp, config, info); 442 | } 443 | 444 | /// Lossless encoding bitmap to WebP (Simple encoding API) 445 | /// Bitmap with the image 446 | /// Compressed data 447 | public byte[] EncodeLossless(Bitmap bmp) 448 | { 449 | //test bmp 450 | if (bmp.Width == 0 || bmp.Height == 0) 451 | throw new ArgumentException("Bitmap contains no data.", "bmp"); 452 | if (bmp.Width > WEBP_MAX_DIMENSION || bmp.Height > WEBP_MAX_DIMENSION) 453 | throw new NotSupportedException("Bitmap's dimension is too large. Max is " + WEBP_MAX_DIMENSION + "x" + WEBP_MAX_DIMENSION + " pixels."); 454 | if (bmp.PixelFormat != PixelFormat.Format24bppRgb && bmp.PixelFormat != PixelFormat.Format32bppArgb) 455 | throw new NotSupportedException("Only support Format24bppRgb and Format32bppArgb pixelFormat."); 456 | 457 | BitmapData bmpData = null; 458 | IntPtr unmanagedData = IntPtr.Zero; 459 | try 460 | { 461 | //Get bmp data 462 | bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); 463 | 464 | //Compress the bmp data 465 | int size; 466 | if (bmp.PixelFormat == PixelFormat.Format24bppRgb) 467 | size = UnsafeNativeMethods.WebPEncodeLosslessBGR(bmpData.Scan0, bmp.Width, bmp.Height, bmpData.Stride, out unmanagedData); 468 | else 469 | size = UnsafeNativeMethods.WebPEncodeLosslessBGRA(bmpData.Scan0, bmp.Width, bmp.Height, bmpData.Stride, out unmanagedData); 470 | 471 | //Copy image compress data to output array 472 | byte[] rawWebP = new byte[size]; 473 | Marshal.Copy(unmanagedData, rawWebP, 0, size); 474 | 475 | return rawWebP; 476 | } 477 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.EncodeLossless (Simple)"); } 478 | finally 479 | { 480 | //Unlock the pixels 481 | if (bmpData != null) 482 | bmp.UnlockBits(bmpData); 483 | 484 | //Free memory 485 | if (unmanagedData != IntPtr.Zero) 486 | UnsafeNativeMethods.WebPFree(unmanagedData); 487 | } 488 | } 489 | 490 | /// Lossless encoding image in bitmap (Advanced encoding API) 491 | /// Bitmap with the image 492 | /// Between 0 (fastest, lowest compression) and 9 (slower, best compression) 493 | /// Compressed data 494 | public byte[] EncodeLossless(Bitmap bmp, int speed) 495 | { 496 | //Initialize configuration structure 497 | WebPConfig config = new WebPConfig(); 498 | 499 | //Set compression parameters 500 | if (UnsafeNativeMethods.WebPConfigInit(ref config, WebPPreset.WEBP_PRESET_DEFAULT, (speed + 1) * 10) == 0) 501 | throw new Exception("Can´t config preset"); 502 | 503 | //Old version of DLL does not support info and WebPConfigLosslessPreset 504 | if (UnsafeNativeMethods.WebPGetDecoderVersion() > 1082) 505 | { 506 | if (UnsafeNativeMethods.WebPConfigLosslessPreset(ref config, speed) == 0) 507 | throw new Exception("Can´t configure lossless preset"); 508 | } 509 | else 510 | { 511 | config.lossless = 1; 512 | config.method = speed; 513 | if (config.method > 6) 514 | config.method = 6; 515 | config.quality = (speed + 1) * 10; 516 | } 517 | config.pass = speed + 1; 518 | config.thread_level = 1; 519 | config.alpha_filtering = 2; 520 | config.use_sharp_yuv = 1; 521 | config.exact = 0; 522 | 523 | return AdvancedEncode(bmp, config, false); 524 | } 525 | 526 | /// Near lossless encoding image in bitmap 527 | /// Bitmap with the image 528 | /// Between 0 (lower quality, lowest file size) and 100 (highest quality, higher file size) 529 | /// Between 0 (fastest, lowest compression) and 9 (slower, best compression) 530 | /// Compress data 531 | public byte[] EncodeNearLossless(Bitmap bmp, int quality, int speed = 9) 532 | { 533 | //test DLL version 534 | if (UnsafeNativeMethods.WebPGetDecoderVersion() <= 1082) 535 | throw new Exception("This DLL version not support EncodeNearLossless"); 536 | 537 | //Inicialize config struct 538 | WebPConfig config = new WebPConfig(); 539 | 540 | //Set compression parameters 541 | if (UnsafeNativeMethods.WebPConfigInit(ref config, WebPPreset.WEBP_PRESET_DEFAULT, (speed + 1) * 10) == 0) 542 | throw new Exception("Can´t configure preset"); 543 | if (UnsafeNativeMethods.WebPConfigLosslessPreset(ref config, speed) == 0) 544 | throw new Exception("Can´t configure lossless preset"); 545 | config.pass = speed + 1; 546 | config.near_lossless = quality; 547 | config.thread_level = 1; 548 | config.alpha_filtering = 2; 549 | config.use_sharp_yuv = 1; 550 | config.exact = 0; 551 | 552 | return AdvancedEncode(bmp, config, false); 553 | } 554 | #endregion 555 | 556 | #region | Another Public Functions | 557 | /// Get the libwebp version 558 | /// Version of library 559 | public string GetVersion() 560 | { 561 | try 562 | { 563 | uint v = (uint)UnsafeNativeMethods.WebPGetDecoderVersion(); 564 | var revision = v % 256; 565 | var minor = (v >> 8) % 256; 566 | var major = (v >> 16) % 256; 567 | return major + "." + minor + "." + revision; 568 | } 569 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.GetVersion"); } 570 | } 571 | 572 | /// Get info of WEBP data 573 | /// The data of WebP 574 | /// width of image 575 | /// height of image 576 | /// Image has alpha channel 577 | /// Image is a animation 578 | /// Format of image: 0 = undefined (/mixed), 1 = lossy, 2 = lossless 579 | public void GetInfo(byte[] rawWebP, out int width, out int height, out bool has_alpha, out bool has_animation, out string format) 580 | { 581 | VP8StatusCode result; 582 | GCHandle pinnedWebP = GCHandle.Alloc(rawWebP, GCHandleType.Pinned); 583 | 584 | try 585 | { 586 | IntPtr ptrRawWebP = pinnedWebP.AddrOfPinnedObject(); 587 | 588 | WebPBitstreamFeatures features = new WebPBitstreamFeatures(); 589 | result = UnsafeNativeMethods.WebPGetFeatures(ptrRawWebP, rawWebP.Length, ref features); 590 | 591 | if (result != 0) 592 | throw new Exception(result.ToString()); 593 | 594 | width = features.Width; 595 | height = features.Height; 596 | if (features.Has_alpha == 1) has_alpha = true; else has_alpha = false; 597 | if (features.Has_animation == 1) has_animation = true; else has_animation = false; 598 | switch (features.Format) 599 | { 600 | case 1: 601 | format = "lossy"; 602 | break; 603 | case 2: 604 | format = "lossless"; 605 | break; 606 | default: 607 | format = "undefined"; 608 | break; 609 | } 610 | } 611 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.GetInfo"); } 612 | finally 613 | { 614 | //Free memory 615 | if (pinnedWebP.IsAllocated) 616 | pinnedWebP.Free(); 617 | } 618 | } 619 | 620 | /// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Warning: this function is rather CPU-intensive 621 | /// Picture to measure 622 | /// Reference picture 623 | /// 0 = PSNR, 1 = SSIM, 2 = LSIM 624 | /// dB in the Y/U/V/Alpha/All order 625 | public float[] GetPictureDistortion(Bitmap source, Bitmap reference, int metric_type) 626 | { 627 | WebPPicture wpicSource = new WebPPicture(); 628 | WebPPicture wpicReference = new WebPPicture(); 629 | BitmapData sourceBmpData = null; 630 | BitmapData referenceBmpData = null; 631 | float[] result = new float[5]; 632 | GCHandle pinnedResult = GCHandle.Alloc(result, GCHandleType.Pinned); 633 | 634 | try 635 | { 636 | if (source == null) 637 | throw new Exception("Source picture is void"); 638 | if (reference == null) 639 | throw new Exception("Reference picture is void"); 640 | if (metric_type > 2) 641 | throw new Exception("Bad metric_type. Use 0 = PSNR, 1 = SSIM, 2 = LSIM"); 642 | if (source.Width != reference.Width || source.Height != reference.Height) 643 | throw new Exception("Source and Reference pictures have different dimensions"); 644 | 645 | // Setup the source picture data, allocating the bitmap, width and height 646 | sourceBmpData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat); 647 | wpicSource = new WebPPicture(); 648 | if (UnsafeNativeMethods.WebPPictureInitInternal(ref wpicSource) != 1) 649 | throw new Exception("Can´t initialize WebPPictureInit"); 650 | wpicSource.width = (int)source.Width; 651 | wpicSource.height = (int)source.Height; 652 | 653 | //Put the source bitmap componets in wpic 654 | if (sourceBmpData.PixelFormat == PixelFormat.Format32bppArgb) 655 | { 656 | wpicSource.use_argb = 1; 657 | if (UnsafeNativeMethods.WebPPictureImportBGRA(ref wpicSource, sourceBmpData.Scan0, sourceBmpData.Stride) != 1) 658 | throw new Exception("Can´t allocate memory in WebPPictureImportBGR"); 659 | } 660 | else 661 | { 662 | wpicSource.use_argb = 0; 663 | if (UnsafeNativeMethods.WebPPictureImportBGR(ref wpicSource, sourceBmpData.Scan0, sourceBmpData.Stride) != 1) 664 | throw new Exception("Can´t allocate memory in WebPPictureImportBGR"); 665 | } 666 | 667 | // Setup the reference picture data, allocating the bitmap, width and height 668 | referenceBmpData = reference.LockBits(new Rectangle(0, 0, reference.Width, reference.Height), ImageLockMode.ReadOnly, reference.PixelFormat); 669 | wpicReference = new WebPPicture(); 670 | if (UnsafeNativeMethods.WebPPictureInitInternal(ref wpicReference) != 1) 671 | throw new Exception("Can´t initialize WebPPictureInit"); 672 | wpicReference.width = (int)reference.Width; 673 | wpicReference.height = (int)reference.Height; 674 | wpicReference.use_argb = 1; 675 | 676 | //Put the source bitmap contents in WebPPicture instance 677 | if (sourceBmpData.PixelFormat == PixelFormat.Format32bppArgb) 678 | { 679 | wpicSource.use_argb = 1; 680 | if (UnsafeNativeMethods.WebPPictureImportBGRA(ref wpicReference, referenceBmpData.Scan0, referenceBmpData.Stride) != 1) 681 | throw new Exception("Can´t allocate memory in WebPPictureImportBGR"); 682 | } 683 | else 684 | { 685 | wpicSource.use_argb = 0; 686 | if (UnsafeNativeMethods.WebPPictureImportBGR(ref wpicReference, referenceBmpData.Scan0, referenceBmpData.Stride) != 1) 687 | throw new Exception("Can´t allocate memory in WebPPictureImportBGR"); 688 | } 689 | 690 | //Measure 691 | IntPtr ptrResult = pinnedResult.AddrOfPinnedObject(); 692 | if (UnsafeNativeMethods.WebPPictureDistortion(ref wpicSource, ref wpicReference, metric_type, ptrResult) != 1) 693 | throw new Exception("Can´t measure."); 694 | return result; 695 | } 696 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.GetPictureDistortion"); } 697 | finally 698 | { 699 | //Unlock the pixels 700 | if (sourceBmpData != null) 701 | source.UnlockBits(sourceBmpData); 702 | if (referenceBmpData != null) 703 | reference.UnlockBits(referenceBmpData); 704 | 705 | //Free memory 706 | if (wpicSource.argb != IntPtr.Zero) 707 | UnsafeNativeMethods.WebPPictureFree(ref wpicSource); 708 | if (wpicReference.argb != IntPtr.Zero) 709 | UnsafeNativeMethods.WebPPictureFree(ref wpicReference); 710 | //Free memory 711 | if (pinnedResult.IsAllocated) 712 | pinnedResult.Free(); 713 | } 714 | } 715 | #endregion 716 | 717 | #region | Private Methods | 718 | /// Encoding image using Advanced encoding API 719 | /// Bitmap with the image 720 | /// Configuration for encode 721 | /// True if need encode info. 722 | /// Compressed data 723 | private byte[] AdvancedEncode(Bitmap bmp, WebPConfig config, bool info) 724 | { 725 | byte[] rawWebP = null; 726 | byte[] dataWebp = null; 727 | WebPPicture wpic = new WebPPicture(); 728 | BitmapData bmpData = null; 729 | WebPAuxStats stats = new WebPAuxStats(); 730 | IntPtr ptrStats = IntPtr.Zero; 731 | GCHandle pinnedArrayHandle = new GCHandle(); 732 | int dataWebpSize; 733 | try 734 | { 735 | //Validate the configuration 736 | if (UnsafeNativeMethods.WebPValidateConfig(ref config) != 1) 737 | throw new Exception("Bad configuration parameters"); 738 | 739 | //test bmp 740 | if (bmp.Width == 0 || bmp.Height == 0) 741 | throw new ArgumentException("Bitmap contains no data.", "bmp"); 742 | if (bmp.Width > WEBP_MAX_DIMENSION || bmp.Height > WEBP_MAX_DIMENSION) 743 | throw new NotSupportedException("Bitmap's dimension is too large. Max is " + WEBP_MAX_DIMENSION + "x" + WEBP_MAX_DIMENSION + " pixels."); 744 | if (bmp.PixelFormat != PixelFormat.Format24bppRgb && bmp.PixelFormat != PixelFormat.Format32bppArgb) 745 | throw new NotSupportedException("Only support Format24bppRgb and Format32bppArgb pixelFormat."); 746 | 747 | // Setup the input data, allocating a the bitmap, width and height 748 | bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); 749 | if (UnsafeNativeMethods.WebPPictureInitInternal(ref wpic) != 1) 750 | throw new Exception("Can´t initialize WebPPictureInit"); 751 | wpic.width = (int)bmp.Width; 752 | wpic.height = (int)bmp.Height; 753 | wpic.use_argb = 1; 754 | 755 | if (bmp.PixelFormat == PixelFormat.Format32bppArgb) 756 | { 757 | //Put the bitmap componets in wpic 758 | int result = UnsafeNativeMethods.WebPPictureImportBGRA(ref wpic, bmpData.Scan0, bmpData.Stride); 759 | if (result != 1) 760 | throw new Exception("Can´t allocate memory in WebPPictureImportBGRA"); 761 | wpic.colorspace = (uint)WEBP_CSP_MODE.MODE_bgrA; 762 | dataWebpSize = bmp.Width * bmp.Height * 32; 763 | dataWebp = new byte[bmp.Width * bmp.Height * 32]; //Memory for WebP output 764 | } 765 | else 766 | { 767 | //Put the bitmap contents in WebPPicture instance 768 | int result = UnsafeNativeMethods.WebPPictureImportBGR(ref wpic, bmpData.Scan0, bmpData.Stride); 769 | if (result != 1) 770 | throw new Exception("Can´t allocate memory in WebPPictureImportBGR"); 771 | dataWebpSize = bmp.Width * bmp.Height * 24; 772 | 773 | } 774 | 775 | //Set up statistics of compression 776 | if (info) 777 | { 778 | stats = new WebPAuxStats(); 779 | ptrStats = Marshal.AllocHGlobal(Marshal.SizeOf(stats)); 780 | Marshal.StructureToPtr(stats, ptrStats, false); 781 | wpic.stats = ptrStats; 782 | } 783 | 784 | //Memory for WebP output 785 | if (dataWebpSize > 2147483591) 786 | dataWebpSize = 2147483591; 787 | dataWebp = new byte[bmp.Width * bmp.Height * 32]; 788 | pinnedArrayHandle = GCHandle.Alloc(dataWebp, GCHandleType.Pinned); 789 | IntPtr initPtr = pinnedArrayHandle.AddrOfPinnedObject(); 790 | wpic.custom_ptr = initPtr; 791 | 792 | //Set up a byte-writing method (write-to-memory, in this case) 793 | _myWriterDelegate = new UnsafeNativeMethods.WebPMemoryWrite(MyWriter); 794 | wpic.writer = Marshal.GetFunctionPointerForDelegate(_myWriterDelegate); 795 | 796 | //compress the input samples 797 | if (UnsafeNativeMethods.WebPEncode(ref config, ref wpic) != 1) 798 | throw new Exception("Encoding error: " + ((WebPEncodingError)wpic.error_code).ToString()); 799 | 800 | //Remove OnCallback 801 | _myWriterDelegate = null; 802 | 803 | //Unlock the pixels 804 | bmp.UnlockBits(bmpData); 805 | bmpData = null; 806 | 807 | //Copy webpData to rawWebP 808 | int size = (int)((long)wpic.custom_ptr - (long)initPtr); 809 | rawWebP = new byte[size]; 810 | Array.Copy(dataWebp, rawWebP, size); 811 | 812 | //Remove compression data 813 | pinnedArrayHandle.Free(); 814 | dataWebp = null; 815 | 816 | //Show statistics 817 | if (info) 818 | { 819 | stats = (WebPAuxStats)Marshal.PtrToStructure(ptrStats, typeof(WebPAuxStats)); 820 | MessageBox.Show("Dimension: " + wpic.width + " x " + wpic.height + " pixels\n" + 821 | "Output: " + stats.coded_size + " bytes\n" + 822 | "PSNR Y: " + stats.PSNRY + " db\n" + 823 | "PSNR u: " + stats.PSNRU + " db\n" + 824 | "PSNR v: " + stats.PSNRV + " db\n" + 825 | "PSNR ALL: " + stats.PSNRALL + " db\n" + 826 | "Block intra4: " + stats.block_count_intra4 + "\n" + 827 | "Block intra16: " + stats.block_count_intra16 + "\n" + 828 | "Block skipped: " + stats.block_count_skipped + "\n" + 829 | "Header size: " + stats.header_bytes + " bytes\n" + 830 | "Mode-partition: " + stats.mode_partition_0 + " bytes\n" + 831 | "Macro-blocks 0: " + stats.segment_size_segments0 + " residuals bytes\n" + 832 | "Macro-blocks 1: " + stats.segment_size_segments1 + " residuals bytes\n" + 833 | "Macro-blocks 2: " + stats.segment_size_segments2 + " residuals bytes\n" + 834 | "Macro-blocks 3: " + stats.segment_size_segments3 + " residuals bytes\n" + 835 | "Quantizer 0: " + stats.segment_quant_segments0 + " residuals bytes\n" + 836 | "Quantizer 1: " + stats.segment_quant_segments1 + " residuals bytes\n" + 837 | "Quantizer 2: " + stats.segment_quant_segments2 + " residuals bytes\n" + 838 | "Quantizer 3: " + stats.segment_quant_segments3 + " residuals bytes\n" + 839 | "Filter level 0: " + stats.segment_level_segments0 + " residuals bytes\n" + 840 | "Filter level 1: " + stats.segment_level_segments1 + " residuals bytes\n" + 841 | "Filter level 2: " + stats.segment_level_segments2 + " residuals bytes\n" + 842 | "Filter level 3: " + stats.segment_level_segments3 + " residuals bytes\n", "Compression statistics"); 843 | } 844 | 845 | return rawWebP; 846 | } 847 | catch (Exception ex) { throw new Exception(ex.Message + "\r\nIn WebP.AdvancedEncode"); } 848 | finally 849 | { 850 | //Free temporal compress memory 851 | if (pinnedArrayHandle.IsAllocated) 852 | { 853 | pinnedArrayHandle.Free(); 854 | } 855 | 856 | //Free statistics memory 857 | if (ptrStats != IntPtr.Zero) 858 | { 859 | Marshal.FreeHGlobal(ptrStats); 860 | } 861 | 862 | //Unlock the pixels 863 | if (bmpData != null) 864 | { 865 | bmp.UnlockBits(bmpData); 866 | } 867 | 868 | //Free memory 869 | if (wpic.argb != IntPtr.Zero) 870 | { 871 | UnsafeNativeMethods.WebPPictureFree(ref wpic); 872 | } 873 | } 874 | } 875 | 876 | private int MyWriter([InAttribute()] IntPtr data, UIntPtr data_size, ref WebPPicture picture) 877 | { 878 | UnsafeNativeMethods.CopyMemory(picture.custom_ptr, data, (uint)data_size); 879 | //picture.custom_ptr = IntPtr.Add(picture.custom_ptr, (int)data_size); //Only in .NET > 4.0 880 | picture.custom_ptr = new IntPtr(picture.custom_ptr.ToInt64() + (int)data_size); 881 | return 1; 882 | } 883 | 884 | private delegate int MyWriterDelegate([InAttribute()] IntPtr data, UIntPtr data_size, ref WebPPicture picture); 885 | #endregion 886 | 887 | #region | Destruction | 888 | /// Free memory 889 | public void Dispose() 890 | { 891 | GC.SuppressFinalize(this); 892 | } 893 | #endregion 894 | } 895 | 896 | #region | Import libwebp functions | 897 | [SuppressUnmanagedCodeSecurityAttribute] 898 | internal sealed partial class UnsafeNativeMethods 899 | { 900 | 901 | [DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)] 902 | internal static extern void CopyMemory(IntPtr dest, IntPtr src, uint count); 903 | 904 | private static readonly int WEBP_DECODER_ABI_VERSION = 0x0208; 905 | 906 | /// This function will initialize the configuration according to a predefined set of parameters (referred to by 'preset') and a given quality factor 907 | /// The WebPConfig structure 908 | /// Type of image 909 | /// Quality of compression 910 | /// 0 if error 911 | internal static int WebPConfigInit(ref WebPConfig config, WebPPreset preset, float quality) 912 | { 913 | switch (IntPtr.Size) 914 | { 915 | case 4: 916 | return WebPConfigInitInternal_x86(ref config, preset, quality, WEBP_DECODER_ABI_VERSION); 917 | case 8: 918 | return WebPConfigInitInternal_x64(ref config, preset, quality, WEBP_DECODER_ABI_VERSION); 919 | default: 920 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 921 | } 922 | } 923 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigInitInternal")] 924 | private static extern int WebPConfigInitInternal_x86(ref WebPConfig config, WebPPreset preset, float quality, int WEBP_DECODER_ABI_VERSION); 925 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigInitInternal")] 926 | private static extern int WebPConfigInitInternal_x64(ref WebPConfig config, WebPPreset preset, float quality, int WEBP_DECODER_ABI_VERSION); 927 | 928 | /// Get info of WepP image 929 | /// Bytes[] of WebP image 930 | /// Size of rawWebP 931 | /// Features of WebP image 932 | /// VP8StatusCode 933 | internal static VP8StatusCode WebPGetFeatures(IntPtr rawWebP, int data_size, ref WebPBitstreamFeatures features) 934 | { 935 | switch (IntPtr.Size) 936 | { 937 | case 4: 938 | return WebPGetFeaturesInternal_x86(rawWebP, (UIntPtr)data_size, ref features, WEBP_DECODER_ABI_VERSION); 939 | case 8: 940 | return WebPGetFeaturesInternal_x64(rawWebP, (UIntPtr)data_size, ref features, WEBP_DECODER_ABI_VERSION); 941 | default: 942 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 943 | } 944 | } 945 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetFeaturesInternal")] 946 | private static extern VP8StatusCode WebPGetFeaturesInternal_x86([InAttribute()] IntPtr rawWebP, UIntPtr data_size, ref WebPBitstreamFeatures features, int WEBP_DECODER_ABI_VERSION); 947 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetFeaturesInternal")] 948 | private static extern VP8StatusCode WebPGetFeaturesInternal_x64([InAttribute()] IntPtr rawWebP, UIntPtr data_size, ref WebPBitstreamFeatures features, int WEBP_DECODER_ABI_VERSION); 949 | 950 | /// Activate the lossless compression mode with the desired efficiency 951 | /// The WebPConfig struct 952 | /// between 0 (fastest, lowest compression) and 9 (slower, best compression) 953 | /// 0 in case of parameter error 954 | internal static int WebPConfigLosslessPreset(ref WebPConfig config, int level) 955 | { 956 | switch (IntPtr.Size) 957 | { 958 | case 4: 959 | return WebPConfigLosslessPreset_x86(ref config, level); 960 | case 8: 961 | return WebPConfigLosslessPreset_x64(ref config, level); 962 | default: 963 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 964 | } 965 | } 966 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigLosslessPreset")] 967 | private static extern int WebPConfigLosslessPreset_x86(ref WebPConfig config, int level); 968 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPConfigLosslessPreset")] 969 | private static extern int WebPConfigLosslessPreset_x64(ref WebPConfig config, int level); 970 | 971 | /// Check that configuration is non-NULL and all configuration parameters are within their valid ranges 972 | /// The WebPConfig structure 973 | /// 1 if configuration is OK 974 | internal static int WebPValidateConfig(ref WebPConfig config) 975 | { 976 | switch (IntPtr.Size) 977 | { 978 | case 4: 979 | return WebPValidateConfig_x86(ref config); 980 | case 8: 981 | return WebPValidateConfig_x64(ref config); 982 | default: 983 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 984 | } 985 | } 986 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPValidateConfig")] 987 | private static extern int WebPValidateConfig_x86(ref WebPConfig config); 988 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPValidateConfig")] 989 | private static extern int WebPValidateConfig_x64(ref WebPConfig config); 990 | 991 | /// Initialize the WebPPicture structure checking the DLL version 992 | /// The WebPPicture structure 993 | /// 1 if not error 994 | internal static int WebPPictureInitInternal(ref WebPPicture wpic) 995 | { 996 | switch (IntPtr.Size) 997 | { 998 | case 4: 999 | return WebPPictureInitInternal_x86(ref wpic, WEBP_DECODER_ABI_VERSION); 1000 | case 8: 1001 | return WebPPictureInitInternal_x64(ref wpic, WEBP_DECODER_ABI_VERSION); 1002 | default: 1003 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1004 | } 1005 | } 1006 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureInitInternal")] 1007 | private static extern int WebPPictureInitInternal_x86(ref WebPPicture wpic, int WEBP_DECODER_ABI_VERSION); 1008 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureInitInternal")] 1009 | private static extern int WebPPictureInitInternal_x64(ref WebPPicture wpic, int WEBP_DECODER_ABI_VERSION); 1010 | 1011 | /// Colorspace conversion function to import RGB samples 1012 | /// The WebPPicture structure 1013 | /// Point to BGR data 1014 | /// stride of BGR data 1015 | /// Returns 0 in case of memory error. 1016 | internal static int WebPPictureImportBGR(ref WebPPicture wpic, IntPtr bgr, int stride) 1017 | { 1018 | switch (IntPtr.Size) 1019 | { 1020 | case 4: 1021 | return WebPPictureImportBGR_x86(ref wpic, bgr, stride); 1022 | case 8: 1023 | return WebPPictureImportBGR_x64(ref wpic, bgr, stride); 1024 | default: 1025 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1026 | } 1027 | } 1028 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGR")] 1029 | private static extern int WebPPictureImportBGR_x86(ref WebPPicture wpic, IntPtr bgr, int stride); 1030 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGR")] 1031 | private static extern int WebPPictureImportBGR_x64(ref WebPPicture wpic, IntPtr bgr, int stride); 1032 | 1033 | /// Color-space conversion function to import RGB samples 1034 | /// The WebPPicture structure 1035 | /// Point to BGRA data 1036 | /// stride of BGRA data 1037 | /// Returns 0 in case of memory error. 1038 | internal static int WebPPictureImportBGRA(ref WebPPicture wpic, IntPtr bgra, int stride) 1039 | { 1040 | switch (IntPtr.Size) 1041 | { 1042 | case 4: 1043 | return WebPPictureImportBGRA_x86(ref wpic, bgra, stride); 1044 | case 8: 1045 | return WebPPictureImportBGRA_x64(ref wpic, bgra, stride); 1046 | default: 1047 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1048 | } 1049 | } 1050 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRA")] 1051 | private static extern int WebPPictureImportBGRA_x86(ref WebPPicture wpic, IntPtr bgra, int stride); 1052 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRA")] 1053 | private static extern int WebPPictureImportBGRA_x64(ref WebPPicture wpic, IntPtr bgra, int stride); 1054 | 1055 | /// Color-space conversion function to import RGB samples 1056 | /// The WebPPicture structure 1057 | /// Point to BGR data 1058 | /// stride of BGR data 1059 | /// Returns 0 in case of memory error. 1060 | internal static int WebPPictureImportBGRX(ref WebPPicture wpic, IntPtr bgr, int stride) 1061 | { 1062 | switch (IntPtr.Size) 1063 | { 1064 | case 4: 1065 | return WebPPictureImportBGRX_x86(ref wpic, bgr, stride); 1066 | case 8: 1067 | return WebPPictureImportBGRX_x64(ref wpic, bgr, stride); 1068 | default: 1069 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1070 | } 1071 | } 1072 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRX")] 1073 | private static extern int WebPPictureImportBGRX_x86(ref WebPPicture wpic, IntPtr bgr, int stride); 1074 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureImportBGRX")] 1075 | private static extern int WebPPictureImportBGRX_x64(ref WebPPicture wpic, IntPtr bgr, int stride); 1076 | 1077 | /// The writer type for output compress data 1078 | /// Data returned 1079 | /// Size of data returned 1080 | /// Picture structure 1081 | /// 1082 | [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 1083 | internal delegate int WebPMemoryWrite([In()] IntPtr data, UIntPtr data_size, ref WebPPicture wpic); 1084 | 1085 | /// Compress to WebP format 1086 | /// The configuration structure for compression parameters 1087 | /// 'picture' hold the source samples in both YUV(A) or ARGB input 1088 | /// Returns 0 in case of error, 1 otherwise. In case of error, picture->error_code is updated accordingly. 1089 | internal static int WebPEncode(ref WebPConfig config, ref WebPPicture picture) 1090 | { 1091 | switch (IntPtr.Size) 1092 | { 1093 | case 4: 1094 | return WebPEncode_x86(ref config, ref picture); 1095 | case 8: 1096 | return WebPEncode_x64(ref config, ref picture); 1097 | default: 1098 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1099 | } 1100 | } 1101 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncode")] 1102 | private static extern int WebPEncode_x86(ref WebPConfig config, ref WebPPicture picture); 1103 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncode")] 1104 | private static extern int WebPEncode_x64(ref WebPConfig config, ref WebPPicture picture); 1105 | 1106 | /// Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*() 1107 | /// Note that this function does _not_ free the memory used by the 'picture' object itself. 1108 | /// Besides memory (which is reclaimed) all other fields of 'picture' are preserved 1109 | /// Picture structure 1110 | internal static void WebPPictureFree(ref WebPPicture picture) 1111 | { 1112 | switch (IntPtr.Size) 1113 | { 1114 | case 4: 1115 | WebPPictureFree_x86(ref picture); 1116 | break; 1117 | case 8: 1118 | WebPPictureFree_x64(ref picture); 1119 | break; 1120 | default: 1121 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1122 | } 1123 | } 1124 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureFree")] 1125 | private static extern void WebPPictureFree_x86(ref WebPPicture wpic); 1126 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureFree")] 1127 | private static extern void WebPPictureFree_x64(ref WebPPicture wpic); 1128 | 1129 | /// Validate the WebP image header and retrieve the image height and width. Pointers *width and *height can be passed NULL if deemed irrelevant 1130 | /// Pointer to WebP image data 1131 | /// This is the size of the memory block pointed to by data containing the image data 1132 | /// The range is limited currently from 1 to 16383 1133 | /// The range is limited currently from 1 to 16383 1134 | /// 1 if success, otherwise error code returned in the case of (a) formatting error(s). 1135 | internal static int WebPGetInfo(IntPtr data, int data_size, out int width, out int height) 1136 | { 1137 | switch (IntPtr.Size) 1138 | { 1139 | case 4: 1140 | return WebPGetInfo_x86(data, (UIntPtr)data_size, out width, out height); 1141 | case 8: 1142 | return WebPGetInfo_x64(data, (UIntPtr)data_size, out width, out height); 1143 | default: 1144 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1145 | } 1146 | } 1147 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")] 1148 | private static extern int WebPGetInfo_x86([InAttribute()] IntPtr data, UIntPtr data_size, out int width, out int height); 1149 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetInfo")] 1150 | private static extern int WebPGetInfo_x64([InAttribute()] IntPtr data, UIntPtr data_size, out int width, out int height); 1151 | 1152 | /// Decode WEBP image pointed to by *data and returns BGR samples into a preallocated buffer 1153 | /// Pointer to WebP image data 1154 | /// This is the size of the memory block pointed to by data containing the image data 1155 | /// Pointer to decoded WebP image 1156 | /// Size of allocated buffer 1157 | /// Specifies the distance between scan lines 1158 | internal static void WebPDecodeBGRInto(IntPtr data, int data_size, IntPtr output_buffer, int output_buffer_size, int output_stride) 1159 | { 1160 | switch (IntPtr.Size) 1161 | { 1162 | case 4: 1163 | if (WebPDecodeBGRInto_x86(data, (UIntPtr)data_size, output_buffer, output_buffer_size, output_stride) == null) 1164 | throw new InvalidOperationException("Can not decode WebP"); 1165 | break; 1166 | case 8: 1167 | if (WebPDecodeBGRInto_x64(data, (UIntPtr)data_size, output_buffer, output_buffer_size, output_stride) == null) 1168 | throw new InvalidOperationException("Can not decode WebP"); 1169 | break; 1170 | default: 1171 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1172 | } 1173 | } 1174 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRInto")] 1175 | private static extern IntPtr WebPDecodeBGRInto_x86([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, int output_buffer_size, int output_stride); 1176 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRInto")] 1177 | private static extern IntPtr WebPDecodeBGRInto_x64([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, int output_buffer_size, int output_stride); 1178 | 1179 | /// Decode WEBP image pointed to by *data and returns BGRA samples into a preallocated buffer 1180 | /// Pointer to WebP image data 1181 | /// This is the size of the memory block pointed to by data containing the image data 1182 | /// Pointer to decoded WebP image 1183 | /// Size of allocated buffer 1184 | /// Specifies the distance between scan lines 1185 | internal static void WebPDecodeBGRAInto(IntPtr data, int data_size, IntPtr output_buffer, int output_buffer_size, int output_stride) 1186 | { 1187 | switch (IntPtr.Size) 1188 | { 1189 | case 4: 1190 | if (WebPDecodeBGRAInto_x86(data, (UIntPtr)data_size, output_buffer, output_buffer_size, output_stride) == null) 1191 | throw new InvalidOperationException("Can not decode WebP"); 1192 | break; 1193 | case 8: 1194 | if (WebPDecodeBGRAInto_x64(data, (UIntPtr)data_size, output_buffer, output_buffer_size, output_stride) == null) 1195 | throw new InvalidOperationException("Can not decode WebP"); 1196 | break; 1197 | default: 1198 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1199 | } 1200 | } 1201 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")] 1202 | private static extern IntPtr WebPDecodeBGRAInto_x86([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, int output_buffer_size, int output_stride); 1203 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeBGRAInto")] 1204 | private static extern IntPtr WebPDecodeBGRAInto_x64([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, int output_buffer_size, int output_stride); 1205 | 1206 | /// Decode WEBP image pointed to by *data and returns ARGB samples into a preallocated buffer 1207 | /// Pointer to WebP image data 1208 | /// This is the size of the memory block pointed to by data containing the image data 1209 | /// Pointer to decoded WebP image 1210 | /// Size of allocated buffer 1211 | /// Specifies the distance between scan lines 1212 | internal static void WebPDecodeARGBInto(IntPtr data, int data_size, IntPtr output_buffer, int output_buffer_size, int output_stride) 1213 | { 1214 | switch (IntPtr.Size) 1215 | { 1216 | case 4: 1217 | if (WebPDecodeARGBInto_x86(data, (UIntPtr)data_size, output_buffer, output_buffer_size, output_stride) == null) 1218 | throw new InvalidOperationException("Can not decode WebP"); 1219 | break; 1220 | case 8: 1221 | if (WebPDecodeARGBInto_x64(data, (UIntPtr)data_size, output_buffer, output_buffer_size, output_stride) == null) 1222 | throw new InvalidOperationException("Can not decode WebP"); 1223 | break; 1224 | default: 1225 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1226 | } 1227 | } 1228 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeARGBInto")] 1229 | private static extern IntPtr WebPDecodeARGBInto_x86([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, int output_buffer_size, int output_stride); 1230 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecodeARGBInto")] 1231 | private static extern IntPtr WebPDecodeARGBInto_x64([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, int output_buffer_size, int output_stride); 1232 | 1233 | /// Initialize the configuration as empty. This function must always be called first, unless WebPGetFeatures() is to be called 1234 | /// Configuration structure 1235 | /// False in case of mismatched version. 1236 | internal static int WebPInitDecoderConfig(ref WebPDecoderConfig webPDecoderConfig) 1237 | { 1238 | switch (IntPtr.Size) 1239 | { 1240 | case 4: 1241 | return WebPInitDecoderConfigInternal_x86(ref webPDecoderConfig, WEBP_DECODER_ABI_VERSION); 1242 | case 8: 1243 | return WebPInitDecoderConfigInternal_x64(ref webPDecoderConfig, WEBP_DECODER_ABI_VERSION); 1244 | default: 1245 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1246 | } 1247 | } 1248 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPInitDecoderConfigInternal")] 1249 | private static extern int WebPInitDecoderConfigInternal_x86(ref WebPDecoderConfig webPDecoderConfig, int WEBP_DECODER_ABI_VERSION); 1250 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPInitDecoderConfigInternal")] 1251 | private static extern int WebPInitDecoderConfigInternal_x64(ref WebPDecoderConfig webPDecoderConfig, int WEBP_DECODER_ABI_VERSION); 1252 | 1253 | /// Decodes the full data at once, taking configuration into account 1254 | /// WebP raw data to decode 1255 | /// Size of WebP data 1256 | /// Configuration structure 1257 | /// VP8_STATUS_OK if the decoding was successful 1258 | internal static VP8StatusCode WebPDecode(IntPtr data, int data_size, ref WebPDecoderConfig webPDecoderConfig) 1259 | { 1260 | switch (IntPtr.Size) 1261 | { 1262 | case 4: 1263 | return WebPDecode_x86(data, (UIntPtr)data_size, ref webPDecoderConfig); 1264 | case 8: 1265 | return WebPDecode_x64(data, (UIntPtr)data_size, ref webPDecoderConfig); 1266 | default: 1267 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1268 | } 1269 | } 1270 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecode")] 1271 | private static extern VP8StatusCode WebPDecode_x86(IntPtr data, UIntPtr data_size, ref WebPDecoderConfig config); 1272 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPDecode")] 1273 | private static extern VP8StatusCode WebPDecode_x64(IntPtr data, UIntPtr data_size, ref WebPDecoderConfig config); 1274 | 1275 | /// Free any memory associated with the buffer. Must always be called last. Doesn't free the 'buffer' structure itself 1276 | /// WebPDecBuffer 1277 | internal static void WebPFreeDecBuffer(ref WebPDecBuffer buffer) 1278 | { 1279 | switch (IntPtr.Size) 1280 | { 1281 | case 4: 1282 | WebPFreeDecBuffer_x86(ref buffer); 1283 | break; 1284 | case 8: 1285 | WebPFreeDecBuffer_x64(ref buffer); 1286 | break; 1287 | default: 1288 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1289 | } 1290 | } 1291 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFreeDecBuffer")] 1292 | private static extern void WebPFreeDecBuffer_x86(ref WebPDecBuffer buffer); 1293 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFreeDecBuffer")] 1294 | private static extern void WebPFreeDecBuffer_x64(ref WebPDecBuffer buffer); 1295 | 1296 | /// Lossy encoding images 1297 | /// Pointer to BGR image data 1298 | /// The range is limited currently from 1 to 16383 1299 | /// The range is limited currently from 1 to 16383 1300 | /// Specifies the distance between scanlines 1301 | /// Ranges from 0 (lower quality) to 100 (highest quality). Controls the loss and quality during compression 1302 | /// output_buffer with WebP image 1303 | /// Size of WebP Image or 0 if an error occurred 1304 | internal static int WebPEncodeBGR(IntPtr bgr, int width, int height, int stride, float quality_factor, out IntPtr output) 1305 | { 1306 | switch (IntPtr.Size) 1307 | { 1308 | case 4: 1309 | return WebPEncodeBGR_x86(bgr, width, height, stride, quality_factor, out output); 1310 | case 8: 1311 | return WebPEncodeBGR_x64(bgr, width, height, stride, quality_factor, out output); 1312 | default: 1313 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1314 | } 1315 | } 1316 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGR")] 1317 | private static extern int WebPEncodeBGR_x86([InAttribute()] IntPtr bgr, int width, int height, int stride, float quality_factor, out IntPtr output); 1318 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGR")] 1319 | private static extern int WebPEncodeBGR_x64([InAttribute()] IntPtr bgr, int width, int height, int stride, float quality_factor, out IntPtr output); 1320 | 1321 | /// Lossy encoding images 1322 | /// Pointer to BGRA image data 1323 | /// The range is limited currently from 1 to 16383 1324 | /// The range is limited currently from 1 to 16383 1325 | /// Specifies the distance between scan lines 1326 | /// Ranges from 0 (lower quality) to 100 (highest quality). Controls the loss and quality during compression 1327 | /// output_buffer with WebP image 1328 | /// Size of WebP Image or 0 if an error occurred 1329 | internal static int WebPEncodeBGRA(IntPtr bgra, int width, int height, int stride, float quality_factor, out IntPtr output) 1330 | { 1331 | switch (IntPtr.Size) 1332 | { 1333 | case 4: 1334 | return WebPEncodeBGRA_x86(bgra, width, height, stride, quality_factor, out output); 1335 | case 8: 1336 | return WebPEncodeBGRA_x64(bgra, width, height, stride, quality_factor, out output); 1337 | default: 1338 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1339 | } 1340 | } 1341 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")] 1342 | private static extern int WebPEncodeBGRA_x86([InAttribute()] IntPtr bgra, int width, int height, int stride, float quality_factor, out IntPtr output); 1343 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeBGRA")] 1344 | private static extern int WebPEncodeBGRA_x64([InAttribute()] IntPtr bgra, int width, int height, int stride, float quality_factor, out IntPtr output); 1345 | 1346 | /// Lossless encoding images pointed to by *data in WebP format 1347 | /// Pointer to BGR image data 1348 | /// The range is limited currently from 1 to 16383 1349 | /// The range is limited currently from 1 to 16383 1350 | /// Specifies the distance between scan lines 1351 | /// output_buffer with WebP image 1352 | /// Size of WebP Image or 0 if an error occurred 1353 | internal static int WebPEncodeLosslessBGR(IntPtr bgr, int width, int height, int stride, out IntPtr output) 1354 | { 1355 | switch (IntPtr.Size) 1356 | { 1357 | case 4: 1358 | return WebPEncodeLosslessBGR_x86(bgr, width, height, stride, out output); 1359 | case 8: 1360 | return WebPEncodeLosslessBGR_x64(bgr, width, height, stride, out output); 1361 | default: 1362 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1363 | } 1364 | } 1365 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGR")] 1366 | private static extern int WebPEncodeLosslessBGR_x86([InAttribute()] IntPtr bgr, int width, int height, int stride, out IntPtr output); 1367 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGR")] 1368 | private static extern int WebPEncodeLosslessBGR_x64([InAttribute()] IntPtr bgr, int width, int height, int stride, out IntPtr output); 1369 | 1370 | /// Lossless encoding images pointed to by *data in WebP format 1371 | /// Pointer to BGRA image data 1372 | /// The range is limited currently from 1 to 16383 1373 | /// The range is limited currently from 1 to 16383 1374 | /// Specifies the distance between scan lines 1375 | /// output_buffer with WebP image 1376 | /// Size of WebP Image or 0 if an error occurred 1377 | internal static int WebPEncodeLosslessBGRA(IntPtr bgra, int width, int height, int stride, out IntPtr output) 1378 | { 1379 | switch (IntPtr.Size) 1380 | { 1381 | case 4: 1382 | return WebPEncodeLosslessBGRA_x86(bgra, width, height, stride, out output); 1383 | case 8: 1384 | return WebPEncodeLosslessBGRA_x64(bgra, width, height, stride, out output); 1385 | default: 1386 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1387 | } 1388 | } 1389 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGRA")] 1390 | private static extern int WebPEncodeLosslessBGRA_x86([InAttribute()] IntPtr bgra, int width, int height, int stride, out IntPtr output); 1391 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPEncodeLosslessBGRA")] 1392 | private static extern int WebPEncodeLosslessBGRA_x64([InAttribute()] IntPtr bgra, int width, int height, int stride, out IntPtr output); 1393 | 1394 | /// Releases memory returned by the WebPEncode 1395 | /// Pointer to memory 1396 | internal static void WebPFree(IntPtr p) 1397 | { 1398 | switch (IntPtr.Size) 1399 | { 1400 | case 4: 1401 | WebPFree_x86(p); 1402 | break; 1403 | case 8: 1404 | WebPFree_x64(p); 1405 | break; 1406 | default: 1407 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1408 | } 1409 | } 1410 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")] 1411 | private static extern void WebPFree_x86(IntPtr p); 1412 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPFree")] 1413 | private static extern void WebPFree_x64(IntPtr p); 1414 | 1415 | /// Get the WebP version library 1416 | /// 8bits for each of major/minor/revision packet in integer. E.g: v2.5.7 is 0x020507 1417 | internal static int WebPGetDecoderVersion() 1418 | { 1419 | switch (IntPtr.Size) 1420 | { 1421 | case 4: 1422 | return WebPGetDecoderVersion_x86(); 1423 | case 8: 1424 | return WebPGetDecoderVersion_x64(); 1425 | default: 1426 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1427 | } 1428 | } 1429 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetDecoderVersion")] 1430 | private static extern int WebPGetDecoderVersion_x86(); 1431 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPGetDecoderVersion")] 1432 | private static extern int WebPGetDecoderVersion_x64(); 1433 | 1434 | /// Compute PSNR, SSIM or LSIM distortion metric between two pictures 1435 | /// Picture to measure 1436 | /// Reference picture 1437 | /// 0 = PSNR, 1 = SSIM, 2 = LSIM 1438 | /// dB in the Y/U/V/Alpha/All order 1439 | /// False in case of error (the two pictures don't have same dimension, ...) 1440 | internal static int WebPPictureDistortion(ref WebPPicture srcPicture, ref WebPPicture refPicture, int metric_type, IntPtr pResult) 1441 | { 1442 | switch (IntPtr.Size) 1443 | { 1444 | case 4: 1445 | return WebPPictureDistortion_x86(ref srcPicture, ref refPicture, metric_type, pResult); 1446 | case 8: 1447 | return WebPPictureDistortion_x64(ref srcPicture, ref refPicture, metric_type, pResult); 1448 | default: 1449 | throw new InvalidOperationException("Invalid platform. Can not find proper function"); 1450 | } 1451 | } 1452 | [DllImport("libwebp_x86.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureDistortion")] 1453 | private static extern int WebPPictureDistortion_x86(ref WebPPicture srcPicture, ref WebPPicture refPicture, int metric_type, IntPtr pResult); 1454 | [DllImport("libwebp_x64.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "WebPPictureDistortion")] 1455 | private static extern int WebPPictureDistortion_x64(ref WebPPicture srcPicture, ref WebPPicture refPicture, int metric_type, IntPtr pResult); 1456 | } 1457 | #endregion 1458 | 1459 | #region | Predefined | 1460 | /// Enumerate some predefined settings for WebPConfig, depending on the type of source picture. These presets are used when calling WebPConfigPreset() 1461 | internal enum WebPPreset 1462 | { 1463 | /// Default preset 1464 | WEBP_PRESET_DEFAULT = 0, 1465 | /// Digital picture, like portrait, inner shot 1466 | WEBP_PRESET_PICTURE, 1467 | /// Outdoor photograph, with natural lighting 1468 | WEBP_PRESET_PHOTO, 1469 | /// Hand or line drawing, with high-contrast details 1470 | WEBP_PRESET_DRAWING, 1471 | /// Small-sized colorful images 1472 | WEBP_PRESET_ICON, 1473 | /// Text-like 1474 | WEBP_PRESET_TEXT 1475 | }; 1476 | 1477 | /// Encoding error conditions 1478 | internal enum WebPEncodingError 1479 | { 1480 | /// No error 1481 | VP8_ENC_OK = 0, 1482 | /// Memory error allocating objects 1483 | VP8_ENC_ERROR_OUT_OF_MEMORY, 1484 | /// Memory error while flushing bits 1485 | VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, 1486 | /// A pointer parameter is NULL 1487 | VP8_ENC_ERROR_NULL_PARAMETER, 1488 | /// Configuration is invalid 1489 | VP8_ENC_ERROR_INVALID_CONFIGURATION, 1490 | /// Picture has invalid width/height 1491 | VP8_ENC_ERROR_BAD_DIMENSION, 1492 | /// Partition is bigger than 512k 1493 | VP8_ENC_ERROR_PARTITION0_OVERFLOW, 1494 | /// Partition is bigger than 16M 1495 | VP8_ENC_ERROR_PARTITION_OVERFLOW, 1496 | /// Error while flushing bytes 1497 | VP8_ENC_ERROR_BAD_WRITE, 1498 | /// File is bigger than 4G 1499 | VP8_ENC_ERROR_FILE_TOO_BIG, 1500 | /// Abort request by user 1501 | VP8_ENC_ERROR_USER_ABORT, 1502 | /// List terminator. Always last 1503 | VP8_ENC_ERROR_LAST, 1504 | } 1505 | 1506 | /// Enumeration of the status codes 1507 | internal enum VP8StatusCode 1508 | { 1509 | /// No error 1510 | VP8_STATUS_OK = 0, 1511 | /// Memory error allocating objects 1512 | VP8_STATUS_OUT_OF_MEMORY, 1513 | /// Configuration is invalid 1514 | VP8_STATUS_INVALID_PARAM, 1515 | VP8_STATUS_BITSTREAM_ERROR, 1516 | /// Configuration is invalid 1517 | VP8_STATUS_UNSUPPORTED_FEATURE, 1518 | VP8_STATUS_SUSPENDED, 1519 | /// Abort request by user 1520 | VP8_STATUS_USER_ABORT, 1521 | VP8_STATUS_NOT_ENOUGH_DATA, 1522 | } 1523 | 1524 | /// Image characteristics hint for the underlying encoder 1525 | internal enum WebPImageHint 1526 | { 1527 | /// Default preset 1528 | WEBP_HINT_DEFAULT = 0, 1529 | /// Digital picture, like portrait, inner shot 1530 | WEBP_HINT_PICTURE, 1531 | /// Outdoor photograph, with natural lighting 1532 | WEBP_HINT_PHOTO, 1533 | /// Discrete tone image (graph, map-tile etc) 1534 | WEBP_HINT_GRAPH, 1535 | /// List terminator. Always last 1536 | WEBP_HINT_LAST 1537 | }; 1538 | 1539 | /// Describes the byte-ordering of packed samples in memory 1540 | internal enum WEBP_CSP_MODE 1541 | { 1542 | /// Byte-order: R,G,B,R,G,B,.. 1543 | MODE_RGB = 0, 1544 | /// Byte-order: R,G,B,A,R,G,B,A,.. 1545 | MODE_RGBA = 1, 1546 | /// Byte-order: B,G,R,B,G,R,.. 1547 | MODE_BGR = 2, 1548 | /// Byte-order: B,G,R,A,B,G,R,A,.. 1549 | MODE_BGRA = 3, 1550 | /// Byte-order: A,R,G,B,A,R,G,B,.. 1551 | MODE_ARGB = 4, 1552 | /// Byte-order: RGB-565: [a4 a3 a2 a1 a0 r5 r4 r3], [r2 r1 r0 g4 g3 g2 g1 g0], ... 1553 | /// WEBP_SWAP_16BITS_CSP is defined, 1554 | /// Byte-order: RGB-565: [a4 a3 a2 a1 a0 b5 b4 b3], [b2 b1 b0 g4 g3 g2 g1 g0], .. 1555 | MODE_RGBA_4444 = 5, 1556 | /// Byte-order: RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... 1557 | /// WEBP_SWAP_16BITS_CSP is defined, 1558 | /// Byte-order: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], .. 1559 | MODE_RGB_565 = 6, 1560 | /// RGB-premultiplied transparent modes (alpha value is preserved) 1561 | MODE_rgbA = 7, 1562 | /// RGB-premultiplied transparent modes (alpha value is preserved) 1563 | MODE_bgrA = 8, 1564 | /// RGB-premultiplied transparent modes (alpha value is preserved) 1565 | MODE_Argb = 9, 1566 | /// RGB-premultiplied transparent modes (alpha value is preserved) 1567 | MODE_rgbA_4444 = 10, 1568 | /// YUV 4:2:0 1569 | MODE_YUV = 11, 1570 | /// YUV 4:2:0 1571 | MODE_YUVA = 12, 1572 | /// MODE_LAST -> 13 1573 | MODE_LAST = 13, 1574 | } 1575 | 1576 | /// 1577 | /// Decoding states. State normally flows as: 1578 | /// WEBP_HEADER->VP8_HEADER->VP8_PARTS0->VP8_DATA->DONE for a lossy image, and 1579 | /// WEBP_HEADER->VP8L_HEADER->VP8L_DATA->DONE for a lossless image. 1580 | /// If there is any error the decoder goes into state ERROR. 1581 | /// 1582 | internal enum DecState 1583 | { 1584 | STATE_WEBP_HEADER, // All the data before that of the VP8/VP8L chunk. 1585 | STATE_VP8_HEADER, // The VP8 Frame header (within the VP8 chunk). 1586 | STATE_VP8_PARTS0, 1587 | STATE_VP8_DATA, 1588 | STATE_VP8L_HEADER, 1589 | STATE_VP8L_DATA, 1590 | STATE_DONE, 1591 | STATE_ERROR 1592 | }; 1593 | #endregion 1594 | 1595 | #region | libwebp structs | 1596 | /// Features gathered from the bit stream 1597 | [StructLayoutAttribute(LayoutKind.Sequential)] 1598 | internal struct WebPBitstreamFeatures 1599 | { 1600 | /// Width in pixels, as read from the bit stream 1601 | public int Width; 1602 | /// Height in pixels, as read from the bit stream 1603 | public int Height; 1604 | /// True if the bit stream contains an alpha channel 1605 | public int Has_alpha; 1606 | /// True if the bit stream is an animation 1607 | public int Has_animation; 1608 | /// 0 = undefined (/mixed), 1 = lossy, 2 = lossless 1609 | public int Format; 1610 | /// Padding for later use 1611 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.U4)] 1612 | private readonly uint[] pad; 1613 | }; 1614 | 1615 | /// Compression parameters 1616 | [StructLayoutAttribute(LayoutKind.Sequential)] 1617 | internal struct WebPConfig 1618 | { 1619 | /// Lossless encoding (0=lossy(default), 1=lossless) 1620 | public int lossless; 1621 | /// Between 0 (smallest file) and 100 (biggest) 1622 | public float quality; 1623 | /// Quality/speed trade-off (0=fast, 6=slower-better) 1624 | public int method; 1625 | /// Hint for image type (lossless only for now) 1626 | public WebPImageHint image_hint; 1627 | /// If non-zero, set the desired target size in bytes. Takes precedence over the 'compression' parameter 1628 | public int target_size; 1629 | /// If non-zero, specifies the minimal distortion to try to achieve. Takes precedence over target_size 1630 | public float target_PSNR; 1631 | /// Maximum number of segments to use, in [1..4] 1632 | public int segments; 1633 | /// Spatial Noise Shaping. 0=off, 100=maximum 1634 | public int sns_strength; 1635 | /// Range: [0 = off .. 100 = strongest] 1636 | public int filter_strength; 1637 | /// Range: [0 = off .. 7 = least sharp] 1638 | public int filter_sharpness; 1639 | /// Filtering type: 0 = simple, 1 = strong (only used if filter_strength > 0 or auto-filter > 0) 1640 | public int filter_type; 1641 | /// Auto adjust filter's strength [0 = off, 1 = on] 1642 | public int autofilter; 1643 | /// Algorithm for encoding the alpha plane (0 = none, 1 = compressed with WebP lossless). Default is 1 1644 | public int alpha_compression; 1645 | /// Predictive filtering method for alpha plane. 0: none, 1: fast, 2: best. Default if 1 1646 | public int alpha_filtering; 1647 | /// Between 0 (smallest size) and 100 (lossless). Default is 100 1648 | public int alpha_quality; 1649 | /// Number of entropy-analysis passes (in [1..10]) 1650 | public int pass; 1651 | /// If true, export the compressed picture back. In-loop filtering is not applied 1652 | public int show_compressed; 1653 | /// Preprocessing filter (0=none, 1=segment-smooth, 2=pseudo-random dithering) 1654 | public int preprocessing; 1655 | /// Log2(number of token partitions) in [0..3] Default is set to 0 for easier progressive decoding 1656 | public int partitions; 1657 | /// Quality degradation allowed to fit the 512k limit on prediction modes coding (0: no degradation, 100: maximum possible degradation) 1658 | public int partition_limit; 1659 | /// If true, compression parameters will be remapped to better match the expected output size from JPEG compression. Generally, the output size will be similar but the degradation will be lower 1660 | public int emulate_jpeg_size; 1661 | /// If non-zero, try and use multi-threaded encoding 1662 | public int thread_level; 1663 | /// If set, reduce memory usage (but increase CPU use) 1664 | public int low_memory; 1665 | /// Near lossless encoding [0 = max loss .. 100 = off (default)] 1666 | public int near_lossless; 1667 | /// If non-zero, preserve the exact RGB values under transparent area. Otherwise, discard this invisible RGB information for better compression. The default value is 0 1668 | public int exact; 1669 | /// Reserved for future lossless feature 1670 | public int delta_palettization; 1671 | /// If needed, use sharp (and slow) RGB->YUV conversion 1672 | public int use_sharp_yuv; 1673 | /// Padding for later use 1674 | private readonly int pad1; 1675 | private readonly int pad2; 1676 | }; 1677 | 1678 | /// Main exchange structure (input samples, output bytes, statistics) 1679 | [StructLayoutAttribute(LayoutKind.Sequential)] 1680 | internal struct WebPPicture 1681 | { 1682 | /// Main flag for encoder selecting between ARGB or YUV input. Recommended to use ARGB input (*argb, argb_stride) for lossless, and YUV input (*y, *u, *v, etc.) for lossy 1683 | public int use_argb; 1684 | /// Color-space: should be YUV420 for now (=Y'CbCr). Value = 0 1685 | public UInt32 colorspace; 1686 | /// Width of picture (less or equal to WEBP_MAX_DIMENSION) 1687 | public int width; 1688 | /// Height of picture (less or equal to WEBP_MAX_DIMENSION) 1689 | public int height; 1690 | /// Pointer to luma plane 1691 | public IntPtr y; 1692 | /// Pointer to chroma U plane 1693 | public IntPtr u; 1694 | /// Pointer to chroma V plane 1695 | public IntPtr v; 1696 | /// Luma stride 1697 | public int y_stride; 1698 | /// Chroma stride 1699 | public int uv_stride; 1700 | /// Pointer to the alpha plane 1701 | public IntPtr a; 1702 | /// stride of the alpha plane 1703 | public int a_stride; 1704 | /// Padding for later use 1705 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)] 1706 | private readonly uint[] pad1; 1707 | /// Pointer to ARGB (32 bit) plane 1708 | public IntPtr argb; 1709 | /// This is stride in pixels units, not bytes 1710 | public int argb_stride; 1711 | /// Padding for later use 1712 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U4)] 1713 | private readonly uint[] pad2; 1714 | /// Byte-emission hook, to store compressed bytes as they are ready 1715 | public IntPtr writer; 1716 | /// Can be used by the writer 1717 | public IntPtr custom_ptr; 1718 | // map for extra information (only for lossy compression mode) 1719 | /// 1: intra type, 2: segment, 3: quant, 4: intra-16 prediction mode, 5: chroma prediction mode, 6: bit cost, 7: distortion 1720 | public int extra_info_type; 1721 | /// If not NULL, points to an array of size ((width + 15) / 16) * ((height + 15) / 16) that will be filled with a macroblock map, depending on extra_info_type 1722 | public IntPtr extra_info; 1723 | /// Pointer to side statistics (updated only if not NULL) 1724 | public IntPtr stats; 1725 | /// Error code for the latest error encountered during encoding 1726 | public UInt32 error_code; 1727 | /// If not NULL, report progress during encoding 1728 | public IntPtr progress_hook; 1729 | /// This field is free to be set to any value and used during callbacks (like progress-report e.g.) 1730 | public IntPtr user_data; 1731 | /// Padding for later use 1732 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 13, ArraySubType = UnmanagedType.U4)] 1733 | private readonly uint[] pad3; 1734 | /// Row chunk of memory for YUVA planes 1735 | private readonly IntPtr memory_; 1736 | /// Row chunk of memory for ARGB planes 1737 | private readonly IntPtr memory_argb_; 1738 | /// Padding for later use 1739 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)] 1740 | private readonly uint[] pad4; 1741 | }; 1742 | 1743 | /// Structure for storing auxiliary statistics (mostly for lossy encoding) 1744 | [StructLayoutAttribute(LayoutKind.Sequential)] 1745 | internal struct WebPAuxStats 1746 | { 1747 | /// Final size 1748 | public int coded_size; 1749 | /// Peak-signal-to-noise ratio for Y 1750 | public float PSNRY; 1751 | /// Peak-signal-to-noise ratio for U 1752 | public float PSNRU; 1753 | /// Peak-signal-to-noise ratio for V 1754 | public float PSNRV; 1755 | /// Peak-signal-to-noise ratio for All 1756 | public float PSNRALL; 1757 | /// Peak-signal-to-noise ratio for Alpha 1758 | public float PSNRAlpha; 1759 | /// Number of intra4 1760 | public int block_count_intra4; 1761 | /// Number of intra16 1762 | public int block_count_intra16; 1763 | /// Number of skipped macro-blocks 1764 | public int block_count_skipped; 1765 | /// Approximate number of bytes spent for header 1766 | public int header_bytes; 1767 | /// Approximate number of bytes spent for mode-partition #0 1768 | public int mode_partition_0; 1769 | /// Approximate number of bytes spent for DC coefficients for segment 0 1770 | public int residual_bytes_DC_segments0; 1771 | /// Approximate number of bytes spent for AC coefficients for segment 0 1772 | public int residual_bytes_AC_segments0; 1773 | /// Approximate number of bytes spent for UV coefficients for segment 0 1774 | public int residual_bytes_uv_segments0; 1775 | /// Approximate number of bytes spent for DC coefficients for segment 1 1776 | public int residual_bytes_DC_segments1; 1777 | /// Approximate number of bytes spent for AC coefficients for segment 1 1778 | public int residual_bytes_AC_segments1; 1779 | /// Approximate number of bytes spent for UV coefficients for segment 1 1780 | public int residual_bytes_uv_segments1; 1781 | /// Approximate number of bytes spent for DC coefficients for segment 2 1782 | public int residual_bytes_DC_segments2; 1783 | /// Approximate number of bytes spent for AC coefficients for segment 2 1784 | public int residual_bytes_AC_segments2; 1785 | /// Approximate number of bytes spent for UV coefficients for segment 2 1786 | public int residual_bytes_uv_segments2; 1787 | /// Approximate number of bytes spent for DC coefficients for segment 3 1788 | public int residual_bytes_DC_segments3; 1789 | /// Approximate number of bytes spent for AC coefficients for segment 3 1790 | public int residual_bytes_AC_segments3; 1791 | /// Approximate number of bytes spent for UV coefficients for segment 3 1792 | public int residual_bytes_uv_segments3; 1793 | /// Number of macro-blocks in segments 0 1794 | public int segment_size_segments0; 1795 | /// Number of macro-blocks in segments 1 1796 | public int segment_size_segments1; 1797 | /// Number of macro-blocks in segments 2 1798 | public int segment_size_segments2; 1799 | /// Number of macro-blocks in segments 3 1800 | public int segment_size_segments3; 1801 | /// Quantizer values for segment 0 1802 | public int segment_quant_segments0; 1803 | /// Quantizer values for segment 1 1804 | public int segment_quant_segments1; 1805 | /// Quantizer values for segment 2 1806 | public int segment_quant_segments2; 1807 | /// Quantizer values for segment 3 1808 | public int segment_quant_segments3; 1809 | /// Filtering strength for segment 0 [0..63] 1810 | public int segment_level_segments0; 1811 | /// Filtering strength for segment 1 [0..63] 1812 | public int segment_level_segments1; 1813 | /// Filtering strength for segment 2 [0..63] 1814 | public int segment_level_segments2; 1815 | /// Filtering strength for segment 3 [0..63] 1816 | public int segment_level_segments3; 1817 | /// Size of the transparency data 1818 | public int alpha_data_size; 1819 | /// Size of the enhancement layer data 1820 | public int layer_data_size; 1821 | 1822 | // lossless encoder statistics 1823 | /// bit0:predictor bit1:cross-color transform bit2:subtract-green bit3:color indexing 1824 | public Int32 lossless_features; 1825 | /// Number of precision bits of histogram 1826 | public int histogram_bits; 1827 | /// Precision bits for transform 1828 | public int transform_bits; 1829 | /// Number of bits for color cache lookup 1830 | public int cache_bits; 1831 | /// Number of color in palette, if used 1832 | public int palette_size; 1833 | /// Final lossless size 1834 | public int lossless_size; 1835 | /// Lossless header (transform, Huffman, etc) size 1836 | public int lossless_hdr_size; 1837 | /// Lossless image data size 1838 | public int lossless_data_size; 1839 | /// Padding for later use 1840 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)] 1841 | private readonly uint[] pad; 1842 | }; 1843 | 1844 | [StructLayoutAttribute(LayoutKind.Sequential)] 1845 | internal struct WebPDecoderConfig 1846 | { 1847 | /// Immutable bit stream features (optional) 1848 | public WebPBitstreamFeatures input; 1849 | /// Output buffer (can point to external memory) 1850 | public WebPDecBuffer output; 1851 | /// Decoding options 1852 | public WebPDecoderOptions options; 1853 | } 1854 | 1855 | /// Output buffer 1856 | [StructLayoutAttribute(LayoutKind.Sequential)] 1857 | internal struct WebPDecBuffer 1858 | { 1859 | /// Color space 1860 | public WEBP_CSP_MODE colorspace; 1861 | /// Width of image 1862 | public int width; 1863 | /// Height of image 1864 | public int height; 1865 | /// If non-zero, 'internal_memory' pointer is not used. If value is '2' or more, the external memory is considered 'slow' and multiple read/write will be avoided 1866 | public int is_external_memory; 1867 | /// Output buffer parameters 1868 | public RGBA_YUVA_Buffer u; 1869 | /// Padding for later use 1870 | private readonly UInt32 pad1; 1871 | /// Padding for later use 1872 | private readonly UInt32 pad2; 1873 | /// Padding for later use 1874 | private readonly UInt32 pad3; 1875 | /// Padding for later use 1876 | private readonly UInt32 pad4; 1877 | /// Internally allocated memory (only when is_external_memory is 0). Should not be used externally, but accessed via WebPRGBABuffer 1878 | public IntPtr private_memory; 1879 | } 1880 | 1881 | /// Union of buffer parameters 1882 | [StructLayoutAttribute(LayoutKind.Explicit)] 1883 | internal struct RGBA_YUVA_Buffer 1884 | { 1885 | [FieldOffsetAttribute(0)] 1886 | public WebPRGBABuffer RGBA; 1887 | 1888 | [FieldOffsetAttribute(0)] 1889 | public WebPYUVABuffer YUVA; 1890 | } 1891 | 1892 | [StructLayoutAttribute(LayoutKind.Sequential)] 1893 | internal struct WebPYUVABuffer 1894 | { 1895 | /// Pointer to luma samples 1896 | public IntPtr y; 1897 | /// Pointer to chroma U samples 1898 | public IntPtr u; 1899 | /// Pointer to chroma V samples 1900 | public IntPtr v; 1901 | /// Pointer to alpha samples 1902 | public IntPtr a; 1903 | /// Luma stride 1904 | public int y_stride; 1905 | /// Chroma U stride 1906 | public int u_stride; 1907 | /// Chroma V stride 1908 | public int v_stride; 1909 | /// Alpha stride 1910 | public int a_stride; 1911 | /// Luma plane size 1912 | public UIntPtr y_size; 1913 | /// Chroma plane U size 1914 | public UIntPtr u_size; 1915 | /// Chroma plane V size 1916 | public UIntPtr v_size; 1917 | /// Alpha plane size 1918 | public UIntPtr a_size; 1919 | } 1920 | 1921 | /// Generic structure for describing the output sample buffer 1922 | [StructLayoutAttribute(LayoutKind.Sequential)] 1923 | internal struct WebPRGBABuffer 1924 | { 1925 | /// Pointer to RGBA samples 1926 | public IntPtr rgba; 1927 | /// Stride in bytes from one scanline to the next 1928 | public int stride; 1929 | /// Total size of the RGBA buffer 1930 | public UIntPtr size; 1931 | } 1932 | 1933 | /// Decoding options 1934 | [StructLayout(LayoutKind.Sequential)] 1935 | public struct WebPDecoderOptions 1936 | { 1937 | /// If true, skip the in-loop filtering 1938 | public int bypass_filtering; 1939 | /// If true, use faster point-wise up-sampler 1940 | public int no_fancy_upsampling; 1941 | /// If true, cropping is applied _first_ 1942 | public int use_cropping; 1943 | /// Left position for cropping. Will be snapped to even values 1944 | public int crop_left; 1945 | /// Top position for cropping. Will be snapped to even values 1946 | public int crop_top; 1947 | /// Width of the cropping area 1948 | public int crop_width; 1949 | /// Height of the cropping area 1950 | public int crop_height; 1951 | /// If true, scaling is applied _afterward_ 1952 | public int use_scaling; 1953 | /// Final width 1954 | public int scaled_width; 1955 | /// Final height 1956 | public int scaled_height; 1957 | /// If true, use multi-threaded decoding 1958 | public int use_threads; 1959 | /// Dithering strength (0=Off, 100=full) 1960 | public int dithering_strength; 1961 | /// Flip output vertically 1962 | public int flip; 1963 | /// Alpha dithering strength in [0..100] 1964 | public int alpha_dithering_strength; 1965 | /// Padding for later use 1966 | private readonly UInt32 pad1; 1967 | /// Padding for later use 1968 | private readonly UInt32 pad2; 1969 | /// Padding for later use 1970 | private readonly UInt32 pad3; 1971 | /// Padding for later use 1972 | private readonly UInt32 pad4; 1973 | /// Padding for later use 1974 | private readonly UInt32 pad5; 1975 | }; 1976 | #endregion 1977 | } --------------------------------------------------------------------------------