├── 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 | }
--------------------------------------------------------------------------------