How to blur for background of grid on uwp? - c#

grid background="white"
Now, I want to blur it that such as blur on ios.

Use Blur by UWPCommunityToolkit.
<Grid>
<Grid>
<interactivity:Interaction.Behaviors>
<behaviors:Blur x:Name="BlurBehavior" Value="25" Duration="0"
Delay="0" AutomaticallyStart="True"/>
</interactivity:Interaction.Behaviors>
</Grid>
<Grid>
<!-- Your Content -->
</Grid>
</Grid>
If you want to increase or decrease the amount of blur then change the value in behaviours.
If you want any code sample, check out this GitHub project.
UWP Hamburger Menu with Frosted glass effect and Swipe to Open/Close.

Opacity is not a blur effect.
To make a pure blur effect, you will can use the RendertargetBitmap or Win2D.
I prefere to use Win2D because the gaussian blur effect is explicit and can be more precisely configured :
using (var stream = await Content.RenderToRandomAccessStream())
{
var device = new CanvasDevice();
var bitmap = await CanvasBitmap.LoadAsync(device, stream);
var renderer = new CanvasRenderTarget(device,
bitmap.SizeInPixels.Width,
bitmap.SizeInPixels.Height, bitmap.Dpi);
using (var ds = renderer.CreateDrawingSession())
{
var blur = new GaussianBlurEffect();
blur.BlurAmount = 5.0f;
blur.Source = bitmap;
ds.DrawImage(blur);
}
stream.Seek(0);
await renderer.SaveAsync(stream, CanvasBitmapFileFormat.Png);
BitmapImage image = new BitmapImage();
image.SetSource(stream);
paneBackground.ImageSource = image;
}
If you want to read more about it, here is the MSDN page.

You can apply a blur using the Composition APIs with the Windows 10 Anniversary update. However, if you're trying to blur things that are behind the window or app, that won't be possible. On the other hand, if you have something like a picture behind your grid and want the picture be blurred then this will work.
I wrote an answer to a similar question here.

Related

No bitmapimage in uwp?

I need to enter an image source from the code in C#. In my previous projects (not in uwp) I would do the following:
imagename.Source=new BitmapImage(new Uri(stringPath));
but in UWP the BitmapImage class seems not to exist.
Is there something similar to use or any solution for this problem?
MSDN reckons BitmapImage is still a thing.
See here: MSDN help document
Its usage is a little different though:
<Image Loaded="Image_Loaded"/>
And the C#:
void Image_Loaded(object sender, RoutedEventArgs e)
{
Image img = sender as Image;
BitmapImage bitmapImage = new BitmapImage();
img.Width = bitmapImage.DecodePixelWidth = 80;
// Natural px width of image source.
// You don't need to set Height; the system maintains aspect ratio, and calculates the other
// dimension, as long as one dimension measurement is provided.
bitmapImage.UriSource = new Uri(img.BaseUri,"Images/myimage.png");
}
There is a BitmapImage API within UWP. Microsoft has a guide for its use too.
This is the code sample taken directly from the guide for the C# segment:
// Create Image Element
Image myImage = new Image();
myImage.Width = 200;
// Create source
BitmapImage myBitmapImage = new BitmapImage();
// BitmapImage.UriSource must be in a BeginInit/EndInit block
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(#"C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg");
// To save significant application memory, set the DecodePixelWidth or
// DecodePixelHeight of the BitmapImage value of the image source to the desired
// height or width of the rendered image. If you don't do this, the application will
// cache the image as though it were rendered as its normal size rather then just
// the size that is displayed.
// Note: In order to preserve aspect ratio, set DecodePixelWidth
// or DecodePixelHeight but not both.
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();
//set image source
myImage.Source = myBitmapImage;
And this is the XAML segment:
<!-- Simple image rendering. However, rendering an image this way may not
result in the best use of application memory. See markup below which
creates the same end result but using less memory. -->
<Image Width="200"
Source="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg"/>
<Image Width="200">
<Image.Source>
<!-- To save significant application memory, set the DecodePixelWidth or
DecodePixelHeight of the BitmapImage value of the image source to the desired
height and width of the rendered image. If you don't do this, the application will
cache the image as though it were rendered as its normal size rather then just
the size that is displayed. -->
<!-- Note: In order to preserve aspect ratio, only set either DecodePixelWidth
or DecodePixelHeight but not both. -->
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg" />
</Image.Source>
</Image>
Especially if you come from WPF you have to add the using directive
using Windows.UI.Xaml.Media.Imaging;
What was next in going from WPF to UWP is the image source string. It needs the absolute path:
imagename.UriSource = new Uri("ms-appx:/your_path");

While Rendering Canvas control in Png I lost the background image

My application is a windows 8 store app . It takes a photo with the camera, then i draw over the image, and i want to save both the image and the drawing. What i have come result is only the drawing. i lost the background image.
Below you have my implementation :
XAML code:
(in place of having an Image control for the photo taken and a canvas for the drawing, i binded the photo = CurrentPicture as the background of the canvas)
<Canvas Grid.Row="1"
Grid.Column="0"
x:Name="InkCanvas"
Background="{Binding CurrentPicture, Converter={StaticResource WPhotoToCanvasBackgroundConverter}}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="0"
Width="1024"
Height="768" />
C# :
private async Task<IPhoto> RenderCanvasToPNG()
{
MemoryStream stream = await WriteableBitmapRenderExtensions.RenderToPngStream(InkCanvas);
var bitmap = new BitmapImage();
await bitmap.SetSourceAsync(System.IO.WindowsRuntimeStreamExtensions.AsRandomAccessStream(stream));
byte[] byteme = stream.ToArray();
var photo = new WPhotos(null, byteme, bitmap.PixelWidth, bitmap.PixelHeight, bitmap);
return photo;
}
Thank you a lot for your time :)
There isn't a direct way to extract the pixels from a BitmapImage or ImageBrush. I believe WriteableBitmapEx fakes this by finding the image's source URI and looking that up, but this method works only if the image was loaded from a URI. If it was streamed into the image then there is no way to extract it.
Instead, you can use RenderTargetBitmap to render your UIElements to a bitmap. Since this uses the Xaml rendering engine it has access to the ImageBrush used for the Canvas' background and should completely render the Canvas and its contents (barring non-renderable contents such as a MediaElement or SwapChainPanel).

