Resizing an image using Win2D with proportional aspect ratio - c#

I'm having an issue in my UWP Win2D app. I have an image and text being displayed in a CanvasAnimatedControl, and when I resize the window, it stretches both image and text instead of maintaining their proportions:
This is a portion of the code which loads and draws the image:
private void Draw(ICanvasAnimatedControl sender, CanvasAnimatedDrawEventArgs args)
{
if (!IsLoadInProgress())
{
args.DrawingSession.DrawImage(_bitmap);
DrawText(args, "...TESTING TEXT...");
}
}
private void DrawText(CanvasAnimatedDrawEventArgs args, string text)
{
using (var textFormat = new CanvasTextFormat()
{
FontSize = 96,
FontFamily = "Segoe UI",
FontWeight = FontWeights.Medium
})
{
args.DrawingSession.DrawText(
text,
new Vector2(20, (float)_bitmap.Size.Height / 2),
Colors.White,
textFormat);
}
}
private async Task SetImageAndSize()
{
if (_imagePath != null)
{
_bitmap = await CanvasBitmap.LoadAsync(AnimatedControl, new Uri(_imagePath, UriKind.RelativeOrAbsolute));
// Set the controls size according to image pixels to display for image
AnimatedControl.Height = _bitmap.SizeInPixels.Height;
AnimatedControl.Width = _bitmap.SizeInPixels.Width;
}
}
The sample project can be downloaded here:
PROJECT LINK
What do I need to change so that the Image and Text don't stretch on resize??

Found my solution, I use a ViewBox:
<Viewbox Stretch="Fill">
<canvas:CanvasAnimatedControl x:Name="AnimatedControl" />
</Viewbox>
I had to change the Stretch on it:
<Viewbox Stretch="UniformToFill">
<canvas:CanvasAnimatedControl x:Name="AnimatedControl" />
</Viewbox>

Related

Drag & Drop from explorer to wpf element

Everything seems to be simple and there are quite a few tutorials, but I cannot transfer data (in my case, an image) to a wpf window element. I was able to implement the transfer of an image from one element to another. But when I capture an image (for example, a desktop), when I transfer it to the desired element, the transfer option does not even appear, only a crossed-out circle and does not work out more than one event associated with drop (as if AllowDrop = false)
My code:
XAML
<Image x:Name="mainContent" Grid.Column="1" Stretch="Fill" AllowDrop="True" Drop="MainContent_Drop" />
C#
private void SpImageLeft_MouseDown(object sender, MouseButtonEventArgs e)
{
Image image = sender as Image;
DragDrop.DoDragDrop(image, image, DragDropEffects.Copy);
}
private void MainContent_Drop(object sender, DragEventArgs e)
{
Image image = (Image)e.Data.GetData(typeof(Image));
mainContent.Source = image.Source;
}
I understand that when I take an image from explorer it will be different there, something like this, but it still does not even show that you can add an image
private void MainContent_Drop(object sender, DragEventArgs e)
{
string[] arr = (string[])e.Data.GetData(DataFormats.FileDrop);
mainContent.Source = (ImageSource)new ImageSourceConverter().ConvertFromString(arr[0]);
}
The following worked for me as a Drop event handler for an Image control:
private void OnMainImageDrop(object sender, DragEventArgs e)
{
if (sender is Image image && e.Data.GetDataPresent(DataFormats.FileDrop))
{
if (e.Data.GetData(DataFormats.FileDrop) is string[] filePaths)
{
image.Source.Freeze();
string filePath = filePaths[0];
var uriSource = new Uri(filePath);
var imageSource = new BitmapImage(uriSource);
image.Source = imageSource;
}
}
}
I used a placeholder image to make sure the image had a size and served as a mouse hover surface.
XAML:
<Image x:Name="MainImage" Grid.Row="1"
Source="Images/DotNetLogo.png"
Stretch="Uniform"
AllowDrop="True" Drop="OnMainImageDrop"/>

