Wpf: Making image display pixel perfect at original size - wpf

I have an image that is 24x24. If i do not enter width and height in xaml and set Stretch="None" my 24x24 will size up to 32x32. Shouldn't 'no stretch' mean that the image displays at 24x24?
If i forcibly set the image to 24x24 then i get extra pixels that are not there in the original image.
I would like the image to be displayed at 100% size/scale with "pixel perfect"/"point filtering" rendering.
I read on a related question that something about some images having 96 DPI and some 72 which can cause weird behavior. I tried checking the DPI of my image following a tutorial, but there is no DPI info in the place the tutorial said (at the red line):
Either way, even if i fix so the image DPI is the same as my screen DPI (dont know how to check that either) wont't there be a problem on other people's screens? I don't want the image to be pixel perfect on only 96 DPI screens. I want it to be pixel perfect always, i always want 1 pixel of the image to correspond to 1 pixel in the application/on-screen.
Is this impossible to achieve in WPF? If it is, how can i at least make it so the awkward extra pixels are "uniform" (look at the image in the middle, it has extra pixels on the width but not height) and so that all images scale the same way (depending on where in the window the image is placed the extra pixels are in different places, i would like every instance of the same image to look the same).

In order to size an Image element to the PixelWidth and PixelHeight of its Source image, you may bind its Width and Height like shown below.
Also set RenderOptions.BitmapScalingMode to NearestNeighbor to avoid pixel interpolation.
<Image ...
Width="{Binding Source.PixelWidth, RelativeSource={RelativeSource Self}}"
Height="{Binding Source.PixelHeight, RelativeSource={RelativeSource Self}}"
RenderOptions.BitmapScalingMode="NearestNeighbor"/>

Related

[XAML-WP8.1]Grid View background image clip to bounds

I'm new on Windows development and more in Windows Phone Development.
I'm trying to create a grid view composed of three cell.
Each grid view are composed of one image (for the background) and a textblock.
My background image is a cloud image and I want the first image partialy hidden by the second one and the second one partially hidden by the third one.
I tried to play with the margin of the cell for the y part, that's works but my cloud image doesn't make the entire width of my cell. So I tried the "UnifirmToFill" option but my images are cropped...
On iOS development in this case we can use the magic property "ClipToBounds", everywhere I saw the answer "use the clip to bounds property" but apparently this property is a legend or Visual Studio lie me...
Do you have an idea to resolve my problem ?
Thank you in advance!
To resume:
If I use the "uniformToFill" stretch option, my image is zoomed. It is ok for me.
But there is a way to display the cropped part? I want my image zoomed and displayed out the cell view.
In XAML there are four possible Stretch options:
None
The image is shown in it's original size. If its larger than the parent element, it'll only show the top left portion of the image that fits inside. If the image is smaller than the parent element, then it's shown in it's entirety.
Fill
The image is resized to fill the parent element. If the aspect ratios are different, then the image will be stretched to fit the parent. This will distort the image.
Uniform
The image will be scaled up as large as it can be, while still being completely inside of the parent. Unlike Fill which will stretch the image to make it fit perfectly, Uniform will keep the aspect ratio of the image and stop scaling when it reaches the bounds of the parent.
UniformToFill
This is the bastard child of the previous two. It will scale the image, while keeping the aspect ratio, until it fills the parent element. This means that some parts of the image will be clipped if the aspect ratios are different.
For more information on the Stretch enumeration, hit it up on MSDN
UPDATE
If you want to show the image outside of the bounds of the parent you could do something like this:
<Grid Width="100" Height="50">
<Grid.Clip>
<RectangleGeometry Rect="0 0 100 50"/>
</Grid.Clip>
</Grid>
This was suggested here on SO

Get padding caused by stretch value Uniform

