RenderTargetBitmap renders whole screen instead of Visual only [duplicate] - c#

This question already has answers here:
Re positioning canvas control
(1 answer)
Snapshot of an WPF Canvas Area using RenderTargetBitmap
(2 answers)
Closed 4 years ago.
i want to save a circle as png.
This is the code is use:
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap((int)Width, (int)Height, 96, 96, PixelFormats.Pbgra32);
renderTargetBitmap.Render(kreis);
PngBitmapEncoder pngImage = new PngBitmapEncoder();
pngImage.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
if (File.Exists(dateipfad + textBox.Text + ".png"))
File.Delete(dateipfad + textBox.Text + ".png");
using (Stream fileStream = File.Create(dateipfad + textBox.Text + ".png"))
{
pngImage.Save(fileStream);
}
however it saves always a 525x350 png file (with the circle).
What i want, is that the size of the png file is the same size than the circle.
But when i change Width and Height to Kreis.Width and Kreis.Height
by the way: "Kreis" is german for "circle"
then the image has the correct size, but doesn't contain the circle in it, because the circle is on the right side of the application. And it just makes a screen from the left side.
Is it possible to not only set Width and Height for the RenderTargetBitmap but somehow also set the startX and startY?
Edit:
this is the XAML of the circle:
<Ellipse x:Name="kreis" Grid.Column="1" HorizontalAlignment="Center" Height="{Binding ElementName=slider, Path=Value}" Margin="0" Stroke="#FF8F8FF9" VerticalAlignment="Center" Width="{Binding ElementName=slider, Path=Value}" Fill="#FF5555D1" StrokeThickness="2"/>
This is the image i recieve:
(if you click on the image, you can see that it contains not only the circle. What i would need is that the image contains the circle only, so the width/height of the image is the width/height of the circle.

Try the answer of ILIA BROUDNO in this question: Snapshot of an WPF Canvas Area using RenderTargetBitmap
Your XAML shows that the circle is included in a grid, because the attached property Grid.Column is set to 1. This makes me assue that the size of the circle is painted relative to the grid or even to the window.
So creating a VisualBrush from the Kreis-Element and then explicitly painting this VisualBrush on position 0,0 might solve your problem.

Related

Copying rotated image to existing image in C# code-behind

I am trying to copy a rotated image to an existing image in the code-behind.
Here are my 2 images:
<Image x:Name="tempImage1" Source="Images/firstImage.jpg" Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center" />
<Image x:Name="myImage2" Source="Images/secondImage.jpg" Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center" />
And the rotation in the code-behind:
RotateTransform rt = new RotateTransform(-theta, 200, 300);
tempImage1.RenderTransform = rt;
myImage2.Source = tempImage1.Source;
I know I'm not doing it right (still very new to this). Could someone please help point me in the right direction? The result I'm looking for is to have myImage2 have show tempImage1 in its rotated form, not the original source.
Using a RenderTargetBitmap solved the issue for me.
With images tempImage1 and myImage2 in your XAML:
RenderTargetBitmap rtb = new RenderTargetBitmap(_width, _height, 96, 96, PixelFormats.Default);
rtb.Render(tempImage1);
myImage2.Source = rtb;
The above is done with the assumption that tempImage1 has already been rotated and transformed.
Well if you do that you must know that the first image would be visible as it is in the background well I simply rotated as per your question in an angle of 30 degree the XAML remains same the new C# code is
RotateTransform rt = new RotateTransform();
rt.Angle = 30;
tempImage1.RenderTransform = rt;
myImage2.Source = tempImage1.Source;

How to draw a rectangle on a WPF canvas

I'm trying to draw a Rectangle on a Canvas as follows:
System.Windows.Shapes.Rectangle rect;
rect = new System.Windows.Shapes.Rectangle();
rect.Stroke = new SolidColorBrush(Colors.Black);
rect.Fill = new SolidColorBrush(Colors.Black);
rect.Width=200;
rect.Height=200;
Canvas.SetLeft(rect,0);
Canvas.SetTop(rect,0);
front_canvas.Children.Add(rect);
Why would this code not draw a rectangle?
The canvas is defined in the associated XAML as follows:
<Canvas Height="200" Width="200" Name="front_canvas" Grid.Row="1" Grid.Column="0">
</Canvas>
The canvas shows up fine. I can tell because of the gap it leaves in the layout grid.
This should draw your rectangle as a 200x200 black square, provided front_canvas is displayed correctly.
Why would this code not draw a rectangle?
The main reasons this would not draw are:
front_canvas is not visible
front_canvas is not in the visual tree and being displayed correctly
Some other FrameworkElement is obscuring front_canvas, at least the upper left corner.
There is another object in the canvas at a higher z order.
Note that you'd typically also want to set StrokeThickness if you want to see the Stroke you specify.
To View Rectangle you must specify the StrokeThickness and set any Integer value greater than zero:
rect.StrokeThickness=2;
// ...
front_canvas.Children.Add(rect);
Size size = new Size(front_canvas.Width, front_canvas.Height);
front_canvas.Measure(size);
front_canvas.Arrange(new Rect(size));

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.

Saving Bitmap Moves The Canvas

I'm trying to save a canvas drawing as a bitmap. The code works fine, however once the drawing has been saved the canvas moves to the top left of the parent application. My code is as follows:
public void SaveBitmap()
{
Size size = new Size(canvas.ActualWidth, canvas.ActualHeight);
canvas.Measure(size);
canvas.Arrange(new Rect(size));
RenderTargetBitmap renderBitmap =
new RenderTargetBitmap(
(int)size.Width,
(int)size.Height,
96d,
96d,
PixelFormats.Pbgra32);
renderBitmap.Render(canvas);
using (FileStream outStream = new FileStream("C:\\Users\\Darren\\Desktop\\test.bmp", FileMode.Create))
{
BmpBitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
encoder.Save(outStream);
}
}
The line that caused the problem is canvas.Arrange. Anybody shed any light?
Thanks.
The reason is that you’re not specifying any position in your Rect constructor, which therefore defaults to a position of (0,0).
My suggestion for using RenderTargetBitmap is to place your Canvas inside a Grid, and then perform any explicit positioning required by your UI on this outer Grid, letting your inner Canvas naturally assume a position of (0,0) within this parent Grid.
For example, if you have:
<Window>
<Canvas Left="10" Top="30" />
</Window>
Change it to:
<Window>
<Grid Left="10" Top="30">
<Canvas />
</Grid>
</Window>
Then, you could eliminate your calls to Measure and Arrange altogether. However, make sure that you still pass the child Canvas to your RenderTargetBitmap.Render method, not the parent Grid.

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