Image is not converted from Uri to Bitmap image in UWP - c#

I have referred the below thread for combing multiple images as single image in uwp.
Merging multiple Images
But the image is not properly converted from Uri to bitmap images for the tiles downloaded from below link
https://a.tile.openstreetmap.org/0/0/0.png
public MainPage()
{
this.InitializeComponent();
MergeImages();
}
async void MergeImages()
{
byte[] Canvas = new byte[512 * 512 * 4];
Windows.Storage.Streams.IRandomAccessStream random = await Windows.Storage.Streams.RandomAccessStreamReference.CreateFromUri(
new Uri("https://a.tile.openstreetmap.org/1/0/0.png",UriKind.RelativeOrAbsolute)).OpenReadAsync();
Windows.Graphics.Imaging.BitmapDecoder decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(random);
Windows.Graphics.Imaging.PixelDataProvider pixelData = await decoder.GetPixelDataAsync();
byte[] tileImage = pixelData.DetachPixelData();
Canvas = PutOnCanvas(Canvas, tileImage, 0,
0, 256, 256, 512);
InMemoryRandomAccessStream memStream = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(Windows.Graphics.Imaging.BitmapEncoder.PngEncoderId, memStream);
encoder.SetPixelData(
Windows.Graphics.Imaging.BitmapPixelFormat.Bgra8,
Windows.Graphics.Imaging.BitmapAlphaMode.Straight,
512, // pixel width
512, // pixel height
96, // horizontal DPI
96, // vertical DPI
Canvas);
try
{
await encoder.FlushAsync();
var bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(memStream);
image.Source = bitmapImage;
}
catch { }
memStream.Dispose();
}
byte[] PutOnCanvas(byte[] Canvas, byte[] Image, uint x, uint y, uint imageheight, uint imagewidth, uint CanvasWidth)
{
for (uint row = y; row < y + imageheight; row++)
for (uint col = x; col < x + imagewidth; col++)
for (int i = 0; i < 4; i++)
Canvas[(row * CanvasWidth + col) * 4 + i] = Image[((row - y) * imagewidth + (col - x)) * 4 + i];
return Canvas;
}
Sample
Actual Output:
Expected output

I found your previous two threads:
How to avoid the flickering effect when dynamically changes the image source in uwp
How to combine multiple image as single image in UWP
They all aimed to avoid the flickering effect. As I comment in your second thread, the flickering effect is caused by you change the images's source in a short time, if you want to avoid it, you can use the animation to change the images with a progress. Here is a example to use the DoubleAnimation Storyboard to animate Opacity property of the Images stackpanel base on your first thread sample:
MainPage.xaml: I create two storyboard to make the images stackpanel disappear or display and give the disappearStoryboard a disappearStoryboard_Completed event handler.
<Page.Resources>
<Storyboard x:Name="disappearStoryboard" Completed="disappearStoryboard_Completed">
<DoubleAnimation
Storyboard.TargetName="RootStackPanel"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:1"/>
</Storyboard>
<Storyboard x:Name="displayStoryboard">
<DoubleAnimation
Storyboard.TargetName="RootStackPanel"
Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:1"/>
</Storyboard>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Name="RootStackPanel">
<StackPanel Orientation="Horizontal">
<Image x:Name="image1" Height="200" Width="200" Source="ms-appx:///Assets/custom200.png"/>
<Image x:Name="image2" Height="200" Width="200" Source="ms-appx:///Assets/custom201.png"/>
<Image x:Name="image3" Height="200" Width="200" Source="ms-appx:///Assets/custom202.png"/>
<Image x:Name="image4" Height="200" Width="200" Source="ms-appx:///Assets/custom203.png"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image x:Name="image5" Height="200" Width="200" Source="ms-appx:///Assets/custom210.png"/>
<Image x:Name="image6" Height="200" Width="200" Source="ms-appx:///Assets/custom211.png"/>
<Image x:Name="image7" Height="200" Width="200" Source="ms-appx:///Assets/custom212.png"/>
<Image x:Name="image8" Height="200" Width="200" Source="ms-appx:///Assets/custom213.png"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image x:Name="image9" Height="200" Width="200" Source="ms-appx:///Assets/custom220.png"/>
<Image x:Name="image10" Height="200" Width="200" Source="ms-appx:///Assets/custom221.png"/>
<Image x:Name="image11" Height="200" Width="200" Source="ms-appx:///Assets/custom222.png"/>
<Image x:Name="image12" Height="200" Width="200" Source="ms-appx:///Assets/custom223.png"/>
</StackPanel>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button Height="50" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
Content="ReplaceCustom" x:Name="replaceCustom" Click="replaceCustom_Click" Margin="5"/>
<Button Height="50" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
Content="Replace OSM" x:Name="replaceOSM" Click="replace_Click" Margin="5"/>
<Button Height="50" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
Content="Replace Tile" x:Name="replaceTile" Click="replaceTile_Click" Margin="5"/>
</StackPanel>
</Grid>
MainPage.xaml.cs: I change the Images' resource in the disappearStoryboard 's disappearStoryboard_Completed event handler.
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
bool replaceButtonClicked, replaceCustomButtonClicked, replaceTileButtonClicked;
private void replace_Click(object sender, RoutedEventArgs e)
{
replaceButtonClicked = true;
disappearStoryboard.Begin();
}
private void replaceCustom_Click(object sender, RoutedEventArgs e)
{
replaceCustomButtonClicked = true;
disappearStoryboard.Begin();
}
private void replaceTile_Click(object sender, RoutedEventArgs e)
{
replaceTileButtonClicked = true;
disappearStoryboard.Begin();
}
private void disappearStoryboard_Completed(object sender, object e)
{
if (replaceButtonClicked)
{
image1.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM200.png",
UriKind.RelativeOrAbsolute));
image2.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM201.png",
UriKind.RelativeOrAbsolute));
image3.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM202.png",
UriKind.RelativeOrAbsolute));
image4.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM203.png",
UriKind.RelativeOrAbsolute));
image5.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM210.png",
UriKind.RelativeOrAbsolute));
image6.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM211.png",
UriKind.RelativeOrAbsolute));
image7.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM212.png",
UriKind.RelativeOrAbsolute));
image8.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM213.png",
UriKind.RelativeOrAbsolute));
image9.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM220.png",
UriKind.RelativeOrAbsolute));
image10.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM221.png",
UriKind.RelativeOrAbsolute));
image11.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM222.png",
UriKind.RelativeOrAbsolute));
image12.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM223.png",
UriKind.RelativeOrAbsolute));
replaceButtonClicked = false;
}
if (replaceCustomButtonClicked)
{
image1.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom200.png",
UriKind.RelativeOrAbsolute));
image2.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom201.png",
UriKind.RelativeOrAbsolute));
image3.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom202.png",
UriKind.RelativeOrAbsolute));
image4.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom203.png",
UriKind.RelativeOrAbsolute));
image5.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom210.png",
UriKind.RelativeOrAbsolute));
image6.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom211.png",
UriKind.RelativeOrAbsolute));
image7.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom212.png",
UriKind.RelativeOrAbsolute));
image8.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom213.png",
UriKind.RelativeOrAbsolute));
image9.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom220.png",
UriKind.RelativeOrAbsolute));
image10.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom221.png",
UriKind.RelativeOrAbsolute));
image11.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom222.png",
UriKind.RelativeOrAbsolute));
image12.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom223.png",
UriKind.RelativeOrAbsolute));
replaceCustomButtonClicked = false;
}
if (replaceTileButtonClicked)
{
image1.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM300.png",
UriKind.RelativeOrAbsolute));
image2.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM301.png",
UriKind.RelativeOrAbsolute));
image3.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM302.png",
UriKind.RelativeOrAbsolute));
image4.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM303.png",
UriKind.RelativeOrAbsolute));
image5.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM304.png",
UriKind.RelativeOrAbsolute));
image6.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM305.png",
UriKind.RelativeOrAbsolute));
image7.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM306.png",
UriKind.RelativeOrAbsolute));
image8.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM301.png",
UriKind.RelativeOrAbsolute));
image9.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM302.png",
UriKind.RelativeOrAbsolute));
image10.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM303.png",
UriKind.RelativeOrAbsolute));
image11.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM310.png",
UriKind.RelativeOrAbsolute));
image12.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM311.png",
UriKind.RelativeOrAbsolute));
replaceTileButtonClicked = false;
}
displayStoryboard.Begin();
}
}

