【发布时间】:2023-03-26 11:48:01
【问题描述】:
我有一个带有Image Control 的 wpf 应用程序。我画线和文字,根据文字的type在图像上显示不同颜色的文字字段。
对于这个例子,所有颜色都是白色的。
然后我将按下一个按钮,将图像转换为BlackWhite,将其显示到图像控件,然后生成一个光栅文件。
我遇到的问题是,当我将其转换为黑白时,线条和文本周围的阴影会变为 Pixelated。
有没有办法摆脱阴影或阻止它们进入 像素化?
我什至可以同时绘制一个额外隐藏的黑白图像,并从该图像而不是用户看到的图像生成光栅。
最小可行示例
xaml
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="500">
<Grid>
<Image x:Name="originalImage" HorizontalAlignment="Left" Height="100" Margin="30,100,0,0" VerticalAlignment="Top" Width="183" />
<Image x:Name="convertedImage" HorizontalAlignment="Left" Height="100" Margin="250,100,0,0" VerticalAlignment="Top" Width="183" />
</Grid>
</Window>
xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DrawingVisual visual = new DrawingVisual();
using (DrawingContext dc = visual.RenderOpen())
{
int fs = 28;
string textContain = "Testing 123";
Point p = new Point(0, 0);
dc.DrawRectangle(Brushes.Black, null, new Rect(0, 0, originalImage.Width, originalImage.Height));
dc.DrawText(new FormattedText(textContain, System.Globalization.CultureInfo.InvariantCulture, FlowDirection.LeftToRight,
new Typeface("Arial"), fs, Brushes.White, VisualTreeHelper.GetDpi(visual).PixelsPerDip), p);
}
RenderTargetBitmap target =
new RenderTargetBitmap((int)originalImage.Width, (int)originalImage.Height, 96, 96, PixelFormats.Default);
target.Render(visual);
FormatConvertedBitmap grayBitmapSource1 =
new FormatConvertedBitmap(target as BitmapSource, PixelFormats.Bgr24, null, 0);
var grayBitmapSource = new FormatConvertedBitmap();
grayBitmapSource.BeginInit();
grayBitmapSource.Source = grayBitmapSource1.Source as BitmapSource;
grayBitmapSource.DestinationFormat = PixelFormats.BlackWhite;
grayBitmapSource.EndInit();
originalImage.Source = target;
convertedImage.Source = grayBitmapSource;
}
}
}
【问题讨论】:
-
如果没有一个好的minimal reproducible example 可以可靠地重现问题,您不太可能找到愿意花时间解决问题的人。也就是说:您所说的“像素化”在我看来只是由转换为黑白时使用的阈值算法引起的抗锯齿伪影。尝试更仔细地控制转换,并允许任何非零像素值在黑白图像中成为前景。或者,您可以将文本渲染为路径,然后将其直接绘制到黑白图像中,而不是转换原始彩色图像。
-
@PeterDuniho 感谢伙伴的提醒。希望现在可以了。在我转换它之前,我正在考虑一次“读取”图像一个像素,然后在另一个图像上“写入”该像素。如果 r 或 g 或 b 不为零,则在 1 位 bmp 图像上绘制一个黑点。但我快速浏览了一下,找不到从图像控件获取 rgb 值并制作 1bpp 图像(并在其上设置像素)的方法
-
我现在正在探索的另一件事是在原始图像旁边绘制一个 System.Drawing.Image,然后从中导出光栅。我遇到的问题是带有内存流的drawing.image中的字节数组与我使用CopyPixels得到的原始字节数组不同(对我来说似乎是倒置的)。
-
现在回想起来,我隐约记得WPF 不允许
RenderTargetBitmap使用1bpp 格式。这是不幸的,因为这确实是最好的方法。我认为第二好的方法是按照您的建议使用WriteableBitmap,直接自己转换像素。使用 GDI+(即System.Drawing.Image)也是一种选择,如下所示:stackoverflow.com/questions/6550731/…