Clearing canvas has a delay - c#

Below is the code for a simple app that draws a rectangle on a canvas in a window and then takes a screen shot of the app using the CopyFromScreen function when any key is pressed. Just before this is called however, I call canvas.Children.Clear(). I would then expect the resultant image to not have the rectangle in it, but it does. It seems that the actual rectangle image isn't removed from the canvas when the function is called but some time after.
I tried putting in a System.Threading.Thread.Sleep(1000); after the Clear() call but the rectangle stays on screen for that full second as well. Clearly it's getting removed after the key press function finishes, is there any way to remove it before the CopyFromScreen call?
To run this you will need to add a reference to System.Drawing.
XAML code
<Window x:Class="CanvasTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="210" Height="240"
KeyDown="keyPressed">
<Window.Background>
<SolidColorBrush Color="White"/>
</Window.Background>
<Grid>
<Canvas Name="canvas"
HorizontalAlignment="Left" VerticalAlignment="Top">
</Canvas>
</Grid>
</Window>
.cs code
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
namespace CanvasTest {
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
Left = 0;
Top = 0;
Rectangle rect = new Rectangle {
Stroke = System.Windows.Media.Brushes.Black,
StrokeThickness = 1,
Width = 100,
Height = 100
};
canvas.Children.Add(rect);
Canvas.SetLeft(rect, 50);
Canvas.SetTop(rect, 50);
}
private void keyPressed(object sender, System.Windows.Input.KeyEventArgs e) {
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap((int)Width, (int)Height);
System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmap);
canvas.Children.Clear();
graphics.CopyFromScreen(0, 0, 0, 0,
new System.Drawing.Size(bitmap.Width, bitmap.Height),
System.Drawing.CopyPixelOperation.SourceCopy);
String path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
path += "\\MuckleEwesPic.png";
bitmap.Save(path, System.Drawing.Imaging.ImageFormat.Png);
}
}
}
How can I clear the canvas and then take a screen shot without this behaviour happening? And no 'don't add the rect' isn't a solution ha, this is just a minimal example of a larger app in which the problem is occurring.
Thanks.

Using something like in ColinSmith's link:
static void WaitForRenderPass()
{
Application.Current.Dispatcher
.BeginInvoke( DispatcherPriority.ApplicationIdle, new Action( () => {} ) )
.Wait();
}
sort of works for waiting on a render pass but the problem is it's not possible (afaik) to tell if that render pass contains everything you want.
In practice depending on system load/video card drivers/... it has to be called multiple times. I've had one machine where it had to be called in a loop up to 3 times, and each of those calls took about 2 frames #60Hz to complete. Only then a call to the above would return immediately indicating the render thread is really idle, which likely means all changes you want have been rendered, which in turn means screen captures contain everything they should have. So we ended up using
for( int i = 0 ; i < 5 ; ++i )
{
WaitForRenderPass();
Thread.Sleep( 10 );
}
It's ugly and it's a hack but it hasn't failed (yet).
Regarding HighCore's comment: you can capture the screen with Wpf-only classes as well, however:
it has the same problem the OP started this questiomn for in the first place so it won't immediately solve anything (except from not using System.Drawing)
you won't be able to get a main window's chrome in the capture
it's markedly slower than CopyScreen
it does not render the exact same pixels as rendered to the screen

Related

Massive memory leak in .NET6.0 dialog

