Image in WPF getting Blurry - c#

I am developing an application in WPF using C#. I am putting Images in a WrapPanel and showing inside a Grid with one more Border and using images in Buttons also. Problem is my Image control loosing its quality. I am not able to post my image here so I am simply describing here.
I used SnapsToDevicePixels="True" for the images but still it looks blurry.
Updated:
Here I shared the Image below:

I think what Markus told is the one way to resolve your issue and try by adding one more property in it RenderOptions.EdgeMode="Aliased" for each image I mean :
<Image Source="/LoginPanel;component/Icons/icoLogin.ico"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.EdgeMode="Aliased"/>
if you still not able to fix your problem then you can refer this http://blogs.msdn.com/b/dwayneneed/archive/2007/10/05/blurry-bitmaps.aspx to create a custom Bitmap class and apply on all Images which are creating trouble for you.
You can also see this Stack Overflow Question

SnapsToDevicePixels seems not working for bitmaps.
The NearestNeighbor options actually converts the bitmap and will end up with different one to the original bitmap.
In WPF 4, a property "UseLayoutRounding" on the FrameworkElement is introduced to solve this problem.
By setting this property to True on your root element, such as Window will align children elements on the edges of pixels.
<Window UseLayoutRounding="True">...</Window>

This works for me
<Image Source="/LoginPanel;component/Icons/icoLogin.ico"
RenderOptions.BitmapScalingMode="NearestNeighbor"</Image>
Set RenderOptions.BitmapScalingMode="NearestNeighbor" for each image. Alternatively see this question here on StackOverflow.
Edit:
Here is my sample code
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="661">
<WrapPanel>
<Button VerticalAlignment="Center">
<Image Source="/WpfApplication1;component/icoChip32x32.ico"
RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
</Button>
<Button VerticalAlignment="Center">
<Image Source="/WpfApplication1;component/icoChip32x32.ico"
RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
</Button>
<Button VerticalAlignment="Center">
<Image Source="/WpfApplication1;component/Presentation-Edit.png"
RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
</Button>
<Button VerticalAlignment="Center">
<Image Source="/WpfApplication1;component/Presentation-Edit.png"
RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="None"></Image>
</Button>
</WrapPanel>
</Window>
And this is my result:

Use UseLayoutRounding="True" property on the parent element if image is used as a content. In your case it is the Button.

I ran into a blurriness issue with image backgrounds caused by scaling and the solution was much simpler than you may think. While at first I wondered if it was being scaled up to a power-of-two texture size, the scaling actually matched the ratio of System DPI (96) : Image DPI (72, which is the default for many editors). If you adjust the image to 96 DPI it should display pixel-perfect with the default Windows settings.
EDIT: Tried an image with high detail contrast and it is slightly softened.

WPF doesn't use concrete pixel values for sizes and positioning, so that it can scale well with DPI.
This can lead to a problem where it tries to use a position that doesn't correspond to a discrete on-screen pixel; some of the image pixels are rendered over multiple on-screen pixels which we see as blurring.
UseLayoutRendering=true with SnapToDevicePixels=false should solve this issue. You also need to set it at the main window level too, so that the calculations cascade down to the image level.
You can try this out by creating a simple WPF application with one window, and your images. Setting the image margin to be something silly like (10.452, 0.736, 0, 0) will lead to blurring. This goes away with UseLayoutRendering=true on the image.
If you then set the margin again in your window's constructor after InitializeComponent(), it is blurry regardless of whether you set UseLayoutRendering=true on the image, since the calculations to line up with on-screen pixels were made before you then moved the image to a location which doesn't match up with these.
I'm not entirely sure what the difference is between UseLayoutRendering and SnapToDevicePixels - I think it is just the time that the calculations are made. UseLayoutRendering seems to be preferable for images.
Stretching/squashing an image from its original size can also lead to blurring problems.

