【问题标题】:Bitmap Graphics vs WinForm Control Graphics位图图形与 WinForm 控制图形
【发布时间】:2015-04-09 07:00:54
【问题描述】:

我只是使用名为PdfiumViewerPdfium .NET 端口。它在 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 对象上几乎所有可能的选项,包括TextContrast,TextRenderingHint,SmoothingMode,PixelOffsetMode, ...

Bitmap 对象上缺少哪些配置会导致此问题?

编辑 2

经过大量搜索,正如@BoeseB 提到的,我刚刚发现 Pdfium 通过提供第二种渲染方法 FPDF_RenderPageBitmap 以不同的方式渲染设备处理和位图,目前我正在努力将其原生 BGRA 位图格式转换为托管 Bitmap .

编辑

TextRenderingHint的不同模式

也试过Application.SetCompatibleTextRenderingDefault(false),没有明显区别。

【问题讨论】:

  • 在我的初始屏幕项目中,我在将文本渲染到图像上时遇到了类似的问题。它有助于设置 TextRenderingHint。您已经尝试了所有不同的设置?结果如何看待不同的设置?
  • 请描述文本呈现问题,或者最好包含指向错误屏幕截图的链接。另外,我只想指出 WPF 总是绘制缩放到其 DPI 的位图。由于您没有在上面的代码中明确设置 DPI,因此位图的 DPI 和显示器的 DPI 之间可能不匹配。
  • 如果你使用 Application.SetCompatibleTextRenderingDefault(false);在显示控件之前?我猜控件使用 GDI+ (graphics.DrawString) 来显示文本,而你的绘制到位图使用 GDI (TextRenderer.DrawText) 看到这个答案stackoverflow.com/a/23230570/4369295
  • @BoeseB,请查看我的编辑。我还检查了 Control 和 Bitmap 是否具有相同的 96 个垂直和水平分辨率。
  • 问题中的图像质量太差,无法得出结论。事实上,“坏”图像的文本更粗,但是非常符合一种模式。当文本在透明背景上呈现时会发生这种情况。文本渲染器不支持 alpha 混合,它会从黑色文本到黑色背景进行反锯齿处理。这完全破坏了视觉效果,字母只是变成了一团黑色像素。这是如何发生的还不清楚,你肯定会努力使背景像素变白。通常使用 Graphics.Clear() btw 完成。

标签: c# wpf winforms bitmap gdi+


【解决方案1】:

这不是你的issue 吗? 查看最近的fix。 如您所见,存储库所有者提交了更新版本的 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

这是一种将 Image 转换为 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 更快更漂亮。猜猜你的问题已经解决了。
猜你喜欢
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
相关资源
最近更新 更多