Search code examples
c#background-imagerdlcexport-to-pdfhigh-resolution

RDLC export to pdf with high resolution background image


Recently, for one of my current clients, I had to create a RDLC Report. More specifically an invoice on a digital stationary paper. (see “stationary_paper_example.png” 1).

Problems

When a high-resolution image is set as report background the scaling of the image is completely off. See “stationary_paper_falsely_scaled.png” 2

Previous workaround

As the reports with digital stationary paper were introduced just a project before, we got it working by setting an image-element in the background (z-index) and set a high-resolution image. But this time we got some new implicit restrictions.

Implicit restrictions

  1. Current page number

The client wanted to show the current page number above the invoice articles table (see "stationary_paper_page_number.png" 3). You can get this information only in the header or footer section of the report

  1. Image-Element

The image element I set as “report background” can’t be placed inside header, body and footer of the report (see "stationary_paper_image_as_background.png" 4)

So either the client would change their report layout or I get this thing going.

New problems

  1. Setting high-resolution image as background

As already mentioned, when you simply set a high-resolution image as background you will (probably) experience a “scaling” bug as seen in “stationary_paper_falsely_scaled.png” 2. The image is rendered almost completely out of scope.

  1. Setting low-resolution image as background

If you set a low-res image as background you will (probably) see a kind of fuzzy background as seen in “stationary_paper_low_res.png” 5. This will also happen when you export this solution with a “pdf printer” such as “Microsoft print to pdf”.


Solution

  • After some digging and testing I finally got it working (at least imo)

    Solution

    1. Setting the background of the report

    I set the background of the report as following:

    Source:   External
    Value:    ="file:" + Parameters!PathToStationeryPaper.Value
    MIMEType: image/jpeg
    
    1. Check usage of stationary paper As not all reports of the whole software solution use stationary paper, I just check the reports parameter.
    private bool reportUsesStationaryPaper()
    {
       var result = false;
       foreach (var param in reportViewer1.LocalReport.GetParameters())
       {
          if (param.Name.Equals("UsesStationeryPaper"))
          {
             result = true;
             break;
          }
       }
       return result;
    }
    
    1. Show low-res image on preview In the event “reportviewer_RenderingBegin” I set a low-resolution image to improve performance. You can also set a version of the stationary paper with a watermark here
    private void reportViewer1_RenderingBegin(object sender, CancelEventArgs e)
    {
       if (reportUsesStationaryPaper())
       {
          //Reset report to low-resolution mode for screen rendering
          var pathToStationaryPaper = "[…]/stationary_lowres.png";
          reportViewer1.LocalReport.SetParameters(new Microsoft.Reporting.WinForms.ReportParameter("PathToStationeryPaper", pathToStationaryPaper));
       }
    }
    
    1. Add device info In the event “reportviewer_ReportExport” I set the path to a high-resolution image and additionally add device infos (“ReportExportEventArgs.DeviceInfo”) to increase the resolution as the export functionality seems to be able to work with higher quality.
    private void reportViewer1_ReportExport(object sender, ReportExportEventArgs e)
    {
       if (reportUsesStationaryPaper())
       {
          //Reset report to high-resolution mode for printing
          string deviceInfo =
                   @"<DeviceInfo>         
                      <DpiX>300</DpiX>
                      <DpiY>300</DpiY>
                     </DeviceInfo>";
          e.DeviceInfo = deviceInfo; 
          var pathToStationaryPaper = "[…]/stationary_highres.png";
          reportViewer1.LocalReport.SetParameters(new Microsoft.Reporting.WinForms.ReportParameter("PathToStationeryPaper", pathToStationaryPaper));
       }
    }
    
    1. [OPT] Show export button If you don’t need a separate button to call the export method of the reportviewer element you can just enable it via UI Designer or code

    Result

    1. Preview

    Higher performance as a lower resolution can be set and, if you want, a “preview” watermark 1

    1. Print on a „pdf printer“ (here „Microsoft print to pdf”)

    Still fuzzy as we can’t set the resolution in “reportviewer_PrintingBegin” or “reportviewer_Print”

    1. Export with Reportviewer

    When exported via export of the reportviewer control you will now get a beautiful high-resolution image as background of the report 😊

    Further consequences

    As the users of my client were used to “print to pdf” the client now either needs to train the users to use the reportviewer export button or a separate button “Export to PDF” will be introduced in the view.