在对bitmap类图像进行RGB数据提取时,个人发生过图像错位的情况,而这种情况的原因是由于4字节的对齐:内存分配单位是4字节,而位图中每行象素的数据是连续的,下一行不能和上一行共一个分配单元(4字节),所以每行象素的数据长度必须是4字节的倍数,当不足时不足的部分将用0填充
所以一个每行17像素的Bitmap,其实际存储的像素数据为17*3=51字节,而51/4=12.75,也就是说会占用13个分配单元,其中剩下的第52字节就会用0填充,此时如果不将其跳过仍然将其作为图像数据读取就会造成图像的错位
public static bool GetRGB(Bitmap Source, out int[,] R, out int[,] G, out int[,] B)//分离RGB波段
{
int iWidth = Source.Width;
int iHeight = Source.Height;
Rectangle rect = new Rectangle(0, 0, iWidth, iHeight);//将Bitmap锁定到系统内存中,获得BitmapData
System.Drawing.Imaging.BitmapData bmpData = Source.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, Source.PixelFormat);
IntPtr iPtr = bmpData.Scan0;//获取第一个像素地址
int four_byte_for_width = (iWidth * 3 + 3) / 4 * 4;//计算4字节对齐后每行的字节数
int iBytes = four_byte_for_width * iHeight;
byte[] PixelValues = new byte[iBytes];
System.Runtime.InteropServices.Marshal.Copy(iPtr, PixelValues, 0, iBytes);
Source.UnlockBits(bmpData);//解锁
R = new int[iHeight, iWidth];
G = new int[iHeight, iWidth];
B = new int[iHeight, iWidth];
int iPoint = 0;
for (int i = 0; i < iHeight; i++)
{
for (int j = 0; j < iWidth; j++)
{
B[i, j] = Convert.ToInt32(PixelValues[iPoint++]);
G[i, j] = Convert.ToInt32(PixelValues[iPoint++]);
R[i, j] = Convert.ToInt32(PixelValues[iPoint++]);
}
while ((iPoint) % 4 != 0)//跳过4字节对齐中的空值字节
{
iPoint++;
}
}
return true;
}