mono / SkiaSharp

SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
MIT License
4.14k stars 522 forks source link

[BUG] Text Missing When Running From AWS Lambda #2827

Closed WheelerAustin closed 5 days ago

WheelerAustin commented 1 month ago

Description

When generating a png image with SKCanvas the text is missing. The image displays properly when run locally on a windows 10 environment, but the text is missing when running from AWS Lambda. There are no exceptions being thrown for me to troubleshoot with.

This code was working last year, until I upgraded to .net 8 and changed my pdf nuget to QuestPDF. Not sure of the relevance.

Code

using SKBitmap bitmap = new(imageWidth, imageHeight);
using SKCanvas canvas = new(bitmap);

canvas.DrawText("my text", myPoint, myPaint);

using SKImage image = SKImage.FromBitmap(bitmap);
using SKData data = image.Encode(SKEncodedImageFormat.Png, 100);

using MemoryStream dataStream = new();
data.SaveTo(dataStream);

return dataStream.ToArray();
<ItemGroup>
  <PackageReference Include="QuestPDF" Version="2023.12.6" />
  <PackageReference Include="SkiaSharp" Version="2.88.8" />
  <PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.8" />
</ItemGroup>

Expected Behavior

No response

Actual Behavior

No response

Version of SkiaSharp

2.88.3 (Current)

Last Known Good Version of SkiaSharp

2.88.2 (Previous)

IDE / Editor

Visual Studio (Windows)

Platform / Operating System

Linux

Platform / Operating System Version

-AWS Lambda

Devices

No response

Relevant Screenshots

Run Locally image

Run From AWS Lambda image

Relevant Log Output

No response

Code of Conduct

swharden commented 5 days ago

Hi @WheelerAustin, I recently ran into the same issue. Were you able to reach a solution?

WheelerAustin commented 5 days ago

I did find a solution. I don't believe this is actually a bug as SkiaSharp.NativeAssets.Linux.NoDependencies is supposed to work this way. Its just not very obvious.

Basically when you use SKCanvas.DrawText() on a windows computer, the font defaults to the system font. When running on AWS lambda there is no default system font and no exception is thrown telling you this. The best path forward in my position was to simply embed a font into my project and have full control of the fonts in the jpeg.

Its really not too hard.

  1. Just find a font file (.TTF) you want. I stole mine from my windows OS C:\Windows\Fonts by coping the Consolas files and pasting into a folder I made in my project named 'Fonts'.
  2. Change the build action on the files to Embedded resource. They should show up in the csproj file like so:
    <ItemGroup>
    <EmbeddedResource Include="Fonts\CONSOLA.TTF" />
    <EmbeddedResource Include="Fonts\CONSOLAB.TTF" />
    <EmbeddedResource Include="Fonts\CONSOLAI.TTF" />
    <EmbeddedResource Include="Fonts\CONSOLAZ.TTF" />
    </ItemGroup>
  3. Using a stream, pick the files out of your project and add them as the typeface for your SKPaint
    
    using Stream consolaStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("{YourProjectName}.Fonts.CONSOLA.TTF")!;
    SKTypeface font = SKTypeface.FromStream(consolaStream);

using SKPaint textPaint = new() { Typeface = font, Color = SKColors.Black, TextSize = 24, IsAntialias = true };


4. Make sure to use that paint when in your ```SKCanvas.DrawText("myText", myPoint,  myPaintWithConsolasTypeface);```

Hopefully this helps!
swharden commented 5 days ago

Hi @WheelerAustin, thank you for this detailed response!

When running on AWS lambda there is no default system font and no exception is thrown telling you this. The best path forward in my position was to simply embed a font into my project and have full control of the fonts in the jpeg.

Makes sense! Your code examples really help too.

Connecting some dots, I followed-up here because it seemed to be the same issue described in https://github.com/ScottPlot/ScottPlot/discussions/3825, and your response saved the day.

When I see strangers on the internet working together to create technical solutions for complex problems like this, it reminds me how awesome the open source community really is! 🚀 🚀 🚀 Thanks again