locked
How do I ensure Images are drawn in a pixel-perfect way on a Canvas? RRS feed

  • Question

  • I asked this question on StackOverflow and couldn't get an answer:

    http://stackoverflow.com/questions/18926130/winrt-how-do-i-ensure-images-are-drawn-in-a-pixel-perfect-way-on-a-canvas

    Maybe someone here has a solution? I want to draw images in a pixel perfect way using XAML & C# for a Windows Store App? Is it possible. I tried may things but everything is always slightly blurry or a little bit off on high resolution screens with 140 or 180 scale factor. This is a really big problem when trying to tile images .

    Tuesday, October 8, 2013 1:52 AM

All replies

  • What does "pixel perfect" mean? 

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Tuesday, October 8, 2013 7:27 PM
    Moderator
  • If you supply correctly scaled images they should display fine.  There is guidance here: http://msdn.microsoft.com/en-us/library/windows/apps/hh465362.aspx

    Realize however pixel density comes into play too!  SVG or Drawing simple images will work great given any combination (if that is an option).


    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Tuesday, October 8, 2013 7:28 PM
    Moderator
  • Pixel perfect means that if I have a bitmap that is 100x100px I want to draw it on screen and have it rendered in a 100x100px area. I don't want it scaled up or down or the have the pixel data modified any way by the OS before it is blitted to the screen. Windows 8 seems to take the DPI of the display into account and then scales the bitmap before drawing it to the screen, I don't want that. There was something in .NET called DrawImageUnscaled that did this I think.
    Tuesday, October 8, 2013 9:48 PM
  • I tried this, the only time it works is if I supply 3 different scale images: scale-100, scale-140 and scale-180. Then it is drawn in a pixel perfect way, BUT it only works if in fact the images are exact factors of 1.4 and 1.8. For example 100x100px 140x140px and 180x180px. But what if I want an image that is 33x29px? I can't create an image that is 46.2 pixels, and if I pick 46 or 47 it won't draw correctly and gets blurred slightly by the OS.
    Tuesday, October 8, 2013 9:55 PM
  • That is absolutely correct!

    There is no magic here.  If the pixel you want to draw does not line up with a physical location on screen, what do you expect to happen?  There are lots of anti-aliasing type algorithms employed to help make this appear better (especially as you back away from the display), but you are dealing with a digital representation so there will always be some sort of distortion if you do not fall on a pixel boundary.  Drawing these lines and curves at runtime helps immensely if this is important to you.  That is a great use for SVG for example.


    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Wednesday, October 9, 2013 12:50 PM
    Moderator
  • Share your XAML for the image.  Did you try the 'Stretch="None"' attribute?

    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Wednesday, October 9, 2013 12:54 PM
    Moderator
  • Here is a link to SLN that demonstrates the problem. Please run this in a simulator with resolution that is scaleresolution 140% or 180%.

    http://sdrv.ms/17nO2k6

    The tile PNG at 100% is 77x77 and thus does not scale to an integer value at 140% or 180% since 77 * 1.4 = 107.8 and 77 * 1.8 = 138.6. So I had to make the PNG 108x108 for 140% and 139x139 for 180%.

    Notice that you will see black lines through-out the screen and the dots are blurry. This is why I want to turn off the scaling completely. I tried Stretch=None and it doesn't work.
    Wednesday, October 9, 2013 7:15 PM
  • I found this issue quite problematic as well. I'm creating custom bitmaps and drawing them at different positions on the canvas. I couldn't find a way in the XAML, but I found a way using Direct2D. When you set up your D2DContext, there's a function called SetUnitMode(). The default unit mode is "DIPS" which causes all drawing to be scaled. By switching to PIXELS mode, the system stops scaling the drawing and does everything 1:1.

    m_d2dContext->SetUnitMode(D2D1_UNIT_MODE_PIXELS);

    Sunday, October 27, 2013 7:19 PM
  • I am of the impression that this scenario is somewhat underserved in WinRT right now.  You can demonstrate the problem vividly by taking a screenshot on a high-DPI device, and then opening the screenshot in the Photos app.  It displays blurry, even though the saved image maps to the display matrix perfectly.  All blur artifacts seem to be introduced by WinRT, most likely due to unnecessary DPI roundtripping it forces upon the app.






    Friday, December 20, 2013 10:20 PM