C#中使用byte[]數據,生成Bitmap(256色 灰度 BMP位圖)源代碼

原文出處: http://www.cnblogs.com/sunrack/articles/893073.html

 

C#中使用byte[]數據,生成Bitmap(256色 灰度 BMP位圖)源代碼
Posted on 2007-09-14 15:06 sunrack 閱讀(2656) 評論(5) 編輯 收藏 所屬分類: DotNet

摸索了3天,終於成功實現了使用已知byte[]數據,生成Bitmap(256色灰度 BMP位圖)。

其中遇到了很多問題:

如何在C#(GDI+)中操作Bitmap,獲取位圖的各種數據,就像在C++|中一樣

如何修改Bitmap的調色板

如何解決位圖顯示錯位的問題,即位圖的4字節對齊問題

如何用數據生成位圖

總結一下,希望對需要的朋友有所幫助,少走彎路。


/// <summary>
/// 使用byte[]數據,生成256色灰度 BMP 位圖
/// </summary>
/// <param name="originalImageData"></param>
/// <param name="originalWidth"></param>
/// <param name="originalHeight"></param>
/// <returns></returns>
public static Bitmap CreateBitmap(byte[] originalImageData, int originalWidth, int originalHeight)
{
//指定8位格式,即256色
Bitmap resultBitmap = new Bitmap(originalWidth, originalHeight, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);

//將該位圖存入內存中
MemoryStream curImageStream = new MemoryStream();
resultBitmap.Save(curImageStream, System.Drawing.Imaging.ImageFormat.Bmp);
curImageStream.Flush();

//由於位圖數據需要DWORD對齊(4byte倍數),計算需要補位的個數
int curPadNum = ((originalWidth * 8 + 31) / 32 * 4) - originalWidth;

//最終生成的位圖數據大小
int bitmapDataSize = ((originalWidth * 8 + 31) / 32 * 4) * originalHeight;

//數據部分相對文件開始偏移,具體可以參考位圖文件格式
int dataOffset = ReadData(curImageStream, 10, 4);


//改變調色板,因爲默認的調色板是32位彩色的,需要修改爲256色的調色板
int paletteStart = 54;
int paletteEnd = dataOffset;
int color = 0;

for (int i = paletteStart; i < paletteEnd; i += 4)
{
byte[] tempColor = new byte[4];
tempColor[0] = (byte)color;
tempColor[1] = (byte)color;
tempColor[2] = (byte)color;
tempColor[3] = (byte)0;
color++;

curImageStream.Position = i;
curImageStream.Write(tempColor, 0, 4);
}

//最終生成的位圖數據,以及大小,高度沒有變,寬度需要調整
byte[] destImageData = new byte[bitmapDataSize];
int destWidth = originalWidth + curPadNum;

//生成最終的位圖數據,注意的是,位圖數據 從左到右,從下到上,所以需要顛倒
for (int originalRowIndex = originalHeight - 1; originalRowIndex >= 0; originalRowIndex--)
{
int destRowIndex = originalHeight - originalRowIndex - 1;

for (int dataIndex = 0; dataIndex < originalWidth; dataIndex++)
{
//同時還要注意,新的位圖數據的寬度已經變化destWidth,否則會產生錯位
destImageData[destRowIndex * destWidth + dataIndex] = originalImageData[originalRowIndex * originalWidth + dataIndex];
}
}


//將流的Position移到數據段
curImageStream.Position = dataOffset;

//將新位圖數據寫入內存中
curImageStream.Write(destImageData, 0, bitmapDataSize);

curImageStream.Flush();

//將內存中的位圖寫入Bitmap對象
resultBitmap = new Bitmap(curImageStream);

return resultBitmap;
}

/// <summary>
/// 從內存流中指定位置,讀取數據
/// </summary>
/// <param name="curStream"></param>
/// <param name="startPosition"></param>
/// <param name="length"></param>
/// <returns></returns>
public static int ReadData(MemoryStream curStream, int startPosition, int length)
{
int result = -1;

byte[] tempData = new byte[length];
curStream.Position = startPosition;
curStream.Read(tempData, 0, length);
result = BitConverter.ToInt32(tempData, 0);

return result;
}

/// <summary>
/// 向內存流中指定位置,寫入數據
/// </summary>
/// <param name="curStream"></param>
/// <param name="startPosition"></param>
/// <param name="length"></param>
/// <param name="value"></param>
public static void WriteData(MemoryStream curStream, int startPosition, int length, int value)
{
curStream.Position = startPosition;
curStream.Write(BitConverter.GetBytes(value), 0, length);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章