我寫了一個這個函數的版本,它將灰度位圖作爲蒙板和源位圖,並輸出一個位圖,其中應用了蒙板SetPixel
和GetPixel
,但速度很慢,所以改爲我試圖寫一個使用BitmapData和指針算術,但我得到一個訪問衝突,我不知道爲什麼。在圖像蒙板中使用BitmapData訪問衝突
當寫入結果位圖中的像素時,我得到一個AccessViolationException
- 我認爲這是由不正確的索引造成的,但我看不到我出錯的地方。
public static Bitmap ApplyAlphaMask2(Bitmap source, Bitmap mask)
{
if (source.Size != mask.Size)
{
throw new NotImplementedException("Applying a mask of a different size to the source image is not yet implemented");
}
Bitmap result = new Bitmap(source.Width, source.Height);
unsafe
{
BitmapData source_data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
BitmapData mask_data = mask.LockBits(new Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
BitmapData result_data = result.LockBits(new Rectangle(0, 0, result.Width, result.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
for(int column = 0; column < source.Height; column++)
{
Int32* source_column_ptr = (Int32*)source_data.Scan0 + (column * Math.Abs(source_data.Stride));
Int32* mask_column_ptr = (Int32*)mask_data.Scan0 + (column * Math.Abs(mask_data.Stride));
Int32* result_column_ptr = (Int32*)result_data.Scan0 + (column * Math.Abs(mask_data.Stride));
for (int row = 0; row < source.Width; row++)
{
Color source_color = Color.FromArgb(source_column_ptr[row]);
Color mask_color = Color.FromArgb(mask_column_ptr[row]);
Int32* result_pixel_ptr = &result_column_ptr[row];
Color result_color = Color.FromArgb((int)(255.0f * mask_color.GetBrightness()), source_color);
*result_pixel_ptr = result_color.ToArgb(); //Access violation!
}
}
source.UnlockBits(source_data);
mask.UnlockBits(mask_data);
result.UnlockBits(result_data);
}
return result;
}
任何幫助,將不勝感激。
編輯:這並不總是發生在同一列,但該行始終顯示爲0
僅使用Math.Abs是因爲示例顯示它在此msdn頁面上使用:http://msdn.microsoft.com/zh-cn/library/system。 drawing.imaging.bitmapdata.aspx另外,從'mask_data.Stride'改爲'result_data.Stride'沒有幫助:/ – Ell
步幅是否定的?請檢查所有3個步驟。嘗試沒有吸收。該示例僅使用Abs分配空間,而不是「導航」現有緩衝區。 – usr
@所有文檔都包含以下語句:「跨度是單行像素(掃描線)的寬度,四捨五入爲四字節邊界。如果跨度爲正,則位圖爲自上而下。如果步幅是負值,則位圖是自下而上的。「所以這似乎是錯誤 - 位圖是自下而上的。 – usr