How can I wrap an image around the canvas like this? The obvious way I can think of is to duplicate the image, and offset by the width/height of the image in the opposite direction. Is there another way to achieve this?
You could fill a Rectangle with an ImageBrush with this image, and set its TileMode and Viewport properties as needed.
For example:
<Rectangle Width="128" Height="128">
<Rectangle.Fill>
<ImageBrush ImageSource="Images\Tile.png" TileMode="Tile"
ViewportUnits="Absolute" Viewport="64,64,128,128"/>
</Rectangle.Fill>
</Rectangle>
The above XAML creates the following output:
from this source image:
No. There is no other way around. You will have to draw all images. Because a control doesn't split up.
You can calculate and then generate Image boxes to show no. of images based on offset.
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 placed a PNG Image with some transparent areas on my window. It's over a Button control, now when i want to click on My Button, it has some UnClickable points because transparent space of image is over it.
Now, i want mask my image with another control like polygon or use a good way to solve my problem.
I tested following way, but it didn't fill all of the polygon area by image. It is like a rectangle image inside a polygon:
<Polygon
Points="0 50,50 60,58 50,60 50,85 50,95 65,112 65,130,40135,40135 90,0 90"
Stroke="Purple"
StrokeThickness="2" Margin="0,0,146,99" HorizontalAlignment="Right" Width="139" VerticalAlignment="Bottom" Height="99">
<Polygon.Fill>
<ImageBrush ImageSource="/Resources/myImage.png" AlignmentY="Top" Stretch="None" />
</Polygon.Fill>
</Polygon>
Result is like this:
.............................................................
But I want something like this:
......................................
Make the fill image of your polygon rectangular and use Stretch=None or Fill or....
I am using c# wpf for windows surface 2.0.
I have been working with a set of images that i import in the xmpl file.
I found some examples for text, but for the images they used GDI+ to manipulate images and animate them, but I do not want that.
The main thing that I want to do now is to rotate(transform rotate) an image and show that it is rotating.
Here is how I am addressing the images:
Canvas.SetTop(image1, 0);
Canvas.SetLeft(image1, 200);
Any help would be much appreciated.
Thank you.
If you want to rotate your image automatically and without user interaction, check Clemens' answer. However if you want to rotate with touch manipulations, I find it easy to put the image in a ScatterViewItem like so:
<s:ScatterView>
<s:ScatterViewItem CanMove="False" CanScale="False">
<s:ScatterViewItem.Background>
<ImageBrush ImageSource="yourImage.png" Stretch="UniformToFill"/>
</s:ScatterViewItem.Background>
</s:ScatterViewItem>
</s:ScatterView>
Of course, you have the overhead of having to put in a ScatterView and its content
Your question is not very specific and there are a lot of ways to animate the rotation of an image.
A simple approach would be to assign a RotateTransform to the RenderTransform of your Image controls and then animate the Angle property of these RotateTransforms.
<Image x:Name="image" Source="..."
RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform>
<RotateTransform/>
</Image.RenderTransform>
</Image>
Start the animation in code like this:
var transform = (RotateTransform)image.RenderTransform;
var animation = new DoubleAnimation(360, TimeSpan.FromSeconds(5));
transform.BeginAnimation(RotateTransform.AngleProperty, animation);
You may start reading about animations in WPF in the Animation Overview article on MSDN. The Transforms Overview article may also be helpful.
I am currently learning C# in my spare time but have become stuck. I am trying to move an Image control to a random position (Horizontal) on the screen, this is done based on the screen size and the size of the image control itself. Is it possible to set a Image.X and Image.Y position within C# and WPF?
You'll probably want to use a Canvas panel for this, as it allows you to position children at X,Y coordinates.
<Canvas>
<Image x:Name="myImage" Canvas.Top="100" Canvas.Left="200" />
</Canvas>
The Canvas.X and Canvas.Y are attached properties. You can set them from code-behind like this:
myImage.SetValue(Canvas.Left, 200);
myImage.SetValue(Canvas.Top, 400);
I have the following simple code that draws rectangle
<Canvas Name="MainImageLayer" >
<Image >
<Image.Source >
<DrawingImage xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" >
<DrawingImage.Drawing >
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing>
<GeometryDrawing.Pen>
<Pen Brush="#FF1acc33" Thickness="1" />
</GeometryDrawing.Pen>
<GeometryDrawing.Brush>
<SolidColorBrush>Red</SolidColorBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="300,480,287,83" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup.Children>
</DrawingGroup>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
</Canvas>
The result looks like this - note that the rectangle is in (0,0), even that the Rect is defined as
<RectangleGeometry Rect="300,480,287,83" />
I want it to start at (300,480), like that:
I can achieve that by inspecting my DrawingImage and doing :
<Canvas.Top>300</Canvas.Top>
<Canvas.Left>480</Canvas.Left>
But isn't there a better way, considering the fact that this data is encoded into the Geometry?
Your problem comes from the fact that you have all of your geometry wrapped in an 'Image' object. By default, the .Height and .Width properties of an Image object are set to 'Auto', and the .Stretch property is set to 'Uniform'. This guarantees that your rectangle will always appear in the top left corner of your Canvas.
If you really need to encapsulate your geometry in an 'Image' object (which I would caution you not to do) you will need to set the Margin of your Image object to 300,480,0,0. in order to get your rectangle to appear where you want it. This is required because of the way an 'Image' object handles its contents.
An Image object does not behave like a Canvas object, even if it is inside one.
Unless there is some overwhelming reason to keep the Image object, you will have much better success if you discard the Image and draw directly on the Canvas.
EDIT
Why should an Image object not be used in this case?
An Image object is primarily used for displaying...well, images, like bitmaps and such. It is not suited for drawing geometry in it at a specific location (and size). Like most WPF controls, it is what I would call a 'relative' control, meaning it is well suited for automatically resizing and positioning itself in relation to both its contents and its parent. A Canvas on the other hand is an example of an 'absolute' control. Its entire reason for existence is to allow content to be drawn upon it in an exact location with an exact size. Adding an Image inside a Canvas and then drawing the geometry inside the Image just adds an unnecessary layer of complexity between the Canvas and the geometry that needs to be drawn.
How can the geometry be added directly?
One of the easiest ways would be to use the Path object given in Clemens' answer. Just replace your entire Image object and all its contents with the 5 lines of that Path and your rectangle will appear exactly where it should be. You can also do it with a single line and a Rectangle object:
<Rectangle Height="83" Width="287" Margin="300,480,0,0" Stroke="#FF1acc33" StrokeThickness="1" Fill="Red" />
but I would recommend the Path since it contains the size and position of the rectangle in one set of numbers. The Path also allows you much more flexibility if you are working with shapes other than rectangles.
Seems like the DrawingImage (or the GeometryDrawing?) is somehow adjusted to its visible rectangle. Anyway, wouldn't this be a much simpler solution, instead of Image?
<Path Stroke="#FF1acc33" StrokeThickness="1" Fill="Red">
<Path.Data>
<RectangleGeometry Rect="300,480,287,83" />
</Path.Data>
</Path>
You can also add another non-empty GeometryDrawing that covers (0,0) (e.g. a RectangeGeometry with Rect="0,0,1,1") with a transparent brush to the DrawingGroup.
EDIT: As i understood, the DrawingImage is adjusted to Drawing.Bounds