2014-01-26 77 views
1

有沒有辦法使用c#指針訪問BitmapImage對象的底層內存?帶指針的BitmapSource訪問

我知道有一個CopyPixels方法,但它將pixels數組的副本複製到一個新數組(複製內存要求)。如果你打開一個大的圖像(2GB),它會分配很多無用的東西。如果你想進行某種細化,比如CCLA,它需要大量的內存。我只需要讀取像素數組。

System.Drawing.Bitmap那樣可以像直接尋址像素嗎?

我寫了一個System.Drawing.Bitmap的快速位圖訪問,但由於我使用的是WPF,因此我需要BitmapSource的相同功能。否則,我不得不復製圖像加載(我的舊方法的位圖和BitmapSource以在WPF中顯示圖像)佔用大量的內存和時間。

謝謝 洛倫佐

回答

1

位圖源不一定對整個圖像支持內存。一個例子,它不會是一個懶惰加載的磁盤上的圖像文件。

您對WIC以及WPF的唯一訪問權限是CopyPixels方法。 BitmapSource的某些子類將允許訪問緩衝區,但它們只是在內部分配內存並自己調用CopyPixels

我會假設無論什麼操作都不需要一次訪問整個圖像。如果是這樣,你可以撥打CopyPixels到一個較小的緩衝區,並窗口訪問圖像。大多數解碼器在請求單個像素時將緩衝整個步幅,或者在JPEG的情況下,然後是整個塊。

我不確定CCLA是什麼,也找不到合適的定義,但如果它是對源圖像的某種轉換,則可以將其實現爲BitmapSource。這樣一來,就可以compose a full chain

仔細注意源圖像,以及變換的順序使用的CacheOption,你應該能夠在不顯著內存的影響訪問任意大的圖像。

如果您已經擁有GDI的高效算法(System.Drawing),則沒有意義重新實現它。您仍然可以使用Imaging.CreateBitmapSourceFromHBitmap或使用WindowsFormsHost來顯示您的最終位圖來託管您之前構建的控件。

+0

CCLA代表連接組件標記算法[HERE](http://en.wikipedia.org/wiki/Connected-component_labeling)。爲了工作,它需要整個圖像分配。是的,我有一個剛剛寫在System.Drawing中的算法。當我加載2-4gb的圖像時,使用您建議的方法,它會創建位圖的COPY以呈現圖像(CreateBitmapSourceForHBitmap)。同樣,CCLA需要一個int數組來標記我需要的大約14〜15GB的RAM來完成這個工作。如果沒有圖像轉換,我只需要9gb的內存。 – LoxLox

+0

如何使用WriteableBitmap.BackBuffer直接訪問圖像?你認爲這是一個好主意嗎?你認爲可寫位圖創建了原始位圖的副本嗎? – LoxLox

+0

可寫位圖只能調用'CopyPixels'。如果你使這個唯一的副本存在,那麼我認爲訪問'WritableBitmap'的'BackBuffer'是一個好主意。在開窗後或者使用'WindowsFormsHost'後,我還會繼續通過'CreateBitmapSourceForHBitmap'使用GDI算法,但那只是我自己。 – Mitch