如何在Image中使用RenderTargetBitmap呈现FormattedText?

时间:2014-09-02 12:44:15

标签: wpf image xaml rendertargetbitmap formatted-text

我在Google上找不到答案。

我有很多字符串要在画布上呈现。将使用从ItemsControl调用的字符串转换器中的FormattedText()方法创建每个字符串。

代码的问题在于它在RenderTargetBitmap()中需要一个非常大的宽度和高度来显示不同位置的所有字符串,即使每个字符串的实际宽度大约为700,实际高度为40(似乎RenderTargetBitmap()需要足够大,不仅可以保存字符串,还可以保存绘图上下文中该字符串的位置。

如何使用格式化文本的正确实际高度和宽度创建仅包含单个格式化文本字符串的图像,然后将该图像正确定位在“topleft”点?

从ItemsControl调用的转换器定义为:

 public class InkConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var stringviewmodel = value as StringViewModel;
        if (stringviewmodel != null)
        {
           stringviewmodel.ft = new FormattedText(
           stringviewmodel.text,
           CultureInfo.CurrentCulture,
           FlowDirection.LeftToRight,
           new Typeface(new FontFamily("Segoe Script"), FontStyles.Italic, FontWeights.Normal, FontStretches.Normal),
           stringviewmodel.emSize,
           stringviewmodel.color);

           stringviewmodel.ft.TextAlignment = TextAlignment.Left;
           stringviewmodel.ft.LineHeight =(double)stringviewmodel.lineheight;

            Image myImage = new Image();

            DrawingVisual dw = new DrawingVisual();
            DrawingContext dc = dw.RenderOpen();
            dc.DrawText(stringviewmodel.ft, stringviewmodel.topleft);
            dc.Close();


            int Width = 2000;
            int Height = 2000;
            RenderTargetBitmap bmp = new RenderTargetBitmap(Width, Height, 120, 96, PixelFormats.Pbgra32);  

            bmp.Render(dw);
            myImage.Source = bmp;

            return myImage;
        }
        else
        {
            return null;
        }
    }

    public object  ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

}

附录:

我写了这个解决了问题,但没有回答我的问题。 (删除了gt和lt符号)。

  1. 将itemscontrol更改为包括:

    ItemsControl.ItemContainerStyle                     Style TargetType =“{x:Type FrameworkElement}                         Setter Property =“Canvas.Top”Value =“{Binding topleft.Y}”                         Setter Property =“Canvas.Left”Value =“{Binding topleft.X}”                         Setter Property =“Height”Value =“{Binding ft.Height}”                         

  2. 从转换器中删除了所有定位。转换器现在读为

    public object Convert(object value, Type targetType, object parameter,   
    System.Globalization.CultureInfo culture)
    {
        var stringviewmodel = value as StringViewModel;
        if (stringviewmodel != null)
        {
           stringviewmodel.ft = new FormattedText(
           stringviewmodel.text,
           CultureInfo.CurrentCulture,
           FlowDirection.LeftToRight,
           new Typeface(new FontFamily("Segoe Script"), FontStyles.Italic, FontWeights.Normal, FontStretches.Normal),
           stringviewmodel.emSize,
           stringviewmodel.color);
    
    
            stringviewmodel.ft.TextAlignment = TextAlignment.Left;
            stringviewmodel.ft.LineHeight =(double)stringviewmodel.lineheight;
    
            Image myImage = new Image();
            DrawingVisual dw = new DrawingVisual();
            DrawingContext dc = dw.RenderOpen();
    
            dc.DrawText(stringviewmodel.ft, new Point(0,0));
    
            dc.Close();
    
           double width = stringviewmodel.ft.text.Width - stringviewmodel.text.OverhangLeading -   stringviewmodel.text.OverhangTrailing;
    
            RenderTargetBitmap bmp = new RenderTargetBitmap(
            (int)(width,
            (int)stringviewmodel.ft.Height,
            96d,            
            96d,
            PixelFormats.Pbgra32);  
    
            bmp.Render(dw);
            myImage.Source = bmp;
    
            return myImage;
        }
        else
        {
            return null;
        }
    }
    

1 个答案:

答案 0 :(得分:1)

你生活在过去的所有WinForms代码......这是WPF!首先,您不需要任何FormattedText个对象,因为您可以非常轻松地在XAML中执行此操作。拿这个基本的例子:

<TextBlock Name="TextBlockToGetImageFrom">
    <Run FontFamily="Arial" FontWeight="Bold" FontSize="40" Foreground="Red" Text="W" />
    <Run FontFamily="Tahoma" Text="indows" FontSize="20" BaselineAlignment="Bottom" />
    <Run FontFamily="Arial" FontWeight="Bold" FontSize="40" Foreground="Red" Text=" P" />
    <Run FontFamily="Tahoma" Text="resentation" FontSize="20" BaselineAlignment="Center" />
    <Run FontFamily="Arial" FontWeight="Bold" FontSize="40" Foreground="Red" Text=" F" />
    <Run FontFamily="Tahoma" Text="ormat" FontSize="20" BaselineAlignment="Top" />
</TextBlock>

enter image description here

这只是展示了WPF的一些灵活性,而且还有更多选项未在此处显示。因此,一旦您根据需要设置了TextBlock,就可以使用RenderTargetBitmap class将其转换为只需几行代码的图片:

RenderTargetBitmap renderTargetBitmap = 
    new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
renderTargetBitmap.Render(TextBlockToGetImageFrom); 
PngBitmapEncoder pngImage = new PngBitmapEncoder();
pngImage.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (Stream fileStream = File.Create(filePath))
{
    pngImage.Save(fileStream);
}