Creating Image Dynamically - c#

I am having a problem while making a Whack a Mole type game, I am trying to create the images where the mole will appear dynamically, yet there is only a blank white screen where the stack panel is. It is fair to say that I am a noob.
This is my loop where I am trying to create these images:
Image[] ImageArray = new Image[50];
InitializeComponent();
//string ImageName = "Image";
for (int i = 0; i <= 8; i++)
{
Image Image = new Image();
ImageArray[i] = Image;
Image.Name = "Image" + i.ToString();
StackPanel1.Children.Add(ImageArray[i]);
}
//Random Number Generator
Random rnd = new Random();
int num = rnd.Next(1, 9);
//If Random Number is "1" Then Image will display
if (num == 1)
{
ImageSource MoleImage = new BitmapImage(new Uri(ImgNameMole));
ImageArray[1].Source = MoleImage;
}
This is the StackPanel XAML:
<Window x:Name="Window1" x:Class="WhackaMole.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="468.843" Width="666.045" OpacityMask="#FFF70D0D" Icon="mole2.png" Cursor="" >
<Grid OpacityMask="#FF5D1313">
<Image Margin="422,191,-185,-69" Source="mole2.png" Stretch="Fill" HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
<TextBlock HorizontalAlignment="Left" Margin="35,31,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="52" Width="595" FontSize="50" FontFamily="SimHei"><Run Language="en-ca" Text="Can You Catch the Mole?"/></TextBlock>
<Button x:Name="NewGameBttn" Content="New Game" HorizontalAlignment="Left" Margin="77,0,0,16" VerticalAlignment="Bottom" Width="139" Height="50" FontSize="25" Click="NewGameBttn_Click"/>
<Button x:Name="CloseBttn" Content="Close" HorizontalAlignment="Left" Margin="245,365,0,0" VerticalAlignment="Top" Width="76" Height="50" FontSize="29" Click="CloseBttn_Click"/>
<StackPanel x:Name="StackPanel1" HorizontalAlignment="Left" Height="231" Margin="35,112,0,0" VerticalAlignment="Top" Width="525"/>
</Grid>
</Window>

As far as I can tell you're creating a new object of type Image but that Image really doesn't have anything to display. You need to set the Source of your Image. Here's an example stolen from MSDN.
Image myImage = new Image();
myImage.Source = new BitmapImage(new Uri("myPicture.jpg", UriKind.RelativeOrAbsolute));
LayoutRoot.Children.Add(myImage);
As townsean pointed out, you should probably create a Style for your Image where you can set common properties such as Height, Width etc.

My guess is that since you are adding the items to a StackPanel, the StackPanel is choosing the default mins for height and width on the image (which is probably 0), and that is why you are not seeing anything.
Try setting a value for the Height and Width of the image and see if anything shows.
Also, as Tejas pointed out you are not setting the image source.
EDIT: Set the Image width like this:
Image myImage = new Image();
myImage.Width = 25;
myImage.Height = 25;
Do something like this in your for-loop where you first create the images.

Related

Draw rectangle over SwapChainPanel

