Image cropping windows phone - c#

I want to crop an image in wp7 such that only some part of it appears in an imagebox (or just the 'image' control). I used image.clip, but it actually retains the whole image, and just whitens the 'to-be-cropped' portion. How can i crop the image so that the cropped image is the resultant image?
Note: I am looking for a way in xaml

This is working for me just fine with Light and Dark themes. I'm showing a square image inside an ellipse clip and adding a border around it; it's not showing through.
<Grid>
<Ellipse
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="78"
Height="78"
StrokeThickness="5"
Stroke=""/>
<Image
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="UniformToFill"
Source="{Binding MediumPhotoUrl}"
Width="64"
Height="64" >
<Image.Clip>
<EllipseGeometry RadiusX="32" RadiusY="32" Center="32,32"/>
</Image.Clip>
</Image>
</Grid>
Are you sure you're doing clip correctly?

If you know the size of the initial image, you can calculate the required transforms, for example:
<Image Width="100" Height="100">
<Image.Clip>
<!-- Image after clipping takes only a small area in the center -->
<RectangleGeometry Rect="25,25,50,50"/>
</Image.Clip>
<Image.RenderTransform>
<!-- Transforms Rect(25,25,50,50) into Rect(0,0,100,100) -->
<TransformGroup>
<TranslateTransform X="-25" Y="-25"/>
<ScaleTransform ScaleX="2" ScaleY="2"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
I don't know a way of doing it automatically (without code behind).

Related

Using SkiaSharp to create crossed out circle filled with color

I am new to working with skiasharp with avalonia. I looked at the documentation and examples of how to make some basic shapes, like circles, rectangles, etc. Can anyone give advice or suggestion on how to make a crossed circle filled with color? I think it would be best to do UserControl, something like in wpf.
How you package this up (UserControl) really depends on the use case and intention of the UI element.
<Viewbox x:Name="Vol2"
Width="25"
Height="25">
<Canvas Width="100" Height="100">
<Ellipse x:Name="MyCirlce" Width="100" Height="100" Fill="Black">
</Ellipse>
<Rectangle Height="50" Fill="White" Width="15" Canvas.Top="50" Canvas.Left="42.5" RenderTransformOrigin="0,0">
<Rectangle.RenderTransform>
<RotateTransform Angle="45"></RotateTransform>
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
</Viewbox>
A ViewBox scales it's content, like an SVG.
We then plop a Canvas in there and add our Ellipse. We then add a Rectangle and position in (Left, Right) and then add a RotateTransform.
This should get you going.

In WPF, How can I draw a rectangle over an image without fading the color and being transparent?

I have an image control in WPF and want to create highlighting over the image without fading the color of the rectangle when you change the opacity. This is what I want it to look like:
But I'm getting this:
Here is the code I have now.
<Grid>
<Image
x:Name="img"
Stretch="Uniform"
VerticalAlignment="Top"
HorizontalAlignment="Center"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
Source="Images/Doc.bmp" />
<Canvas>
<Rectangle
Width="300"
Fill="Yellow"
Opacity=".5"
Height="100"
Canvas.Top="200"
Canvas.Left="100" />
</Canvas>
</Grid>
What do I need to do to the rectangle to create the effect of the first image?

ViewportControl and Images - how to avoid endless scrolling

