none
SSRS 2008 DPI Confusion?

    Question

  • I have a report deployed to an SSRS 2005 server and to an SSRS 2008 server. I have an application that uses the ReportExecution2005 web service to load and render the report as an EMF image and then prints the returned streams as pages.

    If I point my application at the 2005 server all works fine. If I point my application at the 2008 server the printed output prints too large: the fonts are too big, the margins are too big, etc.

    The device info string I’m using just specifies creating an EMF file:

            deviceInfo = "<DeviceInfo><OutputFormat>EMF</OutputFormat></DeviceInfo>";

     

    Here is the code I was using to print the rendered streams:

            private void printDocument_PrintPage(object sender, PrintPageEventArgs e)

            {

                using (MemoryStream stream = new MemoryStream(_renderedReport.Pages[_currentPage]))

                {

                    using (Metafile page = new Metafile(stream))

                    {

                        e.Graphics.DrawImage(page, 0, 0, page.Width, page.Height);

                    }

                }

     

                e.HasMorePages = ++_currentPage < _renderedReport.Pages.Count;

            }

     

    By comparing the page.Width and page.Height values from the 2005 and 2008 returned streams I determined that if I reduced the page width and height for returned streams by a factor of 3.13 then the report prints correctly when rendered on the SSRS 2008 instance:

            private void printDocument_PrintPage(object sender, PrintPageEventArgs e)

            {

                using (MemoryStream stream = new MemoryStream(_renderedReport.Pages[_currentPage]))

                {

                    using (Metafile page = new Metafile(stream))

                    {

                        e.Graphics.DrawImage(page, 0, 0, Convert.ToInt32(page.Width/3.13), Convert.ToInt32(page.Height/3.13));

                    }

                }

     

                e.HasMorePages = ++_currentPage < _renderedReport.Pages.Count;

            }

     

    I find it very interesting that the ratio of 300dpi to 96dpi is 3.13 : 1. So it appears the image is being generated at 300dpi but when printed there’s an assumption that the image was generated at 96dpi. This is clearly a difference between SSRS 2005 and SSRS2008 but I can’t find anything that points me to what the difference is and how to accommodate it. I don’t think I can just build in the scaling factor since I can’t guarantee to which SSRS version the application will be pointing.

    What really is going on here, and what can I do about it?

     

    Thanks,

    MIke

     

    Friday, July 24, 2009 11:09 PM

Answers

  • On one server the following device info string fixes this problem:

    string

     

    deviceInfo = "<DeviceInfo><OutputFormat>emf</OutputFormat><PrintDpiX>96</PrintDpiX><PrintDpiY>96</PrintDpiY></DeviceInfo>";

    On another server this helps but the printed document is still not exactly right. The first server, now working well, is a 32-bit machine running Sql Server 2008 SP1, Developer Edition. The second server is a 64-bit machine running Sql Server 2008 SP1, Enterprise Edition (64-bit).

    When I run a report against the still bad server, the created metafiles have HorizontalResolution=101.6 and VerticalResolution=81.27999. When I run a report against the now working server the created metafiles have HorizontalResolution=81.27999 and VerticalResolution=81.27999. So it seems the trick now is to determine how to get the horizontal resolution adjusted.

    To be clear on what I'm doing here, I have a process running on a single machine that uses the ReportExecution2005 web service to run reports. If I point the process to a Sql Server 2005 instance URL, the report prints and looks great. If I point the process to a Sql Server 2008 instance URL, with no other changes, the report prints as if it has been magnified about 3 times. If I change the device info string used in the web service call to contain the PrintDpiX and PrintDpiY values listed above then the report prints and looks great. If I point the process to a difference Sql Server 2008 instance URL and include the PrintDpi<x> values then the report does not appear magnified 3 times but the print quality is poor -- the printed text is skewed somewhat and all the spacing is missing between characters.

    If you now how I can get the horizontal resolution adjusted then please let me know!

    Thanks,
    Mike

    Tuesday, September 15, 2009 10:32 PM