A WPF UI element has defined a width and height, the background is set to an image brush and pointed the image source to some random images on run-time. The stretch property is not set, hence I assume it is the default value "Fill" that comes into play. Since control size and image size are different, in run-time, the background image brush is filled with some aspect ratio, i.e with a padding (visually) inside the control. Is there a way to get this padded values?
Sample code :
<Grid Width="2000" Height="2000">
<ListBox>
<ListBox.Background>
<ImageBrush ImageSource="{Binding Source={x:Static local:MyModel.Instance},Path=ImageSource,Converter={StaticResource pathImageConverter}}" />
</ListBox.Background>
</ListBox>
</Grid>
Instead of image brush if I use a color, it fills the entire area.But if I use an image say 5000 * 4000 dimension, it stretches somewhat to fill inside the space (without skewing and cropping). That is not the real padding, visually we feel there is a padding from the list box boundaries and image boundaries. Let me try to get a snapshot of this.
There are multiple tools to get those values, and where they are assigned when running the application:
XAMLSpy
Snoop
And probably more, but these are the ones I use when encountering a problem like yours.
There is no API to get those values, I'm afraid you need to do the calculations yourself. Let me elaborate...
As indicated in the comments, the ImageBrush is not causing your padding. The brush will simply paint the area it gets. Of course, depending on the mode of the ImageBrush, it won't paint the entire area, but only a portion. Changing the brush to a SolidColorBrush will show you the entire area the brush will get. That should be identical to the area the image brush will fill, if it's put in... well, Fill mode.
However, I highly doubt it's the brush, but rather the ControlTemplate of the ListBox. If you're running in the Aero theme, by default, the template starts with a Border, which has its Background property template binded back to the ListBox, and it does the same with the BorderThickness (and to make things worse, it also has a fixed padding of 1, however, the background is drawn on top of that).
So to calculate the "padding" of the brush, you need to do the same as Border does: BorderThickness + Padding.
However, if you're running in a different theme, or if your controls have been restyled, then your control templates might be different, and the calculation might be different...

How can I create an opacity mask in wpf that doesn't scale?

Ok, I've created a PNG-24 with transparency. It's basically a grayscale image that uses 'colors' in between black and transparent instead of black and white. I did this so I can use this as the Opacity Mask of a colored rectangle, thus rendering the image in whatever color I want using only a single graphic.
However, for the life of me, I can't get WPF to stop anti-aliasing the da*n image!!
I've set 'SnapesToDevicePixels' on the rectangle to which the brush is applied... I've set the ImageBrush's Scale to 'None'... I've set its ViewPort and the ViewBox to absolute units and sized them exactly to the source image. But no matter what I try, WPF still insists on trying to smooth things out! This is VERY frustrating!!!
So... anyone know how to use an image as an opacity mask but not lose the pixel-precise drawing that we have done? I just want WPF to render the damn thing as we drew it, period!
I have tried to reproduce your problem. Simply like this:
<Rectangle Width="200" Height="200" Fill="Red">
<Rectangle.OpacityMask>
<ImageBrush ImageSource="/mask.png"/>
</Rectangle.OpacityMask>
</Rectangle>
mask.png contains a simple diagonal mask, like that half of rectange is visible and other half is 100% transparent.
And recrangle is rendering pixel perfect (and aliased, as you want).
I think, that you may a DPI setting, that is not native to your monitor, and WPF just can`t render images correctly.
GOT IT! It's a layout issue that for some reason, there's no easy way to change. However, there's a value you can set called UseLayoutRounding that fixes it. I just set it at the root level (for this fauxample, a grid...)
<Grid UseLayoutRounding="True">
....
</Grid>
...and BAM! Works like a charm! "Sort of" like a 'SnapsToDevicePixels' but for positioning of elements (i.e. it rounds all layout-related values like left, width, etc. whereas SnapsToDevicePixels snaps the layout to the on-screen pixels when rendering.)
M

resolution in WPF

In my applcaiton,i make Grid of size Grid Width="1300.441" Height="80",
Its working fien in this resolution.But when i changed my resolution to 1152 width,quater of application get out of the desktop.
How can i avoid that?
I want to display full page in all resolution.
Pls help me
In WPF, the pixel size is 1/96 inch. There's no other resolution. It seems that your content is 13.54626 inches wide. My guess is that this is an XPS document or a raster or something? In this case, there is no way to display the whole thing in 1152 pixels at 100% without cropping and needing to scroll.
You can place your grid inside a ViewBox element, it will scale everything down to whatever resolution you need.
<ViewBox Width="1000">
<Grid Width="1300.441">
...
</Grid>
</ViewBox>

WPF: How do I create a background that repeats horizontally without scaling?

I would like to create a background for my window which is an image that I want repeated horizontally. So far I've tried with the ImageBrush, but this option repeats the image horizontally and vertically. Also, I don't want it to scale when user resize the window, as it makes the image look funny.
If what you want to do is tile an image horizontally as you would in CSS with the simple one liner "background-repeat: repeat-x" then after some (!) trial and error what you need in XAML is this:
<ImageBrush ImageSource="Images/my-background-image.png"
TileMode="FlipY"
Stretch="Uniform"
AlignmentY="Top"
Viewport="0,0,90,3000"
ViewportUnits="Absolute" />
Where the last 2 values on the Viewport attribute are the width of your image in pixels and then a very large number that is higher than your viewport height so that the image is not repeated in the Y direction within that height.

Resources