簡體   English   中英

利用BitmapSource的高硬件使用率

[英]Draw on BitmapSource high hardware usage

我想在BitmapSource上繪制。

我的相框來源來自位圖類型的網絡攝像頭。 我將其轉換為BitmapSource,繪制一個rect並設置為具有數據綁定的Image控件源。

    //convert Bitmap to BitmapSource:

    //WinForms -> WPF
    public BitmapSource BitmapToBitmapSource(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;
    }

    //Drawing code:

    public static BitmapSource DrawRect(BitmapSource frame)
    {
        RenderTargetBitmap rtb = new RenderTargetBitmap(frame.PixelWidth, frame.PixelHeight, frame.DpiX, frame.DpiY, PixelFormats.Pbgra32);
        DrawingVisual dv = new DrawingVisual();

        using (DrawingContext dc = dv.RenderOpen())
        {
            dc.DrawImage(frame, new Rect(0, 0, frame.Width, frame.Height));
            //dc.DrawLine(new Pen(Brushes.White, 1), new Point(0, 0), new Point(frame.Width, frame.Height));
            dc.DrawRectangle(null, new Pen(Brushes.Red, 1), new Rect(50, 50, 100, 100));
        }

        rtb.Render(dv);
        rtb.Freeze();

        return rtb;
    }

我的硬件使用結果:

CPU:24%GPU:5.4%

在2.8Ghz的Intel Core i7-4900MQ上; 4核; 8線程/ NVIDIA Quadro K2100M

結果視頻不流暢,有點慢。

有誰知道我怎么能最快?

System.Drawing.Bitmap轉換為System.Windows.Media.Imaging.BitmapSourceSystem.Windows.Media.ImageSource (基類)非常容易,但您必須小心。

首先,所有您需要在每次使用System.Drawing.Bitmap后都將其處置。 這樣,您就可以在內存中騰出可用空間

轉換可以通過兩種方式完成。 使用GDI或內存流。 我個人更喜歡GDI方式。 此外,GDI還允許您使用GPU而不是CPU。 如果要渲染視覺效果,那是您想要的。

記憶方式

 public static System.Windows.Media.ImageSource ToImageSource2(this Bitmap bitmap)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            bitmap.Save(stream, ImageFormat.Bmp);
            stream.Position = 0;
            System.Windows.Media.Imaging.BitmapImage result = new System.Windows.Media.Imaging.BitmapImage();
            result.BeginInit();
            result.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
            result.StreamSource = stream;
            result.EndInit();
            result.Freeze();
            return result;
        }
    }

GDI方式

[DllImport("gdi32.dll", EntryPoint = "DeleteObject")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteObject([In] IntPtr hObject);
public static System.Windows.Media.ImageSource ToImageSource(this Bitmap bitmap)
{
    System.Windows.Media.ImageSource image;
    IntPtr handle = bitmap.GetHbitmap();
    try
    {
        image = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
        image.Freeze();
    }
    finally
    {
       DeleteObject(handle);
    }


    return image;
}

測試樣本

        public static void Test()
    {
        System.Windows.Media.ImageSource img;
        System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(@"filepath");

        //From GDI
        img =  bmp.ToImageSource();

        //From MemoryStream
        img =  bmp.ToImageSource2();

        //Dispose from memory
        bmp.Dispose();

    }

如果您只需要在圖像周圍繪制邊框,則可以對BitmapSource進行任何操作,然后在用戶界面中將Image包裹在適當的Border

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    <Grid>
        <Border BorderBrush="Red" BorderThickness="1">
            <Image x:Name="Image1" />
        </Border>
    </Grid>
</Window>

然后查看它是否有所改善,否則您將需要檢查調用方法的方式和頻率。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM