SkiaSharp throws when run in Windows container.
Steps to reproduce:
using SkiaSharp;
using System;namespace SkiaSharpDockerTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Environment.OSVersion);try { using (SKBitmap bmp = new SKBitmap(100, 100)) using (SKCanvas canvas = new SKCanvas(bmp)) using (SKPaint p = new SKPaint()) { p.Color = SKColors.Red; canvas.DrawCircle(50, 50, 50, p); using (SKFileWStream fs = new SKFileWStream("out.png")) bmp.Encode(fs, SKEncodedImageFormat.Png, 100); } } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); }}
}
FROM microsoft/dotnet:2.0-sdk
WORKDIR /app
COPY . ./
RUN dotnet publish -c Release -o out
ENTRYPOINT ["dotnet", "out/SkiaSharpDockerTest.dll"]
As a result exception is thrown
The type initializer for 'SkiaSharp.SKImageInfo' threw an exception.
at SkiaSharp.SKBitmap..ctor(Int32 width, Int32 height, Boolean isOpaque)
at AsposeWordsDockerTest.Program.Main(String[] args) in C:\app\Program.cs:line 15
Red circle image should be created
throws an exception
Any update on this?
@AlexNosk
You are probably missing Visual C++ runtime. See https://github.com/mono/SkiaSharp/issues/136
@kekekeks This is one issue with running SkiaSharp inside Windows containers but not the only one. libSkiaSharp.dll also has a dependency on both opengl32.dll and glu32.dll.
@AlexNosk In your dockerfile copy these two assemblies in to the windows/system32 folder and things work fine - least they did for me. This is a hack, and so long as you don't any of whatever skiasharp requires from those libraries to actually work you're all good. I think they're working on 3d support for windows containers at the moment.
On Linux opengl references are resolved dynamically. See https://github.com/mono/skia/pull/50 and
https://github.com/mono/skia/commit/b5793908b1fa1510c31cf7548035d7df0566f7bc
I guess on Windows we can do the same.
@kekekeks I am thinking that maybe we should - it appears that those assemblies are not always distributed on some "versions"... What are they actually? @chrismellard what container were you using? I thought they were always part of all Windows.
@mattleibow Container I had to copy those libraries in from was
FROM microsoft/iis:windowsservercore-1803
Thanks. I will investigate.
~Hmm. I see opengl32.dll is already dynamically loaded:
https://github.com/google/skia/blob/36f7e3298e9d8e21d095197db0ec72c155f7d61f/src/gpu/gl/win/GrGLMakeNativeInterface_win.cpp~ (this is untrue 😞)
After that commit, the new dependency tree is basically:

I am also working on making sure that there is an easy path for Docker. I have managed to basically get this working:
RUN Invoke-WebRequest -OutFile vc_redist.x64.exe https://aka.ms/vs/15/release/vc_redist.x64.exe `
Start-Process vc_redist.x64.exe -ArgumentList '/install /passive /norestart' -Wait
I will be creating a wiki with all the steps for creating a Docker container for both Windows and Linux.
Right now, nanoserver is not playing nice and several dependencies are missing, so I don't think that support will be coming soon, but it will work fine with windowsservercore variants.
May be it's time to reconsider about static CRT linking? It doesn't increase binary size that much, but decreases surprise factor by a lot.
Having a look at Nano Server... Ran the NanoServerApiScan.exe tool from: https://blogs.technet.microsoft.com/nanoserver/2016/04/27/nanoserverapiscan-exe-updated-for-tp5/
=== libSkiaSharp.dll ===
ERRORS:
FONTSUB.dll
CreateFontPackage(Proc not found)
USER32.dll
SystemParametersInfoW(Proc not found)
MSVCP140.dll
…
…
…
Please copy Nano Server compliant MSVCP140.dll from %ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\redist\onecore\x64\Microsoft.VC140.CRT\
VCRUNTIME140.dll
…
…
…
Please copy Nano Server compliant VCRUNTIME140.dll from %ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\redist\onecore\x64\Microsoft.VC140.CRT\
I need to investigate the 2 usages that appear to be bad:
Just did some investigation :)
CreateFontPackage from FONTSUB.dll is just for XPS support - and this is also just for font subsetting. The UWP build does not have this at all, so I could just remove it for a nano build.
SystemParametersInfoW from USER32.dll is also not too essential - it is just for determining the default font. Again, this is not available for UWP - we just pick the "Segoe UI" which we know is available by default.
Nano Server support could very well be possible in the near future - just have to check priorities.
@kekekeks I have been thinking about this and I will link in #136 so we can keep the discussion linked, but that discussion should be done there. (going to make a comment there now)
Closing this as I have done a few things:
I have opened a new issue to support Nano server: #676
Nano server images are now supported after #1040
Just linking this new issue : https://github.com/NuGet/Home/issues/8894
I ended up here because of some confusion over SkiaSharp in a NanoServer docker container. While I was able to get some things working after including SkiaSharp.NativeAssets.NanoServer, I noticed that I cannot draw text onto a bitmap using a font that I load from a file:
var typeFace = SKTypeface.FromFile("Font Awesome 5 Free-Solid-900.otf");
var paint = new SKPaint() { TextSize = 40, Color = SKColor.Parse("FF0000"), Typeface = typeFace};
SKRect bounds = new SKRect();
paint.MeasureText(unicodeCharacter, ref bounds);
bounds is always 0x0.
I see that SkiaSharp.NativeAssets.NanoServer shows:
_This variation of the Windows native assets includes the build of libSkiaSharp.dll that does not make use of the typeface subsetting when creating XPS documents (CreateFontPackage from FONTSUB.dll)._
So I'm guessing this has to do with something.
Is there any way to use a font in NanoServer?
Unfortunately there is currently no support for text rendering on Nano Server. That will most likely change with the next major release of SkiaSharp when Freetype can be used for Windows builds.
@djarvis as @Gillibald says, there is currently an issue #1105
For now, is it possible to use the Linux images? Typically they are smaller and just as good. And, if you have a Windows host, they can be run side-by-side with Windows containers. That is the best for now, or use a Windows Server Core image - like this example.
@mattleibow We have been using solely Linux containers but now have to offer up Windows containers. I'd rather not have the 4.8GB footprint just to be able to draw a font onto a bitmap so I'd like to stick to the nanoserver images.
We need to support simple, single-machine deployments. With the need to run along side legacy Windows apps, we see Windows Server 2019 as a solution since it comes with a free Docker EE license and as of now LCOW is still in an unsupported preview. Otherwise we'd just continue with Linux containers.
I just need to draw this one font onto a bitmap so I might be able to take the svg and find a renderer and draw it manually but I haven't looked too far into that.
You will be soon able to generate glyph outlines with the help of HarfBuzzSharp. Maybe thats a good way to get text rendered without having to rely on a font host implementation.
Luckily since I just needed to draw the Font Awesome glyphs I was able to use SkiaSharp.Svg to draw the relatively simple svgs onto a bitmap
This seems to work on Linux and Windows.