背景:
我正在开发一个使用Silverlight(1.0)构建的应用程序,动态地在特定位置叠加图标和文本,形成美国地图。这个地图在浏览器中运行良好,现在我需要获取一个静态的(可打印并可以插入到文档/幻灯片中的)已显示的地图副本。
目标: 为了获得可打印的地图副本,该副本也可用于PowerPoint幻灯片、Word等,我选择创建一个ASP.NET HttpHandler,在WPF中从服务器端重新创建xaml,然后将WPF渲染为位图图像,并作为png文件返回,生成的分辨率为300dpi,以获得更好的打印质量。
问题: 这个方法非常好,但有一个问题,就是我无法将图像缩放到指定的大小。我尝试了几种不同的方法,其中一些可以在注释掉的行中看到。我需要能够指定图像的高度和宽度,无论是英寸还是像素,我并不在意,只要xaml能够按照指定的大小进行缩放生成位图即可。目前,如果我将大小设置得比根画布大,那么画布会以其原始大小呈现在生成的图像的左上角,并且大小与指定的大小相同。下面是我的httphandler的重要部分。存储为"MyImage"的根画布高度为600,宽度为800。我错过了什么,以便使内容按比例缩放以适应指定的大小?
我不完全理解传递到Arrange()和Measure()中的维度所做的工作,因为其中一些代码是从在线示例中获取的。我也不完全理解RenderTargetBitmap的东西。任何指导都将不胜感激。
目标: 为了获得可打印的地图副本,该副本也可用于PowerPoint幻灯片、Word等,我选择创建一个ASP.NET HttpHandler,在WPF中从服务器端重新创建xaml,然后将WPF渲染为位图图像,并作为png文件返回,生成的分辨率为300dpi,以获得更好的打印质量。
问题: 这个方法非常好,但有一个问题,就是我无法将图像缩放到指定的大小。我尝试了几种不同的方法,其中一些可以在注释掉的行中看到。我需要能够指定图像的高度和宽度,无论是英寸还是像素,我并不在意,只要xaml能够按照指定的大小进行缩放生成位图即可。目前,如果我将大小设置得比根画布大,那么画布会以其原始大小呈现在生成的图像的左上角,并且大小与指定的大小相同。下面是我的httphandler的重要部分。存储为"MyImage"的根画布高度为600,宽度为800。我错过了什么,以便使内容按比例缩放以适应指定的大小?
我不完全理解传递到Arrange()和Measure()中的维度所做的工作,因为其中一些代码是从在线示例中获取的。我也不完全理解RenderTargetBitmap的东西。任何指导都将不胜感激。
Public Sub Capture(ByVal MyImage As Canvas)
' Determine the constraining scale to maintain the aspect ratio and the bounds of the image size
Dim scale As Double = Math.Min(Width / MyImage.Width, Height / MyImage.Height)
'Dim vbox As New Viewbox()
'vbox.Stretch = Stretch.Uniform
'vbox.StretchDirection = StretchDirection.Both
'vbox.Height = Height * scale * 300 / 96.0
'vbox.Width = Width * scale * 300 / 96.0
'vbox.Child = MyImage
Dim bounds As Rect = New Rect(0, 0, MyImage.Width * scale, MyImage.Height * scale)
MyImage.Measure(New Size(Width * scale, Height * scale))
MyImage.Arrange(bounds)
'MyImage.UpdateLayout()
' Create the target bitmap
Dim rtb As RenderTargetBitmap = New RenderTargetBitmap(CInt(Width * scale * 300 / 96.0), CInt(Height * scale * 300 / 96.0), 300, 300, 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)
'Dim vb As New VisualBrush(vbox)
ctx.DrawRectangle(vb, Nothing, New Rect(New System.Windows.Point(), bounds.Size))
End Using
rtb.Render(dv)
' Encode the image in the format selected
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()
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