I am coding a kind of map (for a very simple game) which is (for now) an image.
I want the user to be able to scroll the image around and resize it.
I tried a lot around, and currently i am using the ViewportControl, and the XAML looks more or less like the following (see below).
I works as it does all i need - BUT the image itself can be scrolled within the ViewportControll without any boundaries. As a result the image scrolls away.
Question: is there any way to prevent the Viewportcontroll to scroll the image out of a specified region?
<ViewportControl x:Name="viewport" Height="600" Width="440">
<Canvas x:Name="ParentCanvas" Background="Red" MaxHeight="600" MaxWidth="440">
<Image x:Name="MapImage" Source="/Artwork/map.png" RenderTransformOrigin="0.2,0.2" Stretch="UniformToFill" HorizontalAlignment="Left" VerticalAlignment="Center" Canvas.Left="-200" Canvas.Top="-300" Width="1320" Height="1800">
<Image.RenderTransform>
<CompositeTransform x:Name="transform" />
</Image.RenderTransform>
</Image>
<tk:GestureService.GestureListener>
<tk:GestureListener PinchStarted="OnPinchStarted" PinchDelta="OnPinchDelta" />
</tk:GestureService.GestureListener>
</Canvas>
</ViewportControl>
After testing around i have a solution for my problem.
The most important part is to add the Bounds-tag to the ViewportControl as you can see below.
The scrolling is then handled by the ViewportControl itself. The pinch-gesture must be done manually, but it is possible, because the events will reach the correct UI-Element (here: the image).
In the example below, i used the Windows Phone Toolkit to handle the event more easily.
<ViewportControl x:Name="viewportCtrl" ScrollViewer.VerticalScrollBarVisibility="Visible" VerticalContentAlignment="Center" Bounds="0,0,1320,1800">
<Canvas x:Name="ParentCanvas" Background="Red" Height="1000" Width="800">
<Image x:Name="MapImage" Source="/Artwork/map.png" RenderTransformOrigin="0.2,0.2" >
<Image.RenderTransform>
<CompositeTransform x:Name="transform" />
</Image.RenderTransform>
</Image>
<Canvas x:Name="BlueCanvas" Top="100" Left="200" Background="Blue" Height="180" Width="180"></Canvas>
<tk:GestureService.GestureListener>
<tk:GestureListener PinchStarted="OnPinchStarted" PinchDelta="OnPinchDelta" />
</tk:GestureService.GestureListener>
</Canvas>
</ViewportControl>

RenderTransform RotateTransform Blurry Image

