[英]Visual Basic - Get Bitmap pixels as array
我正在使用.NET Framework 4在Visual Basic中制作游戏。是否有与此类似的内容(来自Java):
private int[] pixels = ((DataBufferInt) bufferedImage.getRaster().getDataBuffer()).getData();
对于位图? 谢谢。
您正在寻找LockBits
方法。
Bitmap
类提供LockBits
和相应的UnlockBits
方法,使您可以修复内存中位图像素数据数组的一部分,直接访问它,最后用修改后的数据替换位图中的位。 LockBits
返回一个BitmapData
类,该类描述了锁定数组中数据的布局和位置。
BitmapData
类包含以下重要属性;
Scan0固定数据阵列内存中的地址
跨度单行像素数据的宽度(以字节为单位)。 该宽度是图像像素尺寸的倍数,或者可能是数倍,并且可以填充以包括更多字节。
PixelFormat数据的实际像素格式。 这对于找到正确的字节很重要
宽度锁定图像的宽度
高度锁定图像的高度
Scan0和Stride与内存中的数组的关系如下所示:
如图所示, Stride属性保留一行的宽度(以字节为单位)。 但是,行的大小可能不是像素大小的精确倍数,因为为了提高效率,系统确保将数据打包到以四个字节为边界的行中,并填充为四个字节的倍数。 例如,这意味着一个17位宽的每像素24位图像的步幅为52。每行中使用的数据将占用3 * 17 = 51字节,而1字节的填充将每行扩展为52字节或13 * 4字节 一个17像素宽的4BppIndexed图像的步幅为12。其中9个字节(或更合适的是8个半字节)将包含数据,并且该行将被另外3个字节填充到4字节边界。
如上所述,该行的数据承载部分根据像素格式进行布局。 包含RGB数据的每像素24位图像将每3个字节有一个新像素,每像素RGBA每4个字节有32位。 每字节包含一个以上像素的像素格式(例如,每个像素索引4位和每个像素索引1位)必须谨慎处理,以使所需像素不会与同一字节中的近邻像素混淆。
找到正确的字节。
因为跨步是行的宽度,所以要索引任何给定的行或Y坐标,可以将跨步乘以Y坐标以获得特定行的开始。 在行中查找正确的像素可能会更加困难,并且取决于了解像素格式的布局。 以下示例说明如何访问给定像素格式的特定像素。
Format32BppArgb给定X和Y坐标,像素中第一个元素的地址为Scan0 +(y * stride)+(x * 4)。 这指向蓝色字节。 接下来的三个字节包含绿色,红色和Alpha字节。
Format24BppRgb给定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
* Bob Powell的代码和文章,摘自Internet存档
不知道为什么您可能需要这样做,但是GetPixel和SetPixel可以正常工作以编辑或检索像素的颜色。
Bitmap.GetPixel(X, Y) ' Returns a color.
Bitmap.SetPixel(X, Y, Color)
希望这对您有所帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.