ImageSharp.Drawing icon indicating copy to clipboard operation
ImageSharp.Drawing copied to clipboard

DrawText results in blank image (UWP Release x64)

Open Sergio0694 opened this issue 3 years ago • 11 comments

Prerequisites

  • [X] I have written a descriptive issue title
  • [X] I have verified that I am running the latest version of ImageSharp
  • [X] I have verified if the problem exist in both DEBUG and RELEASE mode
  • [X] I have searched open and closed issues to ensure it has not already been reported

Description

It looks like the DrawText extension isn't working properly in ImageSharp only in UWP Release x64. Testing in Release x86 and Debug x86/x64 works fine. The app does run, but the resulting image just remains blank, no exceptions or anything.

Originally reported by @emiliano84.

Steps to Reproduce

  • Create a new UWP app
  • Add a Button in MainPage.xaml
  • Paste this code in MainPage.xaml.cs:
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    var font = SystemFonts.CreateFont("Courier New", 14);
    var text = "Hello World";
    var size = TextMeasurer.Measure(text, new RendererOptions(font));

    var finalImage = new Image<Rgba32>((int)size.Width, (int)size.Height);
    finalImage.Mutate(i =>
    {
        i.Fill(Color.White);
        i.DrawText(text, font, Color.Black, new PointF(0, 0));
    });

    var savePicker = new Windows.Storage.Pickers.FileSavePicker();
    savePicker.FileTypeChoices.Add("Picture", new List<string> { ".png" });
    StorageFile storageFile = await savePicker.PickSaveFileAsync();

    using (IRandomAccessStream stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
    {
        finalImage.SaveAsPng(stream.AsStreamForWrite());
    }
}
  • Start the app, click the button
  • Open the resulting image

Expected result (eg. on Release x86)

imaagesharptext

Result on Release x64

image2

System Configuration

  • ImageSharp version: SixLabors.ImageSharp.Drawing 1.0.0-beta0010
  • Environment (Operating system, version and so on): Windows 10 Pro 19041.572
  • .NET Framework version: Microsoft.NETCore.UniversalWindowsPlatform 6.2.10
  • App targeting SDK 19041 as both minimum and target

Sergio0694 avatar Oct 16 '20 13:10 Sergio0694

@Sergio0694 or @emiliano84 can you please try if filling regions work? (i.FillPolygon(Color.Red, new PointF[] { .... }) )

antonfirsov avatar Oct 16 '20 14:10 antonfirsov

Oh whoops @JimBobSquarePants my bad, forgot we had split the two packages into separate repos 😅

@antonfirsov sure, on it!

Sergio0694 avatar Oct 16 '20 14:10 Sergio0694

If filling polygons also reproduces the issue, please also try:

  • ctx.Fill(Color.Red)
  • ctx.Fill(someNonSolidBrush) (Eg. Brushes.Percent20Pattern)

antonfirsov avatar Oct 16 '20 14:10 antonfirsov

@antonfirsov FillPolygon seems to work fine 😄

For reference:

private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    var finalImage = new Image<Rgba32>(256, 256);
    finalImage.Mutate(i =>
    {
        i.Fill(Color.White);
        i.FillPolygon(Color.Red, new PointF(0, 0), new PointF(128, 0), new PointF(128, 128), new PointF(0, 128));
    });

    var savePicker = new Windows.Storage.Pickers.FileSavePicker();
    savePicker.FileTypeChoices.Add("Picture", new List<string> { ".png" });
    StorageFile storageFile = await savePicker.PickSaveFileAsync();

    using (IRandomAccessStream stream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
    {
        finalImage.SaveAsPng(stream.AsStreamForWrite());
    }
}

Debug x64

fill

Release x64

fill2

Sergio0694 avatar Oct 16 '20 14:10 Sergio0694

Sighs and unpacks the Raspberry Pi...

JimBobSquarePants avatar Oct 16 '20 15:10 JimBobSquarePants

@JimBobSquarePants Wait, why the Raspberry Pi? You can repro this on Desktop, am I missing something obvious? 🤔 The issue is in Release x64, not ARM!

Sergio0694 avatar Oct 16 '20 15:10 Sergio0694

Oh that's something... I thought this was gonna be another one of those ARM ones, I just see UWP and assume the worst!

They use their own shonky version of NET Core for this though yeah?

JimBobSquarePants avatar Oct 16 '20 17:10 JimBobSquarePants

I just see UWP and assume the worst

That hurts, but I can't really blame you 🤣

They use their own shonky version of NET Core for this though yeah?

It's always the same UWP setup regardless of the architecture:

  • Some weird custom .NET Core 2.0 derived runtime in Debug mode
  • .NET Native in Release mode

I should note that .NET Native is not just the compiler, it's an entirely different runtime which is used in Release. It's basically kinda like CoreRT (in fact the two share a lot of code), heavily tuned to work with all the various WinRT stuff.