Related

How to get the area of an image in WPF that is bounded inside a rectangle as a separate image? [duplicate]

I was following this article and I got my canvas to be saved, however, I want to extend the code's functionality and save a particular part of my canvas as an image, rather than my entire canvas.
I tried setting the rect.Offset and rect.Location properties but the image is always saved from the upper left corner of my canvas.
Does anyone know how can I achieve my wanted functionality in a similar way?
Thanks!
A simple method would be to use a CroppedBitmap after rendering the whole canvas. You could reuse the same RenderTargetBitmap, if you need multiple images.
RenderTargetBitmap rtb = new RenderTargetBitmap((int)canvas.RenderSize.Width,
(int)canvas.RenderSize.Height, 96d, 96d, System.Windows.Media.PixelFormats.Default);
rtb.Render(canvas);
var crop = new CroppedBitmap(rtb, new Int32Rect(50, 50, 250, 250));
BitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(crop));
using (var fs = System.IO.File.OpenWrite("logo.png"))
{
pngEncoder.Save(fs);
}
If you want to save to a bitmap object instead of a file, you can use:
using (Stream s = new MemoryStream())
{
pngEncoder.Save(s);
Bitmap myBitmap = new Bitmap(s);
}
I know this is an old question, but it took me a while of searching and trying different answers to come up with something that worked reliably well. So to save some time for those in the future, here is a little service to either save a canvas out to a file, or return an ImageSource for display elsewhere in your application.
It should be made more robust for a production application, additional null and error checking, etc..
public static class RenderVisualService
{
private const double defaultDpi = 96.0;
public static ImageSource RenderToPNGImageSource(Visual targetControl)
{
var renderTargetBitmap = GetRenderTargetBitmapFromControl(targetControl);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
var result = new BitmapImage();
using (var memoryStream = new MemoryStream())
{
encoder.Save(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
result.BeginInit();
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = memoryStream;
result.EndInit();
}
return result;
}
public static void RenderToPNGFile(Visual targetControl, string filename)
{
var renderTargetBitmap = GetRenderTargetBitmapFromControl(targetControl);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
var result = new BitmapImage();
try
{
using (var fileStream = new FileStream(filename, FileMode.Create))
{
encoder.Save(fileStream);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"There was an error saving the file: {ex.Message}");
}
}
private static BitmapSource GetRenderTargetBitmapFromControl(Visual targetControl, double dpi = defaultDpi)
{
if (targetControl == null) return null;
var bounds = VisualTreeHelper.GetDescendantBounds(targetControl);
var renderTargetBitmap = new RenderTargetBitmap((int)(bounds.Width * dpi / 96.0),
(int)(bounds.Height * dpi / 96.0),
dpi,
dpi,
PixelFormats.Pbgra32);
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
{
var visualBrush = new VisualBrush(targetControl);
drawingContext.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size));
}
renderTargetBitmap.Render(drawingVisual);
return renderTargetBitmap;
}
}
And a sample WPF app demonstrating it's use.
MainWindow.xaml
<Window x:Class="CanvasToBitmapDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CanvasToBitmapDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Click="Button_Click" Content="Capture Image" Width="100"/>
<Button Click="Button_Click_1" Content="Save To Disk" Width="100"/>
</StackPanel>
<Canvas x:Name="PART_Canvas" Grid.Row="1" Grid.Column="0">
<Ellipse Canvas.Top="50"
Canvas.Left="60"
Fill="Gold"
Width="250"
Height="250" />
<Polyline Stroke="#FF853D00"
StrokeThickness="10"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round"
Points="110,100 120,97 130,95 140,94 150,95 160,97 170,100" />
<Ellipse Canvas.Top="115"
Canvas.Left="114"
Fill="#FF853D00"
Width="45"
Height="50" />
<Polyline Stroke="#FF853D00"
StrokeThickness="10"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round"
Points="205,120 215,117 225,115 235,114 245,115 255,117 265,120" />
<Ellipse Canvas.Top="120"
Canvas.Left="208"
Fill="#FF853D00"
Width="45"
Height="50" />
<Polyline Stroke="#FF853D00"
StrokeThickness="10"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round"
Points="150,220 160,216 170,215 180,215 190,216 202,218 215,221" />
</Canvas>
<Image x:Name="PART_Image" Grid.Row="1" Grid.Column="1" Stretch="None"/>
</Grid>
And the code behind making the calls into the service.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
PART_Image.Source = RenderVisualService.RenderToPNGImageSource(PART_Canvas);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
RenderVisualService.RenderToPNGFile(PART_Canvas, "myawesomeimage.png");
}
}
Looking at the link you posted, obviously you can choose the rendered target coordinates here.
RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right,
(int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default);
See if this solution works for you.
Size size = new Size(width, height);
canvas.Measure(size);
canvas.Arrange(new Rect(X, Y, width, height));
//Save Image
...
...
// Revert old position
canvas.Measure(new Size());
In my case, I needed to apply a size constraint for the resulting image, since the images needed to be stored and later used as a small icon.
I was able to scale the image down to a reasonable size using CreateScaledRect below in combination with GetScaledRenderTargetBitmapFromControl (thanks to code from #Andy Stagg's post).
Then, to store the image for later use, I used the SaveImageOfControlToStream method below.
private static Rect CreateScaledRect(Visual targetControl)
{
Rect scaledRect;
var bounds = VisualTreeHelper.GetDescendantBounds(targetControl);
// maintain aspect ratio and make sure scaledRect is at least 64 wide or 64 high
if (bounds.Width < bounds.Height)
{
scaledRect = new Rect(new Point(), new Size(64, bounds.Height / bounds.Width * 64));
}
else
{
scaledRect = new Rect(new Point(), new Size(bounds.Width / bounds.Height * 64, 64));
}
return scaledRect;
}
private static BitmapSource GetScaledRenderTargetBitmapFromControl(Visual targetControl, double dpi = defaultDpi)
{
if (targetControl == null) return null;
// Calling CreateScaledRect here to reduce image size
var bounds = CreateScaledRect(targetControl);
var renderTargetBitmap = new RenderTargetBitmap((int)(bounds.Width * dpi / 96.0),
(int)(bounds.Height * dpi / 96.0),
dpi,
dpi,
PixelFormats.Pbgra32);
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
{
var visualBrush = new VisualBrush(targetControl);
drawingContext.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size));
}
renderTargetBitmap.Render(drawingVisual);
return renderTargetBitmap;
}
public static void SaveImageOfControlToStream(Stream outputStream, Visual targetControl)
{
var bitmapSource = GetScaledRenderTargetBitmapFromControl(targetControl);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource ));
encoder.Save(outputStream);
}