I'm receiving a live video from a DJI drone in a SwapChainPanel and I'm using template matching from OpenCV to find an image inside the frames of the video.
I want to draw a rectangle when the subgimage is detected, but there are white spaces in both sides of the frames and I don't know how to get the size of those or align the image to the left and top.
Here is the XAML:
<SwapChainPanel x:Name="swapChainPanel" Grid.Column="8" Grid.ColumnSpan="4" Grid.Row="2" Grid.RowSpan="11">
<Canvas>
<Rectangle x:Name="rectFiducial" Visibility="Collapsed" Stroke="Red"></Rectangle>
<Rectangle Stroke="Blue" Width="400" Height="400"></Rectangle>
</Canvas>
</SwapChainPanel>
Here is the code when I try to draw the rectangle with the results of the Template Matching:
SoftwareBitmap inputBitmap = SoftwareBitmap.CreateCopyFromBuffer(CryptographicBuffer.CreateFromByteArray(imageData),
BitmapPixelFormat.Rgba8,
imageWidth,
imageHeight);
if (inputBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8
|| inputBitmap.BitmapAlphaMode != BitmapAlphaMode.Premultiplied)
{
inputBitmap = SoftwareBitmap.Convert(inputBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
}
int x = 0, y = 0, matchMethod = 0;
double matchResult = 0;
Stopwatch testWatch = new Stopwatch();
testWatch.Start();
await txtMatchMethod.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
int.TryParse(txtMatchMethod.Text, out matchMethod);
});
OpenCV.TemplateMatching(inputBitmap, template, matchMethod, out x, out y, out matchResult);
testWatch.Stop();
await txtMatchTime.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
txtMatchTime.Text = testWatch.ElapsedMilliseconds.ToString();
txtMatchResult.Text = matchResult.ToString();
double swapX = x * swapChainPanel.ActualWidth / imageWidth;
double swapY = y * swapChainPanel.ActualHeight / imageHeight;
double swapWidth = template.PixelWidth * swapChainPanel.ActualWidth / imageWidth;
double swapHeight = template.PixelHeight * swapChainPanel.ActualHeight / imageHeight;
rectFiducial.SetValue(Canvas.LeftProperty, swapX);
rectFiducial.SetValue(Canvas.TopProperty, swapY);
rectFiducial.Width = swapWidth;
rectFiducial.Height = swapHeight;
rectFiducial.Visibility = Visibility.Visible;
});
}
There is an event where I can get the bytes of the image and I tried to display it in an Image inside a Canvas, but the image didn't stretch to fit the canvas size.
Edit
I realized that I'm calculating the position based on the width and height of the SwapChainPanel, but I have to calculate it with the width and height of the image inside.
So I would need to get the data of the resized image that is inside the SwapChainPanel and the padding of the left side.
Well, I couldn't find a solution for the SwapChainPanel, but I found a solution with the image and the canvas.
I was trying to make something like this:
<Canvas x:Name="canvas" Grid.Column="8" Grid.ColumnSpan="4" Grid.Row="4" Grid.RowSpan="11">
<Image x:Name="imgDrone" HorizontalAlignment="Left"/>
<Rectangle x:Name="rectFiducial" Visibility="Collapsed" Stroke="Red"></Rectangle>
<Rectangle Stroke="Blue" Width="400" Height="400"></Rectangle>
</Canvas>
But I couldn't stretch the image, it was displayed with it's real size.
So instead of declaring the image inside the Canvas I just took it out and set it's column and row with the same values of the canvas.
Like this:
<Image x:Name="imgDrone" HorizontalAlignment="Left" Grid.Column="8" Grid.ColumnSpan="2" Grid.Row="2" Grid.RowSpan="11"/>
<Canvas x:Name="canvas" Grid.Column="8" Grid.ColumnSpan="4" Grid.Row="4" Grid.RowSpan="11">
<Rectangle x:Name="rectFiducial" Visibility="Collapsed" Stroke="Red"></Rectangle>
<Rectangle Stroke="Blue" Width="400" Height="400"></Rectangle>
</Canvas>

How can you specify the coordinates that you want a bitmap to appear on a canvas?

Given a bitmap:
Swamp1 = new BitmapImage(new Uri("pack://application:,,,/Images/Swamp-Corner-Transparent.png"));
How can I specify the coordinates that it will appear on a canvas:
<Canvas Grid.Column="2" HorizontalAlignment="Right" Height="822" VerticalAlignment="Top" Width="1198" Name="MainCanvas">
<Image Name="MapBorderSource" />
</Canvas>
I've done this before, but it was a long time ago. Specifically, I need to draw the BitmapImage 'Swamp1' at the coordinates X,Y of the Canvas 'MainCanvas' on top of the Image 'MapBorderSource'. The PNG has white set to Alpha 0.
In code behind, you would write
var image = new Image
{
Source = new BitmapImage(new Uri(
"pack://application:,,,/Images/Swamp-Corner-Transparent.png"));
};
Canvas.SetLeft(image, x);
Canvas.SetTop(image, y);
MainCanvas.Children.Add(image);
If you need to put the new Image directly on top of MapBorderSource, below any possible other child elements, you could write
var index = MainCanvas.Children.IndexOf(MapBorderSource) + 1;
MainCanvas.Children.Insert(index, image);
You can specify coordinates like this..
<Image Name="MapBorderSource" Canvas.Top="10" Canvas.Left="10" />

Prevent resize of control in grid WPF C#

