XPS打印质量c#与XPS查看器
本文关键字:XPS 打印质量 | 更新日期: 2023-09-27 18:14:55
我在c#应用程序中有一个有点奇怪的打印质量问题。我有一个XPS文件(它基本上只是一个1页的图像,最初是扫描的黑白图像),我试图通过c#应用程序将其打印到IBM infopprint Mainframe驱动程序。我已经打印到许多其他的打印驱动程序,从来没有遇到过问题,但是这个驱动程序给了我可怕的质量与它创建的AFP文件。如果我在微软XPS查看器应用程序中打开相同的文件并打印到相同的驱动程序,质量看起来很好。
试图通过工作的问题,我已经尝试了3或4种不同的方法来打印在c#应用程序。原来的代码做了这样的事情(精简):
System.Windows.Xps.XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(mPrintQueue);
mCollator = writer.CreateVisualsCollator();
mCollator.BeginBatchWrite();
ContainerVisual v = getContainerVisual(xpsFilePath);
//tried all sorts of different options on the print ticket, no effect
mCollator.Write(v,mDefaultTicket);
这段代码(我已经截断了)当然可能有一些奇怪的问题,所以我尝试了一些更简单的东西:
LocalPrintServer localPrintServer = new LocalPrintServer();
PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue();
PrintSystemJobInfo xpsPrintJob = defaultPrintQueue.AddJob("title", xpsDocPath, false);
同样的结果。
我甚至尝试使用WCF打印对话框,同样的质量差(http://msdn.microsoft.com/en-us/library/ms742418.aspx)。
我还没有尝试过的一个领域是使用老式的底层打印API,但我不确定为什么会有不同的行为。我还有另一个选择,我的原始文档是PDF,我有一个很好的第三方库,可以把我变成EMF文件。但是,每次我尝试将EMF文件流式传输到打印机时,都会得到乱码文本。
任何关于为什么这个质量丢失,如何修复,或者如何将EMF文件流到打印驱动程序的想法,将非常感激!
更新:还有一点。这个不错的示例应用程序:http://wrb.home.xs4all.nl/Articles_2010/Article_XPSViewer_01.htm也经历了同样的质量损失。我现在也进行了测试,直接打开PDF并将位图渲染到打印文档,结果图像的模糊性相同。如果我在Acrobat中打开pdf并打印出来,效果会很好
要结束这个问题,似乎IBM infopprint驱动程序(至少在这里使用它的方式)具有完全不同的质量,这取决于您在c#中如何打印。
在这个问题中,我使用的是:
System.Windows.Documents.Serialization.Write(Visual, PrintTicket);
我完全改变了我的方法,完全删除了XPS,并获得了我的文档的emf (windows元文件)版本,然后使用windows打印事件处理程序将该emf文件发送到windows打印机:
using (PrintDocument pd = new PrintDocument())
{
pd.DocumentName = this.mJobName;
pd.PrinterSettings.PrinterName = this.mPrinterName;
pd.PrintController = new StandardPrintController();
pd.PrintPage += new PrintPageEventHandler(DoPrintPage);
pd.Print();
}
(显然我在这里省略了很多代码,但是您可以找到如何相对容易地使用这种方法的示例)
在我的测试中,大多数打印驱动程序对两种打印方法都同样满意,但是IBM infopprint驱动程序对质量极其敏感。一种可能的解释是infopprint打印机被要求配置一个奇怪的固定DPI,它可能在转换方面做得相对较差。
编辑:更详细的示例代码是要求的,所以在这里你去。注意,获取EMF文件是此方法的先决条件。在本例中,我使用的是ABC PDF,它允许您通过一个相对简单的调用从PDF生成EMF文件。 class AbcPrintEmf
{
private Doc mDoc;
private string mJobName;
private string mPrinterName;
private string mTempFilePath;
private bool mRenderTextAsPolygon;
public AbcPdfPrinterApproach(Doc printMe, string jobName, string printerName, bool debug, string tempFilePath, bool renderTextAsPolygon)
{
mDoc = printMe;
mDoc.PageNumber = 1;
mJobName = jobName;
mPrinterName = printerName;
mRenderTextAsPolygon = renderTextAsPolygon;
if (debug)
mTempFilePath = tempFilePath;
}
public void print()
{
using (PrintDocument pd = new PrintDocument())
{
pd.DocumentName = this.mJobName;
pd.PrinterSettings.PrinterName = this.mPrinterName;
pd.PrintController = new StandardPrintController();
pd.PrintPage += new PrintPageEventHandler(DoPrintPage);
pd.Print();
}
}
private void DoPrintPage(object sender, PrintPageEventArgs e)
{
using (Graphics g = e.Graphics)
{
if (mDoc.PageCount == 0) return;
if (mDoc.Page == 0) return;
XRect cropBox = mDoc.CropBox;
double srcWidth = (cropBox.Width / 72) * 100;
double srcHeight = (cropBox.Height / 72) * 100;
double pageWidth = e.PageBounds.Width;
double pageHeight = e.PageBounds.Height;
double marginX = e.PageSettings.HardMarginX;
double marginY = e.PageSettings.HardMarginY;
double dstWidth = pageWidth - (marginX * 2);
double dstHeight = pageHeight - (marginY * 2);
// if source bigger than destination then scale
if ((srcWidth > dstWidth) || (srcHeight > dstHeight))
{
double sx = dstWidth / srcWidth;
double sy = dstHeight / srcHeight;
double s = Math.Min(sx, sy);
srcWidth *= s;
srcHeight *= s;
}
// now center
double x = (pageWidth - srcWidth) / 2;
double y = (pageHeight - srcHeight) / 2;
// save state
RectangleF theRect = new RectangleF((float)x, (float)y, (float)srcWidth, (float)srcHeight);
int theRez = e.PageSettings.PrinterResolution.X;
// draw content
mDoc.Rect.SetRect(cropBox);
mDoc.Rendering.DotsPerInch = theRez;
mDoc.Rendering.ColorSpace = "RGB";
mDoc.Rendering.BitsPerChannel = 8;
if (mRenderTextAsPolygon)
{
//i.e. render text as polygon (non default)
mDoc.SetInfo(0, "RenderTextAsText", "0");
}
byte[] theData = mDoc.Rendering.GetData(".emf");
if (mTempFilePath != null)
{
File.WriteAllBytes(mTempFilePath + @"'" + mDoc.PageNumber + ".emf", theData);
}
using (MemoryStream theStream = new MemoryStream(theData))
{
using (Metafile theEMF = new Metafile(theStream))
{
g.DrawImage(theEMF, theRect);
}
}
e.HasMorePages = mDoc.PageNumber < mDoc.PageCount;
if (!e.HasMorePages) return;
//increment to next page, corrupted PDF's have occasionally failed to increment
//which would otherwise put us in a spooling infinite loop, which is bad, so this check avoids it
int oldPageNumber = mDoc.PageNumber;
++mDoc.PageNumber;
int newPageNumber = mDoc.PageNumber;
if ((oldPageNumber + 1) != newPageNumber)
{
throw new Exception("PDF cannot be printed as it is corrupt, pageNumbers will not increment properly.");
}
}
}
}