the added images lay over each other in WPF

I am adding images to the WPF stack panel using the C# code. For positioning the images, I am using margin keyword but when I have run the project, a white space for the last image created and push the first image. why?
In the below, I have loaded two images from the same source whit different margins and as you see the first image is covered by the white space from the second image. note that the source Image is a png image and has not any with border.
the code is below(note that I used image control first and then i used the border control and both have the same problem ):
Border newLegBorder =new Border();
BitmapImage casingLegBitmapImage = new BitmapImage(new Uri("images/casingleg.png", UriKind.Relative));
newLegBorder.Background = new ImageBrush(casingLegBitmapImage);
newLegBorder.Width = casingLegBitmapImage.Width;
newLegBorder.Height = casingLegBitmapImage.Height;
newLegBorder.SetValue(Grid.ColumnProperty, 0);
newLegBorder.SetValue(Grid.RowProperty, 0);
newLegBorder.VerticalAlignment = VerticalAlignment.Top;
newLegBorder.Margin = new Thickness(0, 0, 100, 0);
newLegBorder.Width = casingLegBitmapImage.Width;
newLegBorder.Height = casingLegBitmapImage.Height;
schematic.Children.Add(newLegBorder);
Border newLeg2Border = new Border();
BitmapImage casingLeg2BitmapImage = new BitmapImage(new Uri("images/casingleg.png", UriKind.Relative));
newLeg2Border.Background = new ImageBrush(casingLeg2BitmapImage);
newLeg2Border.Width = casingLeg2BitmapImage.Width;
newLeg2Border.Height = casingLeg2BitmapImage.Height;
newLeg2Border.SetValue(Grid.ColumnProperty, 0);
newLeg2Border.SetValue(Grid.RowProperty, 0);
newLeg2Border.VerticalAlignment = VerticalAlignment.Top;
newLeg2Border.Margin = new Thickness(100, 0, 0, 0);
newLeg2Border.Width = casingLeg2BitmapImage.Width;
newLeg2Border.Height = casingLeg2BitmapImage.Height;
schematic.Children.Add(newLeg2Border);
<Window
xmlns="schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerikDocking‌​="clr-namespace:Teler‌​ik.Windows.Controls;a‌​ssembly=Telerik.Windo‌​ws.Controls.Docking"
xmlns:System="clr-na‌​mespace:System;assemb‌​ly=mscorlib"
xmlns:telerik="http:‌​//schemas.telerik.com‌​/2008/xaml/presentati‌​on"
xmlns:Chromes="clr-n‌​amespace:Telerik.Wind‌​ows.Controls.Chromes;‌​assembly=Telerik.Wind‌​ows.Controls"
xmlns:Primitives="cl‌​r-namespace:Telerik.Wi‌​ndows.Controls.Primit‌​ives;assembly=Telerik‌​.Windows.Controls.Nav‌​igation"
x:Class="imagetoolbo‌​x.wellSchematic"
Title="wellSchematic‌​"
Height="402" Width="458">
<Grid>
<Grid.ColumnDefiniti‌​ons>
<ColumnDefinition/>
<ColumnDefinition Width="236"/>
</Grid.ColumnDefinit‌​ions>
<StackPanel x:Name="schematic" HorizontalAlignment=‌​"Left" Height="371" VerticalAlignment="T‌​op" Width="214">
</StackPanel>
</Grid>
</Window>
The problem is that the stackpanel will, well, stack all children. The first image is not covered by the second image, they are merely stacked on top of each other.
To position the images you should use the grid directly, combined with margins and alignments.
Play around with the XAML sample below to get the layout you want, and transfer it to codebehind.
<Window
....>
<Grid x:Name="schematic">
<!-- First image will stretch vertically -->
<Image Stretch="Fill" Margin="10,20,0,25" HorizontalAlignment="Left" VerticalAlignment="Top" Width="10">
<Image.Source>
<BitmapImage UriSource="images/casingleg"/>
</Image.Source>
</Image>
<Image Margin="0,30,20,0" HorizontalAlignment="Right" VerticalAlignment="Top" Width="10">
<Image.Source>
<BitmapImage UriSource="images/casingleg"/>
</Image.Source>
</Image>
<Image Margin="40,0,0,10" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="10">
<Image.Source>
<BitmapImage UriSource="images/casingleg"/>
</Image.Source>
</Image>
</Grid>
</Window>
Code-behind for the above sample.
public class WellSchematic : UserControl
{
public WellSchematic()
{
InitializeComponent();
var im1 = CreateImage();
im1.HorizontalAlignment = HorizontalAlignment.Left;
im1.VerticalAlignment = VerticalAlignment.Top;
im1.Margin = new Margin(10,20,0,25);
im1.Stretch = Stretch.Fill;
var im2 = CreateImage();
im2.HorizontalAlignment = HorizontalAlignment.Right;
im2.VerticalAlignment = VerticalAlignment.Top;
im2.Margin = new Margin(0,30,20,0);
var im3 = CreateImage();
im3.HorizontalAlignment = HorizontalAlignment.Left;
im3.VerticalAlignment = VerticalAlignment.Bottom;
im3.Margin = new Margin(40,0,0,10);
// Add more pictures
}
private void CreateImage()
{
var image = new Image();
var bmp = new BitmapImage(new Uri(#"images/casingleg", UriKind.Relative));
image.Source = bmp;
image.Width = bmp.Width;
image.Height = bmp.Height;
schematic.Children.Add(image);
}
}

Windows Phone - Customizing GridView Max Columns

I'm new to Windows Phone programming. I want to create a gridview like the following:
I've done the <DataTemplate>, so I've already done the items and their buttons. But I can't set 2 columns for the grid using MaximumRowsOrColumns, because it limits my grid with only 2 rows (can be ilimited rows, but I need to have only 2 columns).
Coding as below was the closest I made:
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid Orientation="Vertical" MaximumRowsOrColumns="2"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
EDIT: added <DataTemplate>code:
<DataTemplate x:Key="gridClassItem">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="14.96"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="14.96" />
</Grid.ColumnDefinitions>
<Button x:Name="btnItem" Grid.Row="0" Grid.Column="0"
BorderThickness="0 0 0 2" Opacity="100"
Height="70.4" Width="174.24"
Background="#FF6B33"
Click="btnItem_OnClick">
<TextBlock x:Name="txtItem" FontSize="38" Foreground="#5B1F08" Opacity="100" Margin="0" Text="{Binding Name}" TextAlignment="Center"/>
</Button>
<Grid Grid.Row="1" Grid.Column="0" Margin="0, -8, 0, 0" Height="52.8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="86.24"/>
<ColumnDefinition Width="86.24"/>
</Grid.ColumnDefinitions>
<Button x:Name="btn1" Click="btn1_OnClick"
Grid.Row="0" Grid.Column="0"
BorderBrush="#FFFFFF" BorderThickness="0 0 1.76 0"
Margin="-10, -15, 0, 0"
DataContext="{Binding}">
<Button.Background>
<ImageBrush ImageSource="\Assets\bt1.png" Stretch="UniformToFill"/>
</Button.Background>
</Button>
<Button x:Name="btn2" Click="btn2_OnClick"
Grid.Row="0" Grid.Column="1"
BorderBrush="#FFFFFF" BorderThickness="1.76 0 0 0"
Margin="0, -15, -2.5, 0"
DataContext="{Binding}">
<Button.Background>
<ImageBrush ImageSource="\Assets\bt2.png" Stretch="UniformToFill"/>
</Button.Background>
</Button>
</Grid>
<Rectangle Grid.Row="2" Grid.Column="1" Fill="#FFFFFF" Margin="0"/>
</Grid>
</DataTemplate>
Any suggestions?
By the way, any idea how could i change the GridViewItem's background color? I was thinking about a geometric series, like the first item will be orange, the followings - always counting by two - will be green and then orange again. But I don't know how to implement it.
Well, since I couldn't find a way to do it using XAML, I did it at C#. Below is my solution, if someone need something looked like:
enum GridItemColor
{
NONE,
BLUE,
RED
};
//Some event to populate a list
...
myGrid.Items.Clear();
GridItemColor lastColor = GridItemColor.NONE;
foreach (MyModel item in myList)
{
if (lastColor == GridItemColor.NONE || lastColor == GridItemColor.BLUE)
{
myGrid.Items.Add(FormatGridViewItem(item, GridItemColor.RED));
lastColor = GridItemColor.RED;
}
else if (lastColor == GridItemColor.RED)
{
myGrid.Items.Add(FormatGridViewItem(item, GridItemColor.BLUE));
lastColor = GridItemColor.BLUE;
}
}
...
private Grid FormatGridViewItem(MyModel currentItem, GridItemColor itemColor)
{
Grid gridItem = new Grid();
#region Grid Item Row Definition and GridItem Setup
RowDefinition itemRowDef = new RowDefinition();
RowDefinition minorButtonRowDef = new RowDefinition();
itemRowDef.Height = new GridLength(72);
minorButtonRowDef.Height = new GridLength(49);
gridItem.RowDefinitions.Add(classPlanRowDef);
gridItem.RowDefinitions.Add(minorButtonRowDef);
gridItem.MaxWidth = 196;
gridItem.Width = 196;
gridItem.Margin = new Thickness(0, 0, 24, 24);
#endregion
#region Button Item
Button btnItem = new Button();
btnItem.BorderThickness = new Thickness(0);
btnItem.Margin = new Thickness(-3, 0, 0, 0);
btnItem.Opacity = 100;
btnItem.MaxWidth = 203;
btnItem.MinWidth = 203;
btnItem.Height = 78;
btnItem.DataContext = currentItem;
if (itemColor == GridItemColor.RED)
btnItem.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(0xFF, 255, 107, 51));
else
btnItem.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(0xFF, 23, 229, 192));
btnItem.Click += btnItem_Click;
TextBlock txtItem = new TextBlock();
txtItem.FontSize = 40;
if (itemColor == GridItemColor.RED)
txtItem.Foreground = new SolidColorBrush(Windows.UI.Color.FromArgb(0xFF, 91, 31, 8));
else
txtItem.Foreground = new SolidColorBrush(Windows.UI.Color.FromArgb(0xFF, 3, 97, 80));
txtItem.Opacity = 100;
txtItem.TextAlignment = TextAlignment.Center;
txtItem.Text = currentItem.Name;
txtItem.TextTrimming = TextTrimming.CharacterEllipsis;
btnItem.Content = txtItem;
gridItem.Children.Add(btnItem);
Grid.SetRow(btnItem, 0);
#endregion
#region Grid Minor Buttons Row
Grid minorButtonsRow = new Grid();
minorButtonsRow.Margin = new Thickness(0);
if (itemColor == GridItemColor.RED)
minorButtonsRow.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(0xFF, 255, 107, 51));
else
minorButtonsRow.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(0xFF, 23, 229, 192));
ColumnDefinition btnOneColumnDef = new ColumnDefinition();
ColumnDefinition btnTwoColumnDef = new ColumnDefinition();
btnOneColumnDef.Width = new GridLength(98);
btnTwoColumnDef.Width = new GridLength(98);
minorButtonsRow.ColumnDefinitions.Add(btnOneColumnDef);
minorButtonsRow.ColumnDefinitions.Add(btnTwoColumnDef);
// Button One
Button btnOne = new Button();
btnOne.BorderBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(0xFF, 255, 255, 255));
btnOne.BorderThickness = new Thickness(0);
btnOne.MinWidth = 97;
btnOne.MaxWidth = 97;
btnOne.MinHeight = 48;
btnOne.MaxHeight = 48;
btnOne.Margin = new Thickness(0, 0, 1, 0);
btnOne.DataContext = currentItem;
btnOne.Click += btnOne_Click;
ImageBrush imgOne = new ImageBrush();
BitmapImage bitImg;
if (itemColor == GridItemColor.RED)
{
bitImg = new BitmapImage(new Uri("ms-appx:/Assets/Icons/btOneRED.png", UriKind.RelativeOrAbsolute));
btnOne.Style = (Style)this.Resources["btnOneRedStyle"];
}
else
{
bitImg = new BitmapImage(new Uri("ms-appx:/Assets/Icons/btOneBLUE.png", UriKind.RelativeOrAbsolute));
btnOne.Style = (Style)this.Resources["btnOneBlueStyle"];
}
imgOne.ImageSource = bitImg;
imgOne.Stretch = Stretch.UniformToFill;
btnOne.Background = imgOne;
minorButtonsRow.Children.Add(btnOne);
Grid.SetRow(btnOne, 0);
Grid.SetColumn(btnOne, 0);
// END Button One
// Button Two
Button btnTwo = new Button();
btnTwo.BorderBrush = new SolidColorBrush(Windows.UI.Color.FromArgb(0xFF, 255, 255, 255));
btnTwo.BorderThickness = new Thickness(0);
btnTwo.MinWidth = 97;
btnTwo.MaxWidth = 97;
btnTwo.MinHeight = 48;
btnTwo.MaxHeight = 48;
btnTwo.Margin = new Thickness(1, 0, 0, 0);
btnTwo.DataContext = currentItem;
btnTwo.Click += btnTwo_Click;
ImageBrush imgTwo = new ImageBrush();
BitmapImage bitImgTwo;
if (itemColor == GridItemColor.RED)
{
bitImgTwo = new BitmapImage(new Uri("ms-appx:/Assets/Icons/btTwoRED.png", UriKind.RelativeOrAbsolute));
btnTwo.Style = (Style)this.Resources["btnTwoRedStyle"];
}
else
{
bitImgTwo = new BitmapImage(new Uri("ms-appx:/Assets/Icons/bt_AgendaVerde.png", UriKind.RelativeOrAbsolute));
btnTwo.Style = (Style)this.Resources["btnTwoBlueStyle"];
}
imgTwo.ImageSource = bitImgTwo;
imgTwo.Stretch = Stretch.UniformToFill;
btnTwo.Background = imgTwo;
minorButtonsRow.Children.Add(btnTwo);
Grid.SetRow(btnTwo, 0);
Grid.SetColumn(btnTwo, 1);
gridItem.Children.Add(minorButtonsRow);
Grid.SetRow(minorButtonsRow, 1);
Grid.SetColumn(minorButtonsRow, 0);
// END Button Two
#endregion
return gridItem;
}
If you have DataTemplate done correctly, then you don't need the ItemsPanel template. Can you show the code for DataTemplate? Because with it you can do pretty much everything.
For the colors. Declare brushes on your ViewModel and then assign it to your classes.Then just bind the Background. You only need one for each color.
Color binding: say you have SolidColorBrush property on your model named BgBrush. All you need to do is declare Background property on your control (i.e. grid) as "{Binding BgBrush}"

