简体   繁体   English

如何将图像复制到 WriteableBitmap 的一部分(C# 和 WPF)

[英]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).我正在将一些 BitmapImages 写入画布的特定部分,就像这样(片段)。 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;我想做的是将image也复制到WriteableBitmap BlankMap; at the same time and in the same location (MainCanvas and the BlankMap are the same size).在相同的时间和相同的位置(MainCanvas 和 BlankMap 的大小相同)。 This is to create an 'undo'.这是为了创建“撤消”。 Then, assuming the user wants to keep the new composite image copy BlankMap to the final BitmapImage WorkingMap;然后,假设用户想保留新的合成图像,将BlankMap复制到最终的BitmapImage WorkingMap; Lastly, I will need to save the now completed WorkingMap to disk.最后,我需要将现在完成的WorkingMap保存到磁盘。

So my questions are:所以我的问题是:

  1. Is using WriteableBitmaps the correct way to go for this?使用 WriteableBitmaps 是正确的方法吗?
  2. How would I write image to BlankMap ?我将如何将image写入BlankMap
  3. How would I write BlankMap to WorkingMap (though #2 and #3 are probably the same question/answer.我将如何将BlankMap写入WorkingMap (尽管 #2 和 #3 可能是相同的问题/答案。

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.根据我使用映射工具的经验,我担心您正在应用一个在 WinForms 中有意义的思考过程并导致 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.请小心 WPF 中生成的图像,因为它们很容易由于框架深处长期存在的错误而导致内存泄漏。

Question #1问题#1

Is this the right way to do "undo" functionality?这是执行“撤消”功能的正确方法吗? No. However, WPF allows you to add, move, and remove elements quite easily.不可以。但是,WPF 允许您非常轻松地添加、移动和删除元素。

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问题2

When you initialize a WriteableBitmap with an existing ImageSource , you simply initialize it by passing it in the constructor:当您使用现有的ImageSource初始化WriteableBitmap时,您只需将其传递到构造函数中即可对其进行初始化:

var BlankMap = new WriteableBitmap(image);

After that, you would follow the code example listed in the class documentation .之后,您将遵循类文档中列出的代码示例。

Question #3问题#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.位图在 WinForms 中效果很好,所以很容易让人相信它们在 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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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