快速将Bitmap转换为BitmapSource wpf

时间:2015-06-09 08:55:04

标签: c# wpf bitmap copy bitmapsource

我需要在Image分量上以30Hz绘制图像。 我使用这段代码:

public MainWindow()
    {
        InitializeComponent();

        Messenger.Default.Register<Bitmap>(this, (bmp) =>
        {
            ImageTarget.Dispatcher.BeginInvoke((Action)(() =>
            {
                var hBitmap = bmp.GetHbitmap();
                var drawable = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                  hBitmap,
                  IntPtr.Zero,
                  Int32Rect.Empty,
                  BitmapSizeOptions.FromEmptyOptions());
                DeleteObject(hBitmap);
                ImageTarget.Source = drawable;
            }));
        });
    }

问题是,使用此代码,我的CPU使用率约为80%,如果没有转换,它约为6%。

那么为什么转换位图这么长呢? 是否有更快的方法(使用不安全的代码)?

2 个答案:

答案 0 :(得分:33)

这是一种方法(根据我的经验)至少比CreateBitmapSourceFromHBitmap快四倍。

它要求您设置生成的BitmapSource的正确PixelFormat

public BitmapSource Convert(System.Drawing.Bitmap bitmap)
{
    var bitmapData = bitmap.LockBits(
        new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height),
        System.Drawing.Imaging.ImageLockMode.ReadOnly, bitmap.PixelFormat);

    var bitmapSource = BitmapSource.Create(
        bitmapData.Width, bitmapData.Height,
        bitmap.HorizontalResolution, bitmap.VerticalResolution,
        PixelFormats.Bgr24, null,
        bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);

    bitmap.UnlockBits(bitmapData);
    return bitmapSource;
}

答案 1 :(得分:5)

我在克莱门斯回答之前回答了自己:

[DllImport("kernel32.dll", EntryPoint = "CopyMemory", SetLastError = false)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, uint count);

 WriteableBitmap writeableBitmap = new WriteableBitmap(1280, 1024, 96.0, 96.0, PixelFormats.Bgr24, null);
        public MainWindow()
        {
            InitializeComponent();

            ImageTarget.Source = writeableBitmap;

            Messenger.Default.Register<Bitmap>(this, (bmp) =>
            {
                ImageTarget.Dispatcher.BeginInvoke((Action)(() =>
               {
                    BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
                    writeableBitmap.Lock();
                    CopyMemory(writeableBitmap.BackBuffer, data.Scan0,
                        (writeableBitmap.BackBufferStride * bmp.Height));
                    writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, bmp.Width, bmp.Height));
                    writeableBitmap.Unlock();
                    bmp.UnlockBits(data);
                }));
            });
        }

现在我的CPU使用率约为15%