Saving canvas data to image file output is wrong

I want to place an image over a parent image and save the final image. So I used parent image inside Canvas and added the child image in the canvas.
Problems:
Right after when i loaded the thumbnail(child) image, if i click on the parent image, then the thumbnail(child) image become in-Visible.
I couldn't place the the thumbnail(child) image over the parent image precisely using the mouse left button up release.
I couldn't save the final image with the actual image Height & Width. The final saved image output height & width is wrong.
please guide me to fix the above problems.
SpecialEffects XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:System="clr-namespace:System;assembly=mscorlib"
x:Class="ImagePrintUtility.SpecialEffects"
Title="SpecialEffects" Height="768" Width="1024" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="125"/>
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<DockPanel Grid.Row="0" HorizontalAlignment="Stretch" Margin="0" Background="AliceBlue" Name="DockPanel1">
<WrapPanel>
<StackPanel Margin="5">
<Button Content="AddLogo" Click="Button_Click" Height="50" Width="90" />
<Button Content="Reset Logo" x:Name="bresetLogo" Height="50" Width="90" Margin="0,5" />
</StackPanel>
<StackPanel Margin="5">
<Button Name="bSave" Width="90" Height="50" Foreground="White" Content="Save" Click="bSave_Click" />
<Button x:Name="btnClose" Content="Close" Height="50" Width="90" Margin="0,5" FontSize="20" Click="btnClose_Click" />
</StackPanel>
</WrapPanel>
</DockPanel>
<!--<GridSplitter Grid.Row="1" Grid.RowSpan="1" ResizeDirection="Rows" Width="Auto" Height="10" HorizontalAlignment="Stretch" Margin="0" Name="GridSplitter1" />-->
<Grid Grid.Row="1" Margin="0" Background="AliceBlue" Name="Grid1">
<StackPanel >
<Canvas x:Name="canvas" HorizontalAlignment="Stretch"
MouseLeftButtonDown="CanvasMouseLeftButtonDown"
MouseLeftButtonUp="CanvasMouseLeftButtonUp"
MouseMove="CanvasMouseMove" Margin="0,0,31,0">
<Image x:Name="SpecialPhoto" Source="IMG_0071.JPG" Height="586" Width="780"
Stretch="Uniform" VerticalAlignment="Top" HorizontalAlignment="Center" />
</Canvas>
</StackPanel>
</Grid>
</Grid>
</Window>
SpecialEffects.cs Code:
public partial class SpecialEffects : Window
{
private string FileNmae;
private int actualWidth;
private int actualHeight;
public SpecialEffects(string getTheFN) //Load the selected Image from ParentWindow
{
InitializeComponent();
FileNmae = getTheFN;
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri(FileNmae, UriKind.Relative);
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();
SpecialPhoto.Source = src;
}
private Image draggedImage;
private Point mousePosition;
bool captured = false;
private void CanvasMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var image = e.Source as Image;
if (image != null && canvas.CaptureMouse())
{
mousePosition = e.GetPosition(canvas);
draggedImage = image;
Panel.SetZIndex(draggedImage, 1); // in case of multiple images
}
}
private void CanvasMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (draggedImage != null)
{
canvas.ReleaseMouseCapture();
Panel.SetZIndex(draggedImage, 0);
draggedImage = null;
Mouse.Capture(null);
captured = false;
}
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (draggedImage != null)
{
var position = e.GetPosition(canvas);
var offset = position - mousePosition;
mousePosition = position;
double left = Canvas.GetLeft(draggedImage) + offset.X;
double top = Canvas.GetTop(draggedImage) + offset.Y;
if (left < 0)
{
left = 0;
}
if (top < 0)
{
top = 0;
}
if (left + draggedImage.ActualWidth > SpecialPhoto.ActualWidth)
{
left = SpecialPhoto.ActualWidth - draggedImage.ActualWidth;
}
if (top + draggedImage.ActualHeight > SpecialPhoto.ActualHeight)
{
top = SpecialPhoto.ActualHeight - draggedImage.ActualHeight;
}
Canvas.SetLeft(draggedImage, left);
Canvas.SetTop(draggedImage, top);
}
}
private void btnClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
private void bSave_Click(object sender, RoutedEventArgs e)
{
string fileLocation = System.IO.Path.GetDirectoryName(FileNmae);// get the selected file location
string getFileName = System.IO.Path.GetFileName(FileNmae); //get the seleceted filename
DateTime time = DateTime.Now; // Use current time
string format = "MMMddddHHmmssyyyy";
string s2 = time.ToString(format) + getFileName; // add $ at front along with the folde name
string filenamecombined = System.IO.Path.Combine(fileLocation, s2);//combine path.
RenderTargetBitmap renderTarget = new RenderTargetBitmap(
(int)SpecialPhoto.Height,
(int)SpecialPhoto.Width,
96, 96, PixelFormats.Pbgra32);
//renderTarget.Render(ViewedPhoto);
ModifyPosition(canvas as FrameworkElement);
renderTarget.Render(canvas);
ModifyPositionBack(canvas as FrameworkElement);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTarget));
//string imagePath = System.IO.Path.GetTempFileName();
using (FileStream stream = new FileStream(filenamecombined, FileMode.Create))
{
encoder.Save(stream);
stream.Dispose();
}
}
private void ModifyPosition(FrameworkElement fe)
{
/// get the size of the visual with margin
System.Windows.Size fs = new System.Windows.Size(
fe.ActualWidth +
fe.Margin.Left + fe.Margin.Right,
fe.ActualHeight +
fe.Margin.Top + fe.Margin.Bottom);
/// measure the visual with new size
fe.Measure(fs);
/// arrange the visual to align parent with (0,0)
fe.Arrange(new Rect(
-fe.Margin.Left, -fe.Margin.Top,
fs.Width, fs.Height));
}
private void ModifyPositionBack(FrameworkElement fe)
{
/// remeasure a size smaller than need, wpf will
/// rearrange it to the original position
fe.Measure(new System.Windows.Size());
}
private void Button_Click(object sender, RoutedEventArgs e) // To load another image
{
var dialog = new Microsoft.Win32.OpenFileDialog();
dialog.Filter =
"Image Files (*.jpg;*.png; *.jpeg; *.gif; *.bmp)|*.jpg;*.png; *.jpeg; *.gif; *.bmp";
if ((bool)dialog.ShowDialog())
{
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri(dialog.FileName, UriKind.Relative);
src.DecodePixelHeight = 120;
src.DecodePixelWidth = 120;
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();
var image = new Image { Source = src };
Canvas.SetLeft(image, 0);
Canvas.SetTop(image, 0);
canvas.Children.Add(image);
}
}
}
Problem 1 - In your xaml for the Image, add IsEnabled="False". This will stop the clicking from hiding the child image.
<Image x:Name="SpecialPhoto" Source="IMG_0071.JPG" Height="586" Width="780"
IsEnabled="False"
Stretch="Uniform" VerticalAlignment="Top" HorizontalAlignment="Center" />
Problem 2 - I didn't experience this, maybe you have some sort of mouse acceleration turned on in windows?
Problem 3 - You are using the height for the width and the width for the height. Change:
RenderTargetBitmap renderTarget = new RenderTargetBitmap(
(int)SpecialPhoto.Height,
(int)SpecialPhoto.Width,
96, 96, PixelFormats.Pbgra32);
To:
RenderTargetBitmap renderTarget = new RenderTargetBitmap(
(int)SpecialPhoto.Width,
(int)SpecialPhoto.Height,
96, 96, PixelFormats.Pbgra32);
The code for the comment question you asked:
private void bSave_Click(object sender, RoutedEventArgs e)
{
string fileLocation = System.IO.Path.GetDirectoryName(FileNmae);// get the selected file location
string getFileName = System.IO.Path.GetFileName(FileNmae); //get the seleceted filename
DateTime time = DateTime.Now; // Use current time
string format = "MMMddddHHmmssyyyy";
string s2 = time.ToString(format) + getFileName; // add $ at front along with the folde name
string filenamecombined = System.IO.Path.Combine(fileLocation, s2);//combine path.
#region Change the SpecialPhoto to be the size of its image and adjust the other images to match
double w = SpecialPhoto.Width;
double h = SpecialPhoto.Height;
SpecialPhoto.Width = SpecialPhoto.Source.Width;
SpecialPhoto.Height = SpecialPhoto.Source.Height;
// Get the ratio of the change in width/height
double rw = SpecialPhoto.Width / w;
double rh = SpecialPhoto.Height / h;
// Adjust the logos added to keep in the same relative position and size
foreach (Image img in canvas.Children)
{
if (img == SpecialPhoto)
continue;
double left = Canvas.GetLeft(img);
double top = Canvas.GetTop(img);
Canvas.SetLeft(img, left * rw);
Canvas.SetTop(img, top * rh);
img.RenderTransform = new ScaleTransform(rw, rh);
}
#endregion
RenderTargetBitmap renderTarget = new RenderTargetBitmap(
(int)SpecialPhoto.Width,
(int)SpecialPhoto.Height,
96, 96, PixelFormats.Pbgra32);
//renderTarget.Render(ViewedPhoto);
ModifyPosition(canvas as FrameworkElement);
renderTarget.Render(canvas);
ModifyPositionBack(canvas as FrameworkElement);
#region Undo the changes we did to the SpecialPhoto/logos
SpecialPhoto.Width = w;
SpecialPhoto.Height = h;
foreach (Image img in canvas.Children)
{
if (img == SpecialPhoto)
continue;
double left = Canvas.GetLeft(img);
double top = Canvas.GetTop(img);
Canvas.SetLeft(img, left / rw);
Canvas.SetTop(img, top / rh);
img.RenderTransform = new ScaleTransform(1, 1);
}
#endregion
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTarget));
//string imagePath = System.IO.Path.GetTempFileName();
using (FileStream stream = new FileStream(filenamecombined, FileMode.Create))
{
encoder.Save(stream);
stream.Dispose();
}
}
Code for the 2nd comment question (keeping child image in the parent image):
We need to change two methods. The first method is the CanvasMouseMove:
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (draggedImage != null)
{
var position = e.GetPosition(canvas);
var offset = position - mousePosition;
mousePosition = position;
double left = Canvas.GetLeft(draggedImage) + offset.X;
double top = Canvas.GetTop(draggedImage) + offset.Y;
Point tl = SpecialPhoto.TranslatePoint(new Point(0, 0), canvas);
Point br = SpecialPhoto.TranslatePoint(new Point(SpecialPhoto.ActualWidth, SpecialPhoto.ActualHeight), canvas);
if (left < tl.X)
{
left = tl.X;
}
if (top < tl.Y)
{
top = tl.Y;
}
if (left + draggedImage.ActualWidth > br.X)
{
left = br.X - draggedImage.ActualWidth;
}
if (top + draggedImage.ActualHeight > br.Y)
{
top = br.Y - draggedImage.ActualHeight;
}
Canvas.SetLeft(draggedImage, left);
Canvas.SetTop(draggedImage, top);
}
}
The 2nd method is the Button_Click:
private void Button_Click(object sender, RoutedEventArgs e) // To load another image
{
var dialog = new Microsoft.Win32.OpenFileDialog();
dialog.Filter =
"Image Files (*.jpg;*.png; *.jpeg; *.gif; *.bmp)|*.jpg;*.png; *.jpeg; *.gif; *.bmp";
if ((bool)dialog.ShowDialog())
{
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri(dialog.FileName, UriKind.Relative);
src.DecodePixelHeight = 120;
src.DecodePixelWidth = 120;
src.CacheOption = BitmapCacheOption.OnLoad;
src.EndInit();
var image = new Image { Source = src };
Point p = SpecialPhoto.TranslatePoint(new Point(0, 0), canvas);
Canvas.SetLeft(image, p.X);
Canvas.SetTop(image, p.Y);
canvas.Children.Add(image);
}
}

