繁体   English   中英

Visual Basic-将位图像素获取为数组

[英]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数据的实际像素格式。 这对于找到正确的字节很重要

宽度锁定图像的宽度

高度锁定图像的高度

Scan0Stride与内存中的数组的关系如下所示:

的BitmapData

如图所示, 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM