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);
Related
I want to create a collage (different images on an image). This works with a canvas which is defined and visible in my XAML. But how can I achieve this without showing the canvas?
System.Windows.Controls.Image img = new System.Windows.Controls.Image();
img.Source = new BitmapImage(new System.Uri(System.Environment.CurrentDirectory + "/" + b.Wert, System.UriKind.RelativeOrAbsolute));
TransformGroup tg = new TransformGroup();
double scaleX = (double)w / (double)img.Source.Width;
double scaleY = (double)h / (double)img.Source.Height;
tg.Children.Add(new ScaleTransform(scaleX, scaleY));
if (b.Rotation != null)
tg.Children.Add(new RotateTransform(b.Rotation, w/2, h/2));
tg.Children.Add(new TranslateTransform(x, y));
img.RenderTransform = tg;
canvas.Children.Add(img);
double dpi = 96d;
RenderTargetBitmap rtb = new RenderTargetBitmap(collage.Breite, collage.Hoehe, dpi, dpi, System.Windows.Media.PixelFormats.Default);
canvas.UpdateLayout();
rtb.Render(canvas);
// save as png
BitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
using (var fs = System.IO.File.OpenWrite("test.png"))
{
pngEncoder.Save(fs);
}
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);
}
Is it possible to draw a wpf control to memory (Bitmap) without drawing on the screen at all?
I found an example of how to save to Bitmap, but it only works when the window has been drawn in the screen.
BitmapImage bitmap = new BitmapImage();
RenderTargetBitmap renderTarget =
new RenderTargetBitmap((int)canvaspad.Width,
(int)canvaspad.Height,
96,
96,
System.Windows.Media.PixelFormats.Default);
renderTarget.Render(canvaspad);
As the control has no parent container, you need to call Measure and Arrange in order to do a proper layout. As layout is done asynchronously (see Remarks in Measure and Arrange), you may also need to call UpdateLayout to force the layout to be updated immediately.
public BitmapSource RenderToBitmap(UIElement element, Size size)
{
element.Measure(size);
element.Arrange(new Rect(size));
element.UpdateLayout();
var bitmap = new RenderTargetBitmap(
(int)size.Width, (int)size.Height, 96, 96, PixelFormats.Default);
bitmap.Render(element);
return bitmap;
}
In case you have already set the Width and Height of the element you may use that for the size parameter:
var grid = new Grid
{
Width = 200,
Height = 200,
Background = Brushes.Yellow
};
grid.Children.Add(
new Ellipse
{
Width = 100,
Height = 100,
Fill = Brushes.Blue
});
var bitmap = RenderElement(grid, new Size(grid.Width, grid.Height));
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.