All replies

  • Whoops -- please see above. Should have added post instead of editing existing
    Wednesday, September 02, 2009 7:07 PM
  • On one server the following device info string fixes this problem:

    string

     

    deviceInfo = "<DeviceInfo><OutputFormat>emf</OutputFormat><PrintDpiX>96</PrintDpiX><PrintDpiY>96</PrintDpiY></DeviceInfo>";

    On another server this helps but the printed document is still not exactly right. The first server, now working well, is a 32-bit machine running Sql Server 2008 SP1, Developer Edition. The second server is a 64-bit machine running Sql Server 2008 SP1, Enterprise Edition (64-bit).

    When I run a report against the still bad server, the created metafiles have HorizontalResolution=101.6 and VerticalResolution=81.27999. When I run a report against the now working server the created metafiles have HorizontalResolution=81.27999 and VerticalResolution=81.27999. So it seems the trick now is to determine how to get the horizontal resolution adjusted.

    To be clear on what I'm doing here, I have a process running on a single machine that uses the ReportExecution2005 web service to run reports. If I point the process to a Sql Server 2005 instance URL, the report prints and looks great. If I point the process to a Sql Server 2008 instance URL, with no other changes, the report prints as if it has been magnified about 3 times. If I change the device info string used in the web service call to contain the PrintDpiX and PrintDpiY values listed above then the report prints and looks great. If I point the process to a difference Sql Server 2008 instance URL and include the PrintDpi<x> values then the report does not appear magnified 3 times but the print quality is poor -- the printed text is skewed somewhat and all the spacing is missing between characters.

    If you now how I can get the horizontal resolution adjusted then please let me know!

    Thanks,
    Mike

    Tuesday, September 15, 2009 10:32 PM
  • I am having the exact same problem.  I was glad to stumble across this post because these PrintDpiX and PrintDpiY properties aren't documented anywhere as far as I've seen.  Did you end up solving the horizontal resolution problem?  I am having the same issue and am trying to figure out how to fix.
    Friday, June 11, 2010 12:56 PM
  • I don't think I was ever clear on exactly what resolved the issue for me but here are the code bits that were changed at that time and which are now working for us.

    Use the DeviceInfo string given above.

    After calling the Render method on the web service use the following code to collect the output

          renderedReport.Pages.Add(currentPage);
    
          if (printerOutput)
          {
            foreach (var item in streamIds)
            {
              byte[] result;
              serverInfoHeader = executionClient.RenderStream(executionHeader, null, format, item, deviceInfo, out result, out encoding, out mimeType);
              renderedReport.Pages.Add(result);
            }
    
            renderedReport.NumberOfPages = streamIds.Length + 1;
          }
    

     

    where renderedReport.Pages is of type List<byte[]>.

    Use the following code to print the rendered pages in the PrintDocument.PrintPage event handler:

          using (MemoryStream stream = new MemoryStream(_renderedReport.Pages[_currentPage]))
          {
            stream.Position = 0;
            using (Metafile page = new Metafile(stream))
            {
              e.Graphics.DrawImage(page, 0, 0, page.Width, page.Height);
            }
          }
    
          e.HasMorePages = ++_currentPage < _renderedReport.Pages.Count;
    

    I suspect it was switching to the RenderStream method that was the key for us. Good luck, and please post back if you determine a definitive solution.

     

    Mike

    Friday, June 11, 2010 2:48 PM
  • Your approach is slightly different than mine so I'm having a hard time simply swapping in the RenderStream snippet.  I don't suppose you could post a more complete example?  I think the SSRS community would really appreciate it as there doesn't seem to be a working, 2008 compatable, example of this out there.  Even if yours isn't perfect, its sounds like it could serve as an excellent starting point for people to refine.

    Where I'm at right now is the entire report prints now thanks to the secret PrintDpiX and PrintDpiY settings.  (Although I don't understand why changing the dpi changes the report size... I mean, shouldn't that just be the print quality?)  I say "secret" because they are not listed here where one would expect them to be.  There is DpiX and DpiY but these seem to have no effect on my report so perhaps this is a typo Microsoft?  If so, the default seems to be 300, not 96. 

    http://msdn.microsoft.com/en-us/library/ms155373(v=SQL.105).aspx

    The only remaining problem I have at this point is my Arial font seems to be a bit squished (horizontally) and the grid lines of my report are sort of missing in some places.  Hard to explain but I'm guessing both are a result of downgrading the dpi from 300 to 96.

    Friday, June 11, 2010 6:07 PM
  • Mike, I am realizing now that the RenderStream method you are proposing I use won't even effect solving my current issue because the report I'm working with currently is only one page and therefor the code will never even get to where you are suggesting I use RenderStream.  I'm curious what font you're using and if you see a difference between the report when printed from ReportManager compared to using the Web Service approach.  My report prints nicely from ReportManager but with the web service it does not look perfect.

    Friday, June 11, 2010 6:30 PM
  • Just came across this while searching for a solution...  Might be my problem...

    https://connect.microsoft.com/SQLServer/feedback/details/482312/ssrs-report-font-rendering-issue?wa=wsignin1.0#

    Conveniently, it has not been resolved yet however.

    Friday, June 11, 2010 7:11 PM
  • I just posted about basically the same issue .

    For what it's worth, you can check the horizontal and vertical dpi of a Bitmap or Image with .HorizontalResolution and .VerticalResolution.

    My reports are also resulting in oversized images. Also, probably because I convert the images to one-bit before saving, they are losing entire rows of pixels, so as the text goes down the page each next line has fewer and fewer pixel rows until it jumps back up to full size and does it over again. It has to be some kind of moiré side effect of the mismatch in resolutions, as you discovered?

    Where did you learn the PrintDpi DeviceInfo setting? It's not in the official documentation. And the official documentation on is almost exactly the same for 2005 and 2008.

     

     

     

    Saturday, June 12, 2010 2:06 AM
  • Note: I just found out that SSRS 2008 has a problem with Dpi values that are not multiples of 8. As a best guess, internally it must use a multiple of 8 then do a point-sample "stretch" of the grid to yield the final image. This caused the moiré effect I was getting that completely dropped entire rows of pixels.

     

    Wednesday, June 16, 2010 12:08 AM
  • I've been using values of 96 for PrintDpiY and PrintDpiX as Mike is above.  This corrects the zooming effect but produces another problem... the font gets squished.  I've been researching this with another developer who is having the same problem.  So far we know the problem does not go away with SQL 2008 R2 and the lack of spacing between letters, (squishing), sometimes is only noticeable on certain parts of your report.  In the other developers report we had to scroll down to the end of the report page to see the squishing even though there were other words within the same report column that "looked" ok.  My report only spits out 2 rows of data currently but the squishing can be seen in many places on it.

    I wish someone from Microsoft would take a look at this and if not suggest a workaround, give us an example of the "right" way to accomplish what we are trying to do... programatically print a SSRS report using SSRS web service(s).  Jim Chen clued us into the undocumented PrintDpiY & PrintDpiX commands, maybe he can be of further assistance?  I have a feeling the approach we are using was fine with SSRS2005 before the report rendered at 300dpi by dafault but now we may be needing to do something differently.  Intersting to note that 300 is not a multiple of 8.

    Thursday, June 24, 2010 1:02 PM
  • I've been having the corrupt text and invalid size problem in a local C# application ever since upgrading from to the latest Report Viewer that is part of the VS2010 install.

    Spelunking around the code with Reflector leads me to conclude:

    1. For the Image/EMF target, PrintDpiX/Y completely overrides the documented DpiX/Y and whatever value is specified here will be used to measure and layout everything except for any images.

    2. Images are dealt with by using whatever DPI is currently set for the given interative session - e.g. 96dpi or 120dpi

    3. The internal code that generates the Metafile relies on retrieving the real screen size and width, something that older monitors didn't support and that is not supported during a remote desktop or terminal services session

    (Some further discussion about this is here: http://stackoverflow.com/questions/1527867/specifying-dpi-of-a-gdi-device-context/3301368)

    4. The EMF stream generated relies directly on whatever DPI is currently set for the given interactive session (just like point 2)

    For those who want to take a look, use Reflector to examine the CalculateMetafileRectangle internal routine and notice now the GetDeviceCaps(hdc, x) lines return a default of 320/240 when using remote desktop for e.g. But because the resolution is correct, the net result is non-square pixels depending on whether your precise resolution is of the ratio 320/240 (1:33) or not.

    When this happens, you will clearly see corrupt overlapping and badly laid out text - but oddly any images (e.g. the MSChart control) and text within them is fine.

    This may explain why on the server if you restart SSRS from within a console that has a resolution ratio of 1.33 like 1024x768 (thereby matching the 320/240 default size by ratio) the issue is resolved. However, I've only been using the local ReportViewer control so perhaps there's more to it on the server.

    My issues with corrupt text, bad layout and incorrect sizing are now resolved:

    I use a device info string that sets PrintDpiX/Y to DefaultPageSettings.PrinterResolution.X/Y to match the output device.

    In the print callback, use the Metafile(Stream stream) constructor only - not the other ones. Then get the header (mfh) and apply a Graphics.ScaleTransform(mfh.DpiX / PrintDpiX, mfh.DpiY /PrintDpiY).

    It is then possible to simply use Graphics.DrawImageUnscaled(mf, new Point(0,0)) and everything will come out as expected.

    Hope this helps someone out there - I will added to the connect bug as well since these problems seem only to be here because Microsoft chose to generate EMF on the screen instead of directly to the printer context.

    Wednesday, July 21, 2010 4:36 PM
  • This sounds like the solution I've been looking for.  Any chance you could post some code examples of what you're describing you did to resolve the issue?  Metafiles and printer resolutions are not things I normally deal with so any examples would be greatly appreciated! 
    Wednesday, July 21, 2010 5:15 PM
  • I have post a CodeProject article which should be available for viewing soon:

    http://www.codeproject.com/KB/printing/ssrscustomprinting.aspx

     

    Thursday, July 22, 2010 2:22 PM
  • I also have noticed that the Metafile created from the Stream is huge (2500X2500 @ 81DPI). It's only been the second day of trying to get a printing solution going but here is what I'm doing to send a 6"X4" RDL to the printer:

    1.  rex.Render() to get the pages.

    2.  creating Metafile[] from the stream

    3.  Setting the printer paper size to Custom 6x4; taking into consideration Landscape or not. So sometimes 6 is the Height and sometimes 6 is the Width.

    printerSettings.DefaultPageSettings.PaperSize=_isLandscape ? 
                    new PaperSize("Custom", (int)(_stockHeight * 100), (int)(_stockWidth * 100)) :    
                    new PaperSize("Custom", (int)(_stockWidth * 100), (int)(_stockHeight * 100));

    4.  Graphics.EnumerateMetafile() to a 600x400 rectangle.

    int width = Convert.ToInt16(_stockWidth * 100);
            int height = Convert.ToInt16( _stockHeight * 100);
            Point[] points = new Point[3] { new Point(0, 0), new Point(width, 0), new Point(0, height) };
    
            _delegate = new Graphics.EnumerateMetafileProc(MetafileCallback);

    Everything seems to come out kosher so far.

    But I will be trying some of the code inlcuded in the Codeproject article.

    Thanks.


    Thursday, March 24, 2011 11:33 PM
  • This is old so I'm assuming you have found the solution, but since this forum was a top google search result for me, but does not have the true resolution, I want to add it.

    If this is the same issue I found a comment on SQL Server Central a MS developer posted a hotfix in May 2013 -

    sqlservercentral.com/blogs/juggling_with_sql/2011/12/02/workarounds-for-ssrs-2008-font-rendering-issue/

    Thank you for reporting this issue.  This is a known problem and it took a long time for the Reporting Services and Dynamics NAV developers to investigate and dissect the root cause to a Windows Remote Desktop Protocol issue. 

    There are 2 solutions available:

    1. Upgrade the VB2010 host machine to Windows 8 or Windows Server 2012.
    2. Install the Windows Remote Desktop hotfix from
    support.microsoft.com/kb
    /2768741
    for Windows 7 or Windows Server 2008R2 OS.

    Thank you,
    Jing Tong
    Reporting Services developer, Microsoft

    (it wont let me post the links because I'm not verified... but its just a KB. put the second line in front of the first obviously for the hotfix)

    Tuesday, February 18, 2014 2:06 AM