I have a simple WPF application where I display one very large image (9000x2875) and on top of it, many small images (64x64).
To do this, I have a Canvas
with one Image
, then I programatically add the small images as they arrive.
Now I am trying to save portions of the composite image as png
files. I thought I would use a RenderTargetBitmap
to render the portion of the Canvas
that I wanted. My problem is that I cannot find a good way to save the right portion of the image. Here is a开发者_运维百科 my current hack:
private static void SaveImage(Canvas canvas, string file, int x, int y, int width, int height)
{
//changing 0,0 on the canvas so RenderTargetBitmap works as expected.
canvas.RenderTransform = new MatrixTransform(1d, 0d, 0d, 1d, -x, -y);
canvas.UpdateLayout();
RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, 96d, 96d, Pixelformats.Pbgra32);
bmp.Render(canvas);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
using(Stream s = File.Create(file))
{
encoder.Save(s);
}
}
The obvious problem with this is that the display will change due to the RenderTransform
. It also makes the application slower. I did try to do a RenderTargetBitmap of the entire canvas, but that was much slower than doing this.
So my questions are:
Is there an easier way to save just a portion of the viewed image? If not, does someone have a suggestion for a better way to go about this? (I already tried a singleWriteableBitmap
, but that was about as slow as doing the RenderTargetBitmap
of the entire canvas.What you want to use is a CroppedBitmap, which will allow you to save a cropped portion of your image.
// (BitmapSource bmps)
CroppedBitmap crop = new CroppedBitmap(bmps, new Int32Rect(selRect.X, selRect.Y, selRect.Width, selRect.Height));
Edit: Since there seems to be no way to get this to perform the way you want in WPF I would suggest pre-cropping the large image using GDI+ (without displaying it) and loading the region of it you want onto a smaller canvas.
精彩评论