最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解WPF如何使用WriteableBitmap提升Image性能

 更新時(shí)間:2024年01月08日 11:17:55   作者:黑夜中的潛行者  
這篇文章主要為大家詳細(xì)介紹了WPF如何使用WriteableBitmap提升Image性能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

WriteableBitmap 背景

WriteableBitmap 繼承至 System.Windows.Media.Imaging.BitmapSource

“巨硬” 官方介紹:  WriteableBitmap 類

WriteableBitmap使用 類可按幀更新和呈現(xiàn)位圖。 這對(duì)于生成算法內(nèi)容(如分形圖像)和數(shù)據(jù)可視化(如音樂可視化工具)非常有用。

類 WriteableBitmap 使用兩個(gè)緩沖區(qū)。 后臺(tái)緩沖區(qū) 在系統(tǒng)內(nèi)存中分配,并累積當(dāng)前未顯示的內(nèi)容。 前端緩沖區(qū) 在系統(tǒng)內(nèi)存中分配,并包含當(dāng)前顯示的內(nèi)容。 呈現(xiàn)系統(tǒng)將前緩沖區(qū)復(fù)制到視頻內(nèi)存中以供顯示。

兩個(gè)線程使用這些緩沖區(qū)。 用戶界面 (UI) 線程生成 UI,但不會(huì)將其呈現(xiàn)在屏幕上。 UI 線程響應(yīng)用戶輸入、計(jì)時(shí)器和其他事件。 一個(gè)應(yīng)用程序可以有多個(gè) UI 線程。 呈現(xiàn)線程編寫和呈現(xiàn)來自 UI 線程的更改。 每個(gè)應(yīng)用程序只有一個(gè)呈現(xiàn)線程。

UI 線程將內(nèi)容寫入后臺(tái)緩沖區(qū)。 呈現(xiàn)線程從前緩沖區(qū)讀取內(nèi)容并將其復(fù)制到視頻內(nèi)存。 使用更改的矩形區(qū)域跟蹤對(duì)后臺(tái)緩沖區(qū)所做的更改。

調(diào)用其中 WritePixels 一個(gè)重載以自動(dòng)更新和顯示后臺(tái)緩沖區(qū)中的內(nèi)容。

為了更好地控制更新,并且要對(duì)后臺(tái)緩沖區(qū)進(jìn)行多線程訪問,請(qǐng)使用以下工作流:

1.Lock 調(diào)用 方法以保留更新的后臺(tái)緩沖區(qū)。

2.通過訪問 屬性獲取指向后臺(tái)緩沖區(qū)的 BackBuffer 指針。

3.將更改寫入后臺(tái)緩沖區(qū)。 鎖定時(shí) WriteableBitmap ,其他線程可能會(huì)將更改寫入后臺(tái)緩沖區(qū)。

4.AddDirtyRect 調(diào)用 方法以指示已更改的區(qū)域。

5.Unlock 調(diào)用 方法以釋放后臺(tái)緩沖區(qū)并允許在屏幕上演示。

6.將更新發(fā)送到呈現(xiàn)線程時(shí),呈現(xiàn)線程會(huì)將更改后的矩形從后緩沖區(qū)復(fù)制到前緩沖區(qū)。 呈現(xiàn)系統(tǒng)控制此交換以避免死鎖和重繪項(xiàng)目。

WriteableBitmap 渲染原理

在調(diào)用 WriteableBitmap 的 AddDirtyRect 方法的時(shí)候,實(shí)際上是調(diào)用 MILSwDoubleBufferedBitmap.AddDirtyRect,這是 WPF 專門為 WriteableBitmap 而提供的非托管代碼的雙緩沖位圖的實(shí)現(xiàn)。

在 WriteableBitmap 內(nèi)部數(shù)組修改完畢之后,需要調(diào)用 Unlock 來解鎖內(nèi)部緩沖區(qū)的訪問,這時(shí)會(huì)提交所有的修改。

WriteableBitmap 使用技巧

1.WriteableBitmap 的性能瓶頸源于對(duì)臟區(qū)的重新渲染。

臟區(qū)為 0 或者不在可視化樹渲染,則不消耗性能。

只要有臟區(qū),渲染過程就會(huì)開始成為性能瓶頸。

  • CPU 占用基礎(chǔ)值就很高了。
  • 臟區(qū)越大,CPU 占用越高,但增幅不大。

2.內(nèi)存拷貝不是 WriteableBitmap 的性能瓶頸。

建議使用 Windows API 或者 .NET API 來拷貝內(nèi)存數(shù)據(jù)。

特殊的應(yīng)用場(chǎng)景,可以適當(dāng)調(diào)整下自己寫代碼的策略:

  • 如果你希望有較大臟區(qū)的情況下降低 CPU 占用,可以考慮降低 WriteableBitmap 臟區(qū)的刷新率。
  • 如果你希望 WriteableBitmap 有較低的渲染延遲,則考慮減小臟區(qū)。

案例

測(cè)試 Demo 使用 OpenCvSharp 將視頻幀讀取出來,將視頻幀圖像數(shù)據(jù)通過 WriteableBitmap 渲染到界面的 Image 控件。

核心源碼

核心代碼,利用雙緩存區(qū)更新位圖圖像信息

private void ShowImage()
{
    Bitmap.Lock();

    bitmap = frame.ToBitmap();

    bitmapData = bitmap.LockBits(new Rectangle(new System.Drawing.Point(0, 0), bitmap.Size),
        System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

    Bitmap.WritePixels(rect, bitmapData.Scan0, bitmapData.Height * bitmapData.Stride, bitmapData.Stride, 0, 0);

    bitmap.UnlockBits(bitmapData);
    bitmap.Dispose();

    Bitmap.Unlock();
}

完整的 ViewModel 代碼

public class MainWindowViewModel : Prism.Mvvm.BindableBase
{
    #region 屬性、變量、命令

    private WriteableBitmap _bitmap;
    /// <summary>
    /// UI綁定的資源對(duì)象
    /// </summary>                
    public WriteableBitmap Bitmap
    {
        get => _bitmap;
        set => SetProperty(ref _bitmap, value);
    }

    /// <summary>
    /// OpenCvSharp 視頻捕獲對(duì)象
    /// </summary>
    private static VideoCapture videoCapture;

    /// <summary>
    /// 視頻幀
    /// </summary>
    private static Mat frame = new Mat();

    private static BitmapData bitmapData = new BitmapData();
	
	private static Bitmap bitmap;
    
    Int32Rect rect;

    static int width = 0, height = 0;

    /// <summary>
    /// 打開文件
    /// </summary>
    public DelegateCommand OpenFileCommand { get; set; }

    public DelegateCommand MNCommand { get; set; }

    #endregion

    public MainWindowViewModel()
    {
        videoCapture = new VideoCapture();

        OpenFileCommand = new DelegateCommand(OpenFile);
        MNCommand = new DelegateCommand(MN);
    }

    #region 私有方法

    private void OpenFile()
    {
        OpenFileDialog open = new OpenFileDialog()
        {
            Multiselect = false,
            Title = "請(qǐng)選擇文件",
            Filter = "視頻文件(*.mp4, *.wmv, *.mkv, *.flv)|*.mp4;*.wmv;*.mkv;*.flv|所有文件(*.*)|*.*"
        };

        if (open.ShowDialog() is true)
        {           
            ShowMove(open.FileName);
        }
    }

    /// <summary>
    /// 獲取視頻
    /// </summary>
    /// <param name="fileName">文件路徑</param>
    private void ShowMove(string fileName)
    {
        videoCapture.Open(fileName, VideoCaptureAPIs.ANY);

        if (videoCapture.IsOpened())
        {
            var timer = (int)Math.Round(1000 / videoCapture.Fps) - 8;
            width = videoCapture.FrameWidth;
            height = videoCapture.FrameHeight;

            Bitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);
            rect = new Int32Rect(0, 0, Bitmap.PixelWidth, Bitmap.PixelHeight);

            while (true)
            {
                videoCapture.Read(frame);
                if (!frame.Empty())
                {
                    ShowImage();
                    Cv2.WaitKey(timer);
                }
            }
        }
    }

    private void ShowImage()
    {
        Bitmap.Lock();

        bitmap = frame.ToBitmap();

        bitmapData = bitmap.LockBits(new Rectangle(new System.Drawing.Point(0, 0), bitmap.Size),
            System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

        Bitmap.WritePixels(rect, bitmapData.Scan0, bitmapData.Height * bitmapData.Stride, bitmapData.Stride, 0, 0);

        bitmap.UnlockBits(bitmapData);
        bitmap.Dispose();

        Bitmap.Unlock();
    }
}

測(cè)試結(jié)果

測(cè)試結(jié)果,經(jīng)供參考,更精準(zhǔn)的性能測(cè)試請(qǐng)使用專業(yè)工具。

  • VS Debug模式下的性能監(jiān)測(cè),以及Windows任務(wù)管理器中的資源占用,可以看出各項(xiàng)資源的使用是比較穩(wěn)定的。
  • 發(fā)布之后獨(dú)立運(yùn)行資源的占用應(yīng)該會(huì)有5%的降低。

以上就是詳解WPF如何使用WriteableBitmap提升Image性能的詳細(xì)內(nèi)容,更多關(guān)于WPF WriteableBitmap的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#實(shí)現(xiàn)字符串與圖片的Base64編碼轉(zhuǎn)換操作示例

    C#實(shí)現(xiàn)字符串與圖片的Base64編碼轉(zhuǎn)換操作示例

    這篇文章主要介紹了C#實(shí)現(xiàn)字符串與圖片的Base64編碼轉(zhuǎn)換操作,結(jié)合實(shí)例形式分析了C#針對(duì)base64編碼與圖片的相互轉(zhuǎn)換操作技巧,需要的朋友可以參考下
    2017-06-06
  • C#列出當(dāng)前系統(tǒng)所有正在運(yùn)行程序的方法

    C#列出當(dāng)前系統(tǒng)所有正在運(yùn)行程序的方法

    這篇文章主要介紹了C#列出當(dāng)前系統(tǒng)所有正在運(yùn)行程序的方法,涉及C#操作系統(tǒng)進(jìn)程的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-04-04
  • c#異常處理示例分享

    c#異常處理示例分享

    這篇文章主要介紹了c#異常處理示例,需要的朋友可以參考下
    2014-04-04
  • C#數(shù)組的常用操作方法小結(jié)

    C#數(shù)組的常用操作方法小結(jié)

    Array數(shù)組在C#中同樣是最基本的數(shù)據(jù)結(jié)構(gòu),下面為大家C#數(shù)組的常用操作方法小結(jié),皆為細(xì)小的代碼段,歡迎收看收藏
    2016-05-05
  • C#非托管泄漏中HEAP_ENTRY的Size對(duì)不上解析

    C#非托管泄漏中HEAP_ENTRY的Size對(duì)不上解析

    這篇文章主要為大家介紹了C#非托管泄漏中HEAP_ENTRY的Size對(duì)不上解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 詳解LINQ入門(下篇)

    詳解LINQ入門(下篇)

    這篇文章主要介紹了詳解LINQ入門(下篇),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • C#根據(jù)Word模版生成Word文件

    C#根據(jù)Word模版生成Word文件

    這篇文章主要為大家詳細(xì)介紹了C#根據(jù)Word模版生成Word文件的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • C#緩存之SqlCacheDependency用法實(shí)例總結(jié)

    C#緩存之SqlCacheDependency用法實(shí)例總結(jié)

    這篇文章主要介紹了C#緩存之SqlCacheDependency用法,在C#程序設(shè)計(jì)中有一定的實(shí)用價(jià)值,需要的朋友可以參考下
    2014-08-08
  • C#時(shí)間戳基本使用方法詳解

    C#時(shí)間戳基本使用方法詳解

    這篇文章主要給大家介紹了關(guān)于C#時(shí)間戳基本使用方法的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-10-10
  • C#事件訂閱發(fā)布實(shí)現(xiàn)原理詳解

    C#事件訂閱發(fā)布實(shí)現(xiàn)原理詳解

    這篇文章主要介紹了C#事件訂閱發(fā)布實(shí)現(xiàn)原理詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12

最新評(píng)論

茂名市| 遵义市| 三明市| 修文县| 揭阳市| 城市| 筠连县| 临桂县| 安丘市| 射洪县| 泰宁县| 兰考县| 内丘县| 黑龙江省| 乃东县| 确山县| 横山县| 罗源县| 双牌县| 茂名市| 郓城县| 施甸县| 区。| 且末县| 巴楚县| 当雄县| 延长县| 白水县| 咸宁市| 会昌县| 宽甸| 灌阳县| 通辽市| 中卫市| 宁乡县| 吴堡县| 芦溪县| 越西县| 汶上县| 丹寨县| 新余市|