I have the following custom UserControl that represents a card in my application:
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:Core="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Namespace="clr-namespace:MyApp" xmlns:Properties="clr-namespace:MyApp.Properties" Core:Class="MyApp.Card" Height="176" RenderTransformOrigin="0.5,0.5" Width="83" UseLayoutRounding="True">
<UserControl.LayoutTransform>
<TransformGroup>
<RotateTransform/>
<ScaleTransform/>
</TransformGroup>
</UserControl.LayoutTransform>
<UserControl.RenderTransform>
<TransformGroup>
<RotateTransform/>
<ScaleTransform/>
</TransformGroup>
</UserControl.RenderTransform>
<UserControl.Resources>
<Namespace:ImagesConverter Core:Key="ImagesConverter"/>
</UserControl.Resources>
<Canvas Core:Name="Layout">
<Image Core:Name="Image" HorizontalAlignment="Left" Source="{Binding Source={Core:Static Properties:Resources.Cards}, Converter={StaticResource ImagesConverter}}" Stretch="None" VerticalAlignment="Top">
<Image.Clip>
<RectangleGeometry Core:Name="Clipping" Rect="0,0,83,176"/>
</Image.Clip>
<Image.RenderTransform>
<TranslateTransform Core:Name="Translation" X="0" Y="0"/>
</Image.RenderTransform>
</Image>
<Rectangle Core:Name="Highlight" Canvas.Left="-2" Canvas.Top="-2" Height="180" Opacity="0.7" Stroke="#FFFFF500" StrokeThickness="3" Visibility="Collapsed" Width="87"/>
</Canvas>
</UserControl>
As you can see... I have a bit PNG image containing all the card faces and then, when I create a new card passing Suit and Rank enum values in constructor, I calculate the correct clipping rectagle and translation for the image.
Everything works like a charm... except when I try to animate my card with a Storyboard that requires a 90° rotation. Here is my code (the Storyboard is defined in MainWindow.Resources):
<DoubleAnimation BeginTime="00:00:00.4" Duration="00:00:00.2" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(RotateTransform.Angle)" To="90"/>
And here is the result:
I can't understand what's going on... but the images gets somehow stretched and becomes very blurry as you can see. I tried using UseLayoutRounding="True" in my card control and also SnapsToDevicePixels="True" in my MainWindow as suggested somewhere else... but it's not working!
Of course... if I rotate the card using LayoutTransform instead of RenderTransform everything works perfectly and the card is not blurry... but I can't make the card rotate around it's center and my animation requires a 90° rotation from the center. Animating Canvas.Top for half of the card height together with layout rotation looks to me like a very unbrilliant solution... and it also makes my animation looks very bad.
Can you suggest me a solution please?
[EDIT] I tried to use RenderOptions.BitmapScalingMode="NearestNeighbor" and RenderOptions.EdgeMode="Aliased"... but it becomes even worse:
The problem was that the underlying image, and so the layout, had an odd value as Width (83). RenderTransformOrigin, even if set to "0.5,0.5", was probably rounding up or down that value resulting in a very bad rendering.
Changing both the image and layout Width to a even value (82), totally resolved the problem.
You could try changeing the RenderOptions on the Image and see if you can find a setting that works, I have added an example of settings I use for this exact situation in my application
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.EdgeMode="Aliased"
Example:
<Image RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.EdgeMode="Aliased"
Core:Name="Image" HorizontalAlignment="Left" Source="{Binding Source={Core:Static Properties:Resources.Cards}, Converter={StaticResource ImagesConverter}}" Stretch="None" VerticalAlignment="Top">
<Image.Clip>
<RectangleGeometry Core:Name="Clipping" Rect="0,0,83,176"/>
</Image.Clip>
<Image.RenderTransform>
<TranslateTransform Core:Name="Translation" X="0" Y="0"/>
</Image.RenderTransform>
</Image>
You indicated that using LayoutTransform works perfectly without blurring the image. Have you tried using it and specifying the center as the pivot of rotation?
Something like:
<Image ...>
<Image.LayoutTransform>
<RotateTransform CenterX="0.5" CenterY="0.5" Angle="90"/>
</Image.LayoutTransform>
</Image>
As #Tommaso Belluzzo said, this is cause from RenderTransformOrigin="0.5,0.5"
Your answer above really solved my question.
Allow me to show my code as following:
System.Drawing.Bitmap bm = null;
//RotateTransform(angle) with RenderTransformOrigin="0.5,0.5" might cause blurry if the width or height is odd,
using (System.Drawing.Bitmap bitmap = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(path))
{
int width = bitmap.Width;
int height = bitmap.Height;
if (0 != width % 2) width ++;
if (0 != height % 2) height ++;
bm = new System.Drawing.Bitmap(width, height);
bm.SetResolution(96, 96);
using (System.Drawing.Graphics g = System.Drawing. Graphics.FromImage(bm))
{
//I don't want to do anything which may modify(resize) the original image.
g.Clear(System.Drawing.Color.White);
g.DrawImage(bitmap, 0, 0, bitmap.Width, bitmap.Height);
}
//bm.Save(directory+#"\tmp.bmp", ImageFormat.Bmp);
}
//.....(show bm)

Center text horizontally and vertically in Silverlight

I am working on a C# Silverlight application that needs some text rotated 90 degrees CCW and for it to be center within an image that is 100px x 221px. The rotation part was easy to do in the design view, but centering the text has been a nightmare. (I am using a 16px font that cant be changed or resized)
My text is dynamic and can be one or two lines. When it is two lines long I can center it fine...but if It is only one line long, I cannot center it. The only way to center it so far is to resize the box and move it to the right.
Is there an easy way of doing this?
alt text http://www.freeimagehosting.net/uploads/f0435a8c65.png
The answer turned out to be simple:
<Grid x:Name="LayoutRoot">
<Image x:Name="Background" Source="Background.png" Stretch="Fill"/>
<TextBlock x:Name="Title"
Margin="-19.75,68.25,-21.25,67.806" Text="Here is some text to fill this up"
Foreground="#FF00A33D"
FontSize="22" RenderTransformOrigin="0.5,0.5" UseLayoutRounding="False" d:LayoutRounding="Auto"
TextAlignment="Center" TextWrapping="Wrap"
>
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-90"/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</Grid>
Then in the cs file set the alignment when you change the text
Title.VerticalAlignment = VerticalAlignment.Bottom;

Categories