Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What causes WPF printer output to be rasterized?

I've encountered many issues with printing in WPF where particular combinations of items being printed will suddenly trigger rasterization of the printer output (causing ugly and huge printer output, and can cause it to take 30 seconds to print each page). I've found that often things like having any level of opacity set on a control will trigger this. I forget what all else does it (I believe using a canvas with clipping turned on can do it as well), but now I'm running into yet another issue with a stackpanel with a tiled imagebrush filling a border... etc... which is now causing this rasterization yet again.

So before I go poking around again trying to figure out what triggers what etc, I wanted to find out if anyone knows of a definitive source of information on what specific items might trigger this? Or perhaps some way to hook into the system where this is happening to let me at least try to figure it out...

This has by far been the must frustrating part of my several years of working in WPF.

update: I discovered today that just including an image in a canvas can cause it to also become rasterized. Not consistently, but sometimes. Might be tied to size, or maybe whether it is cropped, etc. Argh.

I'm often printing to PDF files, but I've found pretty much the same behavior between the adobe acrobat printer and other physical printers.

like image 726
Brady Moritz Avatar asked Jun 09 '11 00:06

Brady Moritz


1 Answers

I've been struggling with this issue for a while as well. This week I started researching the problem again and begun to write a small test application to isolate the problem. I was able to trigger the rasterization with just a few drawing operations. Four rectangles, a ellipse and a line to be exact.

static void Main(string[] args)
{
    var printers = new LocalPrintServer().GetPrintQueues(new[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections });
    PrintQueue defaultPrinter = LocalPrintServer.GetDefaultPrintQueue();
    PrintQueue printerToUse = printers.FirstOrDefault(p => p.Name.Contains("PDFCreator")) ?? defaultPrinter; // Use PDFCreator if available.
    PrintTicket ticket = printerToUse.DefaultPrintTicket;
    XpsDocumentWriter writer = PrintQueue.CreateXpsDocumentWriter(printerToUse);
    writer.Write(CreateVisual(), ticket);
}

private static Visual CreateVisual()
{
    var visual = new DrawingVisual();
    using (DrawingContext dc = visual.RenderOpen())
    {
        var pen = new Pen(Brushes.Black, 3);
        var opacityBrush = new SolidColorBrush { Color = Colors.Violet, Opacity = 0.7 };
        dc.PushClip(new RectangleGeometry(new Rect(20, 20, 150, 150)));
        dc.DrawLine(pen, new Point(0, 0), new Point(200, 300));
        dc.DrawEllipse(new SolidColorBrush(Colors.LightGreen), pen, new Point(50, 80), 50, 70);
        dc.DrawRectangle(new SolidColorBrush(Colors.LightBlue), pen, new Rect(10, 100, 100, 100));
        dc.DrawRectangle(new SolidColorBrush(Colors.LightPink), pen, new Rect(40, 120, 100, 100));
        dc.DrawRectangle(new SolidColorBrush(Colors.LightGray), pen, new Rect(60, 140, 100, 100));
        dc.DrawRectangle(opacityBrush, pen, new Rect(80, 160, 100, 100));
    }

    return visual;
}

The complete test application can be downloaded from here (VS 2010 solution).

While testing I'm printing to PDFCreator, a virtual PDF printer to prevent massive paper use. But I get the same result with real physical printers. It can be hard to notice the difference on paper using this example however, real world cases can be more noticeable (pic1, pic2).

Here is a screenshot of the result: wpf printing rasterization testapp result When you zoom in the PDF you see that the rectangles and ellipse is no longer in vector format and become blurry.


Conditions for rasterization

It seems very hard to define. I share the same experience as boomhauer that opacity and clipping seems to trigger rasterization quite frequently. And my example indeed includes both of those (kind of used those on purpose when trying to trigger rasterization so). Not to say that any of those need to be present for rasterization to occur.

It make sense that opacity could cause rasterization, but some other subtle changes that you would think to be unrelated to the issue can actually "prevent" rasterization to occur. Like changing the pen thickness in my example (screenshot). Other changes that somehow removes the condition for rasterization is changing the order of the drawing operations, removing any of the operations, and of course removing opacity or the clipping.

Workaround

I have found that generating a XPS file and printing it from Microsoft XPS Viewer will actually result in a raster free output even if exactly the same drawing and printer is used.

private static void GenerateXps()
{
    var xpsDoc = new XpsDocument("wpf_printing_raster_test.xps", FileAccess.ReadWrite);
    XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(xpsDoc);
    writer.Write(CreateVisual());
    xpsDoc.Close();
}

Screenshot here.

So instead of printing directly from your code you could generate a XPS och then programmatically instruct Microsoft XPS Viewer to print the XPS for you.

This is of course a bit of a hack and not a optimal solution. But I would be interested if anyone has a good method of forcing a print from Microsoft XPS Viewer if no fix or real solution is found (haven't tried it myself yet).

I'd also be interested to know if someone still experience rasterized printouts even when printing from Microsoft XPS Viewer.

As a long shot I tried to load the XPS-file in my test application and print it (code). But that didn't work, still got rasterized printout.

Solution?

I don't think this is a printer driver issue. When rasterization occurs, it occurs on all printers with no exception. I've tried 4-5 different printers, from a $100 HP 1020 to a $6000 Konica Minolta C360 and a few virtual printers.

The workaround also indicates that Microsoft XPS Viewer send something different to the printer driver then a direct WPF print does.

We should really try to make Microsoft take a look at this, it was filed as a bug back in 2009 but nothing has happened. Hopefully a small concise code example to reproduce the problem will help.

like image 124
salle55 Avatar answered Oct 22 '22 04:10

salle55