如何在图像中呈现带有 RenderTargetBitmap 的 FormattedText?
Posted
技术标签:
【中文标题】如何在图像中呈现带有 RenderTargetBitmap 的 FormattedText?【英文标题】:How to present FormattedText with RenderTargetBitmap in an Image? 【发布时间】:2014-10-26 17:45:58 【问题描述】:我在 Google 上找不到答案。
我有很多字符串要显示在画布上。每个字符串都将使用从 ItemsControl 调用的字符串转换器中的 FormattedText() 方法创建。
代码的问题在于,它需要在 RenderTargetBitmap() 中使用非常大的宽度和高度来显示不同位置的所有字符串,即使每个字符串的实际宽度大约为 700,实际高度为 40。(似乎 RenderTargetBitmap() 需要足够大,不仅可以容纳字符串,还可以容纳该字符串在绘图上下文中的位置)。
您如何创建一个仅包含单个格式化文本字符串的图像,该图像具有正确的实际高度和宽度,只有格式化文本,然后将该图像正确定位在“左上角”点?
从 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 符号)。
将项目控件更改为包括:
ItemsControl.ItemContainerStyle 样式 TargetType="x:Type FrameworkElement Setter Property="Canvas.Top" Value="Binding topleft.Y" Setter 属性="Canvas.Left" 值="绑定 topleft.X" Setter 属性="高度" 值="绑定 ft.Height"
移除了转换器的所有定位。转换器现在读取为
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;
【问题讨论】:
随着您在这里提出的每一个问题,您似乎越来越纠结于越来越陌生的解决方案。从绑定转换器返回 Image 控件纯属无稽之谈。也许是时候解释一下你的最终目标了。您的应用程序期望做什么?肯定有更简单的方法可以到达那里。拥有 ItemsControl 肯定是正确的,但是您还应该创建一个适当的 DataTemplate(为其 ItemTemplate 属性)来可视化您的字符串。 @Clemens 你可能是正确的。大约 6 年前,我编写了原始代码来执行手写识别和文本编辑。我最近的努力是尝试将旧代码拆开,更好地理解它,并尽可能接近 MVVM 模式。当前的问题来自于采用较旧的格式化文本,将其显示在项目控件中,但需要每行的最终图像尽可能精确到字符串尺寸。然后将针对生成的图像进行命中测试。然后将笔画 + 命中的结果提供给我的编辑器以修改字符串。 @Clemens 如果有更清洁的方法,我肯定愿意接受建议。 老实说,我不明白你在做什么。什么是“旧格式文本”?命中测试有什么用?什么是“击球+击球”?如果你想实现一个真正的 WPF 解决方案,你应该首先从你的所有细节中退一步,并给出目的或你的应用程序的一般描述。它有什么作用?应该如何工作? 那么为什么不创建一个包含 TextBlock 和覆盖 InkCanvas 的 UserControl,两者都包含在 Grid 中,并在 ItemsControl 的 ItemTemplate 中使用它。因此,每个字符串项都有一个 InkCanvas,并且可以摆脱任何命中测试和所有其他复杂的东西。 【参考方案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>
这只是展示了 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);
【讨论】:
以上是关于如何在图像中呈现带有 RenderTargetBitmap 的 FormattedText?的主要内容,如果未能解决你的问题,请参考以下文章
将自定义类插入到由 tinyMCE 通过 jQuery 呈现的 WYSIWIG 输出中(在 Wordpress 中处理带有标题的图像)
在 React Native iOS 中的图像顶部呈现具有透明背景的文本框
带有 OpenGL 和 Kinect v2 的 QT5:错误的图像呈现
在视图而不是模板中生成带有 Django 静态 url 的图像标签