I need to display a cropped region of an image source within a DrawingVisual, but for the past few hours I've just drawn blanks for what should be a simple task.
My plan is to implement timed animation (for a HMI system) which will take a big image containing various frames. Depending on a state variable, the DrawingVisual will extract from this big image, the current frame to show - hence the need to crop.
My code stands as follows:
int width = Convert.ToInt32(_imageSource.Width / 2);
int height = Convert.ToInt32(_imageSource.Height);
BitmapImage bm = _imageSource.Clone() as BitmapImage;
bm.BaseUri = BaseUriHelper.GetBaseUri(this);
CroppedBitmap c = new CroppedBitmap(bm, new Int32Rect(0, 0, width, height));
ImageDrawing id = new ImageDrawing(c, new Rect(0, 0, width, height));
dg.Children.Add(id);
dc.DrawDrawing(dg);
However, upon creating the cropped image, I receive
"value does not fall within expected range"
BTW The image is a png loaded within a resource dictionary (in the current assembly) as
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<BitmapImage x:Key="elbowSmallBlueBL" UriSource="./Assets/HMI/Elbows/Small/Elbow Blue BottomLeft.png" />
and then assigned to the DrawingVisual using (ImageSource)FindResource("...
Firstly I don't understand the error message and can't find an satisfactory explanation anywhere and secondly, why is it sooooo difficult to perform a simple task?
Thanks for any help.
p.s. I think this due to not being able to locate the resource. But if the original imagesource is fine why would the cloned version behave any differently?
p.p.s Removing the line "bm.BaseUri = ..." results in same error.
To simplify things, I've created a test project that only has a button which attempts to create CroppedBitmap when clicked.
The button click =
private void Button_Click(object sender, RoutedEventArgs e)
{
BitmapSource i = (BitmapSource)FindResource("elbowSmallBlueBL");
try
{
CroppedBitmap c = new CroppedBitmap(i, new Int32Rect(0, 0, 100, 100));
}
catch (Exception ex)
{
}
}
}
The resource dictionary references the bitmap :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Elbows -->
<BitmapImage x:Key="elbowSmallBlueBL" UriSource="./Assets/HMI/Elbows/Small/Elbow Blue BottomLeft.png" />
and included the App.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="rdHMIControls.xaml" />
The BitmapSource (i) is valid and the call to CroppedBitmap throws the ArgumentException, "Value does not fall within the accepted range".
Creating, or trying to create a cropped image surely can't be any simpler than this?
Another example which I've taken off MSDN
BitmapSource i = (BitmapSource)this.FindResource("test");
try
{
// Create an Image element.
Image croppedImage = new Image();
croppedImage.Width = 200;
croppedImage.Margin = new Thickness(5);
// Create a CroppedBitmap based off of a xaml defined resource.
CroppedBitmap cb = new CroppedBitmap(
i,
new Int32Rect(30, 20, 105, 50)); //select region rect
croppedImage.Source = cb; //set image source to cropped
Again new CroppedBitmap throws InvalidArgument exceptin
Any thoughts?
Thanks
Related
I would like to use WPF to programmatically print. However, I need all the material to be sent to the printer in vector graphics and not raster graphics.
The main issue is, I cannot get WPF to print vector graphics, the prints always gets rasterized.
I useSharpVectors, which transforms an .svg file into am .xaml drawing group. And then insert that drawing group into an Image into a flowdocument, finally I send the flowdocument to print using an XPSDocumentWriter.
Blurry every time. I compare the print to the .svg file printed from adobe Illustrator. Night and day quality.
Is there any way to take a drawing group and always have it print as vector?
I am putting a bounty on this. You must submit the c# code necessary to send the following drawing group to the printer as vector graphics, this must be reproducible to get the bounty. Also, simply increasing the DPI after the image is rasterized does not qualify as an answer. No vector print - no bounty.
https://drive.google.com/file/d/0B-M6Yes83t08V0ZOOEp1Q3dEYjA/view?usp=sharing
Google Drive
DrawingGroup xaml
Yes you can ! ;-)
I think you'd better forget the image and use a FixedDocument
First create a class, overriding OnRender :
public partial class MapDrawingElement : FrameworkElement
{
public MapDrawingElement()
{
InitializeComponent();
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
var res = Resources["drawingGroup1"] as DrawingGroup;
if (res != null)
drawingContext.DrawDrawing(res);
}
}
The class has a drawingGroup1 Resource in its resource section :
<FrameworkElement x:Class="DemoFixedpageDocument.MapDrawingElement"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="800">
<FrameworkElement.Resources>
<DrawingGroup x:Key="drawingGroup1">
... here your xaml 16k lines ! ...
</DrawingGroup>
</FrameworkElement.Resources>
</FrameworkElement>
Instanciate a FixedDocument, and put the control with the map in a page :
public static class DocumentMaker
{
public static FixedDocument GenerateFixedDocument()
{
FixedDocument fixedDocument = new FixedDocument();
PageContent pageContent1 = new PageContent();
fixedDocument.Pages.Add(pageContent1);
FixedPage page1 = new FixedPage();
// PageContent : some text or an object can be added
((IAddChild)pageContent1).AddChild(page1);
MapDrawingElement elt = new MapDrawingElement();
page1.Children.Add(elt);
return fixedDocument;
}
}
Then you can print :
PrintDocumentImageableArea imageArea = null;
XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(ref imageArea);
if (xpsdw != null)
{
xpsdw.Write(DocumentMaker.GenerateFixedDocument());
}
You can also print preview or send to an XPS file.
See the working demo in the link :
http://1drv.ms/1RefeuJ
Regards
I have a simple UserControl called UserControl1 that contains a TextBlock:
<UserControl x:Class="WpfApplication2.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock Text="{Binding}"/>
</Grid>
</UserControl>
I initialized a new instance of it and gave it a DataContext in code. when the window is closing I have to draw this control to an image file.
The UserControl does not render the bounded text in the file that been created.
and this is my code using the usercontrol:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Closing += MainWindow_Closing;
}
void MainWindow_Closing(object sender, CancelEventArgs e)
{
UserControl1 uc = new UserControl1();
uc.DataContext = "hello";
uc.Height = 100;
uc.Width = 100;
uc.Background = Brushes.LightBlue;
DrawToImage(uc);
}
private void DrawToImage(FrameworkElement element)
{
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(element.DesiredSize));
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)element.Width, (int)element.Height,
120.0, 120.0, PixelFormats.Pbgra32);
bitmap.Render(element);
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
using (Stream s = File.OpenWrite(#"C:\555.png"))
{
encoder.Save(s);
}
}
}
I Hope It's clear enough, any help will be very appreciated.
You just forgot to force a Layout update on your control after manually Measuring/Arrangeing it (which will not be enough to force binding resolving).
A simple call to UpdateLayout makes it work :
private void DrawToImage(FrameworkElement element)
{
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(element.DesiredSize));
element.UpdateLayout();
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)element.Width, (int)element.Height,
120.0, 120.0, PixelFormats.Pbgra32);
bitmap.Render(element);
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
using (Stream s = File.OpenWrite(#"C:\555.png"))
{
encoder.Save(s);
}
}
Edit : More on when bindings are resolved : link
Try to call the function SaveImage() on userControl1.Loaded event
If I do this it works, not sure this is what you want though:
<Window x:Class="DrawImage.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:DrawImage="clr-namespace:DrawImage"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DrawImage:UserControl1 x:Name="uc" Visibility="Hidden"/>
</Grid>
</Window>
void MainWindow_Closing(object sender, CancelEventArgs e)
{
uc.DataContext = "hello";
uc.Height = 100;
uc.Width = 100;
uc.Background = Brushes.LightBlue;
uc.Visibility = Visibility.Visible;
DrawToImage(uc);
}
EDIT
I am now able to reproduce the issue. If I set the DataContext in the Window contstructor then it works. If I set it in the Winndow_Closed event I get the exact same result that you get.
I guess there might no workaround since the WPF needs some time to actually render the text on the UI thread. If you render the PNG before the WPF has rendered the text on the UI thread it will not appear on the PNG.
A workaround does not seem to exist since the window will be destroyed when the Closed event handlers has been running. There is no way to block the UI thread on the one hand to prvevent to window from beeing detroyed when you on the other hand want the UI thread to render the control.
I'd suggest to render the image as soon as the control has been rendered and save the image file when the window is closed.
I posted an Article in my Blog (putting in the account the png Transparancy (causes the black background)):
Saving FrameworkElement as Image
FrameworkElement element = myControl.Content;
// you can set the size as you need.
Size theTargetSize = new Size(1500,2000)
element.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(theTargetSize ));
// to affect the changes in the UI, you must call this method at the end to apply the new changes
element.UpdateLayout();
You can find the full cod in the Blog Post.
I've found a new twist on the "Visual to RenderTargetBitmap" question!
I'm rendering previews of WPF stuff for a designer. That means I need to take a WPF visual and render it to a bitmap without that visual ever being displayed. Got a nice little method to do it like to see it here it goes
private static BitmapSource CreateBitmapSource(FrameworkElement visual)
{
Border b = new Border { Width = visual.Width, Height = visual.Height };
b.BorderBrush = Brushes.Black;
b.BorderThickness = new Thickness(1);
b.Background = Brushes.White;
b.Child = visual;
b.Measure(new Size(b.Width, b.Height));
b.Arrange(new Rect(b.DesiredSize));
RenderTargetBitmap rtb = new RenderTargetBitmap(
(int)b.ActualWidth,
(int)b.ActualHeight,
96,
96,
PixelFormats.Pbgra32);
// intermediate step here to ensure any VisualBrushes are rendered properly
DrawingVisual dv = new DrawingVisual();
using (var dc = dv.RenderOpen())
{
var vb = new VisualBrush(b);
dc.DrawRectangle(vb, null, new Rect(new Point(), b.DesiredSize));
}
rtb.Render(dv);
return rtb;
}
Works fine, except for one leeetle thing... if my FrameworkElement has a VisualBrush, that brush doesn't end up in the final rendered bitmap. Something like this:
<UserControl.Resources>
<VisualBrush
x:Key="LOLgo">
<VisualBrush.Visual>
<!-- blah blah -->
<Grid
Background="{StaticResource LOLgo}">
<!-- yadda yadda -->
Everything else renders to the bitmap, but that VisualBrush just won't show. The obvious google solutions have been attempted and have failed. Even the ones that specifically mention VisualBrushes missing from RTB'd bitmaps.
I have a sneaky suspicion this might be caused by the fact that its a Resource, and that lazy resource isn't being inlined. So a possible fix would be to, somehow(???), force resolution of all static resource references before rendering. But I have absolutely no idea how to do that.
Anybody have a fix for this?
You have two problems:
You didn't set a PresentationSource on your visual so Loaded events won't fire.
You didn't flush the Dispatcher queue. Without flushing the Dispatcher queue, any functionality that uses Dispatcher callbacks won't work.
The immediate cause of your problem is failure to flush the Dispatcher queue, since VisualBrush uses it, but you will probably run into the PresentationSource problem before long so I would fix both of these.
Here is how I do it:
// Create the container
var container = new Border
{
Child = contentVisual,
Background = Brushes.White,
BorderBrush = Brushes.Black,
BorderThickness = new Thickness(1),
};
// Measure and arrange the container
container.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
container.Arrange(new Rect(container.DesiredSize));
// Temporarily add a PresentationSource if none exists
using(var temporaryPresentationSource = new HwndSource(new HwndSourceParameters()) { RootVisual = (VisualTreeHelper.GetParent(container)==null ? container : null) })
{
// Flush the dispatcher queue
Dispatcher.Invoke(DispatcherPriority.SystemIdle, new Action(() => { }));
// Render to bitmap
var rtb = new RenderTargetBitmap((int)b.ActualWidth, (int)b.ActualHeight, 96, 96, PixelFormats.Pbgra32);
rtb.Render(container);
return rtb;
}
FYI, StaticResource lookup is never delayed under any circumstances: It is processed the moment the XAML is loaded and immediately replaced with the value retrieved from the ResourceDictionary. The only way StaticResource could possibly be related is if it picked up the wrong resource because two resources had the same key. I just thought I should explain this -- it has nothing to do with your actual problem.
Well to inline it, you could just do something like this:
<Grid>
<Grid.Background>
<VisualBrush>
<VisualBrush.Visual>
<!-- blah blah -->
</VisualBrush.Visual>
</VisualBrush>
</Grid.Background>
</Grid>
If that doesn't work, my guess would be that it must be something specific with the Visual instance you are using (and that will require further code to better diagnose).
I'm trying to write code that will load an image from a resource, and then crop it. This code works when I do all, or part, of it in XAML. I want to switch from all-XAML to all-code, so I can reuse this more than one place, with different Uris.
But when I try to do the same thing in code, I get a DirectoryNotFoundException, because suddenly it starts trying to look for a folder on disk, instead of loading the image from the resource.
If I load the BitmapImage in XAML, and then create a CroppedBitmap in XAML, everything works.
If I load the BitmapImage in XAML, and then write code to create a CroppedBitmap from it, everything works.
If I load the BitmapImage in code, without creating a CroppedBitmap from it, everything works.
But if I load the BitmapImage in code and create a CroppedBitmap in code, it tries to load from the filesystem instead of the resources, and I get a DirectoryNotFoundException.
Code samples are below. I'm sure I'm doing something stupid, but I've run through the whole thing three times now (once in my real app, once in a test app, and once while writing up this question), and I got the same results all three times.
For all of the following code samples, I've created an Images folder inside my project, and added an existing image there called "elf.png", with properties set to defaults (Build Action = "Resource"; Copy to Output Directory = "Do not copy").
Case 1: Both BitmapImage and CroppedBitmap in XAML.
<Window x:Class="WpfApplication8.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<BitmapImage x:Key="fullImage" UriSource="Images/elf.png"/>
<CroppedBitmap x:Key="croppedImage" Source="{StaticResource fullImage}"
SourceRect="0 0 240 320"/>
</Window.Resources>
<Image Source="{StaticResource croppedImage}"/>
</Window>
This shows the cropped portion of the bitmap, as expected.
Case 2: BitmapImage in XAML; CroppedBitmap in code-behind.
XAML:
<Window x:Class="WpfApplication8.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<BitmapImage x:Key="fullImage" UriSource="Images/elf.png"/>
</Window.Resources>
<Image Name="image"/>
</Window>
Constructor in code-behind:
public Window1()
{
InitializeComponent();
var fullImage = (BitmapImage) FindResource("fullImage");
var croppedImage =
new CroppedBitmap(fullImage, new Int32Rect(0, 0, 240, 320));
image.Source = croppedImage;
}
This also shows the cropped portion of the bitmap, as expected.
Case 3: BitmapImage in code; no CroppedBitmap.
public Window1()
{
InitializeComponent();
var uri = new Uri("Images/elf.png", UriKind.RelativeOrAbsolute);
var fullImage = new BitmapImage(uri);
image.Source = fullImage;
}
This shows the entire bitmap. This isn't what I want, but does tell me that I know how to write C# code to create the right kind of Uri and load a BitmapImage from a resource.
Case 4: BitmapImage and CroppedBitmap in code.
public Window1()
{
InitializeComponent();
var uri = new Uri("Images/elf.png", UriKind.RelativeOrAbsolute);
var fullImage = new BitmapImage(uri);
var croppedImage =
new CroppedBitmap(fullImage, new Int32Rect(0, 0, 240, 320));
image.Source = croppedImage;
}
As far as I can tell, this just puts together the same pieces as before. It uses code that I know will load a BitmapImage from a resource, and code that I know will crop a section from a loaded BitmapImage. But somehow, when the two are put together, it forgets that the resource is there, and tries to load from disk. I get the following exception:
XamlParseException: "Cannot create instance of 'Window1' defined in assembly 'WpfApplication8, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. Exception has been thrown by the target of an invocation. Error in markup file 'Window1.xaml' Line 1 Position 13."
Inner exception: TargetInvocationException: "Exception has been thrown by the target of an invocation."
Inner exception: DirectoryNotFoundException: "Could not find a part of the path 'C:\svn\WpfApplication8\WpfApplication8\bin\Debug\Images\elf.png'."
The inner-inner-exception stack trace shows that the original exception (the DirectoryNotFoundException) is being thrown by the line that instantiates the CroppedBitmap. I don't know why that line would be trying to read from disk, or why it doesn't work when the as-far-as-I-can-tell-equivalent XAML works fine.
Since I know the XAML is using the parameterless constructors, I also tried the following version, which should be much closer to what the XAML actually does:
public Window1()
{
InitializeComponent();
var uri = new Uri("Images/elf.png", UriKind.RelativeOrAbsolute);
var fullImage = new BitmapImage();
fullImage.BeginInit();
fullImage.UriSource = uri;
fullImage.EndInit();
var croppedImage = new CroppedBitmap();
croppedImage.BeginInit();
croppedImage.Source = fullImage;
croppedImage.SourceRect = new Int32Rect(0, 0, 240, 320);
croppedImage.EndInit();
image.Source = croppedImage;
}
Same exception, this time from the croppedImage.EndInit(); line.
Any ideas on how I can get the all-code version to correctly load the resource and crop the image? What's happening in the XAML version that's different?
The magic turned out to be in the BitmapImage's BaseUri property. BaseUri apparently serves as the "current directory" that UriSource is relative to.
When my BitmapImage was being loaded from XAML, BaseUri was being magically set to "pack://application:,,,/WpfApplication8;component/window1.xaml". When I modified code snippet #4 to explicitly set fullImage.BaseUri to that same value before creating the CroppedBitmap, everything worked.
Why it worked from XAML (and from just-BitmapImage-without-CroppedBitmap)
So where did this magic BaseUri value come from?
BaseUri is part of the IUriContext interface. IUriContext.BaseUri is set in two places in the WPF assemblies, and between my various examples, I managed to hit both of them. No wonder I was confused.
BamlRecordReader.ElementInitialize. The BAML loader automatically sets BaseUri anytime it loads an element that implements IUriContext. This explains why my examples #1 and #2 worked: they were loading from the compiled BAML resource.
Image.UpdateBaseUri (called whenever the Source property is changed). This checks to see if the Source implements IUriContext, and if so, sets its BaseUri. This explains why my example #3 worked: pushing the BitmapImage into the GUI forced it to get the right search path.
It only looks for the image in the EXE resources when BaseUri is set to the magic pack:// URI. Without that (as happens when everything is created in code and not pushed into the GUI), it only looks on disk.
The fix
As noted above, I could hard-code BaseUri. But the BaseUriHelper class provides a better fix:
fullImage.BaseUri = BaseUriHelper.GetBaseUri(this);
This sets fullImage to have the same BaseUri as the window (this). If this is done before creating the CroppedBitmap, everything works.
I have a window with a title on it. When the user selects a choice from a drop down list, the title image can change. The problem is when the image loads, it's a blurred, stretched, and pixelated. These are PNG files I'm working with and they look good prior to setting the source dynamically.
Here's the code I'm using to change the image's source.
string strUri2 = String.Format(#"pack://application:,,,/MyAssembly;component/resources/main titles/{0}", CurrenSelection.TitleImage);
Stream iconStream2 = App.GetResourceStream(new Uri(strUri2)).Stream;
imgTitle.Source = HelperFunctions.returnImage(iconStream2);
Here are the helper functions.
public static BitmapImage returnImage(Stream iconStream)
{
Bitmap brush = new Bitmap(iconStream);
System.Drawing.Image img = brush.GetThumbnailImage(brush.Height, brush.Width, null, System.IntPtr.Zero);
var imgbrush = new BitmapImage();
imgbrush.BeginInit();
imgbrush.StreamSource = ConvertImageToMemoryStream(img);
imgbrush.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
imgbrush.EndInit();
var ib = new ImageBrush(imgbrush);
return imgbrush;
}
public static MemoryStream ConvertImageToMemoryStream(System.Drawing.Image img)
{
var ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
return ms;
}
And the XAML
<Image x:Name="imgTitle" HorizontalAlignment="Left" VerticalAlignment="Bottom" Grid.Column="1" Grid.Row="1" Stretch="None" d:IsLocked="False"/>
And for Ref:
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Anyone have any ideas what's up?
I can think of two things:
First, try loading the image with:
string strUri2 = String.Format(#"pack://application:,,,/MyAseemby;component/resources/main titles/{0}", CurrenSelection.TitleImage);
imgTitle.Source = new BitmapImage(new Uri(strUri2));
Maybe the problem is with WinForm's image resizing, if the image is stretched set Stretch on the image control to "Uniform" or "UnfirofmToFill".
Second option is that maybe the image is not aligned to the pixel grid, you can read about it on my blog at http://www.nbdtech.com/blog/archive/2008/11/20/blurred-images-in-wpf.aspx
Hey, this one is kind of ugly but it's one line only:
imgTitle.Source = new BitmapImage(new Uri(#"pack://application:,,,/YourAssembly;component/your_image.png"));
Here is how it worked beautifully for me.
In the window resources add the image.
<Image x:Key="delImg" >
<Image.Source>
<BitmapImage UriSource="Images/delitem.gif"></BitmapImage>
</Image.Source>
</Image>
Then the code goes like this.
Image img = new Image()
img.Source = ((Image)this.Resources["delImg"]).Source;
"this" is referring to the Window object
Like for me -> working is:
string strUri2 = Directory.GetCurrentDirectory()+#"/Images/ok_progress.png";
image1.Source = new BitmapImage(new Uri(strUri2));
Me.imgAddNew.Source = New System.Windows.Media.Imaging.BitmapImage(New Uri("/SPMS;component/Images/Cancel__Red-64.png", UriKind.Relative))
Try Stretch="UniformToFill" on the Image