(Edit) i have an image in tabItem1. when i resize window(dragging by corner or maximize button) the image also resize and occupy whole grid. i added width and height on image and the resisng stopped default to actual image width & height in pixels.
Do i have to apply width and height to prevent resising of control whom i don't want to resize on window scale? or is there any property for controls to prevent resizing.
Basically, i'll have some pics which i don't want to be resided, and there will be some text which i want to be resided.
XAML:
<Window x:Class="Engine.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="600" Height="600">
<Grid>
<TabControl Grid.RowSpan="2">
<TabItem Header="TabItem1">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid x:Name="TGrid1" Background="#FFE5E5E5"/>
</ScrollViewer>
</TabItem>
<TabItem Header="TabItem2">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid x:Name="TGrid2" Background="#FFE5E5E5">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
</ScrollViewer>
</TabItem>
</TabControl>
</Grid>
</Window>
Code:
public MainWindow()
{
InitializeComponent();
var bitmapFrame = BitmapFrame.Create(new Uri(#"" + AppDomain.CurrentDomain.BaseDirectory + "Chrysanthemum.jpg"), BitmapCreateOptions.DelayCreation, BitmapCacheOption.None);
var dragDropImage = new Image
{
Source = bitmapFrame, //new BitmapImage(new Uri(#"" + AppDomain.CurrentDomain.BaseDirectory + "Chrysanthemum.jpg")),
Name = "dragDropImage",
Width = bitmapFrame.PixelWidth,
Height = bitmapFrame.PixelHeight
};
TGrid1.Children.Add(dragDropImage);
var rect = new Rectangle
{
Stroke = new SolidColorBrush(Colors.Red),
Fill = new SolidColorBrush(Colors.Black),
Width = 474,
Height = 405
};
Grid.SetRow(rect, 0);
TGrid2.Children.Add(rect);
}
If you set the properties VerticalAlignment (for example to Top) and HorizontalAlignment (for example to Left) of your components image and rect, these controls will be sized according to the content need, instead of the available space in the container.
Is that what you want ?
EDIT : For your image, you should set its property Stretch="None".
See here.
EDIT 2 :
var dragDropImage = new Image
{
Source = bitmapFrame, //new BitmapImage(new Uri(#"" + AppDomain.CurrentDomain.BaseDirectory + "Chrysanthemum.jpg")),
Name = "dragDropImage",
VerticalAlignment = System.Windows.VerticalAlignment.Top,
HorizontalAlignment = System.Windows.HorizontalAlignment.Right,
Stretch = System.Windows.Media.Stretch.None
};

How to Place Border Around a Picture

In a page I display a picture that I receive from CameraCapureTask in the View
<Grid x:Name="EditPageGrid" Margin="{Binding}">
<Grid Name="ViewportContainer" Margin="12,0,12,24">
<Image x:Name="Viewport" LayoutUpdated="Viewport_LayoutUpdated"
Source="{Binding}"/>
</Grid>
</Grid>
And I wish to be able to place a border around this image. How would it be possible to do this? I was thinking perhaps on a click event of some sort a border could be toggled on or off, but actually applying a border is where I am at a loss.
You can contain the image in a Border, like this:
<Grid x:Name="EditPageGrid" Margin="{Binding}">
<Grid Name="ViewportContainer" Margin="12,0,12,24">
<Border HorizontalAlignment="Center" BorderThickness="4" BorderBrush="Red">
<Image Source="C:\Users\Public\Pictures\Sample Pictures\Jellyfish.jpg"/>
</Border>
</Grid>
</Grid>
I figured out such an event: (probably there is better method, but this also works)
private void Viewport_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
int imageHeight = (Viewport.Source as BitmapImage).PixelHeight;
int imageWidth = (Viewport.Source as BitmapImage).PixelWidth;
Canvas myCanvas = new Canvas();
Rectangle myBorder = new Rectangle();
myBorder.Width = imageWidth;
myBorder.Height = imageHeight;
myBorder.Stroke = new SolidColorBrush(Colors.Red);
myBorder.StrokeThickness = 10;
Image toBorder = new Image();
toBorder.Source = Viewport.Source as BitmapImage;
myCanvas.Children.Add(toBorder);
myCanvas.Children.Add(myBorder);
WriteableBitmap newImage = new WriteableBitmap(myCanvas, null);
//Viewport.Source = newImage; - you can use this but watch out that Viewport.Source now is not BitmapImage
//Below is one method how to make it BitmapImage
//You can of course save newImage to file or whatever you want
//You can also unsubscribe this event to prevent it from second tap which will cause Exception at first line (BitmaImage != WriteableBitmap)
MemoryStream memoryStream = new MemoryStream();
newImage.SaveJpeg(memoryStream, imageWidth, imageHeight, 0, 100);
BitmapImage newBitmap = new BitmapImage();
newBitmap.SetSource(memoryStream);
Viewport.Source = newBitmap;
}
Playing with this memory stream isn't good, but I've not known what you are planning to do with your new Bitmap.
As I've said - it's only example and I'm sure better methods exist (which I don't know). Hope this helps.

Get the item index which is on focus inside a stackpanel

I have added 10 images in a stackpanel horizontally which is inside a scrollviewer. When user swipe the page the scrollviewer stops at certain position, if the scroll stops at &th image i want to get the name of the image. How to get that?
for (int i = 0; i <= 59; i++)
{
Uri uri = new Uri("http://d1mu9ule1cy7bp.cloudfront.net/2012/media/catalogues/47/pages/p_" + i + "/thump.jpg");
ImageSource img1 = new BitmapImage(uri);
Image rect = new Image { RenderTransform = new TranslateTransform() };
rect.Source = img1;
stack.Children.Add(rect);
}
XAML:
<ScrollViewer HorizontalContentAlignment="Left" HorizontalAlignment="Left" Name="scroll" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Visible">
<StackPanel Name="stack" Width="Auto" Orientation="Horizontal" HorizontalAlignment="Left" >
</StackPanel>
</ScrollViewer>
Assuming that your images are all the same size, you could calculate this by looking at the HorizontalOffset of the ScrollViewer.

Categories

Resources