How to draw text on an image and save it using UWP (for Windows 10)

I want to draw text on a template image in UWP (for Windows 10), and then be able to save the image (so the user could print or share it).
I have played around with the canvas control and even the Win2D package from nuget. Any suggestions as to what the best way to do this are appreciated. Sample code of where I left off is below.
XAML
<Page
x:Class="DrawTextExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DrawTextExample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:canvas="using:Microsoft.Graphics.Canvas.UI.Xaml"
mc:Ignorable="d">
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button Name="btnSaveImage" Content="Save the image" Margin="10" Click="btnSaveImage_Click" />
<Grid Name="MyCreatedImage">
<Image Name="imgName" Stretch="UniformToFill" Source="Assets/HelloMyNameIs.jpg" />
<TextBlock Name="lblName" Text="McFly" Margin="20,100,20,20" FontSize="36"/>
</Grid>
</StackPanel>
Code Behind
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
namespace DrawTextExample {
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private async void btnSaveImage_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e) {
var bitmap = new RenderTargetBitmap();
await bitmap.RenderAsync(MyCreatedImage);
}
}
}
Image (HelloMyNameIs.jpg)
I want to draw text on a template image in UWP (for Windows 10), and then be able to save the image (so the user could print or share it).
According to your code snippet, you are trying to use RenderTargetBitmap which can meet your requirements. This class can render the Image with the TextBlock together into one image. Your code snippet just lack of saving. You can save the rendered image as follows:
private async void btnSaveImage_Click(object sender, RoutedEventArgs e)
{
RenderTargetBitmap bitmap = new RenderTargetBitmap();
await bitmap.RenderAsync(MyCreatedImage);
var pixelBuffer = await bitmap.GetPixelsAsync();
var pixels = pixelBuffer.ToArray();
var displayInformation = DisplayInformation.GetForCurrentView();
StorageFolder pictureFolder = KnownFolders.SavedPictures;
var file = await pictureFolder.CreateFileAsync("test2.jpg", CreationCollisionOption.ReplaceExisting);
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied,
(uint)bitmap.PixelWidth,
(uint)bitmap.PixelHeight,
displayInformation.RawDpiX,
displayInformation.RawDpiY,
pixels);
await encoder.FlushAsync();
}
}
You may also try to use Win2D which may be recommended. You can draw images, draw text and draw shapes as you want. It provides the CanvasBitmap.SaveAsync method for saving the result. For example, the following demo showed how to draw the text on the image and save it to the picture folder.
Uri imageuri = new Uri("ms-appx:///Assets/HelloMyNameIs.jpg");
StorageFile inputFile = await StorageFile.GetFileFromApplicationUriAsync(imageuri);
BitmapDecoder imagedecoder;
using (var imagestream = await inputFile.OpenAsync(FileAccessMode.Read))
{
imagedecoder =await BitmapDecoder.CreateAsync(imagestream);
}
CanvasDevice device = CanvasDevice.GetSharedDevice();
CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, imagedecoder.PixelWidth, imagedecoder.PixelHeight, 96);
using (var ds = renderTarget.CreateDrawingSession())
{
ds.Clear(Colors.White);
CanvasBitmap image = await CanvasBitmap.LoadAsync(device, inputFile.Path, 96);
ds.DrawImage(image);
ds.DrawText(lblName.Text, new System.Numerics.Vector2(150, 150), Colors.Black);
}
string filename = "test1.png";
StorageFolder pictureFolder = KnownFolders.SavedPictures;
var file = await pictureFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
await renderTarget.SaveAsync(fileStream, CanvasBitmapFileFormat.Png, 1f);
}
If you want personality text drawing on the image you may consider using InkCanvas to DrawInk. Details you may reference this thread.

Low Allocation Drawing in WPF