In WinRT C# how do I save an offscreen XAML tree using RenderTargetBitmap?

The following code throws a cryptic System.ArgumentException from the RenderAsync method "Value does not fall within the expected range." If on the other hand my Canvas is part of a visible XAML tree it works. Is it impossible to render some XAML that isn't displayed on screen?
Canvas c = new Canvas();
c.Width = 40;
c.Height = 40;
c.Background = new SolidColorBrush(Color.FromArgb(0xff, 0x80, 0xff, 0x80));
RenderTargetBitmap x = new RenderTargetBitmap();
await x.RenderAsync(c);
I almost thought this answer would work, but no luck, I guess it only applies to WPF: Create WPF element offscreen and render to bitmap
UPDATE:
So far my best idea is to put the Canvas I want to render to into the currently visible page but place it beneath what is normally the root UIElement that fills the screen so it isn't visible to the user:
<Grid>
<Canvas x:Name="HiddenCanvas"/>
<Grid x:Name="mainElement" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
</Grid>
</Grid>
It isn't beautiful but it seems to work. Lets see if anyone can do better
satur9nine's solution to put the rendered UI tree somewhere behind an opaque foreground seems to be the only supported solution. You could also fiddle with the opacity of the parent element to avoid having it showing up. Another option is to render it yourself with Direct2D or use something like the WinRTXamlToolkit.Composition.Render() methods from WinRT XAML Toolkit.
WinRTXamlToolkit.Composition namespace has this extension that works. Just call this method:
await WriteableBitmapRenderExtensions.RenderToPngStream(element);

How can I use vector graphics (defined in XAML) as the image of a Ribbon menu item?

