简体   繁体   中英

How to copy an Image into a section of a WriteableBitmap (C# & WPF)

Many apologies if this is a duplicate. I am writing a number of BitmapImages onto a specific portion of a canvas like this (snippet). It works fine:

  TreeFile = "pack://application:,,,/Images/" + TreeFile;

                        var image = new Image
                        {
                            Source = new BitmapImage(new Uri(TreeFile))
                        };
                        image.Width = 10;
                        image.Height = 10;

                        Canvas.SetLeft(image, x );
                        Canvas.SetTop(image, y );
                        MainCanvas.Children.Add(image);

What I want to do is to also copy image to a WriteableBitmap BlankMap; at the same time and in the same location (MainCanvas and the BlankMap are the same size). This is to create an 'undo'. Then, assuming the user wants to keep the new composite image copy BlankMap to the final BitmapImage WorkingMap; Lastly, I will need to save the now completed WorkingMap to disk.

So my questions are:

  1. Is using WriteableBitmaps the correct way to go for this?
  2. How would I write image to BlankMap ?
  3. How would I write BlankMap to WorkingMap (though #2 and #3 are probably the same question/answer.

Thanks! And, again, apologies if this is some form of a duplicate question.

Based on my experience with a mapping tool, I'm concerned that you are applying a thought process that makes sense in WinForms and causes problems in WPF. Please be careful with generated images in WPF as they can easily leak memory due to a long standing bug deep in the framework.

Question #1

Is this the right way to do "undo" functionality? No. However, WPF allows you to add, move, and remove elements quite easily.

I believe it was envisioned that you would implement your changes using commands, and then repeal a command from the stack when you want to undo it. However, I have yet to see an example of this in any meaningful way.

Question #2

When you initialize a WriteableBitmap with an existing ImageSource , you simply initialize it by passing it in the constructor:

var BlankMap = new WriteableBitmap(image);

After that, you would follow the code example listed in the class documentation .

Question #3

You would reverse the process.


The bottom line is that it sounds like you are wanting to do some graphical editing of some sort. Bitmaps work great in WinForms so it's easy to get suckered into believing they will work just as great in WPF. They do not. If you limit your use of bitmaps to display only then you will have a much easier time dealing with memory leaks and such.

This works for me:

    public static void CopyImageTo(Image sourceImage, int x, int y, WriteableBitmap target)
    {
        BitmapSource source = sourceImage.Source as BitmapSource;

        int sourceBytesPerPixel = GetBytesPerPixel(source.Format);
        int sourceBytesPerLine = source.PixelWidth * sourceBytesPerPixel;

        byte[] sourcePixels = new byte[sourceBytesPerLine * source.PixelHeight];
        source.CopyPixels(sourcePixels, sourceBytesPerLine, 0);

        Int32Rect sourceRect = new Int32Rect(x, y, source.PixelWidth, source.PixelHeight);
        target.WritePixels(sourceRect, sourcePixels, sourceBytesPerLine, 0);
    }

    public static int GetBytesPerPixel(PixelFormat format)
    {
        return format.BitsPerPixel / 8;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM