├── .gitignore ├── .paket ├── paket.bootstrapper.exe └── paket.targets ├── .travis.yml ├── Imazen.WebP.sln ├── LICENSE.txt ├── RELEASE_NOTES.md ├── appveyor.yml ├── build.cmd ├── build.fsx ├── build.sh ├── docs ├── content │ └── .dir ├── files │ └── img │ │ ├── logo-template.pdn │ │ └── logo.png └── tools │ ├── generate.fsx │ └── templates │ └── template.cshtml ├── download_libwebp.ps1 ├── interop ├── decode.h ├── encode.h ├── format_constants.h ├── types-prefix-for-headers.txt └── types.h ├── libwebp-build-instructions.txt ├── open_commandline.bat ├── paket.dependencies ├── paket.lock ├── readme.md └── src ├── Imazen.Test.Webp ├── Imazen.Test.Webp.csproj ├── Properties │ └── AssemblyInfo.cs ├── TestSimpleDecoder.cs ├── TestSimpleEncoder.cs ├── TestSimpleEncoderDecoderRoundtrip.cs ├── packages.config ├── paket.references ├── testimage.jpg ├── testimage.webp ├── x64 │ └── put_libwebp_here.txt └── x86 │ └── put_libwebp_here.txt └── Imazen.WebP ├── .gitignore ├── Extern ├── Constants.cs ├── Decode.cs ├── DecodeInlines.cs ├── Encode.cs ├── EncodeInlines.cs ├── Extra.cs └── LoadLibrary.cs ├── Imazen.WebP.csproj ├── Imazen.WebP.csproj.paket.template ├── Properties └── AssemblyInfo.cs ├── SimpleDecoder.cs ├── SimpleEncoder.cs └── packages └── repositories.config /.gitignore: -------------------------------------------------------------------------------- 1 | Imazen.WebP.dll 2 | Imazen.WebP.pdb 3 | Imazen.WebP.xml 4 | *.FileListAbsolute.txt 5 | *.cache 6 | bin/ 7 | obj/ 8 | *.suo 9 | packages/**/* 10 | .paket/paket.exe 11 | paket-files 12 | .fake 13 | docs/content/license.md 14 | docs/content/release-notes.md 15 | docs/output/ 16 | *.dll 17 | src/Imazen.Test.Webp/Imazen.Test.Webp.csproj.user 18 | -------------------------------------------------------------------------------- /.paket/paket.bootstrapper.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imazen/libwebp-net/a19c9b91f9282b890110a5fe2ded5873439f3177/.paket/paket.bootstrapper.exe -------------------------------------------------------------------------------- /.paket/paket.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | true 6 | 7 | true 8 | $(MSBuildThisFileDirectory) 9 | $(MSBuildThisFileDirectory)..\ 10 | 11 | 12 | 13 | $(PaketToolsPath)paket.exe 14 | $(PaketToolsPath)paket.bootstrapper.exe 15 | "$(PaketExePath)" 16 | mono --runtime=v4.0.30319 "$(PaketExePath)" 17 | "$(PaketBootStrapperExePath)" 18 | mono --runtime=v4.0.30319 $(PaketBootStrapperExePath) 19 | 20 | $(PaketCommand) restore 21 | $(PaketBootStrapperCommand) 22 | 23 | RestorePackages; $(BuildDependsOn); 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | 3 | sudo: false # use the new container-based Travis infrastructure 4 | 5 | script: 6 | - ./build.sh All 7 | -------------------------------------------------------------------------------- /Imazen.WebP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30723.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".paket", ".paket", "{E5FD4A8E-2EA4-4B64-8909-4EF4B493385B}" 7 | ProjectSection(SolutionItems) = preProject 8 | paket.dependencies = paket.dependencies 9 | EndProjectSection 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imazen.WebP", "src\Imazen.WebP\Imazen.WebP.csproj", "{92F607A3-2F04-4536-8346-B6FEF8B774FF}" 12 | EndProject 13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Imazen.Test.Webp", "src\Imazen.Test.Webp\Imazen.Test.Webp.csproj", "{6C57E3C1-C04F-4C96-AD90-CDA79AE53574}" 14 | EndProject 15 | Global 16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 17 | Debug|Any CPU = Debug|Any CPU 18 | Debug|x64 = Debug|x64 19 | Debug|x86 = Debug|x86 20 | Release|Any CPU = Release|Any CPU 21 | Release|x64 = Release|x64 22 | Release|x86 = Release|x86 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Debug|x64.ActiveCfg = Debug|x64 28 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Debug|x64.Build.0 = Debug|x64 29 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Debug|x86.ActiveCfg = Debug|x86 30 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Debug|x86.Build.0 = Debug|x86 31 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Release|Any CPU.Build.0 = Release|Any CPU 33 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Release|x64.ActiveCfg = Release|x64 34 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Release|x64.Build.0 = Release|x64 35 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Release|x86.ActiveCfg = Release|x86 36 | {92F607A3-2F04-4536-8346-B6FEF8B774FF}.Release|x86.Build.0 = Release|x86 37 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 38 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Debug|Any CPU.Build.0 = Debug|Any CPU 39 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Debug|x64.ActiveCfg = Debug|x64 40 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Debug|x64.Build.0 = Debug|x64 41 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Debug|x86.ActiveCfg = Debug|x86 42 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Debug|x86.Build.0 = Debug|x86 43 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Release|Any CPU.ActiveCfg = Release|Any CPU 44 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Release|Any CPU.Build.0 = Release|Any CPU 45 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Release|x64.ActiveCfg = Release|x64 46 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Release|x64.Build.0 = Release|x64 47 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Release|x86.ActiveCfg = Release|x86 48 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574}.Release|x86.Build.0 = Release|x86 49 | EndGlobalSection 50 | GlobalSection(SolutionProperties) = preSolution 51 | HideSolutionNode = FALSE 52 | EndGlobalSection 53 | EndGlobal 54 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Imazen 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /RELEASE_NOTES.md: -------------------------------------------------------------------------------- 1 | ### 9.0.1 - October 24 2015 2 | * Upgrade to .NET 4 3 | 4 | #### 9.0.0-beta - October 7 2015 5 | * Integrate project scaffold 6 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | init: 2 | - git config --global core.autocrlf input 3 | build_script: 4 | - ps: '& ".\download_libwebp.ps1"' 5 | - cmd: build.cmd NuGet 6 | #test: off 7 | version: 0.6.0.{build} 8 | artifacts: 9 | - path: bin 10 | name: bin 11 | - path: bin\*.nupkg 12 | 13 | on_success: 14 | - ps: Push-AppveyorArtifact "bin/Imazen.WebP*.nupkg" 15 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | cls 3 | 4 | .paket\paket.bootstrapper.exe 5 | if errorlevel 1 ( 6 | exit /b %errorlevel% 7 | ) 8 | 9 | .paket\paket.exe restore 10 | if errorlevel 1 ( 11 | exit /b %errorlevel% 12 | ) 13 | 14 | IF NOT EXIST build.fsx ( 15 | .paket\paket.exe update 16 | packages\FAKE\tools\FAKE.exe init.fsx 17 | ) 18 | packages\FAKE\tools\FAKE.exe build.fsx %* 19 | -------------------------------------------------------------------------------- /build.fsx: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------- 2 | // FAKE build script 3 | // -------------------------------------------------------------------------------------- 4 | 5 | #r @"packages/FAKE/tools/FakeLib.dll" 6 | open Fake 7 | open Fake.Git 8 | open Fake.AssemblyInfoFile 9 | open Fake.ReleaseNotesHelper 10 | open Fake.UserInputHelper 11 | open Fake.Testing 12 | open System 13 | open System.IO 14 | #if MONO 15 | #else 16 | #load "packages/SourceLink.Fake/tools/Fake.fsx" 17 | open SourceLink 18 | #endif 19 | 20 | // -------------------------------------------------------------------------------------- 21 | // START TODO: Provide project-specific details below 22 | // -------------------------------------------------------------------------------------- 23 | 24 | // Information about the project are used 25 | // - for version and project name in generated AssemblyInfo file 26 | // - by the generated NuGet package 27 | // - to run tests and to publish documentation on GitHub gh-pages 28 | // - for documentation, you also need to edit info in "docs/tools/generate.fsx" 29 | 30 | // The name of the project 31 | // (used by attributes in AssemblyInfo, name of a NuGet package and directory in 'src') 32 | let project = "Imazen.WebP" 33 | 34 | // Short summary of the project 35 | // (used as description in AssemblyInfo and as a short summary for NuGet package) 36 | let summary = ".NET wrapper for libwebp" 37 | 38 | // Longer description of the project 39 | // (used as a description for NuGet package; line breaks are automatically cleaned up) 40 | let description = "Imazen .NET wrapper for libwebp" 41 | 42 | // List of author names (for NuGet package) 43 | let authors = [ "Nathanael Jones" ] 44 | 45 | // Tags for your project (for NuGet package) 46 | let tags = "webp imageresizer" 47 | 48 | // File system information 49 | let solutionFile = "Imazen.WebP.sln" 50 | 51 | // Pattern specifying assemblies to be tested using NUnit 52 | let testAssemblies = "bin/**/*Test.*.dll" 53 | //let testAssemblies = "src/Imazen.Test.Webp/**/bin/Release/*Test.*.dll" 54 | 55 | // Git configuration (used for publishing documentation in gh-pages branch) 56 | // The profile where the project is posted 57 | let gitOwner = "imazen" 58 | let gitHome = "https://github.com/" + gitOwner 59 | 60 | // The name of the project on GitHub 61 | let gitName = "libwebp-net" 62 | 63 | // The url for the raw files hosted 64 | let gitRaw = environVarOrDefault "gitRaw" "https://raw.github.com/imazen" 65 | 66 | // -------------------------------------------------------------------------------------- 67 | // END TODO: The rest of the file includes standard build steps 68 | // -------------------------------------------------------------------------------------- 69 | 70 | // Read additional information from the release notes document 71 | let release = LoadReleaseNotes "RELEASE_NOTES.md" 72 | 73 | // Helper active pattern for project types 74 | let (|Fsproj|Csproj|Vbproj|) (projFileName:string) = 75 | match projFileName with 76 | | f when f.EndsWith("fsproj") -> Fsproj 77 | | f when f.EndsWith("csproj") -> Csproj 78 | | f when f.EndsWith("vbproj") -> Vbproj 79 | | _ -> failwith (sprintf "Project file %s not supported. Unknown project type." projFileName) 80 | 81 | // Generate assembly info files with the right version & up-to-date information 82 | Target "AssemblyInfo" (fun _ -> 83 | let getAssemblyInfoAttributes projectName = 84 | [ Attribute.Title (projectName) 85 | Attribute.Product project 86 | Attribute.Description summary 87 | Attribute.Version release.AssemblyVersion 88 | Attribute.FileVersion release.AssemblyVersion ] 89 | 90 | let getProjectDetails projectPath = 91 | let projectName = System.IO.Path.GetFileNameWithoutExtension(projectPath) 92 | ( projectPath, 93 | projectName, 94 | System.IO.Path.GetDirectoryName(projectPath), 95 | (getAssemblyInfoAttributes projectName) 96 | ) 97 | 98 | !! "src/**/*.??proj" 99 | |> Seq.map getProjectDetails 100 | |> Seq.iter (fun (projFileName, projectName, folderName, attributes) -> 101 | match projFileName with 102 | | Fsproj -> CreateFSharpAssemblyInfo (folderName @@ "AssemblyInfo.fs") attributes 103 | | Csproj -> CreateCSharpAssemblyInfo ((folderName @@ "Properties") @@ "AssemblyInfo.cs") attributes 104 | | Vbproj -> CreateVisualBasicAssemblyInfo ((folderName @@ "My Project") @@ "AssemblyInfo.vb") attributes 105 | ) 106 | ) 107 | 108 | // Copies binaries from default VS location to expected bin folder 109 | // But keeps a subdirectory structure for each project in the 110 | // src folder to support multiple project outputs 111 | Target "CopyBinaries" (fun _ -> 112 | !! "src/**/*.??proj" 113 | |> Seq.map (fun f -> ((System.IO.Path.GetDirectoryName f) @@ "bin/Release", "bin" @@ (System.IO.Path.GetFileNameWithoutExtension f))) 114 | |> Seq.iter (fun (fromDir, toDir) -> CopyDir toDir fromDir (fun _ -> true)) 115 | ) 116 | 117 | // -------------------------------------------------------------------------------------- 118 | // Clean build results 119 | 120 | Target "Clean" (fun _ -> 121 | CleanDirs ["bin"; "temp"; "src/Imazen.Test.Webp/bin"; "src/Imazen.Test.Webp/obj"; "src/Imazen.WebP/bin"; "src/Imazen.WebP/obj"] 122 | ) 123 | 124 | Target "CleanDocs" (fun _ -> 125 | CleanDirs ["docs/output"] 126 | ) 127 | 128 | // -------------------------------------------------------------------------------------- 129 | // Build library & test project 130 | 131 | Target "Build" (fun _ -> 132 | !! solutionFile 133 | |> MSBuildRelease "" "Rebuild" 134 | |> ignore 135 | ) 136 | 137 | // -------------------------------------------------------------------------------------- 138 | // Run the unit tests using test runner 139 | 140 | Target "RunTests" (fun _ -> 141 | !! testAssemblies 142 | |> xUnit2 (fun p -> 143 | { p with 144 | TimeOut = TimeSpan.FromMinutes 20. 145 | ToolPath = "packages/xunit.runner.console/tools/xunit.console.exe" }) 146 | ) 147 | 148 | Target "RunTestsX86" (fun _ -> 149 | !! testAssemblies 150 | |> xUnit2 (fun p -> 151 | { p with 152 | TimeOut = TimeSpan.FromMinutes 20. 153 | ToolPath = "packages/xunit.runner.console/tools/xunit.console.x86.exe" }) 154 | ) 155 | 156 | 157 | 158 | 159 | #if MONO 160 | #else 161 | // -------------------------------------------------------------------------------------- 162 | // SourceLink allows Source Indexing on the PDB generated by the compiler, this allows 163 | // the ability to step through the source code of external libraries http://ctaggart.github.io/SourceLink/ 164 | 165 | Target "SourceLink" (fun _ -> 166 | let baseUrl = sprintf "%s/%s/{0}/%%var2%%" gitRaw project 167 | !! "src/**/*.??proj" 168 | |> Seq.iter (fun projFile -> 169 | let proj = VsProj.LoadRelease projFile 170 | SourceLink.Index proj.CompilesNotLinked proj.OutputFilePdb __SOURCE_DIRECTORY__ baseUrl 171 | ) 172 | ) 173 | 174 | #endif 175 | 176 | // -------------------------------------------------------------------------------------- 177 | // Build a NuGet package 178 | 179 | Target "NuGet" (fun _ -> 180 | Paket.Pack(fun p -> 181 | { p with 182 | OutputPath = "bin" 183 | Version = release.NugetVersion 184 | ReleaseNotes = toLines release.Notes}) 185 | ) 186 | 187 | Target "PublishNuget" (fun _ -> 188 | Paket.Push(fun p -> 189 | { p with 190 | WorkingDir = "bin" }) 191 | ) 192 | 193 | 194 | // -------------------------------------------------------------------------------------- 195 | // Generate the documentation 196 | 197 | Target "GenerateReferenceDocs" (fun _ -> 198 | if not <| executeFSIWithArgs "docs/tools" "generate.fsx" ["--define:RELEASE"; "--define:REFERENCE"] [] then 199 | failwith "generating reference documentation failed" 200 | ) 201 | 202 | let generateHelp' fail debug = 203 | let args = 204 | if debug then ["--define:HELP"] 205 | else ["--define:RELEASE"; "--define:HELP"] 206 | if executeFSIWithArgs "docs/tools" "generate.fsx" args [] then 207 | traceImportant "Help generated" 208 | else 209 | if fail then 210 | failwith "generating help documentation failed" 211 | else 212 | traceImportant "generating help documentation failed" 213 | 214 | let generateHelp fail = 215 | generateHelp' fail false 216 | 217 | Target "GenerateHelp" (fun _ -> 218 | DeleteFile "docs/content/release-notes.md" 219 | CopyFile "docs/content/" "RELEASE_NOTES.md" 220 | Rename "docs/content/release-notes.md" "docs/content/RELEASE_NOTES.md" 221 | 222 | DeleteFile "docs/content/license.md" 223 | CopyFile "docs/content/" "LICENSE.txt" 224 | Rename "docs/content/license.md" "docs/content/LICENSE.txt" 225 | 226 | generateHelp true 227 | ) 228 | 229 | Target "GenerateHelpDebug" (fun _ -> 230 | DeleteFile "docs/content/release-notes.md" 231 | CopyFile "docs/content/" "RELEASE_NOTES.md" 232 | Rename "docs/content/release-notes.md" "docs/content/RELEASE_NOTES.md" 233 | 234 | DeleteFile "docs/content/license.md" 235 | CopyFile "docs/content/" "LICENSE.txt" 236 | Rename "docs/content/license.md" "docs/content/LICENSE.txt" 237 | 238 | generateHelp' true true 239 | ) 240 | 241 | Target "KeepRunning" (fun _ -> 242 | use watcher = !! "docs/content/**/*.*" |> WatchChanges (fun changes -> 243 | generateHelp false 244 | ) 245 | 246 | traceImportant "Waiting for help edits. Press any key to stop." 247 | 248 | System.Console.ReadKey() |> ignore 249 | 250 | watcher.Dispose() 251 | ) 252 | 253 | Target "GenerateDocs" DoNothing 254 | 255 | let createIndexFsx lang = 256 | let content = """(*** hide ***) 257 | // This block of code is omitted in the generated HTML documentation. Use 258 | // it to define helpers that you do not want to show in the documentation. 259 | #I "../../../bin" 260 | 261 | (** 262 | F# Project Scaffold ({0}) 263 | ========================= 264 | *) 265 | """ 266 | let targetDir = "docs/content" @@ lang 267 | let targetFile = targetDir @@ "index.fsx" 268 | ensureDirectory targetDir 269 | System.IO.File.WriteAllText(targetFile, System.String.Format(content, lang)) 270 | 271 | Target "AddLangDocs" (fun _ -> 272 | let args = System.Environment.GetCommandLineArgs() 273 | if args.Length < 4 then 274 | failwith "Language not specified." 275 | 276 | args.[3..] 277 | |> Seq.iter (fun lang -> 278 | if lang.Length <> 2 && lang.Length <> 3 then 279 | failwithf "Language must be 2 or 3 characters (ex. 'de', 'fr', 'ja', 'gsw', etc.): %s" lang 280 | 281 | let templateFileName = "template.cshtml" 282 | let templateDir = "docs/tools/templates" 283 | let langTemplateDir = templateDir @@ lang 284 | let langTemplateFileName = langTemplateDir @@ templateFileName 285 | 286 | if System.IO.File.Exists(langTemplateFileName) then 287 | failwithf "Documents for specified language '%s' have already been added." lang 288 | 289 | ensureDirectory langTemplateDir 290 | Copy langTemplateDir [ templateDir @@ templateFileName ] 291 | 292 | createIndexFsx lang) 293 | ) 294 | 295 | // -------------------------------------------------------------------------------------- 296 | // Release Scripts 297 | 298 | Target "ReleaseDocs" (fun _ -> 299 | let tempDocsDir = "temp/gh-pages" 300 | CleanDir tempDocsDir 301 | Repository.cloneSingleBranch "" (gitHome + "/" + gitName + ".git") "gh-pages" tempDocsDir 302 | 303 | CopyRecursive "docs/output" tempDocsDir true |> tracefn "%A" 304 | StageAll tempDocsDir 305 | Git.Commit.Commit tempDocsDir (sprintf "Update generated documentation for version %s" release.NugetVersion) 306 | Branches.push tempDocsDir 307 | ) 308 | 309 | #load "paket-files/fsharp/FAKE/modules/Octokit/Octokit.fsx" 310 | open Octokit 311 | 312 | Target "Release" (fun _ -> 313 | let user = 314 | match getBuildParam "github-user" with 315 | | s when not (String.IsNullOrWhiteSpace s) -> s 316 | | _ -> getUserInput "Username: " 317 | let pw = 318 | match getBuildParam "github-pw" with 319 | | s when not (String.IsNullOrWhiteSpace s) -> s 320 | | _ -> getUserPassword "Password: " 321 | let remote = 322 | Git.CommandHelper.getGitResult "" "remote -v" 323 | |> Seq.filter (fun (s: string) -> s.EndsWith("(push)")) 324 | |> Seq.tryFind (fun (s: string) -> s.Contains(gitOwner + "/" + gitName)) 325 | |> function None -> gitHome + "/" + gitName | Some (s: string) -> s.Split().[0] 326 | 327 | StageAll "" 328 | Git.Commit.Commit "" (sprintf "Bump version to %s" release.NugetVersion) 329 | Branches.pushBranch "" remote (Information.getBranchName "") 330 | 331 | Branches.tag "" release.NugetVersion 332 | Branches.pushTag "" remote release.NugetVersion 333 | 334 | // release on github 335 | createClient user pw 336 | |> createDraft gitOwner gitName release.NugetVersion (release.SemVer.PreRelease <> None) release.Notes 337 | // TODO: |> uploadFile "PATH_TO_FILE" 338 | |> releaseDraft 339 | |> Async.RunSynchronously 340 | ) 341 | 342 | Target "BuildPackage" DoNothing 343 | 344 | // -------------------------------------------------------------------------------------- 345 | // Run all targets by default. Invoke 'build ' to override 346 | 347 | Target "All" DoNothing 348 | 349 | "Clean" 350 | ==> "AssemblyInfo" 351 | ==> "Build" 352 | ==> "CopyBinaries" 353 | ==> "RunTests" 354 | ==> "RunTestsX86" 355 | ==> "GenerateReferenceDocs" 356 | ==> "GenerateDocs" 357 | ==> "All" 358 | =?> ("ReleaseDocs",isLocalBuild) 359 | 360 | "All" 361 | #if MONO 362 | #else 363 | =?> ("SourceLink", Pdbstr.tryFind().IsSome ) 364 | #endif 365 | ==> "NuGet" 366 | ==> "BuildPackage" 367 | 368 | "CleanDocs" 369 | ==> "GenerateHelp" 370 | ==> "GenerateReferenceDocs" 371 | ==> "GenerateDocs" 372 | 373 | "CleanDocs" 374 | ==> "GenerateHelpDebug" 375 | 376 | "GenerateHelp" 377 | ==> "KeepRunning" 378 | 379 | "ReleaseDocs" 380 | ==> "Release" 381 | 382 | "BuildPackage" 383 | ==> "PublishNuget" 384 | ==> "Release" 385 | 386 | RunTargetOrDefault "All" 387 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | set -o pipefail 5 | 6 | cd `dirname $0` 7 | 8 | FSIARGS="" 9 | OS=${OS:-"unknown"} 10 | if [[ "$OS" != "Windows_NT" ]] 11 | then 12 | FSIARGS="--fsiargs -d:MONO" 13 | fi 14 | 15 | function run() { 16 | if [[ "$OS" != "Windows_NT" ]] 17 | then 18 | mono "$@" 19 | else 20 | "$@" 21 | fi 22 | } 23 | 24 | run .paket/paket.bootstrapper.exe 25 | 26 | if [[ "$OS" != "Windows_NT" ]] && 27 | [ ! -e ~/.config/.mono/certs ] 28 | then 29 | mozroots --import --sync --quiet 30 | fi 31 | 32 | run .paket/paket.exe restore 33 | 34 | [ ! -e build.fsx ] && run .paket/paket.exe update 35 | [ ! -e build.fsx ] && run packages/FAKE/tools/FAKE.exe init.fsx 36 | run packages/FAKE/tools/FAKE.exe "$@" $FSIARGS build.fsx 37 | 38 | -------------------------------------------------------------------------------- /docs/content/.dir: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imazen/libwebp-net/a19c9b91f9282b890110a5fe2ded5873439f3177/docs/content/.dir -------------------------------------------------------------------------------- /docs/files/img/logo-template.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imazen/libwebp-net/a19c9b91f9282b890110a5fe2ded5873439f3177/docs/files/img/logo-template.pdn -------------------------------------------------------------------------------- /docs/files/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imazen/libwebp-net/a19c9b91f9282b890110a5fe2ded5873439f3177/docs/files/img/logo.png -------------------------------------------------------------------------------- /docs/tools/generate.fsx: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------- 2 | // Builds the documentation from `.fsx` and `.md` files in the 'docs/content' directory 3 | // (the generated documentation is stored in the 'docs/output' directory) 4 | // -------------------------------------------------------------------------------------- 5 | 6 | // Binaries that have XML documentation (in a corresponding generated XML file) 7 | // Any binary output / copied to bin/projectName/projectName.dll will 8 | // automatically be added as a binary to generate API docs for. 9 | // for binaries output to root bin folder please add the filename only to the 10 | // referenceBinaries list below in order to generate documentation for the binaries. 11 | // (This is the original behaviour of ProjectScaffold prior to multi project support) 12 | let referenceBinaries = [] 13 | // Web site location for the generated documentation 14 | let website = "/spike" 15 | 16 | let githubLink = "http://github.com/imazen/libwebp-net" 17 | 18 | // Specify more information about your project 19 | let info = 20 | [ "project-name", "libwebp-net" 21 | "project-author", "Imazen" 22 | "project-summary", "A .NET wrapper for libwebp 0.4.1" 23 | "project-github", githubLink 24 | "project-nuget", "http://nuget.org/packages/Imazen.WebP" ] 25 | 26 | // -------------------------------------------------------------------------------------- 27 | // For typical project, no changes are needed below 28 | // -------------------------------------------------------------------------------------- 29 | 30 | #I "../../packages/FAKE/tools/" 31 | #load "../../packages/FSharp.Formatting/FSharp.Formatting.fsx" 32 | #r "NuGet.Core.dll" 33 | #r "FakeLib.dll" 34 | open Fake 35 | open System.IO 36 | open Fake.FileHelper 37 | open FSharp.Literate 38 | open FSharp.MetadataFormat 39 | 40 | // When called from 'build.fsx', use the public project URL as 41 | // otherwise, use the current 'output' directory. 42 | #if RELEASE 43 | let root = website 44 | #else 45 | let root = "file://" + (__SOURCE_DIRECTORY__ @@ "../output") 46 | #endif 47 | 48 | // Paths with template/source/output locations 49 | let bin = __SOURCE_DIRECTORY__ @@ "../../bin" 50 | let content = __SOURCE_DIRECTORY__ @@ "../content" 51 | let output = __SOURCE_DIRECTORY__ @@ "../output" 52 | let files = __SOURCE_DIRECTORY__ @@ "../files" 53 | let templates = __SOURCE_DIRECTORY__ @@ "templates" 54 | let formatting = __SOURCE_DIRECTORY__ @@ "../../packages/FSharp.Formatting/" 55 | let docTemplate = "docpage.cshtml" 56 | 57 | // Where to look for *.csproj templates (in this order) 58 | let layoutRootsAll = new System.Collections.Generic.Dictionary() 59 | layoutRootsAll.Add("en",[ templates; formatting @@ "templates" 60 | formatting @@ "templates/reference" ]) 61 | subDirectories (directoryInfo templates) 62 | |> Seq.iter (fun d -> 63 | let name = d.Name 64 | if name.Length = 2 || name.Length = 3 then 65 | layoutRootsAll.Add( 66 | name, [templates @@ name 67 | formatting @@ "templates" 68 | formatting @@ "templates/reference" ])) 69 | 70 | // Copy static files and CSS + JS from F# Formatting 71 | let copyFiles () = 72 | CopyRecursive files output true |> Log "Copying file: " 73 | ensureDirectory (output @@ "content") 74 | CopyRecursive (formatting @@ "styles") (output @@ "content") true 75 | |> Log "Copying styles and scripts: " 76 | 77 | let binaries = 78 | let manuallyAdded = 79 | referenceBinaries 80 | |> List.map (fun b -> bin @@ b) 81 | 82 | let conventionBased = 83 | directoryInfo bin 84 | |> subDirectories 85 | |> Array.map (fun d -> d.FullName @@ (sprintf "%s.dll" d.Name)) 86 | |> List.ofArray 87 | 88 | conventionBased @ manuallyAdded 89 | 90 | let libDirs = 91 | let conventionBasedbinDirs = 92 | directoryInfo bin 93 | |> subDirectories 94 | |> Array.map (fun d -> d.FullName) 95 | |> List.ofArray 96 | 97 | conventionBasedbinDirs @ [bin] 98 | 99 | // Build API reference from XML comments 100 | let buildReference () = 101 | CleanDir (output @@ "reference") 102 | MetadataFormat.Generate 103 | ( binaries, output @@ "reference", layoutRootsAll.["en"], 104 | parameters = ("root", root)::info, 105 | sourceRepo = githubLink @@ "tree/master", 106 | sourceFolder = __SOURCE_DIRECTORY__ @@ ".." @@ "..", 107 | publicOnly = true,libDirs = libDirs ) 108 | 109 | // Build documentation from `fsx` and `md` files in `docs/content` 110 | let buildDocumentation () = 111 | 112 | // First, process files which are placed in the content root directory. 113 | 114 | Literate.ProcessDirectory 115 | ( content, docTemplate, output, replacements = ("root", root)::info, 116 | layoutRoots = layoutRootsAll.["en"], 117 | generateAnchors = true, 118 | processRecursive = false) 119 | 120 | // And then process files which are placed in the sub directories 121 | // (some sub directories might be for specific language). 122 | 123 | let subdirs = Directory.EnumerateDirectories(content, "*", SearchOption.TopDirectoryOnly) 124 | for dir in subdirs do 125 | let dirname = (new DirectoryInfo(dir)).Name 126 | let layoutRoots = 127 | // Check whether this directory name is for specific language 128 | let key = layoutRootsAll.Keys 129 | |> Seq.tryFind (fun i -> i = dirname) 130 | match key with 131 | | Some lang -> layoutRootsAll.[lang] 132 | | None -> layoutRootsAll.["en"] // "en" is the default language 133 | 134 | Literate.ProcessDirectory 135 | ( dir, docTemplate, output @@ dirname, replacements = ("root", root)::info, 136 | layoutRoots = layoutRoots, 137 | generateAnchors = true ) 138 | 139 | // Generate 140 | copyFiles() 141 | #if HELP 142 | buildDocumentation() 143 | #endif 144 | #if REFERENCE 145 | buildReference() 146 | #endif 147 | -------------------------------------------------------------------------------- /docs/tools/templates/template.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | @Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 |
24 |
25 | 29 |