I need to convert my WPF application, which has a Ribbon, to use vector graphics for the images on buttons, etc., instead of bitmaps. I've got this working so far, except for the RibbonApplicationMenu items, which use their RibbonApplicationMenu.ImageSource property, with type ImageSource to set the graphic that shows up at the left side of the ribbon menu item.
My vector graphics are defined like this in XAML:
<ControlTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ViewBox Width="148.854" Height="150.500">
<Canvas Width="148.854" Height="150.500">
<Path>
<!-- . . . yadda yadda yadda . . . -->
</Path>
</Canvas>
<Viewbox>
</ControlTemplate>
These render properly when I set them to be the .Template of a Button, etc.
I can't figure out, however, how to use them for the images that show up in the RibbonApplicationMenu controls. Just setting the .Template property of the RibbonApplicationMenu does not work (it fills the entire control seems to break its functionality).
I attempted to use a VisualBrush and then render it to a RenderTargetBitmap to use as the .ImageSource (I also have to work mostly in code behind for reasons I won't get into):
ContentControl cc = new ContentControl(); // just picked ContentControl as a test
cc.Template = myTemplate; // assume myTemplate has the proper ControlTemplate
VisualBrush visBrush = new VisualBrush();
visBrush.Visual = cc;
// not really sure about the parameters to this next line
RenderTargetBitmap rend =
new RenderTargetBitmap(148.854, 150.5, 120, 96, PixelFormats.Pbgra32);
rend.Render(cc);
RibbonApplicationMenuItem menu = new RibbonApplicationMenuItem();
menu.ImageSource = render;
This compiles, but just shows a blank where the image would go. If I instead use a BitmapImage loaded from an image file as the .ImageSource, it displays correctly.
Any ideas how I can get this to work?
Two things that might need to be done:
Firstly there is no explicit size set for the Canvas in the ControlTemplate, you'll need to assign it a width and height (see the upvoted answer here for details).
The other thing is that you need to Arrange and Measure the Viewbox so that it assumes the required dimensions.
So altering the xaml for the vector graphics to something like:
<ControlTemplate x:Key="Template">
<Viewbox>
<Canvas Height="100" Width="130">
<Path>
<!-- data -->
</Path>
</Canvas>
</Viewbox>
</ControlTemplate>
And the code to:
ControlTemplate controlTemplate =
FindResource("Template") as ControlTemplate;
ContentControl content = new ContentControl();
content.Template = controlTemplate;
// ensure control has dimensions
content.Measure(new Size(200, 200));
content.Arrange(new Rect(0, 0, 200, 200));
RenderTargetBitmap render =
new RenderTargetBitmap((int)content.ActualWidth, (int)content.ActualHeight, 120, 96, PixelFormats.Pbgra32);
render.Render(content);
RibbonApplicationMenuItem menu = new RibbonApplicationMenuItem();
menu.ImageSource = render;
Will hopefully get it working.

Taking bitmap of Canvas is incorrectly based on top left corner of Window

I have a canvas in my Window and occasionally I want to take snapshots of the content.
I have the following method to do so:
private PngBitmapEncoder captureVisual(Visual v)
{
RenderTargetBitmap bmp = new RenderTargetBitmap(546, 410, 120, 96, PixelFormats.Pbgra32);
bmp.Render(v);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Interlace = PngInterlaceOption.On;
encoder.Frames.Add(BitmapFrame.Create(bmp));
return encoder;
}
I call this method with the following method which is called by a press button action(the idea is to add the picture to another canvas which will display the "photo":
private void take_photo(Object sender, RoutedEventArgs e)
{
System.Windows.Controls.Image photoImg = new System.Windows.Controls.Image();
BitmapEncoder enc = captureVisual(videoCanvas);
photoImg.Source = enc.Frames[0];
photoCanvas.Children.Add(photoImg);
}
The problem:
When I take the photo the origin of the photo/bitmap is not the origin of the canvas but the origin of the window. So the Canvas appears in the bitmap translated towards bottom/right in the same position as it is in relation to the top-left corner of the window. I have no idea why this is happening.
As an example see the pic below: There is white space to the top left and the actual content is translated to the bottom right. The origin should be where the actual image is located. I will try to put around a border to make it easier to visualize the problem(sorry I don't know how to put a border around the image if anyone knows please tell me or edit it yourself. Thanks).
Thanks to the comment of dowhilefor I got the answer from this link:
The problem is WPF implicitly adds the margins of the Canvas in relation to the parent container. In my case the parent container was a Grid and I didn't define any margins, the canvas was filling a specific cell. Nevertheless this somehow gets incorporated in the bitmap.
The solution, wrap the Canvas around another Canvas. That's stupid but it works. IMHO this is a bug in WPF:
<Canvas
Name="outerCanvas"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Grid.Row="1" Grid.Column="1">
<Canvas
Name="videoCanvas"
Canvas.Left="0"
Canvas.Top="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
/>
</Canvas>

Categories

Resources