While experimenting with pixel shaders in WPF I decided to draw some pixels onto a fullscreen image through writeable bitmaps based on the MSDN sample
http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap.aspx
I used a blur shader on the image.
To have a continuous effect I took the image back from the shader and used it as input on the writeable bitmap.
RenderTargetBitmap rtb = new RenderTargetBitmap((int)width, (int)height, 96, 96.0, PixelFormats.Pbgra32);
rtb.Render(imgBackground);
wb = new WriteableBitmap(rtb);
imgBackground.Source = wb;
The above code is really slow.
I need something to make it faster or some way to apply the pixel shader to the writeable bitmap backbuffer instead of the image.
Thx in advance.
Stuck at this problem for some time now ..
RenderTargetBitmap.Render(...) is always rendered in software on the UI thread, so your pixel shader is even being ran in software.
I am unsure what "effect" you are trying to achieve, but maybe you can just set the blur effect on the imgBackground (ie, imgBackground.Effect = new BlurEffect())
Related
as you can read from the title i want to be able to draw some images on the screen, move them in some direction and video capture the movement with a good fps rate.
I want to specify that i do not want to record the desktop nor some portion of it but the content of the actual window in which the images are moving(so the window can also be minimized). Also if possible i want to be able to set a custom size for my view where everything will happen.
Where i should start from?
I have already tried with WPF but as the UI is single threaded i am not able to take a screenshot of the view while something is moving on it.
What library you would suggest me?
Are there similar open-source projects i can learn from?
Any suggestion i welcomed!
Here's some code I recently wrote to do this, it cycles through a number of frames and renders a control (in this case, a Canvas) into PNGs:
private void Export(int frame)
{
// force the control to update after any changes you've just made
theCanvas.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
// render the control into a bitmap
RenderTargetBitmap bitmap = new RenderTargetBitmap(1920, 1080, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(theCanvas);
// save the bitmap out as a PNG
using (var stream = File.Create($"Animation/Frame_{frame.ToString("D3")}.png"))
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(stream);
}
}
You can then use ffmpeg to pack those PNGs into the movie file format of your choice.
I am trying to display image using BitmapImage for some time and it worked.I have changed the image and it stopped working.
For Bitmapimage I was using this code:
`ms.Seek(0, SeekOrigin.Begin); // ms is memory stream
BitmapImage b = new BitmapImage();
b.SetSource(ms);
image.ImageSource = b;`
I have ran into piece of code where it was checking if the length of the bytes[] ==14400
if(bytes.length == 14400)
{
var bmp = new WriteableBitmap(width, height);
Buffer.BlockCopy(buffer, 0, bmp.Pixels, 0, buffer.Length);
}
I want to know when to use WriteableBitmap and BitmapImage .
From iProgrammer:
Bitmaps are generally implemented as immutable objects. What this means is that once you create a bitmap you can't make any changes to it. You can manipulate bitmaps by creating new versions, which then immediately become immutable....
The WriteableBitmap, as its name suggests, isn't immutable and you can get at its individual pixels and manipulate them as much as you want. This is the ideal way to work when you need dynamic bitmaps.
iProgrammer - WriteableBitmap
From MSDN:
"Use the WriteableBitmap class to update and render a bitmap on a per-frame basis..." MSDN - WriteableBitmap Class
The Examples section of the MSDN article also shows how to update a WritableBitmap image when responding to mouse events. The code in the example erases pixels of the image by setting the pixel's ARGB values to 0 when the mouse's right button is down. The code also shows how to update individual pixels in the image where the mouse's left button is down. Essentially the code shows a rudimentary pixel image editor.
The point, however, is that you can't change image data when using regular bitmap - you have to use WritableBitmap instead. You can, however, render both if you wish.
I have a canvas that contains an Image in which I dislay an existing BMP. I draw rectangles on the canvas and add these to the Children colllection. When I click save, I want to update the underlying BMP file.
The following code works, but the rectangle that gets drawn to the BMP is way smaller than what I drew. I guess there's some difference in the co-ordinates? Maybe I shouldn't be using System.Drawing?
using (Graphics g = Graphics.FromImage(image))
{
g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
foreach (var child in canvas.Children)
{
if (child is System.Windows.Shapes.Rectangle)
{
var oldRect = child as System.Windows.Shapes.Rectangle;
// need to do something here to make the new rect bigger as the scale is clearly different
var rect = new Rectangle((int)Canvas.GetLeft(oldRect), (int)Canvas.GetTop(oldRect), (int)oldRect.Width, (int)oldRect.Height);
g.FillRectangle(Brushes.Black, rect);
}
}
... code to save bmp
All suggestions welcome!
Thanks
Try using the System.Windows.Media.Imaging.RenderTargetBitmap Class (an example here).
Wpf uses Device Independent Graphics so you have to compensate for the DPI :
RenderTargetBitmap bmp = new RenderTargetBitmap((int)Canvas1.Width, (int)Canvas1.Height, 96, 96, PixelFormats.Default);
bmp.Render(Canvas1);
From Third Link:
There are two system factors that determine the size of text and graphics on your screen: resolution and DPI. Resolution describes the number of pixels that appear on the screen. As the resolution gets higher, pixels get smaller, causing graphics and text to appear smaller. A graphic displayed on a monitor set to 1024 x 768 will appear much smaller when the resolution is changed to 1600 x 1200.
I'm trying to save a Visual object, which has a transparent background, to a bitmap using RenderTargetBitmap...
public static RenderTargetBitmap RenderToBitmap(this Visual Source, int Width, int Height)
{
var Result = new RenderTargetBitmap(Width, Height, 96, 96, PixelFormats.Default);
Result.Render(Source);
return Result;
}
It works, but the transparent pixels are rendered with black color.
What the simplest way to change these transparent pixels to another color?
If you are saving the image as a JPG, transparent will appear black since JPG does not support transparent channel AFAIK. Possible solution: save as a PNG, or paint with a reasonable background color.
I haven't tested this, but in theory it should work.
Use the CopyPixels() method to extract all the pixel data from your RenderTargetBitmap to an array.
Then query the Alpha channel of all those pixels and where they are equal to 0x00 (fully transparent), set the color to whatever you'd like in the background. If you want to be more elegant, you'd have to do the "color math" to properly set the colors in semi-transparent pixels.
Finally, after you have an adjusted array of pixels, create a new BitmapSource from them.
To save that to disk, you'll probably have to create an Image in memory and set its Source to your new Bitmapsource and run your RenderToBitmap again.
Hope it helps.
EDIT:
After posting this, I had
another thought that may be easier.
If you take a clone or snapshot of the
visual element you're trying to save
and put it into a new in-memory panel
(such as a grid or a canvas), you
could simply change the background of
the panel to be the color you want.
Then you'd use the panel as your
source for RenderTargetBitmap.
This is my first day with Silverlight. I’m trying to prototype an application which (among other functions) should be able to resize user supplied images. It should be able to handle and display several resized images at once. The most obviously approaches I've tried seem to "leak" memory in the sense that the original bitmaps are still being referenced in some way which causes Silverlight to allocate hundreds of megabytes of memory after a while. I just want to be able to load the images one by one, resize them and keep the small versions.
To be precise, I've tried the following:
Creating a list of System.Windows.Controls.Image's (and scaling them). I'm not surprised that this has not worked.
Creating a list of rectangles filled by image brushes. I'm not surprised either.
Rendering the bitmaps into System.Windows.Media.Imaging.WriteableBitmap. I expected this to perform well; I assumed that the bitmaps are really just drawn directly and not referenced in any way. However, the memory consumption indicated otherwise.
Here is a snippet of the relevant piece of code:
// create image source
Stream stream = file.OpenRead();
BitmapImage bmpImg = new BitmapImage();
bmpImg.SetSource(stream);
stream.Close();
// create temporary image from it
Image tmpImg = new Image();
tmpImg.Source = bmpImg;
// this is required by WriteableBitmap
tmpImg.Measure(new Size(100, 100));
tmpImg.Arrange(new Rect(0, 0, 100, 100));
// prepare scaling to 100x100
ScaleTransform scaleTrans = new ScaleTransform();
double scale = (double)100 / (double)Math.Max(bmpImg.PixelHeight, bmpImg.PixelWidth);
scaleTrans.CenterX = 0;
scaleTrans.CenterY = 0;
scaleTrans.ScaleX = scale;
scaleTrans.ScaleY = scale;
// render
WriteableBitmap writeableBitmap = new WriteableBitmap(100, 100);
writeableBitmap.Render(tmpImg, scaleTrans);
writeableBitmap.Invalidate();
// final image
Image img = new Image();
img.Source = writeableBitmap;
I hope I'm not missing anything silly, but it looks to OK to me and does the right thing (except the memory problem). Please also bear in mind that code quality is not supposed to be a production quality; it’s just a quick and dirty prototype.
I noticed that I’m not alone; I found questions related to image manipulation in Silverlight. I’m also aware of the fact that I could use some third party library, do processing on the server or write something even myself, but I’m surprised that Silverlight does not offer any basic image manipulation functions. It does not seem to be an uncommon requirement given where Silverlight positions itself.
Have you looked at the WriteableBitmapEx project? It's an open source project with a tonne of extension methods for the WriteableBitmap class. Here's how you resize:
BitmapImage image = new BitmapImage();
image.SetSource(dialog.File.OpenRead());
WriteableBitmap bitmap = new WriteableBitmap(image);
WriteableBitmap resizedBitmap = bitmap.Resize(500, 500, WriteableBitmapExtensions.Interpolation.Bilinear);
// For uploading
byte[] data = resizedBitmap.ToByteArray();
I don't know about the specifics here, but if you're leaking resources - you might look at which of your objects implements the IDisposable interface. I would guess that the Stream and Image classes implement this interface. And if they do - calling Dispose() on them (or wrapping their usage in a "Using" statement) will cause them to free their resources immediately rather than waiting for the garbage collector to kick in eventually.