I had the same Problem, but in my case I've downloaded Icons and found out, that they all had wrong DPI too... 110,56 and 116,xx and 95,99 etc...
When i changed the DPI to 96 for all, everything was fine!

Related

WPF Scrollview Panning deceleration

So official documentation does not state any "default" values on this topic. I have tried with several values like 0.01, 0.1, 1 and I can't seem to get the effect where the ScrollView keeps scrolling after an user lifts a finger.
<ScrollViewer Margin="0,210,0,66" x:Name="AboutUsScrollViewer" PanningMode="VerticalOnly" PanningDeceleration="1" PanningRatio="2" VerticalScrollBarVisibility="Hidden" VerticalAlignment="Top">
<Image x:Name="AboutUsMainImage" Source="Resources\o nama.png"></Image>
</ScrollViewer>
I'm not sure if these are actually device independent units, if so, how do I find the value where I can see the desired effect?
Note: the image is tall enough so there is clearly a lot of room for scrolling, this is not an issue.

c# W.P.F. image show tiff (just 1 page) blurry [duplicate]

I'm using some Images in my WPF applcation.
XAML:
<Image Name="ImageOrderedList"
Source="images/OrderedList.png"
ToolTip="Ordered List"
Margin="0,0,5,5"
Width="20"
Height="20"
SnapsToDevicePixels="True"
MouseUp="Image_MouseUp"
MouseEnter="Image_MouseEnter"
MouseLeave="Image_MouseLeave" />
But, they appear fuzzy.
Why doesn't that SnapsToDevicePixels="True" line prevent this problem?
You may want to consider trying a new property available now in WPF4. Leave the RenderOptions.BitmapScalingMode to HighQuality or just don't declare it.
NearestNeighbor worked for me except it led to jaggy bitmaps when zooming in on the application. It also didn't seem to fix any glitches where icons were sizing in weird ways.
On your root element (i.e. your main window) add this property: UseLayoutRounding="True".
A property previously only available in Silverlight has now fixed all Bitmap sizing woes. :)
Rather than using SnapsToDevicePixels, I instead used RenderOptions.BitmapScalingMode and they're now nice and crisp!
XAML:
<Image Name="ImageOrderedList"
Source="images/OrderedList.png"
ToolTip="Ordered List"
Margin="0,0,5,5"
Width="20"
Height="20"
RenderOptions.BitmapScalingMode="NearestNeighbor"
MouseUp="Image_MouseUp"
MouseEnter="Image_MouseEnter"
MouseLeave="Image_MouseLeave" />
+1 for Zack Peterson
I'm using .Net 3.5 sp1 and it looks like the most simple solution for a large number of fuzzy images.
It's not a big deal to specify RenderOptions in-place, but for 3rd-party components a style in app-level resource makes sense:
<Style TargetType="{x:Type Image}">
<Setter
Property="RenderOptions.BitmapScalingMode"
Value="NearestNeighbor" />
</Style>
Worked nicely when AvalonDock started to render blurry icons.
Using the UseLayoutRounding="True" on the root Window works in many cases but I encountered a problem when using the WPF Ribbon control. My application relies on Contextual Tabs that appear according to what the user is doing and when I set the UseLayoutRounding to True, the contextual tab would not show up and the RibbonButton's image neither. Also, the application freezes for many seconds and CPU fan starts to sing.
Using RenderOptions.BitmapScalingMode="NearestNeighbor" on my image corrected the image rendering issues (fuzzy and cropped image) and is fully compatible with the Ribbon Contextual Tabs usage.
RenderOptions.BitmapScalingMode="NearestNeighbor" works well most of the time. However, occasionally you'll get graphical glitches (in my case, 4 out of 5 images showed up fine, but the fifth had a slight distortion on the right edge). I fixed it my increasing the Image control's right margin by 1.
If that still doesn't fix it, try the Bitmap class control above that EugeneZ mentions. It's a replacement for the Image control and so far it's worked pretty well for me. See http://blogs.msdn.com/dwayneneed/archive/2007/10/05/blurry-bitmaps.aspx
use UseLayoutRounding=True to the top most element in your application
Make sure you save the image in the same DPI as your WPF application is working in, some image formats have this info stored as metadata. I don't know if this solves the problem but I've hade some problems because of this where images resized to 100% got bigger or smaller than expected.
Might be something similar.
I believe this is a bug (or at least it was). Check out this Microsoft support e-mail exchange page for some ideas to fix it.
I have found that the RenderOptions.BitmapScalingMode="NearestNeighbor" does not work for me. I'm using Windows XP x32 with DirectX 9.0c. As the actual rendering for WPF is done with DirectX, this could have an effect. I do have anti-aliasing turned on for XP with the following registry entries:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Avalon.Graphics]
"MaxMultisampleType"=dword:00000004
"EnableDebugControl"=dword:00000001
However, turning aa off with these settings has no effect on the images. I think this only effects 3D Viewports.
Finally, I found that the blurring occurs with the text of TextBlocks as well as images. And the blurring only happens for some text blocks and images, not all of them.
I have found that no combination of the suggested workarounds would cure my seemingly random blurry image problem. I like many others cannot upgrade to .net 4 in order to use the UseLayoutRendering property.
What I have found to work:
Ensure your [original] image dimensions are multiples of 2. This seems to prevent some of the funky image scaling problems.
Sometimes I have also found that adjusting margins on images by a pixel or 2 can prevent the problem.
My first thought, reading the question, was you were blowing up the image too much, but that does not appear to be the case looking at the image you have of the app.
Second thought is color palette, but with black as one of the colors that is not rendering correctly, this is not as likely.
If you can fully rule out the two above, I am currently stumped.
As an experiment, you can try other graphics formats, but PNG should be fine. I will have to think it through some more to come up with a better answer.
I've tried to use the RenderOptions.BitmapScalingMode=HighQuality, seems like is causes some problems in Windows 8.1, so what i did was to run them through the tool called PngOut.exe
http://advsys.net/ken/utils.htm
Which reduces the header of the png, and also reduces the size, but without changing the image quality.
And now all my images are perfect! :-)

Automatically crop and resize an image

I Need to crop and resize an Image in my WPF application as soon as the Picture is loaded.
So, my Basic Image has a VGA size (640x480), and I Need to crop the edges (top by 18 Pixels, bottom by 36 Pixels, left by 48 Pixels, and right by 24 pixels). The new image (which is 568 x 426 pixels) Need to be refitted into the original size (640 x 480 pixels) - basically it's like a digital zoomc that we're using in photography.
I've already found some sample code (Cropping whitespace from image in C#) - this is however a Little bit too complicated since I don't Need to detect the Whitespace on the image. Is there any simple algorithm just by using XAML to do this ?
Thanks in advance.
I think that you should be able to do that by using the Viewbox Class. From the linked page: Defines a content decorator that can stretch and scale a single child to fill the available space. You literally add one to your Window and set your Image as the contents and then you can set properties to control which part of the image it displays:
<ViewBox Width="500" Height="500" Stretch="Uniform">
<Image Source="Images/SomeImage.jpg" Width="300" Height="300"
Margin="-48,-18,-36,-24" />
</ViewBox>
Experiment with the different StretchDirection values and set the Margin to negative values to crop. There are examples in the linked page, but let me know if you need more help.

How to display SkeletonStream on a DepthStream or ColorStream Kinect Wpf

