0

I am using the FormulaControl from WPF-Math to render a bitmap for a tek equation. The bitmap will be delivered as content over a web service ( slack ). There is no desktop component. I am only using the WPF framework to try to capture the image from the tek control. The code for the renderer component is

public static class Renderer
{
    private static readonly StaTaskScheduler _StaTaskScheduler = new StaTaskScheduler( 1 );
    public static async Task<string> GenerateImage(string formula)
    {
        string Build()
        {

            var control = new FormulaControl
                          {
                              Formula    = formula
                            , Background = Brushes.White
                          };

            control.Measure(new Size(300, 300));
            control.Arrange(new Rect(new Size(300, 300)));

            var bmp = new RenderTargetBitmap(300, 300, 96, 96, PixelFormats.Pbgra32);

            bmp.Render(control);

            var encoder = new PngBitmapEncoder();

            encoder.Frames.Add(BitmapFrame.Create(bmp));

            var file = @"test.png";

            using (Stream stm = File.Create(file))
                encoder.Save(stm);

            return file;

        }

        return await Task.Factory.StartNew
            ( Build, CancellationToken.None, TaskCreationOptions.None, _StaTaskScheduler );
    }
}

Using the above code and the input

k_{n+1} = n^2 + k_n^2 - k_{n-1}

the below image is generated

enter image description here

As you can see, in this case, an arbitrary size of 300x300 is too big and for a different tek input it maybe too small.

The challenge is to generate a bitmap of exactly the correct size for the rendered equation. How can this be done?

bradgonesurfing
  • 30,949
  • 17
  • 114
  • 217

1 Answers1

0

One solution is to render to a large bitmap then auto crop the whitespace. There is a solution for auto cropping whitespace at

Cropping whitespace from image in C#

Using the ImageCrop class from above I modified the rendering code to

public static class Renderer
{
    private static readonly StaTaskScheduler _StaTaskScheduler = new StaTaskScheduler( 1 );

    public static Bitmap Convert( RenderTargetBitmap inmap )
    {
        MemoryStream stream = new MemoryStream();
        BitmapEncoder encoder = new BmpBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(inmap));
        encoder.Save(stream);

        Bitmap bitmap = new Bitmap(stream);
        return bitmap;
    }

    public static async Task<string> GenerateImage(string formula)
    {
        string Build()
        {

            var control = new FormulaControl
                          {
                              Formula    = formula
                            , Background = Brushes.White
                          };

            control.Measure(new Size(300, 300));
            control.Arrange(new Rect(new Size(300, 300)));

            var bmp = new RenderTargetBitmap(300, 300, 96, 96, PixelFormats.Pbgra32);

            bmp.Render(control);

            var image = ImageCrop.AutoCrop( Convert( bmp ) );
            var file = @"test.png";
            image.Save( file,ImageFormat.Png );
            return file;

        }

        return await Task.Factory.StartNew
            ( Build, CancellationToken.None, TaskCreationOptions.None, _StaTaskScheduler );
    }
}

The output in my slackbot is now perfectly cropped.

enter image description here

Obviously this is not perfect as there is an upper bound on the render size.

bradgonesurfing
  • 30,949
  • 17
  • 114
  • 217