I have been chasing a memory leak and have gotten down to a pretty simple case. Whenever the canvas size changes, the window clears the canvas and adds 1,000 random points to the canvas. It also reports the memory usage in the titlebar of the window.
Memory starts out below 2MB.
If you grab the corner of the window and move it around a bit, the memory usage skyrockets to over 100MB in 10 sec. and the UI gets sluggish. Stop moving for 10 sec and the memory creeps back to 11MB (Not shown in the titlebar because there isn't an update but never back to the original <2MB).
Is it possible that simple wpf graphics are this broken? Am I doing something wrong? I call GC.Collect() on every repaint, so why does any memory recovery take so long?
Release/debug mode doesn't make any difference. Making the lines invisible doesn't make any difference. Changing line characteristics doesn't matter Using different color brushes on each line doesn't matter. The leak is proportional to the number of lines on the canvas.
How can it be that simple lines on a canvas aren't collected when the canvas is cleared?
Any ideas greatly appreciated!
Here's the code:
<Window x:Class="SillyLeakTest.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"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800" SizeChanged="Window_SizeChanged">
<Canvas x:Name="theCanvas"/>
</Window>
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
namespace SillyLeakTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Random rand = new Random();
public MainWindow()
{
InitializeComponent();
}
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
GC.Collect();
Title = "Memory Used: " + GC.GetTotalMemory(true).ToString("##,#");
Point windowSize = new Point(theCanvas.ActualWidth, theCanvas.ActualHeight);
Point center = new Point(windowSize.X / 2, windowSize.Y / 2);
theCanvas.Children.Clear();
SolidColorBrush color = new SolidColorBrush(Color.FromArgb(255, (byte)rand.Next(1, 255),
(byte)rand.Next(1, 255), (byte)rand.Next(1, 255)));
double scale = 1;
for (int i = 0; i < 1000; i++)
{
Point p = new Point(rand.Next(-(int)center.X, (int)center.X), rand.Next(-(int)center.Y, (int)center.Y));
theCanvas.Children.Add(new Line
{
X1 = center.X + p.Y * scale,
Y1 = center.Y - p.X * scale,
X2 = center.X + p.Y + 2 * scale,
Y2 = center.Y - p.X + 2 * scale,
StrokeThickness = 1,
//StrokeEndLineCap = PenLineCap.Round,
//StrokeStartLineCap = PenLineCap.Round,
// Stroke = new SolidColorBrush(P1.TheColor)
Stroke = color,
});
}
}
}
}
OK I can confirm. WPF does some weird sht when debugger attached. Start without debugger via CTRL-F5
There is no screen decoration and the app runs smooth and fast , tops out at ~2.8mb.
Attach debugger from VS and suddenly we have a colored border and that strange debug panel at the top of the screen. Now the memory grows exponentially.
see Different behavior of WPF Application: IDE debugging vs directly running the executable

Drawing over a 3D rendered scene using C#

UPDATE: Since originally asking this question, I have changed my approach slightly. Rather than drawing using System.Drawing.Graphics, I am hosting a WPF user control with an InkCanvas. That does everything I need it to do. The problem still is that I cannot get the background of the ElementHost to be transparent. I see the same black square I was seeing before.
ORIGINAL QUESTION: I have a C# WinForms application that renders a 3D scene using Ogre3D to a panel in the form using that panel's handle. I am trying to add the ability to draw on top of that scene (imagine Madden drawing over the TV screen) using C#'s System.Drawing.Graphics.
I'm using the BufferedGraphics class to do this. As a test, I'm trying to simply draw a rectangle on top of the 3D scene. Below is a snippet of the code I'm using to set everything up.
namespace TestApp
{
public partial class TestForm
{
private BufferedGraphics graphicsBuffer;
private BufferedGraphicsContext bufferContext = BufferedGraphicsManager.Current;
public TestForm()
{
InitializeComponent();
UpdateGraphicsBuffer();
}
private void UpdateGraphicsBuffer()
{
bufferContext.MaximumBuffer = new Size(panelRender.Width + 1, panelRender.Height + 1);
graphicsBuffer = bufferContext.Allocate(Graphics.FromHwnd(panelRender.Handle), new Rectangle(49, 49, 100, 100));
graphicsBuffer.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
}
private void TestForm_Load(object sender, EventArgs e)
{
graphicsBuffer.Graphics.DrawRectangle(new Pen(Color.Red), 50, 50, 50, 50);
}
}
}
I've left out a lot of the proprietary code (there is a call to graphicsBuffer.Render(); in part of that proprietary code) and renamed some stuff but hopefully what I have provided will give you the gist. Also, the 3D scene is also using panelRender.Handle to draw into that panel, and the panelRender.BackColor is black.
In a nutshell, what I am seeing is a chunk of my 3D scene missing (specifically a 100x100 chunk) with the 50x50 red rectangle drawn inside it, as pictured here:
Obviously I don't want to lose the scene that I'm trying to draw on top of. Right now, I'm at a loss as to why this is happening. Is what I'm trying to do just not possible? If any additional information/code is needed, I will be happy to provide it, if possible.
EDIT:
To try and simplify matters, I created a really simple WinForms app that has a single panel and used the code above to recreate the issue. The code-behind for that is here:
using System.Drawing;
using System.Windows.Forms;
namespace DoubleBufferTest
{
public partial class Form1 : Form
{
private BufferedGraphics graphicsBuffer = null;
private BufferedGraphicsContext bufferContext = BufferedGraphicsManager.Current;
public Form1()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
this.UpdateStyles();
InitializeComponent();
UpdateGraphicsBuffer();
}
private void UpdateGraphicsBuffer()
{
bufferContext.MaximumBuffer = new Size(panel1.Width + 1, panel1.Height + 1);
graphicsBuffer = bufferContext.Allocate(Graphics.FromHwnd(panel1.Handle), new Rectangle(10, 10, 50, 50));
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
graphicsBuffer.Graphics.DrawRectangle(new Pen(Color.Red, 3.0f), 20, 20, 10, 10);
graphicsBuffer.Render();
}
}
}
The panel's backcolor is set to transparent. Here is the result:
That black square corresponds to the graphics buffer that is getting allocated by the context. Why it always shows up as black is basically what is confusing me now...
Thank you to #Ron Beyer for answering this for me in a different question I posted.
So I was on the right track with the ElementHost control, but because of the transparency issues, Ron suggested that I try using a new WPF window that I could overlay on top of the application (link). The WPF window's background is set to transparent, so drawing on the InkCanvas results in the desired effect.