I am having some serious issues with WPF and using DrawingContext, or specifically VisualDrawingContext coming from overriding OnRender on an element or if using DrawingVisual.RenderOpen().
The problem is this allocates a lot. For example, it seems to be allocating a byte[] buffer each time a drawing context is used.
Examples, of how drawing context is used.
using (var drawingContext = m_drawingVisual.RenderOpen())
{
// Many different drawingContext.Draw calls
// E.g. DrawEllipse, DrawRectangle etc.
}
or
override void OnRender(DrawingContext drawingContext)
{
// Many different drawingContext.Draw calls
// E.g. DrawEllipse, DrawRectangle etc.
}
This causes a lot of allocations, causing some unwanted garbage collections. So yes I need this, and please stay on topic :).
What are the options for drawing in WPF with zero or low number of managed heap allocations? Reusing objects is fine, but I have yet to find a way to do this... or doesn't then have issues with DependencyProperty and allocations around/inside it.
I do know about WritableBitmapEx but was hoping for a solution that does not involve rasterising to predefined bitmap, but instead proper "vector" graphics that can still be zoomed for example.
NOTE: CPU usage is a concern but much less than the massive garbage pressure caused by this.
UPDATE: I am looking for a solution for .NET Framework 4.5+, if there is anything in later versions e.g. 4.7 that might help answer this then that is fine. But it is for the desktop .NET Framework.
UPDATE 2: A brief description of the two main scenarios. All examples have been profiled with CLRProfiler, and it shows clearly that lots of allocations occur due to this and that this is a problem for our use case. Note that this is example code intended to convey the principles not the exact code.
A: This scenario is shown below. Basically, an image is shown and some overlay graphics are drawn via a custom DrawingVisualControl, which then uses using (var drawingContext = m_drawingVisual.RenderOpen()) to get a drawing context and then draws via that. Lots of ellipse, rectangles and text is drawn. This example also shows some scaling stuff, this is just for zooming etc.
<Viewbox x:Name="ImageViewbox" VerticalAlignment="Center" HorizontalAlignment="Center">
<Grid x:Name="ImageGrid" SnapsToDevicePixels="True" ClipToBounds="True">
<Grid.LayoutTransform>
<ScaleTransform x:Name="ImageTransform" CenterX="0" CenterY="0"
ScaleX="{Binding ElementName=ImageScaleSlider, Path=Value}"
ScaleY="{Binding ElementName=ImageScaleSlider, Path=Value}" />
</Grid.LayoutTransform>
<Image x:Name="ImageSource" RenderOptions.BitmapScalingMode="NearestNeighbor" SnapsToDevicePixels="True"
MouseMove="ImageSource_MouseMove" />
<v:DrawingVisualControl x:Name="DrawingVisualControl" Visual="{Binding DrawingVisual}"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="NearestNeighbor"
IsHitTestVisible="False" />
</Grid>
</Viewbox>
The `DrawingVisualControl is defined as:
public class DrawingVisualControl : FrameworkElement
{
public DrawingVisual Visual
{
get { return GetValue(DrawingVisualProperty) as DrawingVisual; }
set { SetValue(DrawingVisualProperty, value); }
}
private void UpdateDrawingVisual(DrawingVisual visual)
{
var oldVisual = Visual;
if (oldVisual != null)
{
RemoveVisualChild(oldVisual);
RemoveLogicalChild(oldVisual);
}
AddVisualChild(visual);
AddLogicalChild(visual);
}
public static readonly DependencyProperty DrawingVisualProperty =
DependencyProperty.Register("Visual",
typeof(DrawingVisual),
typeof(DrawingVisualControl),
new FrameworkPropertyMetadata(OnDrawingVisualChanged));
private static void OnDrawingVisualChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var dcv = d as DrawingVisualControl;
if (dcv == null) { return; }
var visual = e.NewValue as DrawingVisual;
if (visual == null) { return; }
dcv.UpdateDrawingVisual(visual);
}
protected override int VisualChildrenCount
{
get { return (Visual != null) ? 1 : 0; }
}
protected override Visual GetVisualChild(int index)
{
return this.Visual;
}
}
B: The second scenario involves drawing a moving "grid" of data e.g. 20 rows of 100 columns, with elements consisting of a border and text with different colors to display some status. The grid moves depending on external input, and for now is only updated 5-10 times per second. 30 fps would be better. This, thus, updates 2000 items in an ObservableCollection tied to a ListBox (with VirtualizingPanel.IsVirtualizing="True") and the ItemsPanel being a Canvas. We can't even show this during our normal use case, since it allocates so much that the GC pauses become way too long and frequent.
<ListBox x:Name="Items" Background="Black"
VirtualizingPanel.IsVirtualizing="True" SnapsToDevicePixels="True">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type vm:ElementViewModel}">
<Border Width="{Binding Width_mm}" Height="{Binding Height_mm}"
Background="{Binding BackgroundColor}"
BorderBrush="{Binding BorderColor}"
BorderThickness="3">
<TextBlock Foreground="{Binding DrawColor}" Padding="0" Margin="0"
Text="{Binding TextResult}" FontSize="{Binding FontSize_mm}"
TextAlignment="Center" VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Canvas.Left" Value="{Binding X_mm}"/>
<Setter Property="Canvas.Top" Value="{Binding Y_mm}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True"
Width="{Binding CanvasWidth_mm}"
Height="{Binding CanvasHeight_mm}"
/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
There is a lot of data binding here, and the box'ing of value types do incur a lot of allocations, but that is not the main problem here. It is the allocations done by WPF.
Some Inputs
Your piece of code is not available so I can suggest only.
When its comes to performance, use profiling tools available from Microsoft.
You can find the tools here
The one more important link where you can read is WPF graphics
Note:-
Try using Drawing Group
Use WindowsFormsHost as described in Walkthrough: Hosting a Windows Forms Control in WPF by Using XAML and GDI+ for drawing instead. This isn't a perfect solution, but the - for now - best alternative I have been able to find.
<Grid>
<WindowsFormsHost x:Name="WinFormsHost>
<custom:Canvas x:Name="Canvas" />
</WindowsFormsHost>
</Grid>
And then create a custom control and override OnPaint, something like:
public partial class Canvas
: UserControl
{
// Implementing custom double buffered graphics, since this is a lot
// faster both when drawing and with respect to GC, since normal
// double buffered graphics leaks disposable objects that the GC needs to finalize
protected BufferedGraphicsContext m_bufferedGraphicsContext =
new BufferedGraphicsContext();
protected BufferedGraphics m_bufferedGraphics = null;
protected Rectangle m_currentClientRectangle = new Rectangle();
public Canvas()
{
InitializeComponent();
Setup();
}
private void Setup()
{
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint |
ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
DoubleBuffered = false;
this.Dock = DockStyle.Fill;
}
private void DisposeManagedResources()
{
m_bufferedGraphicsContext.Dispose();
if (m_bufferedGraphics != null)
{
m_bufferedGraphics.Dispose();
}
}
protected override void OnPaintBackground(PaintEventArgs e)
{
// Background paint is done in OnPaint
// This reduces the "leaks" of System.Windows.Forms.Internal.DeviceContext
// and the amount of "GC" handles created considerably
// as found by using CLR Profiler
}
protected override void OnPaint(PaintEventArgs e)
{
// Specifically not calling base here since we draw entire area ourselves
// base.OnPaint(e);
// Should this be disposed?
using (e)
using (var targetGraphics = e.Graphics)
{
ReallocBufferedGraphics(targetGraphics);
// Use buffered graphics object
var graphics = m_bufferedGraphics.Graphics;
// Raise paint event
PaintEvent?.Invoke(this.ClientRectangle, e.ClipRectangle, graphics);
// Render to target graphics i.e. paint event args graphics
m_bufferedGraphics.Render(targetGraphics);
}
}
protected virtual void ReallocBufferedGraphics(Graphics graphics)
{
Rectangle newClientRectangle = this.ClientRectangle;
// Realloc if new client rectangle is not contained within the current
// or if no buffered graphics exists
bool reallocBufferedGraphics = ShouldBufferBeReallocated(newClientRectangle);
if (reallocBufferedGraphics)
{
if (m_bufferedGraphics != null)
{
m_bufferedGraphics.Dispose();
}
m_bufferedGraphics = m_bufferedGraphicsContext.Allocate(
graphics, newClientRectangle);
m_currentClientRectangle = newClientRectangle;
}
}
protected virtual bool ShouldBufferBeReallocated(Rectangle newClientRectangle)
{
return !m_currentClientRectangle.Contains(newClientRectangle) ||
m_bufferedGraphics == null;
}
/// <summary>
/// PaintEvent with <c>clientRectangle, clipRectangle, graphics</c> for the canvas.
/// </summary>
public event Action<Rectangle, Rectangle, Graphics> PaintEvent;
}
UPDATE: Updated Canvas control to truly be zero heap allocations.
The WinForms Canvas solution has some issues, especially the so-called "airspace" issues due to how WindowsFormsHost interacts with WPF. To keep it short, this means that no WPF visuals can be drawn on top of the host.
This can be solved by recognizing that since we have to double buffer anyway, we might as well buffer into a WriteableBitmap that can then be drawn as usual via an Image control.
This can be fascillitated by using a utility class like the below:
using System;
using System.Drawing;
using System.Windows;
using SWM = System.Windows.Media;
using SWMI = System.Windows.Media.Imaging;
public class GdiGraphicsWriteableBitmap
{
readonly Action<Rectangle, Graphics> m_draw;
SWMI.WriteableBitmap m_wpfBitmap = null;
Bitmap m_gdiBitmap = null;
public GdiGraphicsWriteableBitmap(Action<Rectangle, Graphics> draw)
{
if (draw == null) { throw new ArgumentNullException(nameof(draw)); }
m_draw = draw;
}
public SWMI.WriteableBitmap WriteableBitmap => m_wpfBitmap;
public bool IfNewSizeResizeAndDraw(int width, int height)
{
if (m_wpfBitmap == null ||
m_wpfBitmap.PixelHeight != height ||
m_wpfBitmap.PixelWidth != width)
{
Reset();
// Can't dispose wpf
const double Dpi = 96;
m_wpfBitmap = new SWMI.WriteableBitmap(width, height, Dpi, Dpi,
SWM.PixelFormats.Bgr24, null);
var ptr = m_wpfBitmap.BackBuffer;
m_gdiBitmap = new Bitmap(width, height, m_wpfBitmap.BackBufferStride,
System.Drawing.Imaging.PixelFormat.Format24bppRgb, ptr);
Draw();
return true;
}
return false;
}
public void Draw()
{
if (m_wpfBitmap != null)
{
m_wpfBitmap.Lock();
int width = m_wpfBitmap.PixelWidth;
int height = m_wpfBitmap.PixelHeight;
{
using (var g = Graphics.FromImage(m_gdiBitmap))
{
m_draw(new Rectangle(0, 0, width, height), g);
}
}
m_wpfBitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
m_wpfBitmap.Unlock();
}
}
// If window containing this is not shown, one can Reset to stop draw or similar...
public void Reset()
{
m_gdiBitmap?.Dispose();
m_wpfBitmap = null;
}
}
And then binding the ImageSource to an Image in XAML:
<Grid x:Name="ImageContainer" SnapsToDevicePixels="True">
<Image x:Name="ImageSource"
RenderOptions.BitmapScalingMode="HighQuality" SnapsToDevicePixels="True">
</Image>
</Grid>
And the handling resize on the Grid to make the WriteableBitmap match in size e.g.:
public partial class SomeView : UserControl
{
ISizeChangedViewModel m_viewModel = null;
public SomeView()
{
InitializeComponent();
this.DataContextChanged += OnDataContextChanged;
}
void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (m_viewModel != null)
{
this.ImageContainer.SizeChanged -= ImageSource_SizeChanged;
}
m_viewModel = e.NewValue as ISizeChangedViewModel;
if (m_viewModel != null)
{
this.ImageContainer.SizeChanged += ImageSource_SizeChanged;
}
}
private void ImageSource_SizeChanged(object sender, SizeChangedEventArgs e)
{
var newSize = e.NewSize;
var width = (int)Math.Round(newSize.Width);
var height = (int)Math.Round(newSize.Height);
m_viewModel?.SizeChanged(width, height);
}
}
This way you can use WinForms/GDI+ for drawing with zero heap allocations and even WriteableBitmapEx if you prefer. Note that you then get great DrawString support with GDI+ incl. MeasureString.
The drawback is this is rasterized and sometimes can have some interpolation issues. So be sure to also set UseLayoutRounding="True" on the parent window/user control.

Enlarge image after click C# UWP

How can I enlarge image in C# (exactly in UWP) after clicking on it?
I tried few things:
1) I tried to add button, with image content, what I want to enlarge, and then I added event Click. But I don't know what I should to add into that code.
2) i also tried to add image directly to my XAML page, and I wanted to create Tapped event, but again, I don't know what I should to add into that code.
I just want to create a small photogallery, so after clicking on image thumbnail will be opened larger image.
Or if there is any possibility to add pdf files, you can write it too. That's another solution of my problem.
You could enlarge the Image by settings its RenderTransform property to a ScaleTransform:
private void Image_Tapped(object sender, TappedRoutedEventArgs e)
{
Image image = sender as Image;
image.RenderTransform = new ScaleTransform() { ScaleX = 2, ScaleY = 2 };
}
<Image Source="ms-appx:///Assets/pic.png" Tapped="Image_Tapped" Stretch="None" />
The ScaleX and ScaleY properties gets or sets the scaling factor. Please refer to the MSDN documentation for more information: https://msdn.microsoft.com/library/windows/apps/br242940?f=255&MSPPError=-2147217396
Looks good, but there is a problem. When I add more images, like into GridView, they are overlapping, and highlighted. Images can overlap, but image, which I click should be always on top...
You could put the tapped Image in a Popup then and then for example add it back to its original Panel when it is tapped again. I put together an example that should give you the idea and something to build on:
private void Image_Tapped(object sender, TappedRoutedEventArgs e)
{
Image image = sender as Image;
Panel parent = image.Parent as Panel;
if (parent != null)
{
image.RenderTransform = new ScaleTransform() { ScaleX = 2, ScaleY = 2 };
parent.Children.Remove(image);
parent.Children.Add(new Popup() { Child = image, IsOpen = true, Tag = parent });
}
else
{
Popup popup = image.Parent as Popup;
popup.Child = null;
Panel panel = popup.Tag as Panel;
image.RenderTransform = null;
panel.Children.Add(image);
}
}
<GridView SelectionMode="None" isItemClickEnabled="True">
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<Image Source="ms-appx:///Assets/pic.png" Tapped="Image_Tapped" Stretch="None" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>

How to add grid background Image in c#

I am trying to change images source or image background in c# when a button is click with xaml design UI.
<Grid x:Name="gridimage">
<Image x:Name="Image" stretch="Fill"/>
</Grid>
private void Button1_click(object sender, RoutedEventArgs e)
{
// NOT WORKING FOR ME
gridimage.Source = new BitmapImage (new Uri("location"));
gridimage.Background = ?
}
Assumed that there is an Assets folder in your Visual Studio project that contains an image file 2.png, and that the image file's Build Action is set to Resource, you would create a BitmapImage in code behind from a Pack URI like this:
var uri = new Uri("pack://application:,,,/Assets/2.png");
var bitmap = new BitmapImage(uri);
Then you would use the BitmapImage as Source of your Image control:
Image.Source = bitmap;
Or use it with an ImageBrush as Background of your Grid:
gridimage.Background = new ImageBrush(bitmap);

Categories

Resources