title: How to get an effective ScaleTransform factor in WPF?
body: <p><strong>UPDATED:</strong> Memory leak eliminated</p>
  
  <p>GDI <code>System.Drawing</code> is a way faster than WPF <code>DrawingContext</code> in many cases, so I extended <code>FrameworkElement</code> with the following overload of <code>OnRender</code>:</p>
  
  <pre><code>protected abstract void OnRender(Graphics graphics);
  </code></pre>
  
  <p>It uses GDI bitmap buffer:</p>
  
  <pre><code>public abstract class GraphicsElement : FrameworkElement
  {
      protected abstract void OnRender(Graphics graphics);
  
      protected override void OnRender(DrawingContext drawingContext)
      {
          if (TooSmall)
              return;
  
          using (var buffer = new Bitmap(BufferWidth, BufferHeight))
          {
              using (var g = Graphics.FromImage(buffer))
              {
                  g.SmoothingMode = SmoothingMode.HighQuality;
                  g.ScaleTransform(XScale, YScale);
                  OnRender(g);
              }
  
              var source = buffer.ToBitmapSource();
              source.Freeze();
              drawingContext.DrawImage(
                  source,
                  new Rect(0, 0, ActualWidth, ActualHeight));
          }
      }
  
      bool TooSmall =&gt; BufferWidth &lt;= 0 || BufferHeight &lt;= 0;
      int BufferWidth =&gt; (int)(ActualWidth * XScale);
      int BufferHeight =&gt; (int)(ActualHeight * YScale);
      float XScale =&gt; (float)(Transformation?.M11 ?? 1.0);
      float YScale =&gt; (float)(Transformation?.M22 ?? 1.0);
      System.Windows.Media.Matrix? Transformation =&gt;
          PresentationSource.FromVisual(this)
              ?.CompositionTarget
              ?.TransformToDevice;
  }
  </code></pre>
  
  <p>Where helpers are:</p>
  
  <pre><code>public static class BitmapInterop
  {
      public static BitmapSource ToBitmapSource(this Bitmap bitmap)
      {
          using (var handle = new SafeBitmapHandle(bitmap.GetHbitmap(), true))
              return Imaging.CreateBitmapSourceFromHBitmap(
                  handle.DangerousGetHandle(),
                  IntPtr.Zero,
                  Int32Rect.Empty,
                  BitmapSizeOptions.FromEmptyOptions());
      }
  }
  
  public class SafeBitmapHandle : SafeHandleZeroOrMinusOneIsInvalid
  {
      [SecurityCritical]
      public SafeBitmapHandle(IntPtr preexistingHandle, bool ownsHandle)
          : base(ownsHandle)
      {
          SetHandle(preexistingHandle);
      }
  
      protected override bool ReleaseHandle() =&gt;            
          DeleteObject(handle);
  
      [DllImport("gdi32.dll")]
      static extern bool DeleteObject(IntPtr hObject);
  }
  </code></pre>
  
  <p>Demo code:</p>
  
  <pre><code>public class Plot : GraphicsElement
  {
      protected override void OnRender(DrawingContext drawingContext)
      {
          base.OnRender(drawingContext);
          drawingContext.DrawRectangle(
              null, 
              new System.Windows.Media.Pen(System.Windows.Media.Brushes.Gray, 1),
              new Rect(0, 0, ActualWidth, ActualHeight));
      }
  
      protected override void OnRender(Graphics graphics)
      {
          graphics.DrawLine(System.Drawing.Pens.Gray, 
              0, 0, (float)ActualWidth, (float)ActualHeight-1);
          graphics.DrawLine(System.Drawing.Pens.Gray, 
              0, (float)ActualHeight - 1, (float)ActualWidth, 0);
      }
  }
  </code></pre>
  
  <p>It works, but I got some pixilation problem when upscaling Layout or Rendering Transform is in effect. I do pay attention to the system screen DPI settings properly. How to calculate an effective DPI factor?</p>