@Properties["project-name"]

30 |
31 |
32 |
33 |
34 | @RenderBody() 35 |
36 |
37 | F# Project 38 | 53 |
54 |
55 |
56 | Fork me on GitHub 57 | 58 | 59 | -------------------------------------------------------------------------------- /download_libwebp.ps1: -------------------------------------------------------------------------------- 1 | $url = "https://s3.amazonaws.com/resizer-dynamic-downloads/webp/0.5.2/x86_64/libwebp.dll" 2 | $output = "$PSScriptRoot\src\Imazen.Test.Webp\x64\libwebp.dll" 3 | 4 | Invoke-WebRequest -Uri $url -OutFile $output 5 | 6 | $url = "https://s3.amazonaws.com/resizer-dynamic-downloads/webp/0.5.2/x86/libwebp.dll" 7 | $output = "$PSScriptRoot\src\Imazen.Test.Webp\x86\libwebp.dll" 8 | 9 | Invoke-WebRequest -Uri $url -OutFile $output -------------------------------------------------------------------------------- /interop/decode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Main decoding functions for WebP images. 11 | // 12 | // Author: Skal (pascal.massimino@gmail.com) 13 | 14 | #ifndef WEBP_WEBP_DECODE_H_ 15 | #define WEBP_WEBP_DECODE_H_ 16 | 17 | #include "./types.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b) 24 | 25 | // Note: forward declaring enumerations is not allowed in (strict) C and C++, 26 | // the types are left here for reference. 27 | // typedef enum VP8StatusCode VP8StatusCode; 28 | // typedef enum WEBP_CSP_MODE WEBP_CSP_MODE; 29 | typedef struct WebPRGBABuffer WebPRGBABuffer; 30 | typedef struct WebPYUVABuffer WebPYUVABuffer; 31 | typedef struct WebPDecBuffer WebPDecBuffer; 32 | typedef struct WebPIDecoder WebPIDecoder; 33 | typedef struct WebPBitstreamFeatures WebPBitstreamFeatures; 34 | typedef struct WebPDecoderOptions WebPDecoderOptions; 35 | typedef struct WebPDecoderConfig WebPDecoderConfig; 36 | 37 | // Return the decoder's version number, packed in hexadecimal using 8bits for 38 | // each of major/minor/revision. E.g: v2.5.7 is 0x020507. 39 | WEBP_EXTERN(int) WebPGetDecoderVersion(void); 40 | 41 | // Retrieve basic header information: width, height. 42 | // This function will also validate the header, returning true on success, 43 | // false otherwise. '*width' and '*height' are only valid on successful return. 44 | // Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. 45 | WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size, 46 | int* width, int* height); 47 | 48 | // Decodes WebP images pointed to by 'data' and returns RGBA samples, along 49 | // with the dimensions in *width and *height. The ordering of samples in 50 | // memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). 51 | // The returned pointer should be deleted calling WebPFree(). 52 | // Returns NULL in case of error. 53 | WEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size, 54 | int* width, int* height); 55 | 56 | // Same as WebPDecodeRGBA, but returning A, R, G, B, A, R, G, B... ordered data. 57 | WEBP_EXTERN(uint8_t*) WebPDecodeARGB(const uint8_t* data, size_t data_size, 58 | int* width, int* height); 59 | 60 | // Same as WebPDecodeRGBA, but returning B, G, R, A, B, G, R, A... ordered data. 61 | WEBP_EXTERN(uint8_t*) WebPDecodeBGRA(const uint8_t* data, size_t data_size, 62 | int* width, int* height); 63 | 64 | // Same as WebPDecodeRGBA, but returning R, G, B, R, G, B... ordered data. 65 | // If the bitstream contains transparency, it is ignored. 66 | WEBP_EXTERN(uint8_t*) WebPDecodeRGB(const uint8_t* data, size_t data_size, 67 | int* width, int* height); 68 | 69 | // Same as WebPDecodeRGB, but returning B, G, R, B, G, R... ordered data. 70 | WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size, 71 | int* width, int* height); 72 | 73 | 74 | // Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer 75 | // returned is the Y samples buffer. Upon return, *u and *v will point to 76 | // the U and V chroma data. These U and V buffers need NOT be passed to 77 | // WebPFree(), unlike the returned Y luma one. The dimension of the U and V 78 | // planes are both (*width + 1) / 2 and (*height + 1)/ 2. 79 | // Upon return, the Y buffer has a stride returned as '*stride', while U and V 80 | // have a common stride returned as '*uv_stride'. 81 | // Return NULL in case of error. 82 | // (*) Also named Y'CbCr. See: http://en.wikipedia.org/wiki/YCbCr 83 | WEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size, 84 | int* width, int* height, 85 | uint8_t** u, uint8_t** v, 86 | int* stride, int* uv_stride); 87 | 88 | // Releases memory returned by the WebPDecode*() functions above. 89 | WEBP_EXTERN(void) WebPFree(void* ptr); 90 | 91 | // These five functions are variants of the above ones, that decode the image 92 | // directly into a pre-allocated buffer 'output_buffer'. The maximum storage 93 | // available in this buffer is indicated by 'output_buffer_size'. If this 94 | // storage is not sufficient (or an error occurred), NULL is returned. 95 | // Otherwise, output_buffer is returned, for convenience. 96 | // The parameter 'output_stride' specifies the distance (in bytes) 97 | // between scanlines. Hence, output_buffer_size is expected to be at least 98 | // output_stride x picture-height. 99 | WEBP_EXTERN(uint8_t*) WebPDecodeRGBAInto( 100 | const uint8_t* data, size_t data_size, 101 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 102 | WEBP_EXTERN(uint8_t*) WebPDecodeARGBInto( 103 | const uint8_t* data, size_t data_size, 104 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 105 | WEBP_EXTERN(uint8_t*) WebPDecodeBGRAInto( 106 | const uint8_t* data, size_t data_size, 107 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 108 | 109 | // RGB and BGR variants. Here too the transparency information, if present, 110 | // will be dropped and ignored. 111 | WEBP_EXTERN(uint8_t*) WebPDecodeRGBInto( 112 | const uint8_t* data, size_t data_size, 113 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 114 | WEBP_EXTERN(uint8_t*) WebPDecodeBGRInto( 115 | const uint8_t* data, size_t data_size, 116 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 117 | 118 | // WebPDecodeYUVInto() is a variant of WebPDecodeYUV() that operates directly 119 | // into pre-allocated luma/chroma plane buffers. This function requires the 120 | // strides to be passed: one for the luma plane and one for each of the 121 | // chroma ones. The size of each plane buffer is passed as 'luma_size', 122 | // 'u_size' and 'v_size' respectively. 123 | // Pointer to the luma plane ('*luma') is returned or NULL if an error occurred 124 | // during decoding (or because some buffers were found to be too small). 125 | WEBP_EXTERN(uint8_t*) WebPDecodeYUVInto( 126 | const uint8_t* data, size_t data_size, 127 | uint8_t* luma, size_t luma_size, int luma_stride, 128 | uint8_t* u, size_t u_size, int u_stride, 129 | uint8_t* v, size_t v_size, int v_stride); 130 | 131 | //------------------------------------------------------------------------------ 132 | // Output colorspaces and buffer 133 | 134 | // Colorspaces 135 | // Note: the naming describes the byte-ordering of packed samples in memory. 136 | // For instance, MODE_BGRA relates to samples ordered as B,G,R,A,B,G,R,A,... 137 | // Non-capital names (e.g.:MODE_Argb) relates to pre-multiplied RGB channels. 138 | // RGBA-4444 and RGB-565 colorspaces are represented by following byte-order: 139 | // RGBA-4444: [r3 r2 r1 r0 g3 g2 g1 g0], [b3 b2 b1 b0 a3 a2 a1 a0], ... 140 | // RGB-565: [r4 r3 r2 r1 r0 g5 g4 g3], [g2 g1 g0 b4 b3 b2 b1 b0], ... 141 | // In the case WEBP_SWAP_16BITS_CSP is defined, the bytes are swapped for 142 | // these two modes: 143 | // RGBA-4444: [b3 b2 b1 b0 a3 a2 a1 a0], [r3 r2 r1 r0 g3 g2 g1 g0], ... 144 | // RGB-565: [g2 g1 g0 b4 b3 b2 b1 b0], [r4 r3 r2 r1 r0 g5 g4 g3], ... 145 | 146 | typedef enum WEBP_CSP_MODE { 147 | MODE_RGB = 0, MODE_RGBA = 1, 148 | MODE_BGR = 2, MODE_BGRA = 3, 149 | MODE_ARGB = 4, MODE_RGBA_4444 = 5, 150 | MODE_RGB_565 = 6, 151 | // RGB-premultiplied transparent modes (alpha value is preserved) 152 | MODE_rgbA = 7, 153 | MODE_bgrA = 8, 154 | MODE_Argb = 9, 155 | MODE_rgbA_4444 = 10, 156 | // YUV modes must come after RGB ones. 157 | MODE_YUV = 11, MODE_YUVA = 12, // yuv 4:2:0 158 | MODE_LAST = 13 159 | } WEBP_CSP_MODE; 160 | 161 | // Some useful macros: 162 | static WEBP_INLINE int WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { 163 | return (mode == MODE_rgbA || mode == MODE_bgrA || mode == MODE_Argb || 164 | mode == MODE_rgbA_4444); 165 | } 166 | 167 | static WEBP_INLINE int WebPIsAlphaMode(WEBP_CSP_MODE mode) { 168 | return (mode == MODE_RGBA || mode == MODE_BGRA || mode == MODE_ARGB || 169 | mode == MODE_RGBA_4444 || mode == MODE_YUVA || 170 | WebPIsPremultipliedMode(mode)); 171 | } 172 | 173 | static WEBP_INLINE int WebPIsRGBMode(WEBP_CSP_MODE mode) { 174 | return (mode < MODE_YUV); 175 | } 176 | 177 | //------------------------------------------------------------------------------ 178 | // WebPDecBuffer: Generic structure for describing the output sample buffer. 179 | 180 | struct WebPRGBABuffer { // view as RGBA 181 | uint8_t* rgba; // pointer to RGBA samples 182 | int stride; // stride in bytes from one scanline to the next. 183 | size_t size; // total size of the *rgba buffer. 184 | }; 185 | 186 | struct WebPYUVABuffer { // view as YUVA 187 | uint8_t* y, *u, *v, *a; // pointer to luma, chroma U/V, alpha samples 188 | int y_stride; // luma stride 189 | int u_stride, v_stride; // chroma strides 190 | int a_stride; // alpha stride 191 | size_t y_size; // luma plane size 192 | size_t u_size, v_size; // chroma planes size 193 | size_t a_size; // alpha-plane size 194 | }; 195 | 196 | // Output buffer 197 | struct WebPDecBuffer { 198 | WEBP_CSP_MODE colorspace; // Colorspace. 199 | int width, height; // Dimensions. 200 | int is_external_memory; // If non-zero, 'internal_memory' pointer is not 201 | // used. If value is '2' or more, the external 202 | // memory is considered 'slow' and multiple 203 | // read/write will be avoided. 204 | union { 205 | WebPRGBABuffer RGBA; 206 | WebPYUVABuffer YUVA; 207 | } u; // Nameless union of buffer parameters. 208 | uint32_t pad[4]; // padding for later use 209 | 210 | uint8_t* private_memory; // Internally allocated memory (only when 211 | // is_external_memory is 0). Should not be used 212 | // externally, but accessed via the buffer union. 213 | }; 214 | 215 | // Internal, version-checked, entry point 216 | WEBP_EXTERN(int) WebPInitDecBufferInternal(WebPDecBuffer*, int); 217 | 218 | // Initialize the structure as empty. Must be called before any other use. 219 | // Returns false in case of version mismatch 220 | static WEBP_INLINE int WebPInitDecBuffer(WebPDecBuffer* buffer) { 221 | return WebPInitDecBufferInternal(buffer, WEBP_DECODER_ABI_VERSION); 222 | } 223 | 224 | // Free any memory associated with the buffer. Must always be called last. 225 | // Note: doesn't free the 'buffer' structure itself. 226 | WEBP_EXTERN(void) WebPFreeDecBuffer(WebPDecBuffer* buffer); 227 | 228 | //------------------------------------------------------------------------------ 229 | // Enumeration of the status codes 230 | 231 | typedef enum VP8StatusCode { 232 | VP8_STATUS_OK = 0, 233 | VP8_STATUS_OUT_OF_MEMORY, 234 | VP8_STATUS_INVALID_PARAM, 235 | VP8_STATUS_BITSTREAM_ERROR, 236 | VP8_STATUS_UNSUPPORTED_FEATURE, 237 | VP8_STATUS_SUSPENDED, 238 | VP8_STATUS_USER_ABORT, 239 | VP8_STATUS_NOT_ENOUGH_DATA 240 | } VP8StatusCode; 241 | 242 | //------------------------------------------------------------------------------ 243 | // Incremental decoding 244 | // 245 | // This API allows streamlined decoding of partial data. 246 | // Picture can be incrementally decoded as data become available thanks to the 247 | // WebPIDecoder object. This object can be left in a SUSPENDED state if the 248 | // picture is only partially decoded, pending additional input. 249 | // Code example: 250 | // 251 | // WebPInitDecBuffer(&output_buffer); 252 | // output_buffer.colorspace = mode; 253 | // ... 254 | // WebPIDecoder* idec = WebPINewDecoder(&output_buffer); 255 | // while (additional_data_is_available) { 256 | // // ... (get additional data in some new_data[] buffer) 257 | // status = WebPIAppend(idec, new_data, new_data_size); 258 | // if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) { 259 | // break; // an error occurred. 260 | // } 261 | // 262 | // // The above call decodes the current available buffer. 263 | // // Part of the image can now be refreshed by calling 264 | // // WebPIDecGetRGB()/WebPIDecGetYUVA() etc. 265 | // } 266 | // WebPIDelete(idec); 267 | 268 | // Creates a new incremental decoder with the supplied buffer parameter. 269 | // This output_buffer can be passed NULL, in which case a default output buffer 270 | // is used (with MODE_RGB). Otherwise, an internal reference to 'output_buffer' 271 | // is kept, which means that the lifespan of 'output_buffer' must be larger than 272 | // that of the returned WebPIDecoder object. 273 | // The supplied 'output_buffer' content MUST NOT be changed between calls to 274 | // WebPIAppend() or WebPIUpdate() unless 'output_buffer.is_external_memory' is 275 | // not set to 0. In such a case, it is allowed to modify the pointers, size and 276 | // stride of output_buffer.u.RGBA or output_buffer.u.YUVA, provided they remain 277 | // within valid bounds. 278 | // All other fields of WebPDecBuffer MUST remain constant between calls. 279 | // Returns NULL if the allocation failed. 280 | WEBP_EXTERN(WebPIDecoder*) WebPINewDecoder(WebPDecBuffer* output_buffer); 281 | 282 | // This function allocates and initializes an incremental-decoder object, which 283 | // will output the RGB/A samples specified by 'csp' into a preallocated 284 | // buffer 'output_buffer'. The size of this buffer is at least 285 | // 'output_buffer_size' and the stride (distance in bytes between two scanlines) 286 | // is specified by 'output_stride'. 287 | // Additionally, output_buffer can be passed NULL in which case the output 288 | // buffer will be allocated automatically when the decoding starts. The 289 | // colorspace 'csp' is taken into account for allocating this buffer. All other 290 | // parameters are ignored. 291 | // Returns NULL if the allocation failed, or if some parameters are invalid. 292 | WEBP_EXTERN(WebPIDecoder*) WebPINewRGB( 293 | WEBP_CSP_MODE csp, 294 | uint8_t* output_buffer, size_t output_buffer_size, int output_stride); 295 | 296 | // This function allocates and initializes an incremental-decoder object, which 297 | // will output the raw luma/chroma samples into a preallocated planes if 298 | // supplied. The luma plane is specified by its pointer 'luma', its size 299 | // 'luma_size' and its stride 'luma_stride'. Similarly, the chroma-u plane 300 | // is specified by the 'u', 'u_size' and 'u_stride' parameters, and the chroma-v 301 | // plane by 'v' and 'v_size'. And same for the alpha-plane. The 'a' pointer 302 | // can be pass NULL in case one is not interested in the transparency plane. 303 | // Conversely, 'luma' can be passed NULL if no preallocated planes are supplied. 304 | // In this case, the output buffer will be automatically allocated (using 305 | // MODE_YUVA) when decoding starts. All parameters are then ignored. 306 | // Returns NULL if the allocation failed or if a parameter is invalid. 307 | WEBP_EXTERN(WebPIDecoder*) WebPINewYUVA( 308 | uint8_t* luma, size_t luma_size, int luma_stride, 309 | uint8_t* u, size_t u_size, int u_stride, 310 | uint8_t* v, size_t v_size, int v_stride, 311 | uint8_t* a, size_t a_size, int a_stride); 312 | 313 | // Deprecated version of the above, without the alpha plane. 314 | // Kept for backward compatibility. 315 | WEBP_EXTERN(WebPIDecoder*) WebPINewYUV( 316 | uint8_t* luma, size_t luma_size, int luma_stride, 317 | uint8_t* u, size_t u_size, int u_stride, 318 | uint8_t* v, size_t v_size, int v_stride); 319 | 320 | // Deletes the WebPIDecoder object and associated memory. Must always be called 321 | // if WebPINewDecoder, WebPINewRGB or WebPINewYUV succeeded. 322 | WEBP_EXTERN(void) WebPIDelete(WebPIDecoder* idec); 323 | 324 | // Copies and decodes the next available data. Returns VP8_STATUS_OK when 325 | // the image is successfully decoded. Returns VP8_STATUS_SUSPENDED when more 326 | // data is expected. Returns error in other cases. 327 | WEBP_EXTERN(VP8StatusCode) WebPIAppend( 328 | WebPIDecoder* idec, const uint8_t* data, size_t data_size); 329 | 330 | // A variant of the above function to be used when data buffer contains 331 | // partial data from the beginning. In this case data buffer is not copied 332 | // to the internal memory. 333 | // Note that the value of the 'data' pointer can change between calls to 334 | // WebPIUpdate, for instance when the data buffer is resized to fit larger data. 335 | WEBP_EXTERN(VP8StatusCode) WebPIUpdate( 336 | WebPIDecoder* idec, const uint8_t* data, size_t data_size); 337 | 338 | // Returns the RGB/A image decoded so far. Returns NULL if output params 339 | // are not initialized yet. The RGB/A output type corresponds to the colorspace 340 | // specified during call to WebPINewDecoder() or WebPINewRGB(). 341 | // *last_y is the index of last decoded row in raster scan order. Some pointers 342 | // (*last_y, *width etc.) can be NULL if corresponding information is not 343 | // needed. 344 | WEBP_EXTERN(uint8_t*) WebPIDecGetRGB( 345 | const WebPIDecoder* idec, int* last_y, 346 | int* width, int* height, int* stride); 347 | 348 | // Same as above function to get a YUVA image. Returns pointer to the luma 349 | // plane or NULL in case of error. If there is no alpha information 350 | // the alpha pointer '*a' will be returned NULL. 351 | WEBP_EXTERN(uint8_t*) WebPIDecGetYUVA( 352 | const WebPIDecoder* idec, int* last_y, 353 | uint8_t** u, uint8_t** v, uint8_t** a, 354 | int* width, int* height, int* stride, int* uv_stride, int* a_stride); 355 | 356 | // Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the 357 | // alpha information (if present). Kept for backward compatibility. 358 | static WEBP_INLINE uint8_t* WebPIDecGetYUV( 359 | const WebPIDecoder* idec, int* last_y, uint8_t** u, uint8_t** v, 360 | int* width, int* height, int* stride, int* uv_stride) { 361 | return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, 362 | stride, uv_stride, NULL); 363 | } 364 | 365 | // Generic call to retrieve information about the displayable area. 366 | // If non NULL, the left/right/width/height pointers are filled with the visible 367 | // rectangular area so far. 368 | // Returns NULL in case the incremental decoder object is in an invalid state. 369 | // Otherwise returns the pointer to the internal representation. This structure 370 | // is read-only, tied to WebPIDecoder's lifespan and should not be modified. 371 | WEBP_EXTERN(const WebPDecBuffer*) WebPIDecodedArea( 372 | const WebPIDecoder* idec, int* left, int* top, int* width, int* height); 373 | 374 | //------------------------------------------------------------------------------ 375 | // Advanced decoding parametrization 376 | // 377 | // Code sample for using the advanced decoding API 378 | /* 379 | // A) Init a configuration object 380 | WebPDecoderConfig config; 381 | CHECK(WebPInitDecoderConfig(&config)); 382 | 383 | // B) optional: retrieve the bitstream's features. 384 | CHECK(WebPGetFeatures(data, data_size, &config.input) == VP8_STATUS_OK); 385 | 386 | // C) Adjust 'config', if needed 387 | config.no_fancy_upsampling = 1; 388 | config.output.colorspace = MODE_BGRA; 389 | // etc. 390 | 391 | // Note that you can also make config.output point to an externally 392 | // supplied memory buffer, provided it's big enough to store the decoded 393 | // picture. Otherwise, config.output will just be used to allocate memory 394 | // and store the decoded picture. 395 | 396 | // D) Decode! 397 | CHECK(WebPDecode(data, data_size, &config) == VP8_STATUS_OK); 398 | 399 | // E) Decoded image is now in config.output (and config.output.u.RGBA) 400 | 401 | // F) Reclaim memory allocated in config's object. It's safe to call 402 | // this function even if the memory is external and wasn't allocated 403 | // by WebPDecode(). 404 | WebPFreeDecBuffer(&config.output); 405 | */ 406 | 407 | // Features gathered from the bitstream 408 | struct WebPBitstreamFeatures { 409 | int width; // Width in pixels, as read from the bitstream. 410 | int height; // Height in pixels, as read from the bitstream. 411 | int has_alpha; // True if the bitstream contains an alpha channel. 412 | int has_animation; // True if the bitstream is an animation. 413 | int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless 414 | 415 | uint32_t pad[5]; // padding for later use 416 | }; 417 | 418 | // Internal, version-checked, entry point 419 | WEBP_EXTERN(VP8StatusCode) WebPGetFeaturesInternal( 420 | const uint8_t*, size_t, WebPBitstreamFeatures*, int); 421 | 422 | // Retrieve features from the bitstream. The *features structure is filled 423 | // with information gathered from the bitstream. 424 | // Returns VP8_STATUS_OK when the features are successfully retrieved. Returns 425 | // VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the 426 | // features from headers. Returns error in other cases. 427 | static WEBP_INLINE VP8StatusCode WebPGetFeatures( 428 | const uint8_t* data, size_t data_size, 429 | WebPBitstreamFeatures* features) { 430 | return WebPGetFeaturesInternal(data, data_size, features, 431 | WEBP_DECODER_ABI_VERSION); 432 | } 433 | 434 | // Decoding options 435 | struct WebPDecoderOptions { 436 | int bypass_filtering; // if true, skip the in-loop filtering 437 | int no_fancy_upsampling; // if true, use faster pointwise upsampler 438 | int use_cropping; // if true, cropping is applied _first_ 439 | int crop_left, crop_top; // top-left position for cropping. 440 | // Will be snapped to even values. 441 | int crop_width, crop_height; // dimension of the cropping area 442 | int use_scaling; // if true, scaling is applied _afterward_ 443 | int scaled_width, scaled_height; // final resolution 444 | int use_threads; // if true, use multi-threaded decoding 445 | int dithering_strength; // dithering strength (0=Off, 100=full) 446 | int flip; // flip output vertically 447 | int alpha_dithering_strength; // alpha dithering strength in [0..100] 448 | 449 | uint32_t pad[5]; // padding for later use 450 | }; 451 | 452 | // Main object storing the configuration for advanced decoding. 453 | struct WebPDecoderConfig { 454 | WebPBitstreamFeatures input; // Immutable bitstream features (optional) 455 | WebPDecBuffer output; // Output buffer (can point to external mem) 456 | WebPDecoderOptions options; // Decoding options 457 | }; 458 | 459 | // Internal, version-checked, entry point 460 | WEBP_EXTERN(int) WebPInitDecoderConfigInternal(WebPDecoderConfig*, int); 461 | 462 | // Initialize the configuration as empty. This function must always be 463 | // called first, unless WebPGetFeatures() is to be called. 464 | // Returns false in case of mismatched version. 465 | static WEBP_INLINE int WebPInitDecoderConfig(WebPDecoderConfig* config) { 466 | return WebPInitDecoderConfigInternal(config, WEBP_DECODER_ABI_VERSION); 467 | } 468 | 469 | // Instantiate a new incremental decoder object with the requested 470 | // configuration. The bitstream can be passed using 'data' and 'data_size' 471 | // parameter, in which case the features will be parsed and stored into 472 | // config->input. Otherwise, 'data' can be NULL and no parsing will occur. 473 | // Note that 'config' can be NULL too, in which case a default configuration 474 | // is used. If 'config' is not NULL, it must outlive the WebPIDecoder object 475 | // as some references to its fields will be used. No internal copy of 'config' 476 | // is made. 477 | // The return WebPIDecoder object must always be deleted calling WebPIDelete(). 478 | // Returns NULL in case of error (and config->status will then reflect 479 | // the error condition, if available). 480 | WEBP_EXTERN(WebPIDecoder*) WebPIDecode(const uint8_t* data, size_t data_size, 481 | WebPDecoderConfig* config); 482 | 483 | // Non-incremental version. This version decodes the full data at once, taking 484 | // 'config' into account. Returns decoding status (which should be VP8_STATUS_OK 485 | // if the decoding was successful). Note that 'config' cannot be NULL. 486 | WEBP_EXTERN(VP8StatusCode) WebPDecode(const uint8_t* data, size_t data_size, 487 | WebPDecoderConfig* config); 488 | 489 | #ifdef __cplusplus 490 | } // extern "C" 491 | #endif 492 | 493 | #endif /* WEBP_WEBP_DECODE_H_ */ 494 | -------------------------------------------------------------------------------- /interop/encode.h: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // WebP encoder: main interface 11 | // 12 | // Author: Skal (pascal.massimino@gmail.com) 13 | 14 | #ifndef WEBP_WEBP_ENCODE_H_ 15 | #define WEBP_WEBP_ENCODE_H_ 16 | 17 | #include "./types.h" 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #define WEBP_ENCODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b) 24 | 25 | // Note: forward declaring enumerations is not allowed in (strict) C and C++, 26 | // the types are left here for reference. 27 | // typedef enum WebPImageHint WebPImageHint; 28 | // typedef enum WebPEncCSP WebPEncCSP; 29 | // typedef enum WebPPreset WebPPreset; 30 | // typedef enum WebPEncodingError WebPEncodingError; 31 | typedef struct WebPConfig WebPConfig; 32 | typedef struct WebPPicture WebPPicture; // main structure for I/O 33 | typedef struct WebPAuxStats WebPAuxStats; 34 | typedef struct WebPMemoryWriter WebPMemoryWriter; 35 | 36 | // Return the encoder's version number, packed in hexadecimal using 8bits for 37 | // each of major/minor/revision. E.g: v2.5.7 is 0x020507. 38 | WEBP_EXTERN(int) WebPGetEncoderVersion(void); 39 | 40 | //------------------------------------------------------------------------------ 41 | // One-stop-shop call! No questions asked: 42 | 43 | // Returns the size of the compressed data (pointed to by *output), or 0 if 44 | // an error occurred. The compressed data must be released by the caller 45 | // using the call 'WebPFree(*output)'. 46 | // These functions compress using the lossy format, and the quality_factor 47 | // can go from 0 (smaller output, lower quality) to 100 (best quality, 48 | // larger output). 49 | WEBP_EXTERN(size_t) WebPEncodeRGB(const uint8_t* rgb, 50 | int width, int height, int stride, 51 | float quality_factor, uint8_t** output); 52 | WEBP_EXTERN(size_t) WebPEncodeBGR(const uint8_t* bgr, 53 | int width, int height, int stride, 54 | float quality_factor, uint8_t** output); 55 | WEBP_EXTERN(size_t) WebPEncodeRGBA(const uint8_t* rgba, 56 | int width, int height, int stride, 57 | float quality_factor, uint8_t** output); 58 | WEBP_EXTERN(size_t) WebPEncodeBGRA(const uint8_t* bgra, 59 | int width, int height, int stride, 60 | float quality_factor, uint8_t** output); 61 | 62 | // These functions are the equivalent of the above, but compressing in a 63 | // lossless manner. Files are usually larger than lossy format, but will 64 | // not suffer any compression loss. 65 | WEBP_EXTERN(size_t) WebPEncodeLosslessRGB(const uint8_t* rgb, 66 | int width, int height, int stride, 67 | uint8_t** output); 68 | WEBP_EXTERN(size_t) WebPEncodeLosslessBGR(const uint8_t* bgr, 69 | int width, int height, int stride, 70 | uint8_t** output); 71 | WEBP_EXTERN(size_t) WebPEncodeLosslessRGBA(const uint8_t* rgba, 72 | int width, int height, int stride, 73 | uint8_t** output); 74 | WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra, 75 | int width, int height, int stride, 76 | uint8_t** output); 77 | 78 | // Releases memory returned by the WebPEncode*() functions above. 79 | WEBP_EXTERN(void) WebPFree(void* ptr); 80 | 81 | //------------------------------------------------------------------------------ 82 | // Coding parameters 83 | 84 | // Image characteristics hint for the underlying encoder. 85 | typedef enum WebPImageHint { 86 | WEBP_HINT_DEFAULT = 0, // default preset. 87 | WEBP_HINT_PICTURE, // digital picture, like portrait, inner shot 88 | WEBP_HINT_PHOTO, // outdoor photograph, with natural lighting 89 | WEBP_HINT_GRAPH, // Discrete tone image (graph, map-tile etc). 90 | WEBP_HINT_LAST 91 | } WebPImageHint; 92 | 93 | // Compression parameters. 94 | struct WebPConfig { 95 | int lossless; // Lossless encoding (0=lossy(default), 1=lossless). 96 | float quality; // between 0 (smallest file) and 100 (biggest) 97 | int method; // quality/speed trade-off (0=fast, 6=slower-better) 98 | 99 | WebPImageHint image_hint; // Hint for image type (lossless only for now). 100 | 101 | // Parameters related to lossy compression only: 102 | int target_size; // if non-zero, set the desired target size in bytes. 103 | // Takes precedence over the 'compression' parameter. 104 | float target_PSNR; // if non-zero, specifies the minimal distortion to 105 | // try to achieve. Takes precedence over target_size. 106 | int segments; // maximum number of segments to use, in [1..4] 107 | int sns_strength; // Spatial Noise Shaping. 0=off, 100=maximum. 108 | int filter_strength; // range: [0 = off .. 100 = strongest] 109 | int filter_sharpness; // range: [0 = off .. 7 = least sharp] 110 | int filter_type; // filtering type: 0 = simple, 1 = strong (only used 111 | // if filter_strength > 0 or autofilter > 0) 112 | int autofilter; // Auto adjust filter's strength [0 = off, 1 = on] 113 | int alpha_compression; // Algorithm for encoding the alpha plane (0 = none, 114 | // 1 = compressed with WebP lossless). Default is 1. 115 | int alpha_filtering; // Predictive filtering method for alpha plane. 116 | // 0: none, 1: fast, 2: best. Default if 1. 117 | int alpha_quality; // Between 0 (smallest size) and 100 (lossless). 118 | // Default is 100. 119 | int pass; // number of entropy-analysis passes (in [1..10]). 120 | 121 | int show_compressed; // if true, export the compressed picture back. 122 | // In-loop filtering is not applied. 123 | int preprocessing; // preprocessing filter: 124 | // 0=none, 1=segment-smooth, 2=pseudo-random dithering 125 | int partitions; // log2(number of token partitions) in [0..3]. Default 126 | // is set to 0 for easier progressive decoding. 127 | int partition_limit; // quality degradation allowed to fit the 512k limit 128 | // on prediction modes coding (0: no degradation, 129 | // 100: maximum possible degradation). 130 | int emulate_jpeg_size; // If true, compression parameters will be remapped 131 | // to better match the expected output size from 132 | // JPEG compression. Generally, the output size will 133 | // be similar but the degradation will be lower. 134 | int thread_level; // If non-zero, try and use multi-threaded encoding. 135 | int low_memory; // If set, reduce memory usage (but increase CPU use). 136 | 137 | int near_lossless; // Near lossless encoding [0 = max loss .. 100 = off 138 | // (default)]. 139 | int exact; // if non-zero, preserve the exact RGB values under 140 | // transparent area. Otherwise, discard this invisible 141 | // RGB information for better compression. The default 142 | // value is 0. 143 | 144 | #ifdef WEBP_EXPERIMENTAL_FEATURES 145 | int delta_palettization; 146 | uint32_t pad[2]; // padding for later use 147 | #else 148 | uint32_t pad[3]; // padding for later use 149 | #endif // WEBP_EXPERIMENTAL_FEATURES 150 | }; 151 | 152 | // Enumerate some predefined settings for WebPConfig, depending on the type 153 | // of source picture. These presets are used when calling WebPConfigPreset(). 154 | typedef enum WebPPreset { 155 | WEBP_PRESET_DEFAULT = 0, // default preset. 156 | WEBP_PRESET_PICTURE, // digital picture, like portrait, inner shot 157 | WEBP_PRESET_PHOTO, // outdoor photograph, with natural lighting 158 | WEBP_PRESET_DRAWING, // hand or line drawing, with high-contrast details 159 | WEBP_PRESET_ICON, // small-sized colorful images 160 | WEBP_PRESET_TEXT // text-like 161 | } WebPPreset; 162 | 163 | // Internal, version-checked, entry point 164 | WEBP_EXTERN(int) WebPConfigInitInternal(WebPConfig*, WebPPreset, float, int); 165 | 166 | // Should always be called, to initialize a fresh WebPConfig structure before 167 | // modification. Returns false in case of version mismatch. WebPConfigInit() 168 | // must have succeeded before using the 'config' object. 169 | // Note that the default values are lossless=0 and quality=75. 170 | static WEBP_INLINE int WebPConfigInit(WebPConfig* config) { 171 | return WebPConfigInitInternal(config, WEBP_PRESET_DEFAULT, 75.f, 172 | WEBP_ENCODER_ABI_VERSION); 173 | } 174 | 175 | // This function will initialize the configuration according to a predefined 176 | // set of parameters (referred to by 'preset') and a given quality factor. 177 | // This function can be called as a replacement to WebPConfigInit(). Will 178 | // return false in case of error. 179 | static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, 180 | WebPPreset preset, float quality) { 181 | return WebPConfigInitInternal(config, preset, quality, 182 | WEBP_ENCODER_ABI_VERSION); 183 | } 184 | 185 | // Activate the lossless compression mode with the desired efficiency level 186 | // between 0 (fastest, lowest compression) and 9 (slower, best compression). 187 | // A good default level is '6', providing a fair tradeoff between compression 188 | // speed and final compressed size. 189 | // This function will overwrite several fields from config: 'method', 'quality' 190 | // and 'lossless'. Returns false in case of parameter error. 191 | WEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level); 192 | 193 | // Returns true if 'config' is non-NULL and all configuration parameters are 194 | // within their valid ranges. 195 | WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config); 196 | 197 | //------------------------------------------------------------------------------ 198 | // Input / Output 199 | // Structure for storing auxiliary statistics (mostly for lossy encoding). 200 | 201 | struct WebPAuxStats { 202 | int coded_size; // final size 203 | 204 | float PSNR[5]; // peak-signal-to-noise ratio for Y/U/V/All/Alpha 205 | int block_count[3]; // number of intra4/intra16/skipped macroblocks 206 | int header_bytes[2]; // approximate number of bytes spent for header 207 | // and mode-partition #0 208 | int residual_bytes[3][4]; // approximate number of bytes spent for 209 | // DC/AC/uv coefficients for each (0..3) segments. 210 | int segment_size[4]; // number of macroblocks in each segments 211 | int segment_quant[4]; // quantizer values for each segments 212 | int segment_level[4]; // filtering strength for each segments [0..63] 213 | 214 | int alpha_data_size; // size of the transparency data 215 | int layer_data_size; // size of the enhancement layer data 216 | 217 | // lossless encoder statistics 218 | uint32_t lossless_features; // bit0:predictor bit1:cross-color transform 219 | // bit2:subtract-green bit3:color indexing 220 | int histogram_bits; // number of precision bits of histogram 221 | int transform_bits; // precision bits for transform 222 | int cache_bits; // number of bits for color cache lookup 223 | int palette_size; // number of color in palette, if used 224 | int lossless_size; // final lossless size 225 | int lossless_hdr_size; // lossless header (transform, huffman etc) size 226 | int lossless_data_size; // lossless image data size 227 | 228 | uint32_t pad[2]; // padding for later use 229 | }; 230 | 231 | // Signature for output function. Should return true if writing was successful. 232 | // data/data_size is the segment of data to write, and 'picture' is for 233 | // reference (and so one can make use of picture->custom_ptr). 234 | typedef int (*WebPWriterFunction)(const uint8_t* data, size_t data_size, 235 | const WebPPicture* picture); 236 | 237 | // WebPMemoryWrite: a special WebPWriterFunction that writes to memory using 238 | // the following WebPMemoryWriter object (to be set as a custom_ptr). 239 | struct WebPMemoryWriter { 240 | uint8_t* mem; // final buffer (of size 'max_size', larger than 'size'). 241 | size_t size; // final size 242 | size_t max_size; // total capacity 243 | uint32_t pad[1]; // padding for later use 244 | }; 245 | 246 | // The following must be called first before any use. 247 | WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer); 248 | 249 | // The following must be called to deallocate writer->mem memory. The 'writer' 250 | // object itself is not deallocated. 251 | WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer); 252 | // The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon 253 | // completion, writer.mem and writer.size will hold the coded data. 254 | // writer.mem must be freed by calling WebPMemoryWriterClear. 255 | WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size, 256 | const WebPPicture* picture); 257 | 258 | // Progress hook, called from time to time to report progress. It can return 259 | // false to request an abort of the encoding process, or true otherwise if 260 | // everything is OK. 261 | typedef int (*WebPProgressHook)(int percent, const WebPPicture* picture); 262 | 263 | // Color spaces. 264 | typedef enum WebPEncCSP { 265 | // chroma sampling 266 | WEBP_YUV420 = 0, // 4:2:0 267 | WEBP_YUV420A = 4, // alpha channel variant 268 | WEBP_CSP_UV_MASK = 3, // bit-mask to get the UV sampling factors 269 | WEBP_CSP_ALPHA_BIT = 4 // bit that is set if alpha is present 270 | } WebPEncCSP; 271 | 272 | // Encoding error conditions. 273 | typedef enum WebPEncodingError { 274 | VP8_ENC_OK = 0, 275 | VP8_ENC_ERROR_OUT_OF_MEMORY, // memory error allocating objects 276 | VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, // memory error while flushing bits 277 | VP8_ENC_ERROR_NULL_PARAMETER, // a pointer parameter is NULL 278 | VP8_ENC_ERROR_INVALID_CONFIGURATION, // configuration is invalid 279 | VP8_ENC_ERROR_BAD_DIMENSION, // picture has invalid width/height 280 | VP8_ENC_ERROR_PARTITION0_OVERFLOW, // partition is bigger than 512k 281 | VP8_ENC_ERROR_PARTITION_OVERFLOW, // partition is bigger than 16M 282 | VP8_ENC_ERROR_BAD_WRITE, // error while flushing bytes 283 | VP8_ENC_ERROR_FILE_TOO_BIG, // file is bigger than 4G 284 | VP8_ENC_ERROR_USER_ABORT, // abort request by user 285 | VP8_ENC_ERROR_LAST // list terminator. always last. 286 | } WebPEncodingError; 287 | 288 | // maximum width/height allowed (inclusive), in pixels 289 | #define WEBP_MAX_DIMENSION 16383 290 | 291 | // Main exchange structure (input samples, output bytes, statistics) 292 | struct WebPPicture { 293 | // INPUT 294 | ////////////// 295 | // Main flag for encoder selecting between ARGB or YUV input. 296 | // It is recommended to use ARGB input (*argb, argb_stride) for lossless 297 | // compression, and YUV input (*y, *u, *v, etc.) for lossy compression 298 | // since these are the respective native colorspace for these formats. 299 | int use_argb; 300 | 301 | // YUV input (mostly used for input to lossy compression) 302 | WebPEncCSP colorspace; // colorspace: should be YUV420 for now (=Y'CbCr). 303 | int width, height; // dimensions (less or equal to WEBP_MAX_DIMENSION) 304 | uint8_t *y, *u, *v; // pointers to luma/chroma planes. 305 | int y_stride, uv_stride; // luma/chroma strides. 306 | uint8_t* a; // pointer to the alpha plane 307 | int a_stride; // stride of the alpha plane 308 | uint32_t pad1[2]; // padding for later use 309 | 310 | // ARGB input (mostly used for input to lossless compression) 311 | uint32_t* argb; // Pointer to argb (32 bit) plane. 312 | int argb_stride; // This is stride in pixels units, not bytes. 313 | uint32_t pad2[3]; // padding for later use 314 | 315 | // OUTPUT 316 | /////////////// 317 | // Byte-emission hook, to store compressed bytes as they are ready. 318 | WebPWriterFunction writer; // can be NULL 319 | void* custom_ptr; // can be used by the writer. 320 | 321 | // map for extra information (only for lossy compression mode) 322 | int extra_info_type; // 1: intra type, 2: segment, 3: quant 323 | // 4: intra-16 prediction mode, 324 | // 5: chroma prediction mode, 325 | // 6: bit cost, 7: distortion 326 | uint8_t* extra_info; // if not NULL, points to an array of size 327 | // ((width + 15) / 16) * ((height + 15) / 16) that 328 | // will be filled with a macroblock map, depending 329 | // on extra_info_type. 330 | 331 | // STATS AND REPORTS 332 | /////////////////////////// 333 | // Pointer to side statistics (updated only if not NULL) 334 | WebPAuxStats* stats; 335 | 336 | // Error code for the latest error encountered during encoding 337 | WebPEncodingError error_code; 338 | 339 | // If not NULL, report progress during encoding. 340 | WebPProgressHook progress_hook; 341 | 342 | void* user_data; // this field is free to be set to any value and 343 | // used during callbacks (like progress-report e.g.). 344 | 345 | uint32_t pad3[3]; // padding for later use 346 | 347 | // Unused for now 348 | uint8_t *pad4, *pad5; 349 | uint32_t pad6[8]; // padding for later use 350 | 351 | // PRIVATE FIELDS 352 | //////////////////// 353 | void* memory_; // row chunk of memory for yuva planes 354 | void* memory_argb_; // and for argb too. 355 | void* pad7[2]; // padding for later use 356 | }; 357 | 358 | // Internal, version-checked, entry point 359 | WEBP_EXTERN(int) WebPPictureInitInternal(WebPPicture*, int); 360 | 361 | // Should always be called, to initialize the structure. Returns false in case 362 | // of version mismatch. WebPPictureInit() must have succeeded before using the 363 | // 'picture' object. 364 | // Note that, by default, use_argb is false and colorspace is WEBP_YUV420. 365 | static WEBP_INLINE int WebPPictureInit(WebPPicture* picture) { 366 | return WebPPictureInitInternal(picture, WEBP_ENCODER_ABI_VERSION); 367 | } 368 | 369 | //------------------------------------------------------------------------------ 370 | // WebPPicture utils 371 | 372 | // Convenience allocation / deallocation based on picture->width/height: 373 | // Allocate y/u/v buffers as per colorspace/width/height specification. 374 | // Note! This function will free the previous buffer if needed. 375 | // Returns false in case of memory error. 376 | WEBP_EXTERN(int) WebPPictureAlloc(WebPPicture* picture); 377 | 378 | // Release the memory allocated by WebPPictureAlloc() or WebPPictureImport*(). 379 | // Note that this function does _not_ free the memory used by the 'picture' 380 | // object itself. 381 | // Besides memory (which is reclaimed) all other fields of 'picture' are 382 | // preserved. 383 | WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture); 384 | 385 | // Copy the pixels of *src into *dst, using WebPPictureAlloc. Upon return, *dst 386 | // will fully own the copied pixels (this is not a view). The 'dst' picture need 387 | // not be initialized as its content is overwritten. 388 | // Returns false in case of memory allocation error. 389 | WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); 390 | 391 | // Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results 392 | // are in dB, stored in result[] in the Y/U/V/Alpha/All or B/G/R/A/All order. 393 | // Returns false in case of error (src and ref don't have same dimension, ...) 394 | // Warning: this function is rather CPU-intensive. 395 | WEBP_EXTERN(int) WebPPictureDistortion( 396 | const WebPPicture* src, const WebPPicture* ref, 397 | int metric_type, // 0 = PSNR, 1 = SSIM, 2 = LSIM 398 | float result[5]); 399 | 400 | // self-crops a picture to the rectangle defined by top/left/width/height. 401 | // Returns false in case of memory allocation error, or if the rectangle is 402 | // outside of the source picture. 403 | // The rectangle for the view is defined by the top-left corner pixel 404 | // coordinates (left, top) as well as its width and height. This rectangle 405 | // must be fully be comprised inside the 'src' source picture. If the source 406 | // picture uses the YUV420 colorspace, the top and left coordinates will be 407 | // snapped to even values. 408 | WEBP_EXTERN(int) WebPPictureCrop(WebPPicture* picture, 409 | int left, int top, int width, int height); 410 | 411 | // Extracts a view from 'src' picture into 'dst'. The rectangle for the view 412 | // is defined by the top-left corner pixel coordinates (left, top) as well 413 | // as its width and height. This rectangle must be fully be comprised inside 414 | // the 'src' source picture. If the source picture uses the YUV420 colorspace, 415 | // the top and left coordinates will be snapped to even values. 416 | // Picture 'src' must out-live 'dst' picture. Self-extraction of view is allowed 417 | // ('src' equal to 'dst') as a mean of fast-cropping (but note that doing so, 418 | // the original dimension will be lost). Picture 'dst' need not be initialized 419 | // with WebPPictureInit() if it is different from 'src', since its content will 420 | // be overwritten. 421 | // Returns false in case of memory allocation error or invalid parameters. 422 | WEBP_EXTERN(int) WebPPictureView(const WebPPicture* src, 423 | int left, int top, int width, int height, 424 | WebPPicture* dst); 425 | 426 | // Returns true if the 'picture' is actually a view and therefore does 427 | // not own the memory for pixels. 428 | WEBP_EXTERN(int) WebPPictureIsView(const WebPPicture* picture); 429 | 430 | // Rescale a picture to new dimension width x height. 431 | // If either 'width' or 'height' (but not both) is 0 the corresponding 432 | // dimension will be calculated preserving the aspect ratio. 433 | // No gamma correction is applied. 434 | // Returns false in case of error (invalid parameter or insufficient memory). 435 | WEBP_EXTERN(int) WebPPictureRescale(WebPPicture* pic, int width, int height); 436 | 437 | // Colorspace conversion function to import RGB samples. 438 | // Previous buffer will be free'd, if any. 439 | // *rgb buffer should have a size of at least height * rgb_stride. 440 | // Returns false in case of memory error. 441 | WEBP_EXTERN(int) WebPPictureImportRGB( 442 | WebPPicture* picture, const uint8_t* rgb, int rgb_stride); 443 | // Same, but for RGBA buffer. 444 | WEBP_EXTERN(int) WebPPictureImportRGBA( 445 | WebPPicture* picture, const uint8_t* rgba, int rgba_stride); 446 | // Same, but for RGBA buffer. Imports the RGB direct from the 32-bit format 447 | // input buffer ignoring the alpha channel. Avoids needing to copy the data 448 | // to a temporary 24-bit RGB buffer to import the RGB only. 449 | WEBP_EXTERN(int) WebPPictureImportRGBX( 450 | WebPPicture* picture, const uint8_t* rgbx, int rgbx_stride); 451 | 452 | // Variants of the above, but taking BGR(A|X) input. 453 | WEBP_EXTERN(int) WebPPictureImportBGR( 454 | WebPPicture* picture, const uint8_t* bgr, int bgr_stride); 455 | WEBP_EXTERN(int) WebPPictureImportBGRA( 456 | WebPPicture* picture, const uint8_t* bgra, int bgra_stride); 457 | WEBP_EXTERN(int) WebPPictureImportBGRX( 458 | WebPPicture* picture, const uint8_t* bgrx, int bgrx_stride); 459 | 460 | // Converts picture->argb data to the YUV420A format. The 'colorspace' 461 | // parameter is deprecated and should be equal to WEBP_YUV420. 462 | // Upon return, picture->use_argb is set to false. The presence of real 463 | // non-opaque transparent values is detected, and 'colorspace' will be 464 | // adjusted accordingly. Note that this method is lossy. 465 | // Returns false in case of error. 466 | WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture, 467 | WebPEncCSP /*colorspace = WEBP_YUV420*/); 468 | 469 | // Same as WebPPictureARGBToYUVA(), but the conversion is done using 470 | // pseudo-random dithering with a strength 'dithering' between 471 | // 0.0 (no dithering) and 1.0 (maximum dithering). This is useful 472 | // for photographic picture. 473 | WEBP_EXTERN(int) WebPPictureARGBToYUVADithered( 474 | WebPPicture* picture, WebPEncCSP colorspace, float dithering); 475 | 476 | // Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion. 477 | // Downsampling is handled with extra care in case of color clipping. This 478 | // method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better 479 | // YUV representation. 480 | // Returns false in case of error. 481 | WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture); 482 | 483 | // Converts picture->yuv to picture->argb and sets picture->use_argb to true. 484 | // The input format must be YUV_420 or YUV_420A. The conversion from YUV420 to 485 | // ARGB incurs a small loss too. 486 | // Note that the use of this colorspace is discouraged if one has access to the 487 | // raw ARGB samples, since using YUV420 is comparatively lossy. 488 | // Returns false in case of error. 489 | WEBP_EXTERN(int) WebPPictureYUVAToARGB(WebPPicture* picture); 490 | 491 | // Helper function: given a width x height plane of RGBA or YUV(A) samples 492 | // clean-up the YUV or RGB samples under fully transparent area, to help 493 | // compressibility (no guarantee, though). 494 | WEBP_EXTERN(void) WebPCleanupTransparentArea(WebPPicture* picture); 495 | 496 | // Scan the picture 'picture' for the presence of non fully opaque alpha values. 497 | // Returns true in such case. Otherwise returns false (indicating that the 498 | // alpha plane can be ignored altogether e.g.). 499 | WEBP_EXTERN(int) WebPPictureHasTransparency(const WebPPicture* picture); 500 | 501 | // Remove the transparency information (if present) by blending the color with 502 | // the background color 'background_rgb' (specified as 24bit RGB triplet). 503 | // After this call, all alpha values are reset to 0xff. 504 | WEBP_EXTERN(void) WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb); 505 | 506 | //------------------------------------------------------------------------------ 507 | // Main call 508 | 509 | // Main encoding call, after config and picture have been initialized. 510 | // 'picture' must be less than 16384x16384 in dimension (cf WEBP_MAX_DIMENSION), 511 | // and the 'config' object must be a valid one. 512 | // Returns false in case of error, true otherwise. 513 | // In case of error, picture->error_code is updated accordingly. 514 | // 'picture' can hold the source samples in both YUV(A) or ARGB input, depending 515 | // on the value of 'picture->use_argb'. It is highly recommended to use 516 | // the former for lossy encoding, and the latter for lossless encoding 517 | // (when config.lossless is true). Automatic conversion from one format to 518 | // another is provided but they both incur some loss. 519 | WEBP_EXTERN(int) WebPEncode(const WebPConfig* config, WebPPicture* picture); 520 | 521 | //------------------------------------------------------------------------------ 522 | 523 | #ifdef __cplusplus 524 | } // extern "C" 525 | #endif 526 | 527 | #endif /* WEBP_WEBP_ENCODE_H_ */ 528 | -------------------------------------------------------------------------------- /interop/format_constants.h: -------------------------------------------------------------------------------- 1 | // Copyright 2012 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Internal header for constants related to WebP file format. 11 | // 12 | // Author: Urvang (urvang@google.com) 13 | 14 | #ifndef WEBP_WEBP_FORMAT_CONSTANTS_H_ 15 | #define WEBP_WEBP_FORMAT_CONSTANTS_H_ 16 | 17 | // Create fourcc of the chunk from the chunk tag characters. 18 | #define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24) 19 | 20 | // VP8 related constants. 21 | #define VP8_SIGNATURE 0x9d012a // Signature in VP8 data. 22 | #define VP8_MAX_PARTITION0_SIZE (1 << 19) // max size of mode partition 23 | #define VP8_MAX_PARTITION_SIZE (1 << 24) // max size for token partition 24 | #define VP8_FRAME_HEADER_SIZE 10 // Size of the frame header within VP8 data. 25 | 26 | // VP8L related constants. 27 | #define VP8L_SIGNATURE_SIZE 1 // VP8L signature size. 28 | #define VP8L_MAGIC_BYTE 0x2f // VP8L signature byte. 29 | #define VP8L_IMAGE_SIZE_BITS 14 // Number of bits used to store 30 | // width and height. 31 | #define VP8L_VERSION_BITS 3 // 3 bits reserved for version. 32 | #define VP8L_VERSION 0 // version 0 33 | #define VP8L_FRAME_HEADER_SIZE 5 // Size of the VP8L frame header. 34 | 35 | #define MAX_PALETTE_SIZE 256 36 | #define MAX_CACHE_BITS 11 37 | #define HUFFMAN_CODES_PER_META_CODE 5 38 | #define ARGB_BLACK 0xff000000 39 | 40 | #define DEFAULT_CODE_LENGTH 8 41 | #define MAX_ALLOWED_CODE_LENGTH 15 42 | 43 | #define NUM_LITERAL_CODES 256 44 | #define NUM_LENGTH_CODES 24 45 | #define NUM_DISTANCE_CODES 40 46 | #define CODE_LENGTH_CODES 19 47 | 48 | #define MIN_HUFFMAN_BITS 2 // min number of Huffman bits 49 | #define MAX_HUFFMAN_BITS 9 // max number of Huffman bits 50 | 51 | #define TRANSFORM_PRESENT 1 // The bit to be written when next data 52 | // to be read is a transform. 53 | #define NUM_TRANSFORMS 4 // Maximum number of allowed transform 54 | // in a bitstream. 55 | typedef enum { 56 | PREDICTOR_TRANSFORM = 0, 57 | CROSS_COLOR_TRANSFORM = 1, 58 | SUBTRACT_GREEN = 2, 59 | COLOR_INDEXING_TRANSFORM = 3 60 | } VP8LImageTransformType; 61 | 62 | // Alpha related constants. 63 | #define ALPHA_HEADER_LEN 1 64 | #define ALPHA_NO_COMPRESSION 0 65 | #define ALPHA_LOSSLESS_COMPRESSION 1 66 | #define ALPHA_PREPROCESSED_LEVELS 1 67 | 68 | // Mux related constants. 69 | #define TAG_SIZE 4 // Size of a chunk tag (e.g. "VP8L"). 70 | #define CHUNK_SIZE_BYTES 4 // Size needed to store chunk's size. 71 | #define CHUNK_HEADER_SIZE 8 // Size of a chunk header. 72 | #define RIFF_HEADER_SIZE 12 // Size of the RIFF header ("RIFFnnnnWEBP"). 73 | #define ANMF_CHUNK_SIZE 16 // Size of an ANMF chunk. 74 | #define ANIM_CHUNK_SIZE 6 // Size of an ANIM chunk. 75 | #define FRGM_CHUNK_SIZE 6 // Size of a FRGM chunk. 76 | #define VP8X_CHUNK_SIZE 10 // Size of a VP8X chunk. 77 | 78 | #define MAX_CANVAS_SIZE (1 << 24) // 24-bit max for VP8X width/height. 79 | #define MAX_IMAGE_AREA (1ULL << 32) // 32-bit max for width x height. 80 | #define MAX_LOOP_COUNT (1 << 16) // maximum value for loop-count 81 | #define MAX_DURATION (1 << 24) // maximum duration 82 | #define MAX_POSITION_OFFSET (1 << 24) // maximum frame/fragment x/y offset 83 | 84 | // Maximum chunk payload is such that adding the header and padding won't 85 | // overflow a uint32_t. 86 | #define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1) 87 | 88 | #endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */ 89 | -------------------------------------------------------------------------------- /interop/types-prefix-for-headers.txt: -------------------------------------------------------------------------------- 1 | typedef signed char int8_t; typedef unsigned char uint8_t; typedef signed short int16_t; typedef unsigned short uint16_t; typedef signed int int32_t; typedef unsigned int uint32_t; typedef unsigned long long int uint64_t; typedef long long int int64_t; #define WEBP_EXTERN(type) extern type 2 | //Note, after pasting in decode.h or encode.h in, ensure you expand any comma-delimited member declarations, like those in the first line of struct WebPYUVABuffer 3 | //Also, modify typedef struct WebPIDecoder WebPIDecoder; to typedef struct {} WebPIDecoder; -------------------------------------------------------------------------------- /interop/types.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 Google Inc. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license 4 | // that can be found in the COPYING file in the root of the source 5 | // tree. An additional intellectual property rights grant can be found 6 | // in the file PATENTS. All contributing project authors may 7 | // be found in the AUTHORS file in the root of the source tree. 8 | // ----------------------------------------------------------------------------- 9 | // 10 | // Common types 11 | // 12 | // Author: Skal (pascal.massimino@gmail.com) 13 | 14 | #ifndef WEBP_WEBP_TYPES_H_ 15 | #define WEBP_WEBP_TYPES_H_ 16 | 17 | #include // for size_t 18 | 19 | #ifndef _MSC_VER 20 | #include 21 | #if defined(__cplusplus) || !defined(__STRICT_ANSI__) || \ 22 | (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) 23 | #define WEBP_INLINE inline 24 | #else 25 | #define WEBP_INLINE 26 | #endif 27 | #else 28 | typedef signed char int8_t; 29 | typedef unsigned char uint8_t; 30 | typedef signed short int16_t; 31 | typedef unsigned short uint16_t; 32 | typedef signed int int32_t; 33 | typedef unsigned int uint32_t; 34 | typedef unsigned long long int uint64_t; 35 | typedef long long int int64_t; 36 | #define WEBP_INLINE __forceinline 37 | #endif /* _MSC_VER */ 38 | 39 | #ifndef WEBP_EXTERN 40 | // This explicitly marks library functions and allows for changing the 41 | // signature for e.g., Windows DLL builds. 42 | # if defined(__GNUC__) && __GNUC__ >= 4 43 | # define WEBP_EXTERN(type) extern __attribute__ ((visibility ("default"))) type 44 | # else 45 | # define WEBP_EXTERN(type) extern type 46 | # endif /* __GNUC__ >= 4 */ 47 | #endif /* WEBP_EXTERN */ 48 | 49 | // Macro to check ABI compatibility (same major revision number) 50 | #define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8)) 51 | 52 | #endif /* WEBP_WEBP_TYPES_H_ */ 53 | -------------------------------------------------------------------------------- /libwebp-build-instructions.txt: -------------------------------------------------------------------------------- 1 | Build instructions for libwebp.dll 2 | 3 | Download libwebp source via git or through http download. 4 | 5 | In Start Menu, run Visual Studio Tools>Command Prompt. 6 | 7 | change to the libwebp directory and run 8 | 9 | nmake /f Makefile.vc CFG=release-dynamic RTLIBCFG=dynamic OBJDIR=output 10 | 11 | Repeat with the 12 | x64 Cross Compiler Command Prompt 13 | 14 | Copy to x86 and x64 directories from /output/ 15 | 16 | To verify p/invokes have not changed: 17 | 18 | Review the following history logs for changes since the last release: 19 | 20 | http://git.chromium.org/gitweb/?p=webm/libwebp.git;a=history;f=src/webp/types.h;hb=HEAD 21 | http://git.chromium.org/gitweb/?p=webm/libwebp.git;a=history;f=src/webp/encode.h;hb=HEAD 22 | http://git.chromium.org/gitweb/?p=webm/libwebp.git;a=history;f=src/webp/decode.h;hb=HEAD 23 | 24 | 25 | Note that Imazen occasonally syncs imazen/libwebp with upstream libwebp 26 | https://github.com/imazen/libwebp 27 | 28 | And merges their build files into release branches, so that AppVeyor can produce clean builds. 29 | https://ci.appveyor.com/project/imazen/libwebp 30 | 31 | 0.5.2 here: 32 | https://ci.appveyor.com/project/imazen/libwebp/build/0.5.2.21 33 | -------------------------------------------------------------------------------- /open_commandline.bat: -------------------------------------------------------------------------------- 1 | 2 | Set nugetkey=inserthere 3 | 4 | echo Type "build PublishNuget" 5 | 6 | cmd /k -------------------------------------------------------------------------------- /paket.dependencies: -------------------------------------------------------------------------------- 1 | source https://www.nuget.org/api/v2/ 2 | 3 | nuget xunit 1.9.2 framework: >= net45 4 | nuget xunit.runner.console 5 | nuget xunit.runner.visualstudio version_in_path: true 6 | 7 | nuget FSharp.Formatting 8 | nuget FAKE 9 | nuget SourceLink.Fake 10 | github fsharp/FAKE modules/Octokit/Octokit.fsx 11 | 12 | -------------------------------------------------------------------------------- /paket.lock: -------------------------------------------------------------------------------- 1 | NUGET 2 | remote: https://www.nuget.org/api/v2 3 | FAKE (4.5.1) 4 | FSharp.Compiler.Service (0.0.90) 5 | FSharp.Formatting (2.11) 6 | FSharp.Compiler.Service (>= 0.0.90 <= 1.3) 7 | FSharpVSPowerTools.Core (1.9) 8 | FSharpVSPowerTools.Core (1.9) 9 | FSharp.Compiler.Service (>= 0.0.90) 10 | Microsoft.Bcl (1.1.10) 11 | Microsoft.Bcl.Build (>= 1.0.14) 12 | Microsoft.Bcl.Build (1.0.21) - import_targets: false 13 | Microsoft.Net.Http (2.2.29) 14 | Microsoft.Bcl (>= 1.1.10) 15 | Microsoft.Bcl.Build (>= 1.0.14) 16 | Octokit (0.16) 17 | Microsoft.Net.Http 18 | SourceLink.Fake (1.1) 19 | xunit (1.9.2) - framework: >= net45 20 | xunit.runner.console (2.1) 21 | xunit.runner.visualstudio (2.1.0) - version_in_path: true 22 | GITHUB 23 | remote: fsharp/FAKE 24 | modules/Octokit/Octokit.fsx (43ae9cef7d74b609d96b716150f731d6700f9520) 25 | Octokit -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # libwebp wrapper for .NET 2 | 3 | NOTICE: Do NOT use versions of Google's libwebp prior to 1.3.2! 4 | 5 | this project is not maintained; please use [Imageflow.Net](https://github.com/imazen/imageflow) instead to work with webp images. Imageflow is continually updated and secured, and bundles libwebp. 6 | 7 | Build status for branch 'master': ![build status](http://img.shields.io/appveyor/ci/imazen/libwebp-net.svg) 8 | Last nuget release: ![Nuget release version](http://img.shields.io/nuget/v/Imazen.WebP.svg) 9 | 10 | This library is available on Nuget as [Imazen.WebP](http://nuget.org/packages/Imazen.WebP). 11 | 12 | This library offers P/Invoke exposure for webp/decode.h and webp/encode.h, but not demux.h and mux.h. 13 | 14 | ## Key APIs 15 | 16 | * `new Imazen.WebP.SimpleDecoder().DecodeFromBytes(byte[] data, long length)` -> `System.Drawing.Bitmap` 17 | * `new Imazen.WebP.SimpleEncoder().Encode(Bitmap from, Stream to, float quality)` 18 | * `Imazen.WebP.SimpleEncoder.GetEncoderVersion() -> String`, `Imazen.WebP.SimpleDecoder.GetDecoderVersion() -> String` 19 | 20 | ## Improvements we're very interested in 21 | 22 | * Expose the power of Imazen.WebP.Extern.WebPConfig and Imazen.WebP.Extern.WebPPreset for better encoding. 23 | * Consider using WebPDecode for better decode error details. 24 | * Animation support 25 | * Make LoadLibrary cross-platform (although it is not strictly neccessary) 26 | * Add .NET Core support. This will likely require introducing a PixelBuffer{width, height, ptr, stride} interface that can wrap System.Drawing.Bitmap via adapter. System.Drawing.Bitmap is currently directly used by the `SimpleDecoder` and `SimpleEncoder` classes, but these total < 200 lines of code. Or, leave the core API as P/Invoke only. libwebp doesn't have a bad API at all. 27 | 28 | This library is binary compatible with as-is NMake builds of libwebp (no custom C/C++). 29 | 30 | ## License 31 | 32 | This software is released under the MIT license: 33 | 34 | Copyright (c) 2012 Imazen 35 | 36 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 37 | 38 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 39 | 40 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 41 | -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/Imazen.Test.Webp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6C57E3C1-C04F-4C96-AD90-CDA79AE53574} 8 | Library 9 | Properties 10 | Imazen.Test.Webp 11 | Imazen.Test.Webp 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | false 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | false 34 | AnyCPU 35 | bin\Release\Imazen.Test.Webp.XML 36 | 37 | 38 | true 39 | bin\x64\Debug\ 40 | DEBUG;TRACE 41 | full 42 | x64 43 | prompt 44 | MinimumRecommendedRules.ruleset 45 | 46 | 47 | bin\x64\Release\ 48 | TRACE 49 | true 50 | pdbonly 51 | x64 52 | prompt 53 | MinimumRecommendedRules.ruleset 54 | 55 | 56 | true 57 | bin\x86\Debug\ 58 | DEBUG;TRACE 59 | full 60 | x86 61 | prompt 62 | MinimumRecommendedRules.ruleset 63 | 64 | 65 | bin\x86\Release\ 66 | TRACE 67 | true 68 | pdbonly 69 | x86 70 | prompt 71 | MinimumRecommendedRules.ruleset 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | Always 93 | 94 | 95 | 96 | 97 | Always 98 | 99 | 100 | Always 101 | 102 | 103 | Always 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | {92f607a3-2f04-4536-8346-b6fef8b774ff} 112 | Imazen.WebP 113 | 114 | 115 | 116 | 117 | 118 | 119 | <__paket__xunit_runner_visualstudio_props>net20\xunit.runner.visualstudio 120 | 121 | 122 | 123 | 124 | <__paket__xunit_runner_visualstudio_props>portable-net45+win8+wp8+wpa81\xunit.runner.visualstudio 125 | 126 | 127 | 128 | 129 | <__paket__xunit_runner_visualstudio_props>win81\xunit.runner.visualstudio 130 | <__paket__xunit_runner_visualstudio_targets>win81\xunit.runner.visualstudio 131 | 132 | 133 | 134 | 135 | <__paket__xunit_runner_visualstudio_props>wpa81\xunit.runner.visualstudio 136 | <__paket__xunit_runner_visualstudio_targets>wpa81\xunit.runner.visualstudio 137 | 138 | 139 | 140 | 141 | 148 | 149 | 150 | 151 | 152 | ..\..\packages\xunit\lib\net20\xunit.dll 153 | True 154 | True 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System.Reflection; 3 | 4 | [assembly: AssemblyTitleAttribute("Imazen.Test.Webp")] 5 | [assembly: AssemblyProductAttribute("Imazen.WebP")] 6 | [assembly: AssemblyDescriptionAttribute(".NET wrapper for libwebp")] 7 | [assembly: AssemblyVersionAttribute("9.0.1")] 8 | [assembly: AssemblyFileVersionAttribute("9.0.1")] 9 | namespace System { 10 | internal static class AssemblyVersionInformation { 11 | internal const string Version = "9.0.1"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/TestSimpleDecoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | using Imazen.WebP; 4 | using System.Drawing; 5 | using System.IO; 6 | 7 | 8 | namespace Imazen.Test.Webp 9 | { 10 | public class TestSimpleDecoder 11 | { 12 | [Fact] 13 | public void TestWebPVersions() 14 | { 15 | Imazen.WebP.Extern.LoadLibrary.LoadWebPOrFail(); 16 | Assert.Equal("0.6.0",SimpleDecoder.GetDecoderVersion()); 17 | } 18 | [Fact] 19 | public void TestDecSimple() 20 | { 21 | Imazen.WebP.Extern.LoadLibrary.LoadWebPOrFail(); 22 | 23 | var decoder = new SimpleDecoder(); 24 | var fileName = "testimage.webp"; 25 | var outFile = "testimageout.jpg"; 26 | File.Delete(outFile); 27 | FileStream outStream = new FileStream(outFile, FileMode.Create); 28 | using (Stream inputStream = File.Open(fileName, System.IO.FileMode.Open)) 29 | { 30 | 31 | var bytes = ReadFully(inputStream); 32 | var outBitmap = decoder.DecodeFromBytes(bytes, bytes.LongLength); 33 | outBitmap.Save(outStream, System.Drawing.Imaging.ImageFormat.Jpeg); 34 | outStream.Close(); 35 | } 36 | 37 | FileInfo finfo = new FileInfo(outFile); 38 | Assert.True(finfo.Exists); 39 | 40 | 41 | } 42 | public static byte[] ReadFully(Stream input) 43 | { 44 | byte[] buffer = new byte[16 * 1024]; 45 | using (MemoryStream ms = new MemoryStream()) 46 | { 47 | int read; 48 | while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 49 | { 50 | ms.Write(buffer, 0, read); 51 | } 52 | return ms.ToArray(); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/TestSimpleEncoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | using Imazen.WebP; 4 | using System.IO; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | using System.Runtime.InteropServices; 8 | using System.Drawing; 9 | using Imazen.WebP.Extern; 10 | 11 | namespace Imazen.Test.WebP 12 | { 13 | public class TestSimpleEncoder 14 | { 15 | [Fact] 16 | public void TestVersion(){ 17 | Imazen.WebP.Extern.LoadLibrary.LoadWebPOrFail(); 18 | Assert.Equal("0.6.0",SimpleEncoder.GetEncoderVersion()); 19 | } 20 | [Fact] 21 | public void TestEncSimple() 22 | { 23 | Imazen.WebP.Extern.LoadLibrary.LoadWebPOrFail(); 24 | 25 | var encoder = new SimpleEncoder(); 26 | var fileName = "testimage.jpg"; 27 | var outFileName = "testimageout.webp"; 28 | File.Delete(outFileName); 29 | 30 | Bitmap mBitmap; 31 | FileStream outStream = new FileStream(outFileName, FileMode.Create); 32 | using (Stream BitmapStream = System.IO.File.Open(fileName, System.IO.FileMode.Open)) 33 | { 34 | Image img = Image.FromStream(BitmapStream); 35 | 36 | mBitmap = new Bitmap(img); 37 | 38 | encoder.Encode(mBitmap, outStream, 100); 39 | } 40 | 41 | FileInfo finfo = new FileInfo(outFileName); 42 | Assert.True(finfo.Exists); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/TestSimpleEncoderDecoderRoundtrip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Drawing.Imaging; 4 | using Xunit; 5 | using Imazen.WebP; 6 | 7 | namespace Imazen.Test.Webp 8 | { 9 | public class TestSimpleEncoderDecoderRoundtrip 10 | { 11 | private static readonly Random random = new Random(); 12 | 13 | private static byte RandomByte() 14 | { 15 | return (byte)random.Next(255); 16 | } 17 | 18 | private static Color RandomRgb() 19 | { 20 | return Color.FromArgb(0, RandomByte(), RandomByte(), RandomByte()); 21 | } 22 | 23 | private static Color RandomArgb() 24 | { 25 | return Color.FromArgb(RandomByte(), RandomRgb()); 26 | } 27 | 28 | private Bitmap GenerateTestBitmap(PixelFormat fmt, int width, int height, Func pixelValue) 29 | { 30 | var bitmap = new Bitmap(width, height, fmt); 31 | for (var y = 0; y < height; y++) 32 | { 33 | for (var x = 0; x < width; x++) 34 | { 35 | var color = pixelValue(); 36 | bitmap.SetPixel(x, y, color); 37 | } 38 | } 39 | 40 | return bitmap; 41 | } 42 | 43 | private void TestLosslessRoundtrip(Bitmap gdiBitmap) 44 | { 45 | var encoder = new SimpleEncoder(); 46 | var decoder = new SimpleDecoder(); 47 | 48 | using (var outStream = new System.IO.MemoryStream()) 49 | { 50 | encoder.Encode(gdiBitmap, outStream, -1); 51 | outStream.Close(); 52 | 53 | var webpBytes = outStream.ToArray(); 54 | var reloaded = decoder.DecodeFromBytes(webpBytes, webpBytes.LongLength); 55 | 56 | Assert.Equal(gdiBitmap.Height, reloaded.Height); 57 | Assert.Equal(gdiBitmap.Width, reloaded.Width); 58 | 59 | for (var y = 0; y < reloaded.Height; y++) 60 | { 61 | for (var x = 0; x < reloaded.Width; x++) 62 | { 63 | var expectedColor = gdiBitmap.GetPixel(x, y); 64 | var actualColor = reloaded.GetPixel(x, y); 65 | Assert.Equal(expectedColor, actualColor); 66 | } 67 | } 68 | } 69 | } 70 | 71 | [Fact] 72 | public void TestRgb32() 73 | { 74 | Imazen.WebP.Extern.LoadLibrary.LoadWebPOrFail(); 75 | 76 | using (var gdiBitmap = GenerateTestBitmap(PixelFormat.Format32bppRgb, 10, 10, TestSimpleEncoderDecoderRoundtrip.RandomRgb)) 77 | { 78 | TestLosslessRoundtrip(gdiBitmap); 79 | } 80 | } 81 | 82 | [Fact] 83 | public void TestRgb24() 84 | { 85 | Imazen.WebP.Extern.LoadLibrary.LoadWebPOrFail(); 86 | 87 | using (var gdiBitmap = GenerateTestBitmap(PixelFormat.Format24bppRgb, 10, 10, TestSimpleEncoderDecoderRoundtrip.RandomRgb)) 88 | { 89 | TestLosslessRoundtrip(gdiBitmap); 90 | } 91 | } 92 | 93 | [Fact] 94 | public void TestAgb32() 95 | { 96 | Imazen.WebP.Extern.LoadLibrary.LoadWebPOrFail(); 97 | 98 | using (var gdiBitmap = GenerateTestBitmap(PixelFormat.Format32bppArgb, 10, 10, TestSimpleEncoderDecoderRoundtrip.RandomArgb)) 99 | { 100 | TestLosslessRoundtrip(gdiBitmap); 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/paket.references: -------------------------------------------------------------------------------- 1 | xunit 2 | xunit.runner.visualstudio 3 | -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/testimage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imazen/libwebp-net/a19c9b91f9282b890110a5fe2ded5873439f3177/src/Imazen.Test.Webp/testimage.jpg -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/testimage.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imazen/libwebp-net/a19c9b91f9282b890110a5fe2ded5873439f3177/src/Imazen.Test.Webp/testimage.webp -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/x64/put_libwebp_here.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imazen/libwebp-net/a19c9b91f9282b890110a5fe2ded5873439f3177/src/Imazen.Test.Webp/x64/put_libwebp_here.txt -------------------------------------------------------------------------------- /src/Imazen.Test.Webp/x86/put_libwebp_here.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/imazen/libwebp-net/a19c9b91f9282b890110a5fe2ded5873439f3177/src/Imazen.Test.Webp/x86/put_libwebp_here.txt -------------------------------------------------------------------------------- /src/Imazen.WebP/.gitignore: -------------------------------------------------------------------------------- 1 | /*.WebP.suo 2 | *.suo 3 | -------------------------------------------------------------------------------- /src/Imazen.WebP/Extern/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | #pragma warning disable 1591 5 | namespace Imazen.WebP.Extern { 6 | public partial class NativeMethods { 7 | 8 | /// WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b) 9 | public const int WEBP_DECODER_ABI_VERSION = 520; 10 | 11 | /// WEBP_ENCODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b) 12 | public const int WEBP_ENCODER_ABI_VERSION = 521; 13 | 14 | /// 15 | /// The maximum length of any dimension of a WebP image is 16383 16 | /// 17 | public const int WEBP_MAX_DIMENSION = 16383; 18 | } 19 | } 20 | #pragma warning restore 1591 21 | -------------------------------------------------------------------------------- /src/Imazen.WebP/Extern/Decode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | #pragma warning disable 1591 6 | 7 | namespace Imazen.WebP.Extern 8 | { 9 | 10 | 11 | [StructLayoutAttribute(LayoutKind.Sequential)] 12 | public struct WebPIDecoder { } 13 | 14 | 15 | 16 | 17 | 18 | public enum WEBP_CSP_MODE 19 | { 20 | 21 | /// MODE_RGB -> 0 22 | MODE_RGB = 0, 23 | 24 | /// MODE_RGBA -> 1 25 | MODE_RGBA = 1, 26 | 27 | /// MODE_BGR -> 2 28 | MODE_BGR = 2, 29 | 30 | /// MODE_BGRA -> 3 31 | MODE_BGRA = 3, 32 | 33 | /// MODE_ARGB -> 4 34 | MODE_ARGB = 4, 35 | 36 | /// MODE_RGBA_4444 -> 5 37 | MODE_RGBA_4444 = 5, 38 | 39 | /// MODE_RGB_565 -> 6 40 | MODE_RGB_565 = 6, 41 | 42 | /// MODE_rgbA -> 7 43 | MODE_rgbA = 7, 44 | 45 | /// MODE_bgrA -> 8 46 | MODE_bgrA = 8, 47 | 48 | /// MODE_Argb -> 9 49 | MODE_Argb = 9, 50 | 51 | /// MODE_rgbA_4444 -> 10 52 | MODE_rgbA_4444 = 10, 53 | 54 | /// MODE_YUV -> 11 55 | MODE_YUV = 11, 56 | 57 | /// MODE_YUVA -> 12 58 | MODE_YUVA = 12, 59 | 60 | /// MODE_LAST -> 13 61 | MODE_LAST = 13, 62 | } 63 | 64 | 65 | 66 | 67 | 68 | 69 | //------------------------------------------------------------------------------ 70 | // WebPDecBuffer: Generic structure for describing the output sample buffer. 71 | 72 | [StructLayoutAttribute(LayoutKind.Sequential)] 73 | public struct WebPRGBABuffer 74 | { 75 | 76 | /// uint8_t* 77 | public IntPtr rgba; 78 | 79 | /// int 80 | public int stride; 81 | 82 | /// size_t->unsigned int 83 | public UIntPtr size; 84 | } 85 | 86 | [StructLayoutAttribute(LayoutKind.Sequential)] 87 | public struct WebPYUVABuffer 88 | { 89 | 90 | /// uint8_t* 91 | public IntPtr y; 92 | 93 | /// uint8_t* 94 | public IntPtr u; 95 | 96 | /// uint8_t* 97 | public IntPtr v; 98 | 99 | /// uint8_t* 100 | public IntPtr a; 101 | 102 | /// int 103 | public int y_stride; 104 | 105 | /// int 106 | public int u_stride; 107 | 108 | /// int 109 | public int v_stride; 110 | 111 | /// int 112 | public int a_stride; 113 | 114 | /// size_t->unsigned int 115 | public UIntPtr y_size; 116 | 117 | /// size_t->unsigned int 118 | public UIntPtr u_size; 119 | 120 | /// size_t->unsigned int 121 | public UIntPtr v_size; 122 | 123 | /// size_t->unsigned int 124 | public UIntPtr a_size; 125 | } 126 | 127 | [StructLayoutAttribute(LayoutKind.Explicit)] 128 | public struct Anonymous_690ed5ec_4c3d_40c6_9bd0_0747b5a28b54 129 | { 130 | 131 | /// WebPRGBABuffer->Anonymous_47cdec86_3c1a_4b39_ab93_76bc7499076a 132 | [FieldOffsetAttribute(0)] 133 | public WebPRGBABuffer RGBA; 134 | 135 | /// WebPYUVABuffer->Anonymous_70de6e8e_c3ae_4506_bef0_c17f17a7e678 136 | [FieldOffsetAttribute(0)] 137 | public WebPYUVABuffer YUVA; 138 | } 139 | 140 | [StructLayoutAttribute(LayoutKind.Sequential)] 141 | public struct WebPDecBuffer 142 | { 143 | 144 | /// WEBP_CSP_MODE->Anonymous_cb136f5b_1d5d_49a0_aca4_656a79e9d159 145 | public WEBP_CSP_MODE colorspace; 146 | 147 | /// int 148 | public int width; 149 | 150 | /// int 151 | public int height; 152 | 153 | /// int 154 | public int is_external_memory; 155 | 156 | /// Anonymous_690ed5ec_4c3d_40c6_9bd0_0747b5a28b54 157 | public Anonymous_690ed5ec_4c3d_40c6_9bd0_0747b5a28b54 u; 158 | 159 | /// uint32_t[4] 160 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U4)] 161 | public uint[] pad; 162 | 163 | /// uint8_t* 164 | public IntPtr private_memory; 165 | } 166 | 167 | 168 | //------------------------------------------------------------------------------ 169 | // Enumeration of the status codes 170 | 171 | public enum VP8StatusCode 172 | { 173 | 174 | /// VP8_STATUS_OK -> 0 175 | VP8_STATUS_OK = 0, 176 | 177 | VP8_STATUS_OUT_OF_MEMORY, 178 | 179 | VP8_STATUS_INVALID_PARAM, 180 | 181 | VP8_STATUS_BITSTREAM_ERROR, 182 | 183 | VP8_STATUS_UNSUPPORTED_FEATURE, 184 | 185 | VP8_STATUS_SUSPENDED, 186 | 187 | VP8_STATUS_USER_ABORT, 188 | 189 | VP8_STATUS_NOT_ENOUGH_DATA, 190 | } 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | [StructLayoutAttribute(LayoutKind.Sequential)] 212 | public struct WebPBitstreamFeatures 213 | { 214 | 215 | /// 216 | /// Width in pixels, as read from the bitstream 217 | /// 218 | public int width; 219 | 220 | /// 221 | /// Height in pixels, as read from the bitstream. 222 | /// 223 | public int height; 224 | 225 | /// 226 | /// // True if the bitstream contains an alpha channel. 227 | /// 228 | public int has_alpha; 229 | 230 | /// 231 | /// True if the bitstream contains an animation 232 | /// 233 | public int has_animation; 234 | 235 | /// 236 | /// 0 = undefined (/mixed), 1 = lossy, 2 = lossless 237 | /// 238 | public int format; 239 | 240 | 241 | /// 242 | /// Padding for later use 243 | /// 244 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.U4)] 245 | public uint[] pad; 246 | } 247 | 248 | 249 | 250 | 251 | // Decoding options 252 | [StructLayoutAttribute(LayoutKind.Sequential)] 253 | public struct WebPDecoderOptions 254 | { 255 | public int bypass_filtering; // if true, skip the in-loop filtering 256 | public int no_fancy_upsampling; // if true, use faster pointwise upsampler 257 | public int use_cropping; // if true, cropping is applied _first_ 258 | public int crop_left, crop_top; // top-left position for cropping. 259 | // Will be snapped to even values. 260 | public int crop_width, crop_height; // dimension of the cropping area 261 | public int use_scaling; // if true, scaling is applied _afterward_ 262 | public int scaled_width, scaled_height; // final resolution 263 | public int use_threads; // if true, use multi-threaded decoding 264 | public int dithering_strength; // dithering strength (0=Off, 100=full) 265 | 266 | public int flip; // flip output vertically 267 | public int alpha_dithering_strength; // alpha dithering strength in [0..100] 268 | 269 | /// uint32_t[5] 270 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.U4)] 271 | public uint[] pad; 272 | }; 273 | 274 | [StructLayoutAttribute(LayoutKind.Sequential)] 275 | public struct WebPDecoderConfig 276 | { 277 | 278 | /// WebPBitstreamFeatures->Anonymous_c6b01f0b_3e38_4731_b2d6_9c0e3bdb71aa 279 | public WebPBitstreamFeatures input; 280 | 281 | /// WebPDecBuffer->Anonymous_5c438b36_7de6_498e_934a_d3613b37f5fc 282 | public WebPDecBuffer output; 283 | 284 | /// WebPDecoderOptions->Anonymous_78066979_3e1e_4d74_aee5_f316b20e3385 285 | public WebPDecoderOptions options; 286 | } 287 | 288 | 289 | public partial class NativeMethods 290 | { 291 | 292 | /// Return Type: int 293 | [DllImportAttribute("libwebp", EntryPoint = "WebPGetDecoderVersion", CallingConvention = CallingConvention.Cdecl)] 294 | public static extern int WebPGetDecoderVersion(); 295 | 296 | 297 | 298 | 299 | /// 300 | /// Retrieve basic header information: width, height. 301 | /// This function will also validate the header and return 0 in 302 | /// case of formatting error. 303 | /// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant. 304 | /// 305 | /// 306 | /// 307 | /// 308 | /// 309 | /// 310 | [DllImportAttribute("libwebp", EntryPoint = "WebPGetInfo", CallingConvention = CallingConvention.Cdecl)] 311 | public static extern int WebPGetInfo([InAttribute()] IntPtr data, UIntPtr data_size, ref int width, ref int height); 312 | 313 | 314 | /// Return Type: uint8_t* 315 | ///data: uint8_t* 316 | ///data_size: size_t->unsigned int 317 | ///width: int* 318 | ///height: int* 319 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeRGBA", CallingConvention = CallingConvention.Cdecl)] 320 | public static extern IntPtr WebPDecodeRGBA([InAttribute()] IntPtr data, UIntPtr data_size, ref int width, ref int height); 321 | 322 | 323 | /// Return Type: uint8_t* 324 | ///data: uint8_t* 325 | ///data_size: size_t->unsigned int 326 | ///width: int* 327 | ///height: int* 328 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeARGB", CallingConvention = CallingConvention.Cdecl)] 329 | public static extern IntPtr WebPDecodeARGB([InAttribute()] IntPtr data, UIntPtr data_size, ref int width, ref int height); 330 | 331 | 332 | /// Return Type: uint8_t* 333 | ///data: uint8_t* 334 | ///data_size: size_t->unsigned int 335 | ///width: int* 336 | ///height: int* 337 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeBGRA", CallingConvention = CallingConvention.Cdecl)] 338 | public static extern IntPtr WebPDecodeBGRA([InAttribute()] IntPtr data, UIntPtr data_size, ref int width, ref int height); 339 | 340 | 341 | /// Return Type: uint8_t* 342 | ///data: uint8_t* 343 | ///data_size: size_t->unsigned int 344 | ///width: int* 345 | ///height: int* 346 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeRGB", CallingConvention = CallingConvention.Cdecl)] 347 | public static extern IntPtr WebPDecodeRGB([InAttribute()] IntPtr data, UIntPtr data_size, ref int width, ref int height); 348 | 349 | 350 | /// Return Type: uint8_t* 351 | ///data: uint8_t* 352 | ///data_size: size_t->unsigned int 353 | ///width: int* 354 | ///height: int* 355 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeBGR", CallingConvention = CallingConvention.Cdecl)] 356 | public static extern IntPtr WebPDecodeBGR([InAttribute()] IntPtr data, UIntPtr data_size, ref int width, ref int height); 357 | 358 | 359 | /// Return Type: uint8_t* 360 | ///data: uint8_t* 361 | ///data_size: size_t->unsigned int 362 | ///width: int* 363 | ///height: int* 364 | ///u: uint8_t** 365 | ///v: uint8_t** 366 | ///stride: int* 367 | ///uv_stride: int* 368 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeYUV", CallingConvention = CallingConvention.Cdecl)] 369 | public static extern IntPtr WebPDecodeYUV([InAttribute()] IntPtr data, UIntPtr data_size, ref int width, ref int height, ref IntPtr u, ref IntPtr v, ref int stride, ref int uv_stride); 370 | 371 | 372 | /// Return Type: uint8_t* 373 | ///data: uint8_t* 374 | ///data_size: size_t->unsigned int 375 | ///output_buffer: uint8_t* 376 | ///output_buffer_size: size_t->unsigned int 377 | ///output_stride: int 378 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeRGBAInto", CallingConvention = CallingConvention.Cdecl)] 379 | public static extern IntPtr WebPDecodeRGBAInto([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); 380 | 381 | 382 | /// Return Type: uint8_t* 383 | ///data: uint8_t* 384 | ///data_size: size_t->unsigned int 385 | ///output_buffer: uint8_t* 386 | ///output_buffer_size: size_t->unsigned int 387 | ///output_stride: int 388 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeARGBInto", CallingConvention = CallingConvention.Cdecl)] 389 | public static extern IntPtr WebPDecodeARGBInto([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); 390 | 391 | 392 | /// Return Type: uint8_t* 393 | ///data: uint8_t* 394 | ///data_size: size_t->unsigned int 395 | ///output_buffer: uint8_t* 396 | ///output_buffer_size: size_t->unsigned int 397 | ///output_stride: int 398 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeBGRAInto", CallingConvention = CallingConvention.Cdecl)] 399 | public static extern IntPtr WebPDecodeBGRAInto([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); 400 | 401 | 402 | /// Return Type: uint8_t* 403 | ///data: uint8_t* 404 | ///data_size: size_t->unsigned int 405 | ///output_buffer: uint8_t* 406 | ///output_buffer_size: size_t->unsigned int 407 | ///output_stride: int 408 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeRGBInto", CallingConvention = CallingConvention.Cdecl)] 409 | public static extern IntPtr WebPDecodeRGBInto([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); 410 | 411 | 412 | /// Return Type: uint8_t* 413 | ///data: uint8_t* 414 | ///data_size: size_t->unsigned int 415 | ///output_buffer: uint8_t* 416 | ///output_buffer_size: size_t->unsigned int 417 | ///output_stride: int 418 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeBGRInto", CallingConvention = CallingConvention.Cdecl)] 419 | public static extern IntPtr WebPDecodeBGRInto([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); 420 | 421 | 422 | /// Return Type: uint8_t* 423 | ///data: uint8_t* 424 | ///data_size: size_t->unsigned int 425 | ///luma: uint8_t* 426 | ///luma_size: size_t->unsigned int 427 | ///luma_stride: int 428 | ///u: uint8_t* 429 | ///u_size: size_t->unsigned int 430 | ///u_stride: int 431 | ///v: uint8_t* 432 | ///v_size: size_t->unsigned int 433 | ///v_stride: int 434 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecodeYUVInto", CallingConvention = CallingConvention.Cdecl)] 435 | public static extern IntPtr WebPDecodeYUVInto([InAttribute()] IntPtr data, UIntPtr data_size, IntPtr luma, UIntPtr luma_size, int luma_stride, IntPtr u, UIntPtr u_size, int u_stride, IntPtr v, UIntPtr v_size, int v_stride); 436 | 437 | 438 | /// Return Type: int 439 | ///param0: WebPDecBuffer* 440 | ///param1: int 441 | [DllImportAttribute("libwebp", EntryPoint = "WebPInitDecBufferInternal", CallingConvention = CallingConvention.Cdecl)] 442 | public static extern int WebPInitDecBufferInternal(ref WebPDecBuffer param0, int param1); 443 | 444 | 445 | /// Return Type: void 446 | ///buffer: WebPDecBuffer* 447 | [DllImportAttribute("libwebp", EntryPoint = "WebPFreeDecBuffer", CallingConvention = CallingConvention.Cdecl)] 448 | public static extern void WebPFreeDecBuffer(ref WebPDecBuffer buffer); 449 | 450 | 451 | /// Return Type: WebPIDecoder* 452 | ///output_buffer: WebPDecBuffer* 453 | [DllImportAttribute("libwebp", EntryPoint = "WebPINewDecoder", CallingConvention = CallingConvention.Cdecl)] 454 | public static extern IntPtr WebPINewDecoder(ref WebPDecBuffer output_buffer); 455 | 456 | 457 | /// Return Type: WebPIDecoder* 458 | ///csp: WEBP_CSP_MODE->Anonymous_cb136f5b_1d5d_49a0_aca4_656a79e9d159 459 | ///output_buffer: uint8_t* 460 | ///output_buffer_size: size_t->unsigned int 461 | ///output_stride: int 462 | [DllImportAttribute("libwebp", EntryPoint = "WebPINewRGB", CallingConvention = CallingConvention.Cdecl)] 463 | public static extern IntPtr WebPINewRGB(WEBP_CSP_MODE csp, IntPtr output_buffer, UIntPtr output_buffer_size, int output_stride); 464 | 465 | 466 | /// Return Type: WebPIDecoder* 467 | ///luma: uint8_t* 468 | ///luma_size: size_t->unsigned int 469 | ///luma_stride: int 470 | ///u: uint8_t* 471 | ///u_size: size_t->unsigned int 472 | ///u_stride: int 473 | ///v: uint8_t* 474 | ///v_size: size_t->unsigned int 475 | ///v_stride: int 476 | ///a: uint8_t* 477 | ///a_size: size_t->unsigned int 478 | ///a_stride: int 479 | [DllImportAttribute("libwebp", EntryPoint = "WebPINewYUVA", CallingConvention = CallingConvention.Cdecl)] 480 | public static extern IntPtr WebPINewYUVA(IntPtr luma, UIntPtr luma_size, int luma_stride, IntPtr u, UIntPtr u_size, int u_stride, IntPtr v, UIntPtr v_size, int v_stride, IntPtr a, UIntPtr a_size, int a_stride); 481 | 482 | 483 | /// Return Type: WebPIDecoder* 484 | ///luma: uint8_t* 485 | ///luma_size: size_t->unsigned int 486 | ///luma_stride: int 487 | ///u: uint8_t* 488 | ///u_size: size_t->unsigned int 489 | ///u_stride: int 490 | ///v: uint8_t* 491 | ///v_size: size_t->unsigned int 492 | ///v_stride: int 493 | [DllImportAttribute("libwebp", EntryPoint = "WebPINewYUV", CallingConvention = CallingConvention.Cdecl)] 494 | public static extern IntPtr WebPINewYUV(IntPtr luma, UIntPtr luma_size, int luma_stride, IntPtr u, UIntPtr u_size, int u_stride, IntPtr v, UIntPtr v_size, int v_stride); 495 | 496 | 497 | /// Return Type: void 498 | ///idec: WebPIDecoder* 499 | [DllImportAttribute("libwebp", EntryPoint = "WebPIDelete", CallingConvention = CallingConvention.Cdecl)] 500 | public static extern void WebPIDelete(ref WebPIDecoder idec); 501 | 502 | 503 | /// Return Type: VP8StatusCode->Anonymous_b244cc15_fbc7_4c41_8884_71fe4f515cd6 504 | ///idec: WebPIDecoder* 505 | ///data: uint8_t* 506 | ///data_size: size_t->unsigned int 507 | [DllImportAttribute("libwebp", EntryPoint = "WebPIAppend", CallingConvention = CallingConvention.Cdecl)] 508 | public static extern VP8StatusCode WebPIAppend(ref WebPIDecoder idec, [InAttribute()] IntPtr data, UIntPtr data_size); 509 | 510 | 511 | /// Return Type: VP8StatusCode->Anonymous_b244cc15_fbc7_4c41_8884_71fe4f515cd6 512 | ///idec: WebPIDecoder* 513 | ///data: uint8_t* 514 | ///data_size: size_t->unsigned int 515 | [DllImportAttribute("libwebp", EntryPoint = "WebPIUpdate", CallingConvention = CallingConvention.Cdecl)] 516 | public static extern VP8StatusCode WebPIUpdate(ref WebPIDecoder idec, [InAttribute()] IntPtr data, UIntPtr data_size); 517 | 518 | 519 | /// Return Type: uint8_t* 520 | ///idec: WebPIDecoder* 521 | ///last_y: int* 522 | ///width: int* 523 | ///height: int* 524 | ///stride: int* 525 | [DllImportAttribute("libwebp", EntryPoint = "WebPIDecGetRGB", CallingConvention = CallingConvention.Cdecl)] 526 | public static extern IntPtr WebPIDecGetRGB(ref WebPIDecoder idec, ref int last_y, ref int width, ref int height, ref int stride); 527 | 528 | 529 | /// Return Type: uint8_t* 530 | ///idec: WebPIDecoder* 531 | ///last_y: int* 532 | ///u: uint8_t** 533 | ///v: uint8_t** 534 | ///a: uint8_t** 535 | ///width: int* 536 | ///height: int* 537 | ///stride: int* 538 | ///uv_stride: int* 539 | ///a_stride: int* 540 | [DllImportAttribute("libwebp", EntryPoint = "WebPIDecGetYUVA", CallingConvention = CallingConvention.Cdecl)] 541 | public static extern IntPtr WebPIDecGetYUVA(ref WebPIDecoder idec, ref int last_y, ref IntPtr u, ref IntPtr v, ref IntPtr a, ref int width, ref int height, ref int stride, ref int uv_stride, ref int a_stride); 542 | 543 | 544 | /// Return Type: WebPDecBuffer* 545 | ///idec: WebPIDecoder* 546 | ///left: int* 547 | ///top: int* 548 | ///width: int* 549 | ///height: int* 550 | [DllImportAttribute("libwebp", EntryPoint = "WebPIDecodedArea", CallingConvention = CallingConvention.Cdecl)] 551 | public static extern IntPtr WebPIDecodedArea(ref WebPIDecoder idec, ref int left, ref int top, ref int width, ref int height); 552 | 553 | 554 | /// Return Type: VP8StatusCode->Anonymous_b244cc15_fbc7_4c41_8884_71fe4f515cd6 555 | ///param0: uint8_t* 556 | ///param1: size_t->unsigned int 557 | ///param2: WebPBitstreamFeatures* 558 | ///param3: int 559 | [DllImportAttribute("libwebp", EntryPoint = "WebPGetFeaturesInternal", CallingConvention = CallingConvention.Cdecl)] 560 | public static extern VP8StatusCode WebPGetFeaturesInternal([InAttribute()] IntPtr param0, UIntPtr param1, ref WebPBitstreamFeatures param2, int param3); 561 | 562 | 563 | /// Return Type: int 564 | ///param0: WebPDecoderConfig* 565 | ///param1: int 566 | [DllImportAttribute("libwebp", EntryPoint = "WebPInitDecoderConfigInternal", CallingConvention = CallingConvention.Cdecl)] 567 | public static extern int WebPInitDecoderConfigInternal(ref WebPDecoderConfig param0, int param1); 568 | 569 | 570 | /// Return Type: WebPIDecoder* 571 | ///data: uint8_t* 572 | ///data_size: size_t->unsigned int 573 | ///config: WebPDecoderConfig* 574 | [DllImportAttribute("libwebp", EntryPoint = "WebPIDecode", CallingConvention = CallingConvention.Cdecl)] 575 | public static extern IntPtr WebPIDecode([InAttribute()] IntPtr data, UIntPtr data_size, ref WebPDecoderConfig config); 576 | 577 | 578 | /// Return Type: VP8StatusCode->Anonymous_b244cc15_fbc7_4c41_8884_71fe4f515cd6 579 | ///data: uint8_t* 580 | ///data_size: size_t->unsigned int 581 | ///config: WebPDecoderConfig* 582 | [DllImportAttribute("libwebp", EntryPoint = "WebPDecode", CallingConvention = CallingConvention.Cdecl)] 583 | public static extern VP8StatusCode WebPDecode([InAttribute()] IntPtr data, UIntPtr data_size, ref WebPDecoderConfig config); 584 | 585 | } 586 | 587 | 588 | } 589 | 590 | #pragma warning restore 1591 -------------------------------------------------------------------------------- /src/Imazen.WebP/Extern/DecodeInlines.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Imazen.WebP.Extern { 6 | public partial class NativeMethods { 7 | 8 | // Some useful macros: 9 | 10 | /// 11 | /// Returns true if the specified mode uses a premultiplied alpha 12 | /// 13 | /// 14 | /// 15 | public static bool WebPIsPremultipliedMode(WEBP_CSP_MODE mode) { 16 | 17 | return (mode == WEBP_CSP_MODE.MODE_rgbA || mode == WEBP_CSP_MODE.MODE_bgrA || mode == WEBP_CSP_MODE.MODE_Argb || 18 | mode == WEBP_CSP_MODE.MODE_rgbA_4444); 19 | 20 | } 21 | 22 | /// 23 | /// Returns true if the given mode is RGB(A) 24 | /// 25 | /// 26 | /// 27 | public static bool WebPIsRGBMode(WEBP_CSP_MODE mode) { 28 | 29 | return (mode < WEBP_CSP_MODE.MODE_YUV); 30 | 31 | } 32 | 33 | 34 | /// 35 | /// Returns true if the given mode has an alpha channel 36 | /// 37 | /// 38 | /// 39 | public static bool WebPIsAlphaMode(WEBP_CSP_MODE mode) { 40 | 41 | return (mode == WEBP_CSP_MODE.MODE_RGBA || mode == WEBP_CSP_MODE.MODE_BGRA || mode == WEBP_CSP_MODE.MODE_ARGB || 42 | mode == WEBP_CSP_MODE.MODE_RGBA_4444 || mode == WEBP_CSP_MODE.MODE_YUVA || 43 | WebPIsPremultipliedMode(mode)); 44 | 45 | } 46 | 47 | 48 | 49 | // 50 | 51 | /// 52 | /// Retrieve features from the bitstream. The *features structure is filled 53 | /// with information gathered from the bitstream. 54 | /// Returns false in case of error or version mismatch. 55 | /// In case of error, features->bitstream_status will reflect the error code. 56 | /// 57 | /// 58 | /// 59 | /// 60 | /// 61 | public static VP8StatusCode WebPGetFeatures(IntPtr data, UIntPtr data_size, ref WebPBitstreamFeatures features) { 62 | return NativeMethods.WebPGetFeaturesInternal(data, data_size, ref features, WEBP_DECODER_ABI_VERSION); 63 | 64 | } 65 | /// 66 | /// Initialize the configuration as empty. This function must always be 67 | /// called first, unless WebPGetFeatures() is to be called. 68 | /// Returns false in case of mismatched version. 69 | /// 70 | /// 71 | /// 72 | public static int WebPInitDecoderConfig(ref WebPDecoderConfig config) { 73 | 74 | return WebPInitDecoderConfigInternal(ref config, WEBP_DECODER_ABI_VERSION); 75 | 76 | } 77 | 78 | 79 | /// 80 | /// Initialize the structure as empty. Must be called before any other use. Returns false in case of version mismatch 81 | /// 82 | /// 83 | /// 84 | public static int WebPInitDecBuffer(ref WebPDecBuffer buffer) { 85 | return WebPInitDecBufferInternal(ref buffer, WEBP_DECODER_ABI_VERSION); 86 | } 87 | 88 | 89 | 90 | // // Deprecated alpha-less version of WebPIDecGetYUVA(): it will ignore the 91 | 92 | //// alpha information (if present). Kept for backward compatibility. 93 | 94 | //public IntPtr WebPIDecGetYUV(IntPtr decoder, int* last_y, uint8_t** u, uint8_t** v, 95 | 96 | // int* width, int* height, int* stride, int* uv_stride) { 97 | 98 | // return WebPIDecGetYUVA(idec, last_y, u, v, NULL, width, height, 99 | 100 | // stride, uv_stride, NULL); 101 | 102 | } 103 | 104 | 105 | 106 | 107 | } 108 | 109 | -------------------------------------------------------------------------------- /src/Imazen.WebP/Extern/Encode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | #pragma warning disable 1591 7 | 8 | namespace Imazen.WebP.Extern 9 | { 10 | 11 | public enum WebPImageHint 12 | { 13 | 14 | /// WEBP_HINT_DEFAULT -> 0 15 | WEBP_HINT_DEFAULT = 0, 16 | 17 | WEBP_HINT_PICTURE, 18 | 19 | WEBP_HINT_PHOTO, 20 | 21 | WEBP_HINT_GRAPH, 22 | 23 | WEBP_HINT_LAST, 24 | } 25 | 26 | [StructLayoutAttribute(LayoutKind.Sequential)] 27 | public struct WebPConfig 28 | { 29 | 30 | /// Lossless encoding (0=lossy(default), 1=lossless). 31 | public int lossless; 32 | 33 | /// between 0 (smallest file) and 100 (biggest) 34 | public float quality; 35 | 36 | /// quality/speed trade-off (0=fast, 6=slower-better) 37 | public int method; 38 | 39 | /// WebPImageHint->Anonymous_838f22f5_6f57_48a0_9ecb_8eec917009f9 40 | public WebPImageHint image_hint; 41 | 42 | // Parameters related to lossy compression only: 43 | 44 | /// if non-zero, set the desired target size in bytes. Takes precedence over the 'compression' parameter. 45 | public int target_size; 46 | 47 | /// if non-zero, specifies the minimal distortion to try to achieve. Takes precedence over target_size. 48 | public float target_PSNR; 49 | 50 | /// maximum number of segments to use, in [1..4] 51 | public int segments; 52 | 53 | /// Spatial Noise Shaping. 0=off, 100=maximum. 54 | public int sns_strength; 55 | 56 | /// range: [0 = off .. 100 = strongest] 57 | public int filter_strength; 58 | 59 | /// range: [0 = off .. 7 = least sharp] 60 | public int filter_sharpness; 61 | 62 | /// filtering type: 0 = simple, 1 = strong (only used 63 | /// if filter_strength > 0 or autofilter > 0) 64 | public int filter_type; 65 | 66 | /// Auto adjust filter's strength [0 = off, 1 = on] 67 | public int autofilter; 68 | 69 | /// Algorithm for encoding the alpha plane (0 = none, 70 | /// 1 = compressed with WebP lossless). Default is 1. 71 | public int alpha_compression; 72 | 73 | /// Predictive filtering method for alpha plane. 74 | /// 0: none, 1: fast, 2: best. Default if 1. 75 | public int alpha_filtering; 76 | 77 | /// Between 0 (smallest size) and 100 (lossless). 78 | // Default is 100. 79 | public int alpha_quality; 80 | 81 | /// number of entropy-analysis passes (in [1..10]). 82 | public int pass; 83 | 84 | /// if true, export the compressed picture back. 85 | /// In-loop filtering is not applied. 86 | public int show_compressed; 87 | 88 | /// preprocessing filter: 89 | /// 0=none, 1=segment-smooth, 2=pseudo-random dithering 90 | public int preprocessing; 91 | 92 | /// log2(number of token partitions) in [0..3]. Default 93 | /// is set to 0 for easier progressive decoding. 94 | public int partitions; 95 | 96 | /// quality degradation allowed to fit the 512k limit 97 | /// on prediction modes coding (0: no degradation, 98 | /// 100: maximum possible degradation). 99 | public int partition_limit; 100 | 101 | /// 102 | /// If true, compression parameters will be remapped 103 | /// to better match the expected output size from 104 | /// JPEG compression. Generally, the output size will 105 | /// be similar but the degradation will be lower. 106 | /// 107 | public int emulate_jpeg_size; 108 | 109 | /// If non-zero, try and use multi-threaded encoding. 110 | public int thread_level; 111 | 112 | /// 113 | /// If set, reduce memory usage (but increase CPU use). 114 | /// 115 | public int low_memory; 116 | 117 | /// 118 | /// Near lossless encoding [0 = max loss .. 100 = off (default)]. 119 | /// 120 | public int near_lossless; 121 | 122 | /// if non-zero, preserve the exact RGB values under 123 | /// transparent area. Otherwise, discard this invisible 124 | /// RGB information for better compression. The default 125 | /// value is 0. 126 | public int exact; 127 | 128 | /// uint32_t[3] 129 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U4)] 130 | public uint[] pad; 131 | } 132 | 133 | public enum WebPPreset 134 | { 135 | 136 | /// WEBP_PRESET_DEFAULT -> 0 137 | WEBP_PRESET_DEFAULT = 0, 138 | 139 | /// digital picture, like portrait, inner shot 140 | WEBP_PRESET_PICTURE, 141 | 142 | /// outdoor photograph, with natural lighting 143 | WEBP_PRESET_PHOTO, 144 | 145 | /// hand or line drawing, with high-contrast details 146 | WEBP_PRESET_DRAWING, 147 | 148 | /// small-sized colorful images 149 | WEBP_PRESET_ICON, 150 | 151 | /// text-like 152 | WEBP_PRESET_TEXT, 153 | } 154 | 155 | 156 | 157 | 158 | 159 | 160 | [StructLayoutAttribute(LayoutKind.Sequential)] 161 | public struct WebPAuxStats 162 | { 163 | 164 | /// int 165 | public int coded_size; 166 | 167 | /// float[5] 168 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 5, ArraySubType = UnmanagedType.R4)] 169 | public float[] PSNR; 170 | 171 | /// int[3] 172 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I4)] 173 | public int[] block_count; 174 | 175 | /// int[2] 176 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.I4)] 177 | public int[] header_bytes; 178 | 179 | /// int[12] 180 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 12, ArraySubType = UnmanagedType.I4)] 181 | public int[] residual_bytes; 182 | 183 | /// int[4] 184 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)] 185 | public int[] segment_size; 186 | 187 | /// int[4] 188 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)] 189 | public int[] segment_quant; 190 | 191 | /// int[4] 192 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.I4)] 193 | public int[] segment_level; 194 | 195 | /// int 196 | public int alpha_data_size; 197 | 198 | /// int 199 | public int layer_data_size; 200 | 201 | /// uint32_t->unsigned int 202 | public uint lossless_features; 203 | 204 | /// int 205 | public int histogram_bits; 206 | 207 | /// int 208 | public int transform_bits; 209 | 210 | /// int 211 | public int cache_bits; 212 | 213 | /// int 214 | public int palette_size; 215 | 216 | /// int 217 | public int lossless_size; 218 | 219 | /// lossless header (transform, huffman etc) size 220 | public int lossless_hdr_size; 221 | 222 | /// lossless image data size 223 | public int lossless_data_size; 224 | /// uint32_t[2] 225 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)] 226 | public uint[] pad; 227 | } 228 | 229 | 230 | /// Return Type: int 231 | ///data: uint8_t* 232 | ///data_size: size_t->unsigned int 233 | ///picture: WebPPicture* 234 | public delegate int WebPWriterFunction([InAttribute()] IntPtr data, UIntPtr data_size, ref WebPPicture picture); 235 | 236 | [StructLayoutAttribute(LayoutKind.Sequential)] 237 | public struct WebPMemoryWriter 238 | { 239 | 240 | /// uint8_t* 241 | public IntPtr mem; 242 | 243 | /// size_t->unsigned int 244 | public UIntPtr size; 245 | 246 | /// size_t->unsigned int 247 | public UIntPtr max_size; 248 | 249 | /// uint32_t[1] 250 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 1, ArraySubType = UnmanagedType.U4)] 251 | public uint[] pad; 252 | } 253 | 254 | 255 | 256 | /// Return Type: int 257 | ///percent: int 258 | ///picture: WebPPicture* 259 | public delegate int WebPProgressHook(int percent, ref WebPPicture picture); 260 | 261 | public enum WebPEncCSP 262 | { 263 | 264 | /// 4:2:0 (half-res chroma x and y) 265 | WEBP_YUV420 = 0, 266 | 267 | /// bit-mask to get the UV sampling factors 268 | WEBP_CSP_UV_MASK = 3, 269 | 270 | /// 4:2:0 with alpha 271 | WEBP_YUV420A = 4, 272 | 273 | /// Bit mask to set alpha 274 | WEBP_CSP_ALPHA_BIT = 4, 275 | } 276 | 277 | 278 | public enum WebPEncodingError 279 | { 280 | 281 | /// VP8_ENC_OK -> 0 282 | VP8_ENC_OK = 0, 283 | 284 | VP8_ENC_ERROR_OUT_OF_MEMORY, 285 | 286 | VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY, 287 | 288 | VP8_ENC_ERROR_NULL_PARAMETER, 289 | 290 | VP8_ENC_ERROR_INVALID_CONFIGURATION, 291 | 292 | VP8_ENC_ERROR_BAD_DIMENSION, 293 | 294 | VP8_ENC_ERROR_PARTITION0_OVERFLOW, 295 | 296 | VP8_ENC_ERROR_PARTITION_OVERFLOW, 297 | 298 | VP8_ENC_ERROR_BAD_WRITE, 299 | 300 | VP8_ENC_ERROR_FILE_TOO_BIG, 301 | 302 | VP8_ENC_ERROR_USER_ABORT, 303 | 304 | VP8_ENC_ERROR_LAST, 305 | } 306 | 307 | 308 | /// 309 | /// Main exchange structure (input samples, output bytes, statistics) 310 | /// 311 | [StructLayoutAttribute(LayoutKind.Sequential)] 312 | public struct WebPPicture 313 | { 314 | 315 | // INPUT 316 | ////////////// 317 | // Main flag for encoder selecting between ARGB or YUV input. 318 | // It is recommended to use ARGB input (*argb, argb_stride) for lossless 319 | // compression, and YUV input (*y, *u, *v, etc.) for lossy compression 320 | // since these are the respective native colorspace for these formats. 321 | public int use_argb; 322 | 323 | // YUV input (mostly used for input to lossy compression) 324 | 325 | /// colorspace: should be YUV420 for now (=Y'CbCr). WebPEncCSP->Anonymous_84ce7065_fe91_48b4_93d8_1f0e84319dba 326 | public WebPEncCSP colorspace; 327 | 328 | /// int 329 | public int width; 330 | 331 | /// int 332 | public int height; 333 | 334 | /// uint8_t* pointers to luma/chroma planes. 335 | public IntPtr y; 336 | 337 | /// uint8_t* 338 | public IntPtr u; 339 | 340 | /// uint8_t* 341 | public IntPtr v; 342 | 343 | /// int 344 | public int y_stride; 345 | 346 | /// int 347 | public int uv_stride; 348 | 349 | /// uint8_t* 350 | public IntPtr a; 351 | 352 | /// int 353 | public int a_stride; 354 | 355 | /// uint32_t[2] 356 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.U4)] 357 | public uint[] pad1; 358 | 359 | /// uint32_t* 360 | public IntPtr argb; 361 | 362 | /// int 363 | public int argb_stride; 364 | 365 | /// uint32_t[3] 366 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U4)] 367 | public uint[] pad2; 368 | 369 | // OUTPUT 370 | 371 | 372 | /// WebPWriterFunction 373 | public WebPWriterFunction writer; 374 | 375 | /// void* 376 | public IntPtr custom_ptr; 377 | 378 | /// int 379 | public int extra_info_type; 380 | 381 | /// uint8_t* 382 | public IntPtr extra_info; 383 | 384 | /// WebPAuxStats* 385 | public IntPtr stats; 386 | 387 | /// WebPEncodingError->Anonymous_8b714d63_f91b_46af_b0d0_667c703ed356 388 | public WebPEncodingError error_code; 389 | 390 | /// WebPProgressHook 391 | public WebPProgressHook progress_hook; 392 | 393 | /// void* 394 | public IntPtr user_data; 395 | 396 | /// uint32_t[3] 397 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.U4)] 398 | public uint[] pad3; 399 | 400 | /// uint8_t* 401 | public IntPtr pad4; 402 | 403 | /// uint8_t* 404 | public IntPtr pad5; 405 | 406 | 407 | /// uint32_t[8] 408 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = UnmanagedType.U4)] 409 | public uint[] pad6; 410 | 411 | /// void* 412 | public IntPtr memory_; 413 | 414 | /// void* 415 | public IntPtr memory_argb_; 416 | 417 | /// void*[2] 418 | [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 2, ArraySubType = UnmanagedType.SysUInt)] 419 | public IntPtr[] pad7; 420 | } 421 | 422 | 423 | public partial class NativeMethods 424 | { 425 | 426 | /// Return Type: int 427 | [DllImportAttribute("libwebp", EntryPoint = "WebPGetEncoderVersion", CallingConvention = CallingConvention.Cdecl)] 428 | public static extern int WebPGetEncoderVersion(); 429 | 430 | 431 | /// Return Type: size_t->unsigned int 432 | ///rgb: uint8_t* 433 | ///width: int 434 | ///height: int 435 | ///stride: int 436 | ///quality_factor: float 437 | ///output: uint8_t** 438 | [DllImportAttribute("libwebp", EntryPoint = "WebPEncodeRGB", CallingConvention = CallingConvention.Cdecl)] 439 | public static extern UIntPtr WebPEncodeRGB([InAttribute()] IntPtr rgb, int width, int height, int stride, float quality_factor, ref IntPtr output); 440 | 441 | 442 | /// Return Type: size_t->unsigned int 443 | ///bgr: uint8_t* 444 | ///width: int 445 | ///height: int 446 | ///stride: int 447 | ///quality_factor: float 448 | ///output: uint8_t** 449 | [DllImportAttribute("libwebp", EntryPoint = "WebPEncodeBGR", CallingConvention = CallingConvention.Cdecl)] 450 | public static extern UIntPtr WebPEncodeBGR([InAttribute()] IntPtr bgr, int width, int height, int stride, float quality_factor, ref IntPtr output); 451 | 452 | 453 | /// Return Type: size_t->unsigned int 454 | ///rgba: uint8_t* 455 | ///width: int 456 | ///height: int 457 | ///stride: int 458 | ///quality_factor: float 459 | ///output: uint8_t** 460 | [DllImportAttribute("libwebp", EntryPoint = "WebPEncodeRGBA", CallingConvention = CallingConvention.Cdecl)] 461 | public static extern UIntPtr WebPEncodeRGBA([InAttribute()] IntPtr rgba, int width, int height, int stride, float quality_factor, ref IntPtr output); 462 | 463 | 464 | /// Return Type: size_t->unsigned int 465 | ///bgra: uint8_t* 466 | ///width: int 467 | ///height: int 468 | ///stride: int 469 | ///quality_factor: float 470 | ///output: uint8_t** 471 | [DllImportAttribute("libwebp", EntryPoint = "WebPEncodeBGRA", CallingConvention = CallingConvention.Cdecl)] 472 | public static extern IntPtr WebPEncodeBGRA([InAttribute()] IntPtr bgra, int width, int height, int stride, float quality_factor, ref IntPtr output); 473 | 474 | 475 | /// Return Type: size_t->unsigned int 476 | ///rgb: uint8_t* 477 | ///width: int 478 | ///height: int 479 | ///stride: int 480 | ///output: uint8_t** 481 | [DllImportAttribute("libwebp", EntryPoint = "WebPEncodeLosslessRGB", CallingConvention = CallingConvention.Cdecl)] 482 | public static extern UIntPtr WebPEncodeLosslessRGB([InAttribute()] IntPtr rgb, int width, int height, int stride, ref IntPtr output); 483 | 484 | 485 | /// Return Type: size_t->unsigned int 486 | ///bgr: uint8_t* 487 | ///width: int 488 | ///height: int 489 | ///stride: int 490 | ///output: uint8_t** 491 | [DllImportAttribute("libwebp", EntryPoint = "WebPEncodeLosslessBGR", CallingConvention = CallingConvention.Cdecl)] 492 | public static extern UIntPtr WebPEncodeLosslessBGR([InAttribute()] IntPtr bgr, int width, int height, int stride, ref IntPtr output); 493 | 494 | 495 | /// Return Type: size_t->unsigned int 496 | ///rgba: uint8_t* 497 | ///width: int 498 | ///height: int 499 | ///stride: int 500 | ///output: uint8_t** 501 | [DllImportAttribute("libwebp", EntryPoint = "WebPEncodeLosslessRGBA", CallingConvention = CallingConvention.Cdecl)] 502 | public static extern UIntPtr WebPEncodeLosslessRGBA([InAttribute()] IntPtr rgba, int width, int height, int stride, ref IntPtr output); 503 | 504 | 505 | /// Return Type: size_t->unsigned int 506 | ///bgra: uint8_t* 507 | ///width: int 508 | ///height: int 509 | ///stride: int 510 | ///output: uint8_t** 511 | [DllImportAttribute("libwebp", EntryPoint = "WebPEncodeLosslessBGRA", CallingConvention = CallingConvention.Cdecl)] 512 | public static extern UIntPtr WebPEncodeLosslessBGRA([InAttribute()] IntPtr bgra, int width, int height, int stride, ref IntPtr output); 513 | 514 | 515 | /// Return Type: int 516 | ///param0: WebPConfig* 517 | ///param1: WebPPreset->Anonymous_017d4167_f53e_4b3d_b029_592ff5c3f80b 518 | ///param2: float 519 | ///param3: int 520 | [DllImportAttribute("libwebp", EntryPoint = "WebPConfigInitInternal", CallingConvention = CallingConvention.Cdecl)] 521 | public static extern int WebPConfigInitInternal(ref WebPConfig param0, WebPPreset param1, float param2, int param3); 522 | 523 | 524 | /// Return Type: int 525 | ///config: WebPConfig* 526 | [DllImportAttribute("libwebp", EntryPoint = "WebPConfigLosslessPreset", CallingConvention = CallingConvention.Cdecl)] 527 | public static extern int WebPConfigLosslessPreset(ref WebPConfig config); 528 | 529 | /// Return Type: int 530 | ///config: WebPConfig* 531 | [DllImportAttribute("libwebp", EntryPoint = "WebPValidateConfig", CallingConvention = CallingConvention.Cdecl)] 532 | public static extern int WebPValidateConfig(ref WebPConfig config); 533 | 534 | 535 | /// Return Type: void 536 | ///writer: WebPMemoryWriter* 537 | [DllImportAttribute("libwebp", EntryPoint = "WebPMemoryWriterInit", CallingConvention = CallingConvention.Cdecl)] 538 | public static extern void WebPMemoryWriterInit(ref WebPMemoryWriter writer); 539 | 540 | /// Return Type: void 541 | ///writer: WebPMemoryWriter* 542 | [DllImportAttribute("libwebp", EntryPoint = "WebPMemoryWriterClear", CallingConvention = CallingConvention.Cdecl)] 543 | public static extern void WebPMemoryWriterClear(ref WebPMemoryWriter writer); 544 | 545 | 546 | /// Return Type: int 547 | ///data: uint8_t* 548 | ///data_size: size_t->unsigned int 549 | ///picture: WebPPicture* 550 | [DllImportAttribute("libwebp", EntryPoint = "WebPMemoryWrite", CallingConvention = CallingConvention.Cdecl)] 551 | public static extern int WebPMemoryWrite([InAttribute()] IntPtr data, UIntPtr data_size, ref WebPPicture picture); 552 | 553 | 554 | /// Return Type: int 555 | ///param0: WebPPicture* 556 | ///param1: int 557 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureInitInternal", CallingConvention = CallingConvention.Cdecl)] 558 | public static extern int WebPPictureInitInternal(ref WebPPicture param0, int param1); 559 | 560 | 561 | /// Return Type: int 562 | ///picture: WebPPicture* 563 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureAlloc", CallingConvention = CallingConvention.Cdecl)] 564 | public static extern int WebPPictureAlloc(ref WebPPicture picture); 565 | 566 | 567 | /// Return Type: void 568 | ///picture: WebPPicture* 569 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureFree", CallingConvention = CallingConvention.Cdecl)] 570 | public static extern void WebPPictureFree(ref WebPPicture picture); 571 | 572 | 573 | /// Return Type: int 574 | ///src: WebPPicture* 575 | ///dst: WebPPicture* 576 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureCopy", CallingConvention = CallingConvention.Cdecl)] 577 | public static extern int WebPPictureCopy(ref WebPPicture src, ref WebPPicture dst); 578 | 579 | 580 | /// Return Type: int 581 | ///pic1: WebPPicture* 582 | ///pic2: WebPPicture* 583 | ///metric_type: int 584 | ///result: float* result[5] 585 | /// 586 | 587 | /// 588 | /// Compute PSNR, SSIM or LSIM distortion metric between two pictures. 589 | /// Result is in dB, stores in result[] in the Y/U/V/Alpha/All or B/G/R/A/All order. 590 | /// Returns false in case of error (src and ref don't have same dimension, ...) 591 | /// Warning: this function is rather CPU-intensive. 592 | /// 593 | /// 594 | /// 595 | /// 0 = PSNR, 1 = SSIM, 2 = LSIM 596 | /// 597 | /// 598 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureDistortion", CallingConvention = CallingConvention.Cdecl)] 599 | public static extern int WebPPictureDistortion(ref WebPPicture src, ref WebPPicture reference, int metric_type, ref float result); 600 | 601 | 602 | 603 | 604 | /// Return Type: int 605 | ///picture: WebPPicture* 606 | ///left: int 607 | ///top: int 608 | ///width: int 609 | ///height: int 610 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureCrop", CallingConvention = CallingConvention.Cdecl)] 611 | public static extern int WebPPictureCrop(ref WebPPicture picture, int left, int top, int width, int height); 612 | 613 | 614 | /// Return Type: int 615 | ///src: WebPPicture* 616 | ///left: int 617 | ///top: int 618 | ///width: int 619 | ///height: int 620 | ///dst: WebPPicture* 621 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureView", CallingConvention = CallingConvention.Cdecl)] 622 | public static extern int WebPPictureView(ref WebPPicture src, int left, int top, int width, int height, ref WebPPicture dst); 623 | 624 | 625 | /// Return Type: int 626 | ///picture: WebPPicture* 627 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureIsView", CallingConvention = CallingConvention.Cdecl)] 628 | public static extern int WebPPictureIsView(ref WebPPicture picture); 629 | 630 | 631 | /// Rescale a picture to new dimension width x height. 632 | /// ow gamma correction is applied. 633 | /// 634 | /// Return Type: int 635 | ///pic: WebPPicture* 636 | ///width: int 637 | ///height: int 638 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureRescale", CallingConvention = CallingConvention.Cdecl)] 639 | public static extern int WebPPictureRescale(ref WebPPicture pic, int width, int height); 640 | 641 | 642 | /// Return Type: int 643 | ///picture: WebPPicture* 644 | ///rgb: uint8_t* 645 | ///rgb_stride: int 646 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureImportRGB", CallingConvention = CallingConvention.Cdecl)] 647 | public static extern int WebPPictureImportRGB(ref WebPPicture picture, [InAttribute()] IntPtr rgb, int rgb_stride); 648 | 649 | 650 | /// Return Type: int 651 | ///picture: WebPPicture* 652 | ///rgba: uint8_t* 653 | ///rgba_stride: int 654 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureImportRGBA", CallingConvention = CallingConvention.Cdecl)] 655 | public static extern int WebPPictureImportRGBA(ref WebPPicture picture, [InAttribute()] IntPtr rgba, int rgba_stride); 656 | 657 | 658 | /// Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion. 659 | /// Downsampling is handled with extra care in case of color clipping. This 660 | /// method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better 661 | /// YUV representation. 662 | /// Returns false in case of error. 663 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureSmartARGBToYUVA", CallingConvention = CallingConvention.Cdecl)] 664 | public static extern int WebPPictureSmartARGBToYUVA(ref WebPPicture picture); 665 | 666 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureImportRGBX", CallingConvention = CallingConvention.Cdecl)] 667 | public static extern int WebPPictureImportRGBX(ref WebPPicture picture, [InAttribute()] IntPtr rgbx, int rgbx_stride); 668 | 669 | 670 | 671 | /// Return Type: int 672 | ///picture: WebPPicture* 673 | ///bgr: uint8_t* 674 | ///bgr_stride: int 675 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureImportBGR", CallingConvention = CallingConvention.Cdecl)] 676 | public static extern int WebPPictureImportBGR(ref WebPPicture picture, [InAttribute()] IntPtr bgr, int bgr_stride); 677 | 678 | 679 | /// Return Type: int 680 | ///picture: WebPPicture* 681 | ///bgra: uint8_t* 682 | ///bgra_stride: int 683 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureImportBGRA", CallingConvention = CallingConvention.Cdecl)] 684 | public static extern int WebPPictureImportBGRA(ref WebPPicture picture, [InAttribute()] IntPtr bgra, int bgra_stride); 685 | 686 | 687 | /// Return Type: int 688 | ///picture: WebPPicture* 689 | ///bgrx: uint8_t* 690 | ///bgrx_stride: int 691 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureImportBGRX", CallingConvention = CallingConvention.Cdecl)] 692 | public static extern int WebPPictureImportBGRX(ref WebPPicture picture, [InAttribute()] IntPtr bgrx, int bgrx_stride); 693 | 694 | 695 | /// Return Type: int 696 | ///picture: WebPPicture* 697 | ///colorspace: WebPEncCSP->Anonymous_84ce7065_fe91_48b4_93d8_1f0e84319dba 698 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureARGBToYUVA", CallingConvention = CallingConvention.Cdecl)] 699 | public static extern int WebPPictureARGBToYUVA(ref WebPPicture picture, WebPEncCSP colorspace); 700 | 701 | 702 | /// Return Type: int 703 | ///picture: WebPPicture* 704 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureYUVAToARGB", CallingConvention = CallingConvention.Cdecl)] 705 | public static extern int WebPPictureYUVAToARGB(ref WebPPicture picture); 706 | 707 | 708 | /// Return Type: void 709 | ///picture: WebPPicture* 710 | [DllImportAttribute("libwebp", EntryPoint = "WebPCleanupTransparentArea", CallingConvention = CallingConvention.Cdecl)] 711 | public static extern void WebPCleanupTransparentArea(ref WebPPicture picture); 712 | 713 | 714 | /// Return Type: int 715 | ///picture: WebPPicture* 716 | [DllImportAttribute("libwebp", EntryPoint = "WebPPictureHasTransparency", CallingConvention = CallingConvention.Cdecl)] 717 | public static extern int WebPPictureHasTransparency(ref WebPPicture picture); 718 | 719 | 720 | /// Return Type: int 721 | ///config: WebPConfig* 722 | ///picture: WebPPicture* 723 | [DllImportAttribute("libwebp", EntryPoint = "WebPEncode", CallingConvention = CallingConvention.Cdecl)] 724 | public static extern int WebPEncode(ref WebPConfig config, ref WebPPicture picture); 725 | 726 | } 727 | } 728 | 729 | #pragma warning restore 1591 -------------------------------------------------------------------------------- /src/Imazen.WebP/Extern/EncodeInlines.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Imazen.WebP.Extern { 6 | public partial class NativeMethods { 7 | /// 8 | /// Should always be called, to initialize a fresh WebPConfig structure before 9 | /// modification. Returns false in case of version mismatch. WebPConfigInit() 10 | /// must have succeeded before using the 'config' object. 11 | /// Note that the default values are lossless=0 and quality=75. 12 | /// 13 | /// 14 | /// 15 | public static int WebPConfigInit(ref WebPConfig config) { 16 | return NativeMethods.WebPConfigInitInternal(ref config,WebPPreset.WEBP_PRESET_DEFAULT, 75.0f, WEBP_ENCODER_ABI_VERSION); 17 | } 18 | 19 | /// 20 | /// This function will initialize the configuration according to a predefined 21 | /// set of parameters (referred to by 'preset') and a given quality factor. 22 | /// This function can be called as a replacement to WebPConfigInit(). Will return false in case of error. 23 | /// 24 | /// 25 | /// 26 | /// 27 | /// 28 | public static int WebPConfigPreset(ref WebPConfig config, WebPPreset preset, float quality) { 29 | return NativeMethods.WebPConfigInitInternal(ref config, preset, quality, WEBP_ENCODER_ABI_VERSION); 30 | } 31 | 32 | /// 33 | /// Should always be called, to initialize the structure. Returns false in case 34 | /// of version mismatch. WebPPictureInit() must have succeeded before using the 35 | /// 'picture' object. 36 | /// Note that, by default, use_argb is false and colorspace is WEBP_YUV420. 37 | /// 38 | /// 39 | /// 40 | public static int WebPPictureInit(ref WebPPicture picture) { 41 | 42 | return NativeMethods.WebPPictureInitInternal(ref picture, WEBP_ENCODER_ABI_VERSION); 43 | 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Imazen.WebP/Extern/Extra.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Imazen.WebP.Extern { 7 | public partial class NativeMethods { 8 | 9 | public static void WebPSafeFree(IntPtr toDeallocate) 10 | { 11 | WebPFree(toDeallocate); 12 | } 13 | 14 | 15 | [DllImportAttribute("libwebp", EntryPoint = "WebPFree", CallingConvention = CallingConvention.Cdecl)] 16 | public static extern void WebPFree(IntPtr toDeallocate); 17 | } 18 | } -------------------------------------------------------------------------------- /src/Imazen.WebP/Extern/LoadLibrary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.IO; 5 | using System.Reflection; 6 | using System.Runtime.InteropServices; 7 | using System.Security; 8 | using System.Text; 9 | 10 | namespace Imazen.WebP.Extern 11 | { 12 | public static class LoadLibrary 13 | { 14 | [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.StdCall)] 15 | static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, uint dwFlags); 16 | 17 | public static bool EnsureLoadedByPath(string fullPath, bool throwException) 18 | { 19 | //canonicalize as much as we can 20 | fullPath = Path.GetFullPath(fullPath); 21 | lock (lockObj) 22 | { 23 | IntPtr handle; 24 | if (loaded.TryGetValue(fullPath, out handle)) 25 | { 26 | return true; 27 | } 28 | else 29 | { 30 | handle = LoadByPath(fullPath, throwException); 31 | if (handle != IntPtr.Zero) 32 | { 33 | loaded.Add(fullPath, handle); 34 | return true; 35 | } 36 | } 37 | } 38 | return false; 39 | } 40 | 41 | /// 42 | /// Calls LoadLibraryEx with (Search DLL Load Dir and System32) flags. May increment reference count. Use EnsureLoadedByPath instead if you don't need a pointer. 43 | /// 44 | /// 45 | /// 46 | /// 47 | public static IntPtr LoadByPath(string fullPath, bool throwException) 48 | { 49 | const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100; 50 | const uint LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800; 51 | 52 | var moduleHandle = LoadLibraryEx(fullPath, IntPtr.Zero, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); 53 | if (moduleHandle == IntPtr.Zero && throwException) 54 | throw new Win32Exception(Marshal.GetLastWin32Error()); 55 | return moduleHandle; 56 | } 57 | 58 | 59 | public static void LoadWebPOrFail() 60 | { 61 | if (!AutoLoadNearby("libwebp.dll", true)) 62 | { 63 | throw new FileNotFoundException("Failed to locate libwebp.dll"); 64 | } 65 | } 66 | /// 67 | /// Looks for 'name' inside /x86/ or /x64/ (depending on arch) subfolders of known assembly locations 68 | /// 69 | /// 70 | /// 71 | /// 72 | public static bool AutoLoadNearby(string name, bool throwFailure) 73 | { 74 | var a = Assembly.GetExecutingAssembly(); 75 | return AutoLoad(name, new string[]{Path.GetDirectoryName(a.Location), Path.GetDirectoryName(new Uri(a.CodeBase).LocalPath)},throwFailure,throwFailure); 76 | } 77 | 78 | static object lockObj = new object(); 79 | static Dictionary loaded = new Dictionary(StringComparer.OrdinalIgnoreCase); 80 | 81 | /// 82 | /// Looks for 'name' inside /x86/ and /x64/ subfolders of 'folder', depending on executing architecture. 83 | /// 84 | /// 85 | /// 86 | /// 87 | /// 88 | /// 89 | public static bool AutoLoad(string name, string[] searchFolders, bool throwNotFound, bool throwExceptions) 90 | { 91 | string searched = ""; 92 | foreach (string folder in searchFolders) 93 | { 94 | var basePath = Path.Combine(folder, (IntPtr.Size == 8) ? "x64" : "x86"); 95 | var fullPath = Path.Combine(basePath, name); 96 | if (string.IsNullOrEmpty(Path.GetExtension(fullPath))) 97 | { 98 | fullPath = fullPath + ".dll"; 99 | } 100 | searched = searched + "\"" + fullPath + "\", "; 101 | if (File.Exists(fullPath)) 102 | { 103 | if (EnsureLoadedByPath(fullPath, throwExceptions)) 104 | { 105 | return true; 106 | } 107 | } 108 | } 109 | if (throwNotFound) 110 | { 111 | throw new FileNotFoundException("Failed to locate '" + name + "' as " + searched.TrimEnd(' ', ',')); 112 | } 113 | return false; 114 | } 115 | 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Imazen.WebP/Imazen.WebP.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 8.0.30703 7 | 2.0 8 | {92F607A3-2F04-4536-8346-B6FEF8B774FF} 9 | Library 10 | Properties 11 | Imazen.WebP 12 | Imazen.WebP 13 | v4.5 14 | 512 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | true 26 | bin\Debug\Imazen.WebP.XML 27 | false 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | bin\Release\Imazen.WebP.XML 37 | true 38 | false 39 | 40 | 41 | true 42 | bin\x64\Debug\ 43 | DEBUG;TRACE 44 | true 45 | bin\Debug\Imazen.WebP.XML 46 | full 47 | x64 48 | prompt 49 | MinimumRecommendedRules.ruleset 50 | false 51 | 52 | 53 | bin\x64\Release\ 54 | TRACE 55 | true 56 | bin\Release\Imazen.WebP.XML 57 | true 58 | pdbonly 59 | x64 60 | prompt 61 | MinimumRecommendedRules.ruleset 62 | false 63 | 64 | 65 | true 66 | bin\x86\Debug\ 67 | DEBUG;TRACE 68 | true 69 | bin\Debug\Imazen.WebP.XML 70 | full 71 | x86 72 | prompt 73 | MinimumRecommendedRules.ruleset 74 | false 75 | 76 | 77 | bin\x86\Release\ 78 | TRACE 79 | true 80 | bin\Release\Imazen.WebP.XML 81 | true 82 | pdbonly 83 | x86 84 | prompt 85 | MinimumRecommendedRules.ruleset 86 | false 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 114 | -------------------------------------------------------------------------------- /src/Imazen.WebP/Imazen.WebP.csproj.paket.template: -------------------------------------------------------------------------------- 1 | type project 2 | Authors Nathanael Jones 3 | 4 | -------------------------------------------------------------------------------- /src/Imazen.WebP/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System.Reflection; 3 | 4 | [assembly: AssemblyTitleAttribute("Imazen.WebP")] 5 | [assembly: AssemblyProductAttribute("Imazen.WebP")] 6 | [assembly: AssemblyDescriptionAttribute(".NET wrapper for libwebp")] 7 | [assembly: AssemblyVersionAttribute("9.0.1")] 8 | [assembly: AssemblyFileVersionAttribute("9.0.1")] 9 | namespace System { 10 | internal static class AssemblyVersionInformation { 11 | internal const string Version = "9.0.1"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Imazen.WebP/SimpleDecoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Drawing; 5 | using Imazen.WebP.Extern; 6 | using System.Runtime.InteropServices; 7 | using System.Drawing.Imaging; 8 | 9 | namespace Imazen.WebP { 10 | 11 | 12 | public class SimpleDecoder { 13 | 14 | 15 | public static string GetDecoderVersion() 16 | { 17 | uint v = (uint)NativeMethods.WebPGetDecoderVersion(); 18 | var revision = v % 256; 19 | var minor = (v >> 8) % 256; 20 | var major = (v >> 16) % 256; 21 | return major + "." + minor + "." + revision; 22 | } 23 | /// 24 | /// Creates a new instance of SimpleDecoder 25 | /// 26 | public SimpleDecoder() { 27 | } 28 | 29 | 30 | 31 | public unsafe Bitmap DecodeFromBytes(byte[] data, long length) { 32 | fixed (byte* dataptr = data) { 33 | return DecodeFromPointer((IntPtr)dataptr, length); 34 | } 35 | } 36 | public Bitmap DecodeFromPointer(IntPtr data, long length) { 37 | int w = 0, h = 0; 38 | //Validate header and determine size 39 | if (NativeMethods.WebPGetInfo(data, (UIntPtr)length, ref w, ref h) == 0) throw new Exception("Invalid WebP header detected"); 40 | 41 | bool success = false; 42 | Bitmap b = null; 43 | BitmapData bd = null; 44 | try { 45 | //Allocate canvas 46 | b = new Bitmap(w, h, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 47 | //Lock surface for writing 48 | bd = b.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb); 49 | //Decode to surface 50 | IntPtr result = NativeMethods.WebPDecodeBGRAInto(data, (UIntPtr)length, bd.Scan0, (UIntPtr)( bd.Stride * bd.Height), bd.Stride); 51 | if (bd.Scan0 != result) throw new Exception("Failed to decode WebP image with error " + (long)result); 52 | success = true; 53 | } finally { 54 | //Unlock surface 55 | if (bd != null && b != null) b.UnlockBits(bd); 56 | //Dispose of bitmap if anything went wrong 57 | if (!success && b != null) b.Dispose(); 58 | } 59 | return b; 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Imazen.WebP/SimpleEncoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | using System.Drawing; 6 | using Imazen.WebP.Extern; 7 | using System.IO; 8 | 9 | namespace Imazen.WebP { 10 | /// 11 | /// Encodes Bitmap objects into WebP format 12 | /// 13 | public class SimpleEncoder { 14 | public SimpleEncoder() { } 15 | 16 | public static string GetEncoderVersion() 17 | { 18 | uint v = (uint)NativeMethods.WebPGetEncoderVersion(); 19 | var revision = v % 256; 20 | var minor = (v >> 8) % 256; 21 | var major = (v >> 16) % 256; 22 | return major + "." + minor + "." + revision; 23 | } 24 | 25 | /// 26 | /// Encodes the given RGB(A) bitmap to the given stream. Specify quality = -1 for lossless, otherwise specify a value between 0 and 100. 27 | /// 28 | /// 29 | /// 30 | /// 31 | /// 32 | [Obsolete] 33 | public void Encode(Bitmap from, Stream to, float quality, bool noAlpha) { 34 | Encode(from, to, quality); 35 | } 36 | 37 | /// 38 | /// Encodes the given RGB(A) bitmap to the given stream. Specify quality = -1 for lossless, otherwise specify a value between 0 and 100. 39 | /// 40 | /// 41 | /// 42 | /// 43 | public void Encode(Bitmap from, Stream to, float quality) { 44 | IntPtr result; 45 | long length; 46 | 47 | Encode(from, quality, out result, out length); 48 | try { 49 | byte[] buffer = new byte[4096]; 50 | for (int i = 0; i < length; i += buffer.Length) { 51 | int used = (int)Math.Min((int)buffer.Length, length - i); 52 | Marshal.Copy((IntPtr)((long)result + i), buffer, 0, used); 53 | to.Write(buffer, 0, used); 54 | } 55 | } finally { 56 | NativeMethods.WebPSafeFree(result); 57 | } 58 | 59 | } 60 | 61 | /// 62 | /// Encodes the given RGB(A) bitmap to the given stream. Specify quality = -1 for lossless, otherwise specify a value between 0 and 100. 63 | /// 64 | /// 65 | /// 66 | /// 67 | /// 68 | /// 69 | [Obsolete] 70 | public void Encode(Bitmap b, float quality, bool noAlpha, out IntPtr result, out long length) { 71 | Encode(b, quality, out result, out length); 72 | } 73 | 74 | /// 75 | /// Encodes the given RGB(A) bitmap to an unmanged memory buffer (returned via result/length). Specify quality = -1 for lossless, otherwise specify a value between 0 and 100. 76 | /// 77 | /// 78 | /// 79 | /// 80 | /// 81 | public void Encode(Bitmap b, float quality, out IntPtr result, out long length) { 82 | if (quality < -1) quality = -1; 83 | if (quality > 100) quality = 100; 84 | int w = b.Width; 85 | int h = b.Height; 86 | var bd = b.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, b.PixelFormat); 87 | try { 88 | result = IntPtr.Zero; 89 | 90 | if (b.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) { 91 | if (quality == -1) length = (long)NativeMethods.WebPEncodeLosslessBGRA(bd.Scan0, w, h, bd.Stride, ref result); 92 | else length = (long)NativeMethods.WebPEncodeBGRA(bd.Scan0, w, h, bd.Stride, quality, ref result); 93 | }else if (b.PixelFormat == System.Drawing.Imaging.PixelFormat.Format24bppRgb) 94 | { 95 | if (quality == -1) length = (long)NativeMethods.WebPEncodeLosslessBGR(bd.Scan0, w, h, bd.Stride, ref result); 96 | else length = (long)NativeMethods.WebPEncodeBGR(bd.Scan0, w, h, bd.Stride, quality, ref result); 97 | }else 98 | { 99 | using (Bitmap b2 = b.Clone(new Rectangle(0, 0, b.Width, b.Height), System.Drawing.Imaging.PixelFormat.Format32bppArgb)) 100 | { 101 | Encode(b2, quality, out result, out length); 102 | } 103 | } 104 | if (length == 0) throw new Exception("WebP encode failed!"); 105 | } finally { 106 | b.UnlockBits(bd); 107 | } 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Imazen.WebP/packages/repositories.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------