(simplifying a lot here, Michal if you're reading this don't judge me 😄)

Sergio0694 avatar Oct 16 '20 18:10 Sergio0694

Hi Guys, thanks for your help, I was out for the weekend, but I'm glad that Sergio was available to provide you support. If you have any further questions feel free to ask, I'm looking forward for a fix to be able release an update for my app, thanks a lot for your work!

Panda-Sharp avatar Oct 19 '20 12:10 Panda-Sharp

I have tried to reproduce this with the latest ImageSharp (2.1.2) / Drawing(1.0.0-beta14) version.

I do get an Exception in Release mode:

at System.ValueTuple.System.Runtime.CompilerServices.ITuple.get_Item(Int32 index) in f:\dd\ndp\fxcore\CoreRT\src\System.Private.CoreLib\shared\System\ValueTuple.cs:line 142
at SixLabors.ImageSharp.Drawing.Shapes.Rasterization.ScanEdgeCollection.Create(TessellatedMultipolygon multipolygon, MemoryAllocator allocator, Int32 subsampling)
at SixLabors.ImageSharp.Drawing.Shapes.Rasterization.PolygonScanner.Create(IPath polygon, Int32 minY, Int32 maxY, Int32 subsampling, IntersectionRule intersectionRule, MemoryAllocator allocator)
at SixLabors.ImageSharp.Drawing.Processing.Processors.Text.DrawTextProcessor`1.CachingGlyphRenderer.Render(IPath path)
at SixLabors.ImageSharp.Drawing.Processing.Processors.Text.DrawTextProcessor`1.CachingGlyphRenderer.EndGlyph()
at SixLabors.Fonts.GlyphMetrics.RenderTo(IGlyphRenderer surface, Single pointSize, Vector2 location, TextOptions options)
at SixLabors.Fonts.Glyph.RenderTo(IGlyphRenderer surface, Vector2 location, TextOptions options)
at SixLabors.Fonts.TextRenderer.RenderText(ReadOnlySpan`1 text, TextOptions options)
at SixLabors.Fonts.TextRenderer.RenderText(String text, TextOptions options)
at SixLabors.ImageSharp.Drawing.Processing.Processors.Text.DrawTextProcessor`1.BeforeImageApply()
at SixLabors.ImageSharp.Processing.Processors.ImageProcessor`1.SixLabors.ImageSharp.Processing.Processors.IImageProcessor<TPixel>.Execute()
at SixLabors.ImageSharp.Processing.DefaultImageProcessorContext`1.ApplyProcessor(IImageProcessor processor, Rectangle rectangle)
at SixLabors.ImageSharp.Processing.DefaultImageProcessorContext`1.ApplyProcessor(IImageProcessor processor)
at SixLabors.ImageSharp.Drawing.Processing.DrawTextExtensions.DrawText(IImageProcessingContext source, DrawingOptions drawingOptions, String text, Font font, IBrush brush, IPen pen, PointF location)
at SixLabors.ImageSharp.Drawing.Processing.DrawTextExtensions.DrawText(IImageProcessingContext source, DrawingOptions drawingOptions, String text, Font font, Color color, PointF location)
at UwpTest.MainPage.<>c__DisplayClass1_0.<ButtonBase_OnClick>b__0(IImageProcessingContext i) in C:\Users\brian\source\repos\UwpTest\UwpTest\MainPage.xaml.cs:line 47
at SixLabors.ImageSharp.Processing.ProcessingExtensions.Mutate[TPixel](Image`1 source, Configuration configuration, Action`1 operation)
at SixLabors.ImageSharp.Processing.ProcessingExtensions.Mutate[TPixel](Image`1 source, Action`1 operation)
at UwpTest.MainPage.<ButtonBase_OnClick>d__1.MoveNext() in C:\Users\brian\source\repos\UwpTest\UwpTest\MainPage.xaml.cs:line 44

brianpopow avatar Jun 08 '22 11:06 brianpopow

Something we can point out upstream at least....

JimBobSquarePants avatar Jun 08 '22 12:06 JimBobSquarePants

@Sergio0694 is UWP still a thing? Can I close this?

JimBobSquarePants avatar Aug 13 '23 10:08 JimBobSquarePants

UWP is most definitely still a thing (and will always be), but whether you want to dedicate time investigating and fixing this depends on your support policy I think. Personally, I would kinda suggest to not maybe bother here unless the person reporting the issue has purchased a support license for ImageSharp — the bug is on the older version of the library anyway (UWP currently can't target modern .NET so UWP .NET apps can't use ImageSharp 3.x). And depending on what's causing the issue here exactly it might not be a super trivial investigation either 🤔

Sergio0694 avatar Aug 13 '23 10:08 Sergio0694

Thanks for the update. Yeah, we won't be performing any further updates to legacy versions unless they are security issues. I'm going to close this then.

JimBobSquarePants avatar Aug 13 '23 10:08 JimBobSquarePants