This repository contains some sample code on how you can call libpng from C#.
The code was written to test whether calling libpng natively could be an alternative, performance-wise, for System.Drawing to decode PNG images.
What I found out was:
- Decoding PNG images very slow compared to other formats (for example, jpeg using libjpeg-turbo)
- GDI+ seemed to be at least as performant as libpng on Windows, but libpng is a winner on Linux and macOS
- On Mono, System.Drawing uses libgdiplus which uses libpng under the hood.
Conclusion:
- On Windows, you may want to keep using System.Drawing
- On Linux and macOS, libpng is a better option, performance-wise
libpng uses zlib, of which various forks exist which contain additional performance improvements. These forks have not been tested.
There are Travis and AppVeyor builds which run benchmarks. The list below gives a snapshot of the results:
// * Summary *
BenchmarkDotNet=v0.10.14, OS=Windows 8.1 (6.3.9600.0)
Intel Xeon CPU E5-2697 v3 2.60GHz, 1 CPU, 2 logical and 2 physical cores
.NET Core SDK=2.1.300
[Host] : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Core : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Job=Core Runtime=Core
Method | Mean | Error | StdDev |
--------------------- |-----------:|----------:|----------:|
ImageSharpDecompress | 1,132.6 ms | 13.356 ms | 12.493 ms |
LibPngDecompress | 932.8 ms | 4.741 ms | 4.435 ms |
DrawingDecompress | 783.0 ms | 5.968 ms | 5.290 ms |
// * Summary *
BenchmarkDotNet=v0.10.14, OS=ubuntu 16.04
Intel Xeon CPU 2.50GHz, 1 CPU, 2 logical cores and 1 physical core
.NET Core SDK=2.1.300
[Host] : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Core : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Job=Core Runtime=Core
Method | Mean | Error | StdDev |
--------------------- |--------:|---------:|---------:|
ImageSharpDecompress | 1.408 s | 0.0273 s | 0.0335 s |
LibPngDecompress | 1.227 s | 0.0208 s | 0.0195 s |
DrawingDecompress | NA | NA | NA |
// * Summary *
BenchmarkDotNet=v0.10.14, OS=macOS Sierra 10.12.6 (16G29) [Darwin 16.7.0]
Intel Xeon CPU E5-2697 v2 2.70GHz, 2 CPU, 2 logical and 2 physical cores
.NET Core SDK=2.1.300
[Host] : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Core : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Job=Core Runtime=Core
Method | Mean | Error | StdDev |
--------------------- |--------:|---------:|---------:|
ImageSharpDecompress | 1.266 s | 0.0245 s | 0.0229 s |
LibPngDecompress | 1.027 s | 0.0156 s | 0.0146 s |
DrawingDecompress | 1.481 s | 0.0042 s | 0.0033 s |
// * Summary *
NET Core SDK=2.1.300
[Host] : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Core : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Job=Core Runtime=Core
Method | Mean | Error | StdDev |
--------------------- |-----------:|----------:|----------:|
ImageSharpDecompress | 1,607.5 ms | 4.248 ms | 3.973 ms |
LibPngDecompress | 1,153.8 ms | 10.889 ms | 10.186 ms |
DrawingDecompress | 948.6 ms | 18.685 ms | 19.992 ms |
// * Summary *
BenchmarkDotNet=v0.10.14, OS=ubuntu 16.04
Intel Xeon CPU 2.50GHz, 1 CPU, 2 logical cores and 1 physical core
.NET Core SDK=2.1.300
[Host] : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Core : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Job=Core Runtime=Core 9m
Method | Mean | Error | StdDev |
--------------------- |--------:|---------:|---------:|
ImageSharpDecompress | 1.672 s | 0.0334 s | 0.0397 s |
LibPngDecompress | 1.226 s | 0.0209 s | 0.0195 s |
DrawingDecompress | 1.896 s | 0.0250 s | 0.0234 s |
// * Summary *
BenchmarkDotNet=v0.10.14, OS=macOS Sierra 10.12.6 (16G29) [Darwin 16.7.0]
Intel Xeon CPU E5-2697 v2 2.70GHz, 2 CPU, 2 logical and 2 physical cores
.NET Core SDK=2.1.300
[Host] : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Core : .NET Core 2.1.0 (CoreCLR 4.6.26515.07, CoreFX 4.6.26515.06), 64bit RyuJIT
Job=Core Runtime=Core
Method | Mean | Error | StdDev |9m
--------------------- |--------:|---------:|---------:|
ImageSharpDecompress | 1.537 s | 0.0300 s | 0.0281 s |
LibPngDecompress | 1.073 s | 0.0145 s | 0.0135 s |
DrawingDecompress | 1.497 s | 0.0116 s | 0.0108 s |