Scaling WPF content before rendering to bitmap
This should be enough to get you started:
private void ExportCanvas(int width, int height){ string path = @"c:\temp\Test.tif"; FileStream fs = new FileStream(path, FileMode.Create); RenderTargetBitmap renderBitmap = new RenderTargetBitmap(width, height, 1/300, 1/300, PixelFormats.Pbgra32); DrawingVisual visual = new DrawingVisual(); using (DrawingContext context = visual.RenderOpen()) { VisualBrush brush = new VisualBrush(MyCanvas); context.DrawRectangle(brush, null, new Rect(new Point(), new Size(MyCanvas.Width, MyCanvas.Height))); } visual.Transform = new ScaleTransform(width / MyCanvas.ActualWidth, height / MyCanvas.ActualHeight); renderBitmap.Render(visual); BitmapEncoder encoder = new TiffBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(renderBitmap)); encoder.Save(fs); fs.Close();}
This is what ended up working for me:
Public Sub Capture(ByVal MyImage As Canvas) ' Normally we would obtain a user's configured DPI setting to account for the possibilty of a high DPI setting. ' However, this code is running server side so the client's DPI is not obtainable. Const SCREEN_DPI As Double = 96.0 ' Screen DPI Const TARGET_DPI As Double = 300.0 ' Print Quality DPI ' Determine the constraining scale to maintain the aspect ratio and the bounds of the image size Dim scale As Double = Math.Min(Width * SCREEN_DPI / MyImage.Width, Height * SCREEN_DPI / MyImage.Height) ' Setup the bounds of the image Dim bounds As Rect = New Rect(0, 0, MyImage.Width * scale, MyImage.Height * scale) MyImage.Measure(New Size(MyImage.Width * scale, MyImage.Height * scale)) MyImage.Arrange(bounds) ' Create the target bitmap Dim rtb As RenderTargetBitmap = New RenderTargetBitmap(CDbl(MyImage.Width * scale / SCREEN_DPI * TARGET_DPI), CDbl(MyImage.Height * scale / SCREEN_DPI * TARGET_DPI), TARGET_DPI, TARGET_DPI, PixelFormats.Pbgra32) ' Render the image to the target bitmap Dim dv As DrawingVisual = New DrawingVisual() Using ctx As DrawingContext = dv.RenderOpen() Dim vb As New VisualBrush(MyImage) ctx.DrawRectangle(vb, Nothing, New Rect(New System.Windows.Point(), bounds.Size)) End Using ' Transform the visual to scale the image to our desired size. 'dv.Transform = New ScaleTransform(scale, scale) ' Render the visual to the bitmap. rtb.Render(dv) ' Encode the image in the format selected. If no valid format was selected, default to png. Dim encoder As System.Windows.Media.Imaging.BitmapEncoder Select Case Encoding.ToLower Case "jpg" encoder = New System.Windows.Media.Imaging.JpegBitmapEncoder() Case "png" encoder = New System.Windows.Media.Imaging.PngBitmapEncoder() Case "gif" encoder = New System.Windows.Media.Imaging.GifBitmapEncoder() Case "bmp" encoder = New System.Windows.Media.Imaging.BmpBitmapEncoder() Case "tif" encoder = New System.Windows.Media.Imaging.TiffBitmapEncoder() Case "wmp" encoder = New System.Windows.Media.Imaging.WmpBitmapEncoder() Case Else encoder = New System.Windows.Media.Imaging.PngBitmapEncoder() End Select encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(rtb)) ' Create the memory stream to save the encoded image. retImageStream = New System.IO.MemoryStream() encoder.Save(retImageStream) retImageStream.Flush() retImageStream.Seek(0, System.IO.SeekOrigin.Begin) MyImage = Nothing End Sub