I am trying to add the image of a usercontrol to viewbox.
I am creating the usercontrol dynamically. I am using the code below.
private static RenderTargetBitmap CaptureScreen(Visual target, double dpiX, double dpiY)
{
if (target == null)
{
return null;
}
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
//RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
// (int)(bounds.Height * dpiY / 96.0),
// dpiX,
// dpiY,
// PixelFormats.Pbgra32);
RenderTargetBitmap rtb = new RenderTargetBitmap(596,596,dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(target);
ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
}
rtb.Render(dv);
return rtb;
}
I am creating the user control dynamically and passing this to capture screen method.
UserControls.UserControl1 uc1 = new UserControls.UserControl1();
visualList.Add(uc1);
for(int i = 0;i<=6;i++)
{
Image img = new Image();
img.Source = CaptureScreen(visualList[i], 96, 96);
img.Margin = new Thickness { Top = 2 };
usingWorkaround.Children.Add(img);
}
the VisualTreeHelper.GetDescendantBounds(target) is returning empty bounds. Thats why the image of the screen can not be created. Is there any other method to capture screen of dynamically created user control?
you can call Measure and Arrange As follows
private void ForceUpdate(FrameworkElement element, double width, double height)
{
Size size = new Size(width, height);
element.Measure(size);
element.Arrange(new Rect(0, 0, width, height));
element.UpdateLayout();
}
At the time when you try to create the image the controls don't yet exist in the visual tree and the size has not been calculated.
You will need to call Measure and Arrange on your visual first.
Related
I need to capture UI element in this case LiveCharts chart and save it to a PNG/JPEG
I got this code
private void Button_Click(object sender, RoutedEventArgs e) {
var filePath = "qwerty.png";
var res = CaptureScreen(charts, charts.ActualWidth, charts.ActualHeight);
using (var fileStream = new FileStream(filePath, FileMode.Create)) {
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(res));
encoder.Save(fileStream);
}
}
private BitmapSource CaptureScreen(Visual target, double dpiX, double dpiY) {
if (target == null) {
return null;
}
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
(int)(bounds.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen()) {
VisualBrush vb = new VisualBrush(target);
ctx.DrawRectangle(vb, null, new Rect(new System.Windows.Point(), bounds.Size));
}
rtb.Render(dv);
return rtb;
}
I can get a png no problem. Though it is the picture created is 30k x 9k pixels. The picture has a transparent background. what would be the best practice to capture a UI element and export as a picture with a white backgroun?
I want to save my label Control, but I have no idea to save it.
I tried draw text in Graphics class, but I can't draw "even allocation".
Is there any good way?
public Label makeLabel(string text, double width, double height, FontFamily fontFamily, FontStyle fontStyle, FontStretch fontStretch)
{
var label = new Label();
label.Width = width;
label.Height = height;
label.FontFamily = fontFamily;
label.FontStyle = fontStyle;
label.FontStretch = fontStretch;
label.Content = text;
return label;
}
public void SavePicture(Label label)
{
var path = "label.png";
// I have no idea to save;
}
public void SavePicture(Label label)
{
var path = "label.png";
var width = label.Width;
var height = label.Height;
var viewBox = new Viewbox();
var renderTargetBitmap = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32);
var pngBitmapEncoder = new PngBitmapEncoder();
viewBox.Child = label;
viewBox.Measure(new Size(width, height));
viewBox.Arrange(new Rect(0, 0, width, height));
viewBox.UpdateLayout();
renderTargetBitmap.Render(viewBox);
pngBitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
using (var fileStream = File.Create(path))
{
pngBitmapEncoder.Save(fileStream);
}
}
This works without having label displayed on screen.
void SavePicture(FrameworkElement el)
{
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)el.ActualWidth, (int)el.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(el);
using (FileStream stream = File.Create(#"label.png"))
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream);
}
}
But you can call this method only after the Label is displayed.
I have a FrameworkElement and I want to save it as a Height-Resolution Image (Jpeg). I tried the following code, but the results are not what I had hoped. I got an image with bad resolution when I print it with A4 as the paper size.
// ...
FrameworkElement element = this.Content;
element.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(element.DesiredSize));
element.UpdateLayout();
// i used element.ActulaHeight and ActualWidth but not works.
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)element.Width, (int)element.Height, GPFReporstPageSizeExtension.DPI, GPFReporstPageSizeExtension.DPI, System.Windows.Media.PixelFormats.Pbgra32);
bitmap.Render(element);
// ....
Finally i solved my problem, i posted the full solution in my blog "gamadev web site":
Saving FrameworkElement as Image
FrameworkElement element = myControl.Content;
// you can set the size as you need.
Size theTargetSize = new Size(1500,2000)
element.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(theTargetSize ));
// to affect the changes in the UI, you must call this method at the end to apply the new changes
element.UpdateLayout();
double dpiScale = 300.0 / 96;
double dpiX = 300.0;
double dpiY = 300.0;
RenderTargetBitmap bmp = new RenderTargetBitmap(Convert.ToInt32(
(theTargetSize .Width) * dpiScale),
Convert.ToInt32((theTargetSize .Height) * dpiScale),
dpiX, dpiY, PixelFormats.Pbgra32);
bmp.Render(element);
element.Measure(new System.Windows.Size());
element.Arrange(new Rect());
element.UpdateLayout();
System.Windows.Media.Imaging.BitmapEncoder encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
MemoryStream myStream = new MemoryStream();
encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(this.CreateRenderTargetBitmap()));
encoder.Save(myStream);
var img = System.Drawing.Bitmap.FromStream(myStream);
Bitmap bmp = new Bitmap((int)theTargetSize .Width, (int)theTargetSize .Height);
var g = Graphics.FromImage(bmp);
g.Clear(System.Drawing.Color.White);
g.DrawImage(this.GetPageAsImage(), (int)this.Margin.Left, (int)this.Margin.Top);
fileName = #”D:\myImage.png”;
bmp.Save(fileName);
Actually i am using drawingContext.DrawRectangle method for drawing rectangle on canvas..
i want to add shadow effect on rectangle..
drawingContext.DrawRectangle(new SolidColorBrush(graphicsObjectFillColor),
new Pen(new SolidColorBrush(ObjectColor), ActualLineWidth),
Rectangle);
or i am using this to add drop shadow..
DropShadowEffect effect = new DropShadowEffect();
effect = new DropShadowEffect { Color = Colors.Black, Direction = -45, Opacity = 0.5, ShadowDepth = 4};
this.Effect = effect;
the shadow is showing but add the time of draw all tool on image tha shodow is not shawing
i am using
DrawingVisual vs = new DrawingVisual();
DrawingContext dc = vs.RenderOpen();
// Draw image
dc.DrawImage(image.Source, rect);
double scale = width / image.Source.Width;
// Keep old existing actual scale and set new actual scale.
double oldActualScale = drawingCanvas.ActualScale;
drawingCanvas.ActualScale = oldActualScale;
// Remove clip in the canvas - we set our own clip.
drawingCanvas.RemoveClip();
// Prepare drawing context to draw graphics
rect = new Rect(left, top, width, height);
dc.PushClip(new RectangleGeometry(rect));
double horizontalScale = Math.Abs((positionDrawingCanvas.X) - (positionImage.X));
double verticalScale = Math.Abs((positionDrawingCanvas.Y) - (positionImage.Y));
double difX = 0.0;
double difY = 0.0;
//if (horizontalScale != 0 && verticalScale != 0)
//{
// //horizontalScale = Math.Abs((positionDrawingCanvas.X + Math.Abs((positionImage.X / sliderScale.Value - positionImage.X))) - (positionImage.X));
// //verticalScale = Math.Abs((positionDrawingCanvas.Y + Math.Abs((positionImage.Y / sliderScale.Value - positionImage.Y))) - (positionImage.Y));
// difX = (positionImage.X - positionImage.X / sliderScale.Value);
// difY = (positionImage.Y - positionImage.Y / sliderScale.Value);
//}
dc.PushTransform(new TranslateTransform(difX + left - horizontalScale, difY+top - verticalScale));
dc.PushTransform(new ScaleTransform(1, 1));
// Ask canvas to draw overlays
drawingCanvas.Draw(dc);
// Restore old actual scale.
drawingCanvas.ActualScale = oldActualScale;
// Restore clip
drawingCanvas.RefreshClip();
dc.Pop();
dc.Pop();
dc.Pop();
dc.Close();
width = (Utilityhelper.GetDIPIndependentHorizontal(rect.Width));
height = (Utilityhelper.GetDIPIndependentVertical(rect.Height));
bmp = new RenderTargetBitmap((int)width, (int)(height), Utilityhelper.graphics.DpiX, Utilityhelper.graphics.DpiY, PixelFormats.Default);
//bmp = new RenderTargetBitmap((int)(scale * (rect.Width)), (int)(scale * (rect.Height)), scale * 96, scale * 96, PixelFormats.Default);
bmp.Render(vs);
sliderScale.Value = oldScale;
//imageBackground.Stretch = Stretch.Uniform;
//drawingCanvas.Width = (Utilityhelper.GetDIPDependentHorizontal(drawingCanvas.Width));
//drawingCanvas.Height = (Utilityhelper.GetDIPDependentVertical(drawingCanvas.Height));
return bmp;
You have to just change your render method
RenderTargetBitmap bmp = new RenderTargetBitmap((int)width, (int)(height), DpiX, DpiY, PixelFormats.Default);
BitmapSource source = null;
if (bmp != null)
{
bmp.Render(image);
bmp.Render(drawingCanvas);
source = bmp;
}
Here is how you get image (bitmap) from visual in wpf:
// render content into image
var render = new RenderTargetBitmap((int)ContentPresenter.RenderSize.Width, (int)ContentPresenter.RenderSize.Height, 96, 96, PixelFormats.Default);
render.Render(ContentPresenter);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(render));
using (var stream = new MemoryStream())
{
// create bitmap image
encoder.Save(stream);
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = stream;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.EndInit();
bitmap.Freeze();
// use BitmapImage
...
}
ContentPresenter is some visual.
I am trying to resize image to width=100 height=100
public ActionResult RegisterUser(userAuthModel user, HttpPostedFileBase userimage)
{
if (userimage.ContentLength > 0 && userimage != null)
{
string fname = userimage.FileName;
var path = Server.MapPath("~/Images/User_DP/" + userimage.FileName);
var image_100 = new System.Drawing.Bitmap(userimage, new Size(100, 100));
userimage.SaveAs(path);
}
.
.
.
.
.
}
Here I am using bitmap approach to resize imgae to some specific width and height.
But this shows me error in line-
var image_100 = new System.Drawing.Bitmap(userimage, new Size(100, 100));
of invalid arguments. How Do Ii resize image with using bitmap?
The System.Drawing.Bitmap class asks for two parameters in the constructor your are using:
System.Drawing.Image
System.Drawing.Size
In your code, you are passing the size correctly, but not the image. HttpPostedFileBase does not extend the Image class.
You will need to change that part of your code. If you are using the HttpPostedFileBase as a stream, then keep in mind that System.Drawing.Bitmap has no constructor asking for a Stream and a Size.
References:
System.Drawing.Image
System.Web.HttpPostedFileBase
you have to use mentioned method it may help you
private static BitmapFrame CreateResizedImage(ImageSource source, int width, int height, int margin)
{
var rect = new Rect(margin, margin, width - margin * 2, height - margin * 2);
var group = new DrawingGroup();
RenderOptions.SetBitmapScalingMode(group, BitmapScalingMode.HighQuality);
group.Children.Add(new ImageDrawing(source, rect));
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
drawingContext.DrawDrawing(group);
var resizedImage = new RenderTargetBitmap(
width, height, // Resized dimensions
96, 96, // Default DPI values
PixelFormats.Default); // Default pixel format
resizedImage.Render(drawingVisual);
return BitmapFrame.Create(resizedImage);
}