位图图形与WinForm控制图形

4
我只是使用一个名为PdfiumViewer的 .NET 版本的 Pdfium。在 WinForm 控件中呈现后,它运行得非常好,但当我尝试在 Bitmap 上呈现它以在 WPF 窗口中显示(甚至保存到磁盘)时,呈现的文本存在问题。
var pdfDoc = PdfiumViewer.PdfDocument.Load(FileName);
int width = (int)(this.ActualWidth - 30) / 2;
int height = (int)this.ActualHeight - 30;            

var bitmap = new System.Drawing.Bitmap(width, height);

var g = System.Drawing.Graphics.FromImage(bitmap);

g.FillRegion(System.Drawing.Brushes.White, new System.Drawing.Region(
    new System.Drawing.RectangleF(0, 0, width, height)));

pdfDoc.Render(1, g, g.DpiX, g.DpiY, new System.Drawing.Rectangle(0, 0, width, height), false);

// Neither of these are readable
image.Source = BitmapHelper.ToBitmapSource(bitmap);
bitmap.Save("test.bmp");

// Directly rendering to a System.Windows.Forms.Panel control works well
var controlGraphics = panel.CreateGraphics(); 
pdfDoc.Render(1, controlGraphics, controlGraphics.DpiX, controlGraphics.DpiY,
    new System.Drawing.Rectangle(0, 0, width, height), false);

值得一提的是,我在Graphics对象上测试了几乎所有可能的选项,包括TextContrastTextRenderingHintSmoothingModePixelOffsetMode等。

我错过了哪些Bitmap对象的配置导致这种情况发生?

enter image description here

编辑2

经过大量搜索,正如@BoeseB所提到的那样,我刚刚发现Pdfium渲染设备通过提供第二个渲染方法FPDF_RenderPageBitmap来处理句柄和位图,目前我正在努力将其本地BGRA位图格式转换为托管Bitmap

编辑

TextRenderingHint的不同模式 enter image description here

还尝试了Application.SetCompatibleTextRenderingDefault(false),但没有明显的区别。


1
在我的启动画面项目中,我遇到了类似的问题,即将文本渲染到图像上。设置TextRenderingHint有所帮助。您已经尝试过所有不同的设置了吗?不同的设置效果如何呢? - BoeseB
1
请描述文本渲染问题,最好包括错误截图的链接。另外,我想指出WPF始终会按其DPI缩放位图。由于您在上面的代码中没有明确设置DPI,因此位图的DPI与您的显示器的DPI之间可能存在不匹配。 - RogerN
如果在显示控件之前使用Application.SetCompatibleTextRenderingDefault(false);会发生什么?我猜控件使用GDI+(graphics.DrawString)来显示文本,而您绘制到位图使用GDI(TextRenderer.DrawText),请参见此答案https://dev59.com/TGsy5IYBdhLWcg3w1xiU#23230570。 - BoeseB
@BoeseB,请查看我的编辑。我还检查了Control和Bitmap具有相同的96个垂直和水平分辨率。 - Mohsen Afshin
2
问题中的图像质量太差了,无法得出结论。然而,“不好”的图像中的文本加粗程度强烈地符合一种模式。这种情况发生在文本渲染在透明背景上时。文本渲染器不支持Alpha混合,从黑色文本到黑色背景进行反锯齿处理。这完全破坏了视觉效果,字母只会变成一团黑色像素。如何发生这种情况还不清楚,但您绝对需要努力使背景像素变为白色,通常可以通过Graphics.Clear()实现。 - Hans Passant
显示剩余2条评论
1个回答

1

这不是你的问题吗? 最近修复了它。 正如你所看到的,代码库所有者提交了PdfiumViewer的新版本。现在你可以这样写:

var pdfDoc = PdfDocument.Load(@"mydoc.pdf");
var pageImage = pdfDoc.Render(pageNum, width, height, dpiX, dpiY, isForPrinting);
pageImage.Save("test.png", ImageFormat.Png);

// to display it on WPF canvas
BitmapSource source = ImageToBitmapSource(pageImage);
canvas.DrawImage(source, rect);     // canvas is instance of DrawingContext

这里有一种流行的方法可以将图片转换为ImageSource。
BitmapSource ImageToBitmapSource(System.Drawing.Image image)
{
    using(MemoryStream memory = new MemoryStream())
    {
        image.Save(memory, ImageFormat.Bmp);
        memory.Position = 0;
        var source = new BitmapImage();
        source.BeginInit();
        source.StreamSource = memory;
        source.CacheOption = BitmapCacheOption.OnLoad;
        source.EndInit();

        return source;
    }
}

@MohsenAfshin 我添加了一些代码示例。我使用的是PdfiumViewer v 1.4.0.0进行测试,它的效果非常好。比使用ghostscrypt快得多,而且更美观。我猜你的问题已经解决了。 - shameleo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接