2017-05-07 22 views

回答

3

您在尋找LockBits方法。

Bitmap類提供LockBits和相應UnlockBits方法,使你來修復存儲器位圖像素數據陣列的一部分,直接訪問它,最後在該位圖與修改後的數據替換的位。 LockBits返回描述鎖定數組中數據佈局和位置的BitmapData類。

BitmapData類包含以下重要屬性;

SCAN0在固定數據陣列

步幅寬度,以字節爲單位的像素數據的單列中的存儲器中的地址。該寬度是圖像的像素尺寸的多倍或可能是亞倍數,並且可以被填充以包括更多幾個字節。

PixelFormat數據的實際像素格式。這是爲找到正確的字節

寬度寬度鎖定圖像的

高度鎖定圖像的高度重要

SCAN0步幅到的關係內存中的陣列如下所示:

步幅屬性,如圖所示,以字節爲單位保存一行的寬度。然而,行的大小可能不是像素大小的精確倍數,因爲爲了提高效率,系統可確保將數據打包到從四字節邊界開始並填充爲四個字節的倍數的行中。這意味着例如每像素寬度爲17像素的24位每像素圖像將具有52的步幅。每行中使用的數據將佔用3 * 17 = 51個字節,並且1個字節的填充將使每行擴展至52個字節,或者13 * 4字節。一個17像素寬的4Bpp索引圖像將有一個12的步幅。九個字節或更正確的8個半字節將包含數據,並且該行將被填充進一個3字節到4字節的邊界。

攜帶行的部分的數據,如上面已經建議,根據像素格式佈置。包含RGB數據的24位每像素圖像將每3個字節具有一個新像素,每四個字節每像素RGBA具有32位。包含每個字節多於一個像素的像素格式(例如,每像素4位索引和每像素索引1位)必須仔細處理,以便所需像素不會與相同字節中的相鄰像素混淆。

尋找合適的字節。

由於步幅是一行的寬度,要索引任何給定的行或Y座標,您可以將步幅乘以Y座標以獲得特定行的開始。在行內找到正確的像素可能更困難,並且取決於瞭解像素格式的佈局。以下示例顯示如何訪問給定像素格式的特定像素。給定X和Y座標,像素中第一個元素的地址爲Scan0 +(y * stride)+(x * 4)。這指向藍色字節。以下三個字節包含綠色,紅色和字母字節。給定X和Y座標,像素中第一個元素的地址爲Scan0 +(y * Stride)+(x * 3)。這指向藍色字節,其後是綠色和紅色。

Format8BppIndexed給定X和Y座標,該字節的地址是Scan0 +(y * Stride)+ x。該字節是圖像調色板的索引。

Format4BppIndexed給定X和Y座標,包含像素數據的字節計算爲Scan0 +(y * Stride)+(x/2)。相應的字節包含的兩個像素中,上半字節是最左邊的和低半字節是最右邊兩個像素的。上下半字節的四位用於從16色調色板中選擇顏色。

Format1BppIndexed給定X和Y座標,包含像素的字節由Scan0 +(y * Stride)+(x/8)計算。該字節包含8位,每一位是位8中最左邊像素的一個像素,位0中最右邊的像素。這些位從兩個輸入調色板中選擇。

對於每個像素有一個或多個字節的像素格式,公式很簡單,可以通過按順序遍歷所有Y和X值來完成。以下代碼將每像素32位的藍色分量設置爲255.在這兩種情況下,bm都是先前創建的位圖。在C#中的unsafe塊的指針將用於:

BitmapData bmd=bm.LockBits(new Rectangle(0, 0, 10, 10), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat); 
    int PixelSize=4; 

    for(int y=0; y<bmd.Height; y++) 
    { 
    byte* row=(byte *)bmd.Scan0+(y*bmd.Stride); 
    for(int x=0; x<bmd.Width; x++) 
    { 
     row[x*PixelSize]=255; 
    } 
    } 

在VB中這種操作將被視爲有點不同,因爲VB沒有指針的知識,需要使用Marshal類的訪問非託管數據。

Dim x As Integer 
    Dim y As Integer 
    Dim PixelSize As Integer = 4 
    Dim bmd As BitmapData = bm.LockBits(new Rectangle(0, 0, 10, 10), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat) 

    For y = 0 To bmd.Height - 1 
    For x = 0 To bmd.Width - 1 
     Marshal.WriteByte(bmd.Scan0, (bmd.Stride * y) + (4 * x) , 255) 
    Next 
    Next 

*代碼和文章鮑勃鮑威爾,從Internet Archive

採取
0

不知道爲什麼你可能需要這個,但GetPixel和SetPixel的工作就好,編輯或檢索像素的顏色。

Bitmap.GetPixel(X, Y) ' Returns a color.
Bitmap.SetPixel(X, Y, Color)

希望這有助於!
〜Nic