I would like to know how to overlay two Image objects in Wpf. I've made two streams which output a video, one for bones and another just a normal video. Now I would like to add them together, so the skeleton would be displayed on the color video.
A part of my XAML code is
<Grid Name="layoutGrid">
<Grid Name="VideoGrid" ClipToBounds="True" Background="AliceBlue">
<Image Name="ColorImage" Width="640" Height="480"/>
<Image Name="SkeletalImage" Width="640" Height="480"/>
<Canvas Background="Transparent"/>
</Grid>
<StatusBar VerticalAlignment="Bottom" HorizontalAlignment="Center">
<Button Name="Button1" Content="Skeleton Only" Width="120"/>
</StatusBar>
</Grid>
When I do this, only the Skeletal image is displayed and if I switch the both Images then the color image is shown. It seems like Canvas background doesn't do the trick (to make the black part of skeletal image transparent)
I thought the problem was in my XAML code but it was actually at drawing the transparent background to set the render size. The background for skeleton image was black
dc.DrawRectangle(Brushes.Black, null,
new Rect(0.0, 0.0, RenderWidth, RenderHeight));
instead of transparent
dc.DrawRectangle(Brushes.Transparent, null,
new Rect(0.0, 0.0, RenderWidth, RenderHeight));
that fixed my problem.
Thanks though
I've tried overlaying Skeletal onto color or depth on a canvas, but it never worked out. Instead, when I looked at the Kinect Explorer sample application in the SDK 1.6.0, they overlay using a grid. Unfortunately, I have not learned that much yet, but they used a grid for the color and depth, and a canvas for the skeletal tracking. I can post a snippet if it helps. Good luck!
You are asking basically two different questions: 1) How to display SkeletonStream on a DepthStream, which is very easy, 2) How to display SkeletonStream on a ColorStream, which is still easy but a little more complicated.
Answer to Question 1) The XYZ Vectors of the joints in the skeletal streams are in the same coordinate system as the Depth Stream. So if you plot the Deapth Stream as a quadratic mesh using the focal length of the depth camera from the Kinect SDK, you can plot the skeleton as a line plot in the same coordinate system. The source code that implements exactly what you want to do in OpenGL is available here that will give you an idea how to implement this in wpf.
Answer to Question 2) The video camera has a different field of view from the depth camera. To display the skeleton stream to the ColorStream you need first to map the XYZ vectors of the joints in the skeletal streams to the coordinate system of the depth stream and then draw first the video frame in the background and the skeleton as a line plot on the front.
You can easily do the mapping using the U-V texture coordinates given by the Kinect SDK. See how you can get the UV here.

Changing Display color of PNG with transparency in XAML

I have some PNGs with transparency that I use for buttons in my WPF/C# application.
Right now I have two versions of each PNG, one for normal view and one for hover, each a different color. However, I would really like to just have one single PNG and maybe make everything that's not transparent white (each image is all one color, no detail other than shape.
Would it be possible to then alter the color of each using a SolidColorBrush or similar and create the Normal/Hover versions as a static resource in my XAML?
Something like this:
<Image Key="BtnMenu" Source="Images/Menu.png" Fill="ButtonNormalBrush" />
<Image Key="BtnMenuHover" Source="Images/Menu.png" Fill="ButtonHoverBrush" />
Yeah, I totally made up the "Fill" thing...
But the basic idea is that I have a ResourceDictionary that contains the color scheme that is used throughout the entire application, which makes it so that I can change any of the about 6 colors I use in the application in one place and it updates on every control that references that color... but the one place I cannot do it is those PNGs for the buttons. (Ideally in the future I'll make that ResourceDictionary something that can be loaded in at runtime to make the application have alternate "skins"..but right now the PNGs keep me from doing that).
Edit: BTW, if the solution requires a Converter or something written in code, that's totally fine.
Hmm... If you created a Grid, and put the Image inside that Grid, you could set the Background of the Grid to your fill color.
Edit: Here is some code:
<Button>
<Grid Background="SkyBlue">
<Image Source="img.png" Stretch="None" />
</Grid>
</Button>
There is a solution: http://msdn.microsoft.com/ru-ru/library/ms752364.aspx
You can simply create ImageSource with new Format-object from another ImageSource. Format object specifies color mask for an Image.
You could try to apply a ShaderEffect as the Effect on the hover image or create a markup extension which transforms your image. Another possibility would be to encapsulate such logic in a subclass of Image.

Categories

Resources