I am developing a software using WPF, when I draw a simple shape and rotate it for around 45', I get jagged edges. Antialiasing is not a solution, because I get blurry edges and on diagonals it simply does not work like I want. UseLayoutRounding and SnapsToDevicePixels does not help, because I think, it has something to do with line drawing algorithm. I tried the same with WinForms and I get better results, but I want to stick to WPF, because I am using some features of it already.
Code looks something like that:
Create a shape -> Shape = new Polygon();
Add shape to canvas -> DrawingLayer.Children.Add(Shape);
Rotate the shape -> RotateTransform rt = new RotateTransform(Angle, Centroid.X, Centroid.Y);
Update shape -> Shape.RenderTransform = rt;
WPF rotation:
WinForms rotation:
WPF rotation with Antialiasing:
It's hard to comment without seeing your actual code/markup, but with this markup...
<Window x:Class="StackOverflow.Question54926730"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="StackOverflow 54926730" SizeToContent="WidthAndHeight">
<Canvas Height="400" Width="400">
<Polygon Canvas.Left="100" Canvas.Top="100" Stroke="Black" StrokeThickness="1">
<Polygon.Points>
<Point X="0" Y="0" />
<Point X="200" Y="0" />
<Point X="200" Y="200" />
<Point X="0" Y="200" />
</Polygon.Points>
<Polygon.RenderTransform>
<RotateTransform Angle="45" CenterX="100" CenterY="100" />
</Polygon.RenderTransform>
</Polygon>
</Canvas>
</Window>
...the result looks good to me...
I notice you say you are rotating by "around" 45 degrees and, again, without seeing any code it's not clear what that means (44.95 degrees? 40 degrees?) but at both of those two angles the result looks good. Here's the not-so-round angle of 41.3579 degrees:
Only at multiples of 90 degrees ± 10 do I start to see a pronounced staircase effect. Here's 9 degrees:
Relevant version numbers:
64-bit Windows 10 Pro 1809 v17763.437
Visual Studio Community 2019 v16.0.1
.NET Framework v4.7.2
PresentationCore.dll v4.7.3362.0
PresentationFramework.dll v4.7.3362.0
Related
In Windows Presentation Foundation, I can't seem to find a way of how to cut an image based on the shape of another image.
E.g. I'd like to display someone's photo in the shape of a heart.
There are answers like this one which crop an image into a rectangle or like this one which draw a radius to clip the image into a circle.
But is cropping really the only way?
Can WPF overlay the image on top of a shape and have the image be cut based on the shape dimensions?
The code that I have so far does the inverse of what I'm trying to do. What I have so far uses an overlay layer as a mask to cover the image:
<Image
Name="HeartOverlay"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Panel.ZIndex="2"
/>
<Canvas
Name="Canvas"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Image
Name="Image"
Stretch="Uniform"
Panel.ZIndex="1"
/>
/>
HeartOverlay.Source = new Bitmap(#"C:\heart.png");
Image.Source = new Bitmap(#"C:\image.png");
The problem here is that overlay is merged together with the image and saving/printing the image also shows the overlay.
See image below as an example. Note the white borders, which are especially evident when viewing the image in something like the Mac Preview app. I'm looking to save/print the image without the white borders.
Appreciate any pointers!
You could simply fill a Path with a heart-shaped Geometry with an ImageBrush:
<Path Width="100" Height="150" Stretch="Uniform"
Data="M1,2 L0,1 A0.5,0.5 1 1 1 1,0 A0.5,0.5 1 1 1 2,1 Z">
<Path.Fill>
<ImageBrush ImageSource="C:\image.png"/>
</Path.Fill>
</Path>
I've downloaded the sample here: https://code.msdn.microsoft.com/windowsapps/Media-Capture-Sample-adf87622
I have compiled and everything runs perfectly. However I want to rotate the camera so that it is in portrait mode. After consulting the documentation I found the following code:
MediaCapture.SetPreviewRotation(VideoRotation.Clockwise270Degrees)
and
MediaCapture.SetRecordRotation(VideoRotation.Clockwise270Degrees).
I have added the two lines above and it has indeed rotated the output which is exactly what I am after. The only issue is the preview now has an orange and blue distortion running through it. The Recording one worked perfectly.
Any ideas?
I ended up using the following code for the preview:
<Canvas x:Name="previewCanvas1" Width="576" Height="720" Background="Gray">
<CaptureElement x:Name="previewElement1" Width="720" Height="576" RenderTransformOrigin=".5,.5" >
<CaptureElement.RenderTransform>
<RotateTransform Angle="270" CenterX="0.5" CenterY="0.5" />
</CaptureElement.RenderTransform>
</CaptureElement>
</Canvas>
When I run this code in WPF it gives me 1/4 of a circle. When removing the ClipToBounds tag, i get my whole circle.
1. Why is it clipping before rendering?
2. How to i fix that, while keeping clipping?
<Canvas ClipToBounds="True">
<Ellipse Canvas.Left="-10"
Canvas.Top="-10"
Width="20"
Height="20"
Fill="LightSeaGreen"/>
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="4.8"
ScaleY="4.8"
CenterX="0"
CenterY="0"/>
<TranslateTransform X="48"
Y="48"/>
</TransformGroup>
</Canvas.RenderTransform>
</Canvas>
Why is it clipping before rendering?
It's not.
As you can see from here:
Your Ellipse is rendered perfectly. The ClipToBounds="True" is what ruins is as you can see from your Canvas:
How to i fix that, while keeping clipping?
This is quite a broad question. Your problem comes from the fact you are putting your Ellipse outside the Canvas (Canvas.Left="-10" Canvas.Top="-10") and then you clip it. Explain what is your goal and I can try to help you out.
This behaviour is by design. The authors of the textbook (Computer Graphics: Principles and Practice - Third Edition) have confusingly introduced ClipToBounds in a way that makes it seem like it is a part of the examples that follow in the book. In fact, they are not using ClipToBounds="True". You can verify that by downloading their lab package from http://sklardevelopment.com/graftext/ChapWPF2D/ .
To illustrate, here is the actual source code for one of their examples:
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="ClockCanvas" >
<Ellipse
Width="20.0" Height="20.0"
Canvas.Left="-10.0" Canvas.Top="-10.0"
Fill="lightgray"/>
</Canvas>
Note that there is no ClipToBounds="True" on the canvas.
I'm new to WPF and would like to know what to use to get a shape like the image below:
I also wonder if it is possible that this design may follow the form's dimensions, ie, if the form is resized, the design is too.
In advance, thank you!
Windows 8.1, Visual Studio 2013, C#, WPF Application
To draw the shape you can use a Path. A path can draw any type of shape specified by its Data property. The Fill and Stroke defines the colors of the shape.
To "follow the form's dimensions" you can set the Stretch property to "Uniform". The shape will then scale accordingly to the window.
Here is an example:
<Window x:Class="WpfApplication57.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="800">
<Grid>
<Path Data="F1 M 0 0 800 0 800 30 200 30 150 60 0 60 0 0"
Fill="Yellow"
Stretch="Uniform"
Stroke="Black"
StrokeThickness="4"
VerticalAlignment="Top" />
</Grid>
</Window>
Happy coding :-)
Best regards,
Casper Korshøj
You can use a Path to get that shape and you can even use Blend to draw any shape, if you want just shapes.
<Path Data="M200.125,197.375 L200.125,190.25 277.375,190.25 277.375,191.5 277.375,192.375 220,192.375 217.25,195.125 214.5625,197.8125 z" HorizontalAlignment="Left" Height="8.562" Margin="200.125,190.25,0,0" Stretch="Fill" Stroke="Black" VerticalAlignment="Top" Width="78.25" Fill="#FFF0F00C"/>
That should give you the Shape you wanted and in the comment mention above use that link
http://msdn.microsoft.com/en-us/library/ms747393%28v=vs.110%29.aspx
I am in the following situation: designing an interactive flow-chart GUI. I stuck with animating a scale down animation of the flow-chart. Composed elements of the flow-chart are minimized, but they keep being active.
I have something like this:
<Canvas Canvas.Left="55" Canvas.Top="720" Height="100" Width="500" Tag="stepDown">
<Line Stroke="#99CCFF" StrokeThickness="8" X1="0" X2="720" Y1="10" Y2="10">
<Polygon Stroke="Black" StrokeThickness="2" Points="0,30 40,0 40,60" Canvas.Left="-20" Canvas.Top="-20" Fill="#99CCFF"></Polygon>
<Polygon Stroke="Black" StrokeThickness="2" Points="0,0 0,60 40,30" Canvas.Left="720" Canvas.Top="-20" Fill="#99CCFF"></Polygon>
<Image Canvas.Left="-50" Canvas.Top="-70" Height="53" Name="image32" Source="img/outlet.png" Stretch="Fill" Width="30" Tag="relative" />
</Canvas>
And I would like to shift the whole canvas and its elements to the left - no problem with Translate Transform. Furthermore I would like to scale down only the Line, no problem with Scale Transform.
But (!) at the same time, I want that the Polygons stick to the two line endings of the line. When scaling down only the line, the Polygons, at least one, floats away.
I don't know how to dock these elements or define them at a relative basis. It works fine with a scale down on the whole Canvas, but this changes the Polygon and Images as well.
In order to me you have to define hanchors points, as attached properties. Even define a behavior that track these points accordingly to poligon placements. Then you can bind these property to the line start/end point. In this way line should stay gripped to the polygons. But I did'nt try, is just a design idea.