Creating an image from coordinates recovered before

I try to create an image by superimposing two others (one being the background on which I put the other).
But when I get the final image, I realize that the one I placed using the coordinates previously retrieved moved.
XAML :
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MinHeight="83"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="175,10,345,0">
<Button Content="Ajouter cadre" Name="cadre" Background="{x:Null}" Margin="10,0,0,0" Height="73" HorizontalAlignment="Left" Width="188" Click="Button_Click_1"/>
</StackPanel>
<Image Name="testPicLabpreview" Grid.Row="1" Canvas.ZIndex="500" Width="128" Height="128" />
<Image Name="PicLab" HorizontalAlignment="Left" Width="708" Height="377" VerticalAlignment="Top" Margin="10,10,0,0" Grid.Row="1" />
<Image Name="PicLabpreview" HorizontalAlignment="Left" Width="708" Height="377" VerticalAlignment="Top" Margin="10,10,0,0" Grid.Row="1" Stretch="None" />
<Button Content="Test effects" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Click="Button_Click" Height="72" Width="165"/>
<Button Content="Finaliser" HorizontalAlignment="Left" Margin="586,10,0,0" VerticalAlignment="Top" Width="142" Click="Button_Finalise" Height="72"/>
</Grid>
C#:
private async Task createPicture(Stream storageFile_top, Stream storageFile_bg, double tx, double ty, double zoom, double rot)
{
using (var source_bg = new StreamImageSource(storageFile_bg))
using (var filters_bg = new FilterEffect(source_bg))
using (var render = new JpegRenderer(filters_bg))
using (var source_top = new StreamImageSource(storageFile_top))
using (var filters_top = new FilterEffect(source_top))
{
var topSize = await source_top.GetInfoAsync();
var bgSize = await source_bg.GetInfoAsync();
//top left point of the blend layer
var topLeftLayer = new Windows.Foundation.Point(
topSize.ImageSize.Width/2 - tx/zoom,
//center on source_top and position top left point of the blend layer => trasnlation
topSize.ImageSize.Height/2 - ty/zoom
);
var layerSize = new Windows.Foundation.Size(
bgSize.ImageSize.Width/zoom, //appli factor on layer size => zoom
bgSize.ImageSize.Height/zoom
);
var pivot = new Windows.Foundation.Point(
tx/bgSize.ImageSize.Width,
//rotation pivot point in relative coordinate => rotation around the center of the layer picture
ty/bgSize.ImageSize.Height);
//layer source
filters_top.Filters = new IFilter[]
{new ReframingFilter(new Windows.Foundation.Rect(topLeftLayer, layerSize), rot, pivot)};
filters_bg.Filters = new IFilter[] {new BlendFilter(filters_top, BlendFunction.Normal)};
var buffer = await render.RenderAsync();
var bmp = new BitmapImage();
bmp.SetSource(buffer.AsStream());
PicLabpreview.Source = bmp;
}
}
private async void Button_Click_1(object sender, System.Windows.RoutedEventArgs e)
{
tx = Get_Position().X;
ty = Get_Position().Y;
var source = PhoneApplicationService.Current.State["source"];
WriteableBitmap bmp = new WriteableBitmap((BitmapSource)PhoneApplicationService.Current.State["bmp"]);
WriteableBitmap ImageApply = new WriteableBitmap(bmp);
BitmapImage frame = (BitmapImage) testPicLabpreview.Source;
WriteableBitmap ImageApplytest = new WriteableBitmap(frame);
PicLab.Source = bmp;
PicLabpreview.Source = ImageApply;
testPicLabpreview.Source = ImageApplytest;
var effect = new FilterEffect(source as IImageProvider);
var renderer = new WriteableBitmapRenderer(effect, ImageApplytest);
var fileStreamSource = new MemoryStream();
bmp.SaveJpeg(fileStreamSource, bmp.PixelWidth, bmp.PixelHeight, 0, 100);
fileStreamSource.Seek(0, SeekOrigin.Begin);
IBuffer bufferSrc = fileStreamSource.GetWindowsRuntimeBuffer();
var fileStreamMask = new MemoryStream();
ImageApplytest.SaveJpeg(fileStreamMask, 128, 128, 0, 100);
fileStreamMask.Seek(0, SeekOrigin.Begin);
IBuffer bufferMask = fileStreamMask.GetWindowsRuntimeBuffer();
await createPicture(
fileStreamMask,
fileStreamSource,
tx,
ty,
1,
0);
PicLab.Opacity = 0;
PicLabpreview.Opacity = 100;
testPicLabpreview.Opacity = 0;
}
private Point Get_Position()
{
GeneralTransform myTransform = testPicLabpreview.TransformToVisual(LayoutRoot);
Point relativePosition = myTransform.Transform(new Point(0, 0));
return relativePosition;
}
This my result before "create picture":
After :
Does anybody has a clue from where it can come ?

Categories