打印/图形问题

4

语言: VB .NET 2010 Win Form

范围: 我开发了一个标签打印程序,旨在将自定义标签打印到斑马打印机上。当我尝试将整个标签作为图像打印时,打印机的清晰度存在问题,因此我试图将所有标签中的文本存储到数组中,清除标签,将剩余的图像发送到打印机,并基于存储的数组叠加新文本。这结果旨在向打印机发送文本而不是图像。

问题: 文本的最终标签非常清晰,正如我所希望的那样,但我使用的打印方法对齐存在问题。针对测试,我将原始图像显示为顶部的叠加文本,它们应该完美地对齐或在合理范围内接近。但实际测试结果是它们没有对齐。

测试:

    Dim g2 As Graphics
    g2 = Form1.PictureBox2.CreateGraphics
    g2.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
    g2.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
    g2.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
    g2.Clear(Color.White)

    g2.DrawImage(largeimage, New Point(0, 0))

    Dim myBrush As Brush
    Dim i As Integer = 0
    Do Until i = label_array.Count - 1
        myBrush = New SolidBrush(label_array(i).ForeColor)
        g2.DrawString(label_array(i).Text, label_array(i).Font, myBrush, label_array(i).Location)
        i = i + 1
    Loop

在我使用的打印方法中,我使用了上述方法将覆盖层和图像输出到图片框中。这样做是可行的,但是......

    e.Graphics.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
    e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
    e.Graphics.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
    e.Graphics.Clear(Color.White)

    e.Graphics.DrawImage(largeimage, New Point(0, 0))

    i = 0
    Do Until i = label_array.Count - 1
        myBrush = New SolidBrush(label_array(i).ForeColor)
        e.Graphics.DrawString(label_array(i).Text, label_array(i).Font, myBrush, label_array(i).Location)
        i = i + 1
    Loop

对于上面展示的打印图形,进行操作会导致不对齐的问题......

欢迎任何想法,因为我会尝试一切。我猜打印图形做了一些正常图形没有的额外处理。


我注意到TextRenderer.DrawText相对于DrawString可以改善结果。然而使用它时,结果似乎被某个未知缩放因子从原始大小缩小了......

下面是覆盖在原始图像上的结果:enter image description here


在创建新画笔之前,不要忘记处理旧的画笔。 - John Alexiou
请注意,打印的“矩形”始终从屏幕上的(0,0)开始,但不是在打印机上。检查打印矩形的.Left.Top属性,并相应地偏移文本。 - John Alexiou
边距范围为(100,100),页面范围为(0,0),所以我真的看不出有什么关联。 - Eric F
2个回答

2

您正在重新发现与Graphics.DrawString()相关的一个众所周知的问题,即它不够准确。这个问题最明显的演示是这个样例Winforms表单:

public partial class Form1 : Form {
    public Form1() {
        InitializeComponent();
    }
    protected override void OnPaint(PaintEventArgs e) {
        e.Graphics.DrawString("Hiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", 
            this.Font, Brushes.Black, 0, 0);
    }
}

这看起来像这样:

在此输入图片描述

无论使用多少魔法,都不可能让您在字符串部分重叠,在那里字母之间的间距突然改变。 GDI +是微软首次尝试实现分辨率独立文本呈现,并且效果不佳。 它与WPF一起,WPF是第二次尝试,并因模糊输出而受到很多批评。 以类似于.NET 2.0为Winforms中修复的方式解决,您应始终使用TextRenderer.DrawText()将文本呈现到窗口中。 它不会尝试使呈现的文本平滑缩放,它总是更喜欢适合像素网格。 WPF的idealdisplay渲染模式相同,添加在.NET 4中

您的方法还存在其他重大问题,文本呈现方式显着不适用于打印机。 当您放大时,可以看到像素,SysInternals的ZoomIt实用程序非常好。 我放大了右侧图形中的字母a:

在此输入图片描述

请注意字母形状边缘的红色和蓝色像素。 这是一种抗锯齿技术,称为ClearType,它增强了LCD显示器的感知分辨率。 它仅适用于LCD面板,在没有相同条纹模式的打印机上不起作用。 在纸上,该字母将只是带有彩色边缘的模糊。 尽管在Zebra打印机上情况并不像彩色打印机那样糟糕。

这些都是特定于向监视器呈现文本的工件,这些设备具有相当低的分辨率。 像素网格拟合和ClearType是使文本看起来不错的技巧。 典型显示器每英寸不超过约120个像素。 尽管这最终随着苹果推动“视网膜”显示器而得到改善。 一家在高分辨率显示器中有利益的公司,他们传统上以“理想”模式呈现文本。在此处

这些渲染技巧对于打印机来说是完全不适用的,因为打印机具有更高的分辨率。典型的分辨率为每英寸600像素,比显示器高出5倍以上。通过在打印机上绘制picturebox,实际上是浪费了直接在打印机上绘制时所获得的改进效果。这种差异非常显著,肉眼可以轻易看出。当您以600 dpi呈现文本时,文本看起来更加美丽、清晰。原先以120 dpi呈现并放大到打印机的文本看起来“模糊”和粗糙。

始终使用PrintDocument类来绘制打印机。


1
很久以前,我写了一个打印标签到Zebra打印机的应用程序,也许我可以帮忙。那时我们只有ZPL2 API,并且只能打印文本和简单的图形,没有这个图像的东西。无论如何...
我的怀疑是它是一个缩放问题。这可能解释为什么您的原始图像模糊--也许打印机自动尝试将其缩放以适合标签,并且做得很差?当然,这可以解释上面显示的标签的结果。
关于您上面的代码,让我想到了如何获取Graphics对象。其中一个来自图片框,另一个可能来自打印机。请记住,Graphics对象是设备相关的。也就是说,它的属性和打印方式取决于您是将其打印到特定控件(不同的控件可以具有不同的缩放)还是打印到特定打印机。
您是否尝试使用现有代码打印到激光打印机?看看结果可能会有趣。还要查看Graphics属性,例如ScaleTransform。

所以我假设你在谈论TextRenderer.DrawText方法,并尝试检查它与打印机图形比例的比例?我会尝试并发布结果。 - Eric F

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