I am new to C# and to WPF, and I could be looking at this completely wrong. I have a JPEG byte array as a source. I cannot change this. I need to get the array, perform some calculations and draw rectangles in areas of the JPEG. I then write it to an Image XAML control.
I get the JPEG and I can convert it into an ImageSource and display it to an ImageControl. I can't find a way to get the drawing context from the ImageSource. I use ImageSourceConverter to read in the JPEG array and this class returns an ImageSource instance, duh!.
ImageSource mImage = (ImageSource)mConverter.ConvertFrom(mImageBuffer);
ImageSource does not have a drawing context property.
What it seems like I need is a DrawingImage, it is derived from ImageSource and has a drawing context property.
How can I use a DrawingImage instead of the ImageSource.
I looked at the ImageDrawing class, it has an ImageSource property. This class doesn't have a drawing context.
I am currently looking into the Visual class, and help where to look would be appreciated.
Edit:
Thanks #nefarious for pointing me in the right direction. I ended with the following:
ImageSource mImage = (ImageSource)mConverter.ConvertFrom(mImageBuffer);
BitmapSource bImage = mImage as BitmapSource;
// Draw a Rectangle
DrawingVisual dVisual = new DrawingVisual();
using (DrawingContext dc = dVisual.RenderOpen())
{
dc.DrawImage(bImage, new Rect(0, 0, bImage.PixelWidth, bImage.PixelHeight));
dc.DrawRectangle(Brushes.Green, null, new Rect(20, 20, 150, 100));
}
RenderTargetBitmap targetBitmap = new RenderTargetBitmap(640,480,96,96, PixelFormats.Default);
targetBitmap.Render(dVisual);
WriteableBitmap wBitmap = new WriteableBitmap(targetBitmap);
image.Source = wBitmap;
Have you looked at using Visuals, I don't know how efficient they are but it seems that you will be unable to copy the source into an ImageSource and draw directly into it.
Create a DrawingVisual and draw the ImageSource and the Rectangles into the drawing context of the drawing visual.
Then use WriteableBitmap to show it in the image;
Related
Ok so here's how this works:
camera sends me an image as a writeable bitmap
client.WhenMasterFrameCaptured().ObserveOn(SynchronizationContext.Current).Subscribe(frame => UpdateMasterCameraPreview(frame));
I set that pointer to an image source(wpf Image control) in the method that this is subscribed to
if (cameraOneBitmap != null)
{
frame.Image.CopyTo(cameraOneBitmap);
}
else
{
cameraOneBitmap = frame.Image.ToWriteableBitmap();
}
cameraOneBitmap.Lock();
cameraOneBitmap.AddDirtyRect(new Int32Rect(0, 0, cameraOneBitmap.PixelWidth, cameraOneBitmap.PixelHeight));
cameraOneBitmap.Unlock();
cameraOneImage.Source = cameraOneBitmap;
The Problem: The method feeds me a bitmap that isn't the correct angle and i have no way of changing that. I must rotate it. I'm currently using a render transform in xaml. the problem is it shapes the image all weird in certain window sizes it hangs over the grid into the bottom of the window so i don't want to use that. I've tried using writeablebitmapex library but it creates a new bitmap and that gives me an out of memory exception in about 10 seconds... Is there a way to rotate this bitmap with out have to make a new one every time? Somehow the render transform does it without giving me problems. I was doing this to set the source but it still gives me an exception because it makes a new one.
public static RenderTargetBitmap RotateImage(double angle, WriteableBitmap sourceBitmap)
{
TransformedBitmap tb = new TransformedBitmap(sourceBitmap, new RotateTransform(angle));
DrawingVisual drawingVisual = new DrawingVisual();
DrawingContext drawingContext = drawingVisual.RenderOpen();
drawingContext.DrawImage(tb, new Rect(0, 0, tb.PixelWidth, tb.PixelHeight));
//drawingContext.PushTransform(new RotateTransform(270, .5, .5));
drawingContext.Close();
System.Windows.Media.Imaging.RenderTargetBitmap bmp = new System.Windows.Media.Imaging.RenderTargetBitmap(tb.PixelWidth, tb.PixelHeight, 96, 96, PixelFormats.Pbgra32);
bmp.Render(drawingVisual);
return bmp;
}
I am currently converting a Silverlight application into WPF. In my silverlight application I have the code
WriteableBitmap sceneBitmap = new WriteableBitmap(scene, new TranslateTransform() { Y = 10 });
WriteableBitmap newone = TimelineMainHelper.CropImage(sceneBitmap, 0, 0, sceneBitmap.PixelWidth, sceneBitmap.PixelHeight - 25);
newone.Invalidate();
img.Source = newone;
Where scene is a control.
When putting this into WPF there are no overloads for the writeablebitmap class which take UIElement and Transform as the parameters. Firstly I was wondering why this is? and secondly I was wondering if there was a way getting a control to a writeablebitmap
Instead you will want to use RenderTargetBitmap and CroppedBitmap I believe:
RenderTargetBitmap rtb = new RenderTargetBitmap((int)scene.ActualWidth, (int)scene.ActualHeight, 96, 96, System.Windows.Media.PixelFormats.Pbgra32);
rtb.Render(this.sceneBitmap);
CroppedBitmap crop = new CroppedBitmap(sceneBitmap, new Int32Rect(0, 0, (int)sceneBitmap.ActualWidth, (int)sceneBitmap.ActualHeight));
Then you can do something like:
System.Windows.Controls.Image img = new Image();
img.Source = crop;
And go from there.
Disclaimer:
You may need to use different overloads and what not to do exactly what you wish. I just took a shot guessing what parameters to pass given your snippet.
i want to change in runtime the Background property and i have to set an ImageBrush for it.
I have added some images as Resources on my project, and now i can use them as System.Drawing.Bitmap.
How can i convert System.Drawing.Bitmap into ImageBrush ?
If you are using the codebehind to set it, you can do it like this:
BitmapImage img;
// get bitmapimage from resources and assign to img
ImageBrush brush = new ImageBrush();
brush.ImageSource = img;
myControl.Background = brush;
If you are using databinding you'd need to implement a ValueConverter
From How to create ImageBrush from System.Drawing.Image in WPF?:
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(bitmap.GetHbitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions()
);
bitmap.Dispose();
var brush = new ImageBrush(bitmapSource);
"This solution, however, doesnt free the memory of the handle. For information on how to remove the memory leak see WPF CreateBitmapSourceFromHBitmap() memory leak"
Maybe it's a stupid question, but I have some problems with finding the proper answer:S
How to get frames as Bitmap's or Image's (or something similar) from DrawingGroup? I don't actually know how to bite it. I tried to look for it in the Internet, but had problems with finding something useful.
If you need an image to be used as the Source of an Image control, you could simply put the drawing into a DrawingImage:
var drawing = ...
var drawingImage = new DrawingImage(drawing);
image.Source = drawingImage;
If the question is about creating a BitmapSource (i.e. something that can be encoded by a BitmapEncoder via a BitmapFrame), there is no direct conversion. You have to put the image into an intermediate Image control and render that control into a RenderTargetBitmap, which is a BitmapSource:
var drawing = ...
var drawingImage = new DrawingImage(drawing);
var image = new Image { Source = drawingImage };
var bitmap = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32);
image.Arrange(new Rect(0, 0, bitmap.Width, bitmap.Height));
bitmap.Render(image);
Image img = new Bitmap(Image.FromFile(file.FullName));
using (Graphics g = Graphics.FromImage(img)){
g.DrawRectangle(Pens.Black, 0, 0, img.Width - 2, img.Height - 2);
}
like this
how to do in sliverlight?
Use WriteableBitmap class.
References:
Rendering XAML to a JPEG using Silverlight 3
Silverlight 3.0: WriteableBitmap
Silverlight 3's New Writeable Bitmap
Example:
With WritableBitmap, you can just draw something on a Control or Canvas and then save it to a bitmap using it's public WriteableBitmap(UIElement element,Transform transform) constructor.
You don't need to render a SL Rectangle into the WriteableBitmap. The WriteableBitmapEx open source library is perfect for this. See the project site for an example of the DrawRectangle method.
http://writeablebitmapex.codeplex.com
There are also live samples, including the Shape sample.
You can also find the code of the samples in the source code repository.
You can use a WriteableBitmap for this. Create a Canvas and draw your elements on the Canvas, load other images etc. Then once you are done rendering on the Canvase you can create the WriteableBitmap from the Canvas and then do what every you need.
In the example below I assigned the bitmap as the Source of an Image element to show that the final result.
Canvas canvas = new Canvas();
UIElement ellipse = new Ellipse()
{ Width = 100, Height = 100, Fill = new SolidColorBrush(Colors.Red) };
Canvas.SetLeft(ellipse, 100);
Canvas.SetTop(ellipse, 100);
canvas.Children.Add(ellipse);
WriteableBitmap bmp = new WriteableBitmap(canvas, null);
myImage.Source = bmp;