Making a constantly updating Image (WPF)

So i am messing around with making a simple AI and stuff with basic C#, and in this project i have alot of points which i've been visualising by making a bitmap.
This bitmap i have rendered/loaded to an image object in the WPF window.. but my problem is that this is rendered each milisecond, making the framerate quite bad - so how would i make this better?
Can i load it 'constantly'? or should i take another approach?
What i got now is pretty simple but i can show the important parts anyway, taken out of the full class:
private static Bitmap BitMap = new Bitmap(500, 500);
static Graphics GraphicFromBitMap
{
get
{
return Graphics.FromImage(BitMap);
}
}
public static BitmapSource loadBitmapAsImage()
{
IntPtr intPtr = BitMap.GetHbitmap();
BitmapSource bitmapSource = null;
try
{
bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(intPtr,
IntPtr.Zero, Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
}
finally
{
DeleteObject(intPtr);
}
DeleteObject(intPtr);
return bitmapSource;
}
This is ofcourse only the bitmap part - the actual loading is done the following way:
DispatcherTimer Timer = new DispatcherTimer();
public MainWindow()
{
this.Timer.Tick += new EventHandler(Timer_Tick);
this.Timer.Interval = new TimeSpan(0, 0, 0, 1);
this.Timer.Start();
}
void Timer_Tick(object sender, EventArgs e)
{
WorldMap.Draw();
map.Source = WorldMap.BitMapSource;
}
This is ofcourse only the important parts - i hope my question is understandable but just to clearify and repeat:
I need a WPF image to update 'every frame' or everytime specific values change.
My question might have been answered before, but i couldn't really find anything that work nor something suiting this instance.
BTW making the timer set off more frequently creates an error with the loading, but the exact error code, i can't remember, and i can't seem to create it again - never the less this probably isn't the most practical way of doing this.
EDIT:
For clarification, this is all i got right now: http://imgur.com/EIiSRFQ
I want nothing fancy - it's just for personal projects playing around with programming and math, and that's alot easier if i can visualize the objects that i am 'moving' in my 2D plane.
Right now i am playing around with physics and gravity, trying to create a simple solar system with working physics. this is all just side projects to get to know the different tools better when i am too tired to work on my main project.
I would look to represent the visual elements of the bitmap as controls in WPF. That way you can update them directly and as frequently as they change, without the overhead of creating a bitmap and rendering it.
Performance would be far greater as you'd only update the changes in value.
To demonstrate the point, create a control...
<UserControl x:Class="Sample_Chart.Views.CodeBehindChart"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Canvas x:Name="LayoutRoot" />
</UserControl>
This is as simple as they get. Next edit the code behind file...
public partial class CodeBehindChart : UserControl
{
public CodeBehindChart()
{
InitializeComponent();
Respond();
}
private async void Respond()
{
await Task.Delay(2000);
Random r = new Random();
while (true)
{
this.LayoutRoot.Children.Clear();
for (int i = 0; i < 100; i++)
{
Rectangle rectangle = new Rectangle();
rectangle.SetValue(Canvas.LeftProperty, r.NextDouble() * this.LayoutRoot.ActualWidth);
rectangle.SetValue(Canvas.TopProperty, r.NextDouble() * this.LayoutRoot.ActualHeight);
rectangle.Width = 2;
rectangle.Height = 2;
rectangle.Fill = Brushes.Black;
this.LayoutRoot.Children.Add(rectangle);
}
await Task.Delay(500);
}
}
}
In this code behind we have an async void method which firstly waits for 2 seconds (optional) before then creating 100 visual elements at random locations within the control. It refreshes this every 1/2 second.
If you did the same thing, but based those locations, sizes and fill - even use different shapes - I think you'll have a high performing, scaling and easily extendable solution to your requirements.
Taking this the next stage and controlling from a ViewModel will require a bit more thought which for your 'first project' - albeit an interesting one, may be a step ambitious ;)

Non-smooth DoubleAnimation

I am using DoubleAnimation for zooming and panning in and out of map. My map is an image with huge resolution (15,000 x 8,438). The problem is that on first time the zoom animation is very faltering and not smooth, at second time it`s getting better and so on. How can I make my animation smoother or make some cashing of the image or animation before performing it, or maybe using other form of animation?
My Code:
namespace AnimationTest
{
public partial class MainWindow : Window
{
ScaleTransform transP;
TranslateTransform trans2P;
DoubleAnimation animP;
DoubleAnimation animYP;
DoubleAnimation animXP;
TransformGroup myTransformGroupP;
public MainWindow()
{
InitializeComponent();
transP = new ScaleTransform();
trans2P = new TranslateTransform();
myTransformGroupP = new TransformGroup();
myTransformGroupP.Children.Add(transP);
myTransformGroupP.Children.Add(trans2P);
animP = new DoubleAnimation(1, 20, TimeSpan.FromMilliseconds(3000));
animXP = new DoubleAnimation(0, -14000, TimeSpan.FromMilliseconds(3000));
animYP = new DoubleAnimation(0, -4000, TimeSpan.FromMilliseconds(3000));
}
private void button1_Click(object sender, RoutedEventArgs e)
{
image1.RenderTransform = myTransformGroupP;
transP.BeginAnimation(ScaleTransform.ScaleXProperty, animP);
transP.BeginAnimation(ScaleTransform.ScaleYProperty, animP);
trans2P.BeginAnimation(TranslateTransform.XProperty, animXP);
trans2P.BeginAnimation(TranslateTransform.YProperty, animYP);
}
}
}
I have not tried your animation approach, i tried to implement my own logic to to this.
First i am inspired by zooming animation used by Picasa. So i tried to implement similar type of animation and this works fine for me on my core2duo processor with image size of 10000x5000 without any lag.
This approach consumed a lot of memory, but when i compared my memory usage with Picasa ImageViewer it was almost same. This approach may increase the loading time of your application but this can be handled and not a problem here.
Here is the Code for Main Window Grid that i have Used.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Button Grid.Row="0" Height="30" Width="100" Content="Zoom" Click="ButtonZoom_OnClick" />
<Image RenderOptions.BitmapScalingMode="HighQuality" Stretch="Uniform" Width="100" Height="100" Grid.Row="1"
Margin="30" VerticalAlignment="Center" HorizontalAlignment="Center" Source="mad1.jpg" Name="ImageMain"
x:FieldModifier="private" />
</Grid>
Button Click event Code
private void ButtonZoom_OnClick(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
var i = 0;
while (i++ < 100)
{
var i1 = i;
//var i1 = (-0.00092)*(i*i) + (0.092)*i + 0.2;
Dispatcher.Invoke(new Action(() =>
{
if (i1 < 10 || i1 > 90)
{
ImageMain.Height += 0.5;
ImageMain.Width += 0.5;
}
else if (i1 < 30 || i1 > 70)
{
ImageMain.Height += 1;
ImageMain.Width += 1;
}
else
{
ImageMain.Height += 3;
ImageMain.Width += 3;
}
}));
Thread.Sleep(30);
}
});
}
The commented line in this code is a quadratic equation for a smooth animation for acceleration and acceleration of animation. the roots are calculated for starting zooming by 0.2 and half at 2.5 and stops at 0.2 with in range of [0-100]. if you want to create your fully customized animation you may use WolframAlpha to check your animation graph. but the simple approach is to use simple control statements to control your animation.
This code is only for zooming your image, your approach will be similar for zoom out.
Have you looked into Microsoft's DeepZoom technology (this is what they use for Bing Maps)? http://msdn.microsoft.com/en-us/library/cc645050(v=vs.95).aspx#deep_zoom_examples
Since you have not shown any XAML I'll try from the most basic - try to reduce bitmap scaling mode with RenderOptions.BitmapScalingMode="LowQuality" on your image element like this:
<Image x:Name="image1"
Source="huge-image.jpg"
Stretch="Uniform"
RenderOptions.BitmapScalingMode="LowQuality" />
Note, that this is only actual if you targeting .NET 3.0-3.5 since starting from .NET 4.0 the "LowQuality" setting is already set as default, so you have no need to specify it explicitly. But if your zoom-in animation still faltering you could try to change this default scaling from LowQuality to even more lower NearestNeighbor which, according to documentation:
...provides performance benefits over LowQuality mode when the software rasterizer is used. This mode is often used to magnify a bitmap.
Also since you are about to show large image with some loss of quality it may be better to specify UseLayoutRounding="True" on your image or it parent element to improve image quality.
You want to use a cached composition. Render your map but assign a BitmapCache to the CacheMode property and set the RenderAtScale to a value larger than 1. If you zoom into your map 5x you should use the RenderAtScale with this value as it caches the image for this type of zoom.
This may result in a much higher memory consumption but may smooth the scrolling.
Further more Nolonar may be right. You may need to create mipmaps for the image and provide tile rendering to partially load seen tiles as your image is quite large.

How do I make RenderTargetBitmap and VisualBrush play nice together?

My requirements:
a persistent UserControl that handles logic for a custom image, such as a map or drawing
a set of containers to implement caching on the image during zoom or pan movements
VisualBrush copies of the UserControl that I can add to the containers for use with Effects
I currently implement image caching with a RenderTargetBitmap, but that seems to have trouble with the VisualBrush-covered Rectangle objects I'm using.
My question: What can I add/change in this code to get the VisualBrush objects to render correctly after RenderTargetBitmap uses them? What strange thing is RenderTargetBitmap doing that makes the VisualBrush invisible?
This is a problem that I have been unable to reproduce without a decent amount of code.
In my xaml file I have:
<Window x:Class="ElementRender.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="350" Width="525">
<Grid>
<Grid Name="_contentContainer">
<Rectangle Fill="White"/>
<Grid Name="_content">
<Grid Name="_back"/>
<Grid Name="_body"/>
</Grid>
</Grid>
<StackPanel VerticalAlignment="Bottom" Orientation="Horizontal">
<Button Content="New" Name="New"/>
<Button Content="Move" Name="Move"/>
<Button Content="Update" Name="Update"/>
</StackPanel>
</Grid>
</Window>
and the .xaml.cs:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
public partial class MainWindow : Window
{
private const int imageWidth = 150;
private const int imageHeight = 150;
private readonly UserControl Control;
public MainWindow()
{
InitializeComponent();
// User Control setup
Control = new UserControl() {
Width = imageWidth, Height = imageHeight,
Content = BuildImage()
};
_body.Children.Add(SoftCopy(Control));
// event setup
Move.Click += (sender, e) => _content.RenderTransform = new TranslateTransform(50, 50);
New.Click += (sender, e) => {
HardCopy();
_content.RenderTransform = null;
Control.Content = BuildImage();
};
}
private FrameworkElement BuildImage()
{
return new Rectangle{Fill=Brushes.Blue};
}
private void HardCopy()
{
int width = (int) _contentContainer.ActualWidth;
int height = (int) _contentContainer.ActualHeight;
// render the current image
var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (var context = dv.RenderOpen())
{
var brush = new VisualBrush(_contentContainer) { Opacity = .5 };
context.DrawRectangle(brush, null, new Rect(0, 0, width, height));
}
rtb.Render(dv);
var lastRender = new Image
{
Source = rtb,
Stretch = Stretch.None,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Width = width,
Height = height
};
_back.Children.Clear();
_back.Children.Add(lastRender);
}
private FrameworkElement SoftCopy(FrameworkElement element)
{
return new Rectangle{Fill= new VisualBrush(element), Width=element.Width, Height=element.Height};
}
}
A few helping notes about the code:
the xaml's _contentContainer works with HardCopy() to copy the current images into the image cache, _back.
SoftCopy returns a FrameworkElement that looks exactly like the one past in, but without any transforms, effects, or visual parents. This is very important.
BuildImage simulates building a new image to be pasted over the cache after the initial image has been transformed somehow.
If you build and run the application removing the SoftCopy() from the _body.Children.Add(SoftCopy(Control));, you see the effect that I want to get: the new element is pasted above the old element, and the old element seems to retain its transform.
Alternatively, if you cut out the line var rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32); from HardCopy, the caching function is broken, but the SoftCopy is displayed correctly.
However, if you run the application as-is, you notice that the new BlueRectangle (as rendered through a VisualBrush) doesn't display at all, until you hit the "New" button again, pushing the image to the cache, and still not showing you the new created image.
I'm going to be pompous enough to call this a bug in WPF. I eventually found out how to fix the strange behavior I was getting:
var visual = visualBrush.Visual;
visualBrush.Visual = null;
visualBrush.Visual = visual;
This should essentially be a null operation: by the end, the visual brush has the same visual as when it started. However, adding this code segment after rendering the VisualBrush into the RenderTargetBitmap fixed the issue I was having.
I didn't quite understand the post but there are few important things:
If you apply RenderTransform/Margins to element and take picture of it(RenderTargetBItmap), you're gonna have bad time. It will be offseted and you will get only sub-picture.
The idea is to take picture without any rendertransforms, and then later copy RenderTransform over from the old one. If needed.

Categories

Resources