【问题标题】:How to create an array of bits and turn them into a bitmap VB?如何创建一个位数组并将它们变成位图 VB?
【发布时间】:2015-09-15 16:09:50
【问题描述】:

我想创建一个位数组并在 vb 中将它们转换为位图?我知道如何创建这样的位图Dim NBitmap as new bitmap(width,height),然后像这样编辑它的像素NBitmap.setpixel(x,y,color)。这很慢,但是我认为创建一个数组或其他东西然后将其转换为位图会更快。但我不知道如何......任何帮助都会很好! 示例:

Dim SM = DateTime.Now.Millisecond
Dim Texture As Bitmap = Image.FromFile("C:\Users\Noah\Desktop\graphics\Grass.jpg")
Dim w = 600
Dim h = 600
Dim Pixels(600, 600) As Color
Dim x = 0
Do Until x = 600
    Dim y = 0
    Do Until y = 600
        Pixels(x, y) = Texture.GetPixel(x, y)
        y += 1
    Loop
    x += 1
Loop
Dim EM = DateTime.Now.Millisecond
Dim FM = EM - SM
If FM < 0 Then
    FM += 1000
End If
Dim FPS = 1000 / FM
Dim ETDFrame As New Bitmap(600, 600)
ETDFrame.image = Pixels().convertBMP

我知道这段代码不起作用,但如果我想给出一个例子的话。我的目标是创建一个新的位图并超级快地编辑所有像素,足够快用于 3d 游戏......

【问题讨论】:

  • 您使用该代码创建的不是位数组,而是颜色结构数组(每个结构可能由四个字节组成)。我怀疑您是否会通过尝试编写自己的 SetPixel 代码来提高速度。而且您正在增加从数组转换到数组所需的时间。
  • 我在我的问题中添加了一个额外的句子。

标签: arrays vb.net bitmap


【解决方案1】:

不清楚您要做什么。看起来好像您正在尝试将 .jpg 转换为 .bmp。如果是这样,你可以调用 Image 类的.Save 方法:

'Load the bitmap
Dim bm As Bitmap = Image.FromFile("C:\Users\Noah\Desktop\graphics\Grass.jpg")
'Save as .bmp
bm.Save("C:\Users\Noah\Desktop\graphics\Grass.bmp", System.Drawing.Imaging.ImageFormat.Bmp)

如果你真的需要处理像素,那么使用GetPixelSetPixel 会太慢。您需要使用LockBits 直接处理位图数据。像这样的:

Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices

Private Sub DoGraphics()
    Dim x As Integer
    Dim y As Integer

    'PixelSize is 3 bytes for a 24bpp Argb image.
    'Change this value appropriately
    Dim PixelSize As Integer = 3

    'Load the bitmap
    Dim bm As Bitmap = Image.FromFile("C:\Users\Noah\Desktop\graphics\Grass.jpg")

    'lock the entire bitmap for editing
    'You can change the rectangle to specify different parts of the image if needed.
    Dim bmData As BitmapData = bm.LockBits(New Rectangle(0, 0, bm.Width, bm.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bm.PixelFormat)

    'Declare empty Color array
    Dim pixels(bm.Width - 1, bm.Height - 1) As Color

    'loop through the locked area of the bitmap.
    For x = 0 To bmData.Width - 1
        For y = 0 To bmData.Height - 1
            'Get the various color offset locations for each pixel.
            'This calculation is for a 24bpp rgb bitmap
            Dim blueOfs As Integer = (bmData.Stride * x) + (PixelSize * y)
            Dim greenOfs As Integer = blueOfs + 1
            Dim redOfs As Integer = greenOfs + 1

            'Read the value for each color component for each pixel
            Dim red As Integer = Marshal.ReadByte(bmData.Scan0, redOfs)
            Dim green As Integer = Marshal.ReadByte(bmData.Scan0, greenOfs)
            Dim blue As Integer = Marshal.ReadByte(bmData.Scan0, blueOfs)

            'Create a Color structure from each color component of the pixel
            'and store it in the array
            pixels(x, y) = Color.FromArgb(red, green, blue)
        Next
    Next

    'Do something to the pixels array here:
    For x = 0 To bmData.Width - 1
        For y = 0 To bmData.Height - 1
            pixels(x, y) = Color.Red
        Next
    Next

    'Update the bitmap from the pixels array
    For x = 0 To bmData.Width - 1
        For y = 0 To bmData.Height - 1
            'Get the various color offset locations for each pixel.
            'This calculation is for a 24bpp rgb bitmap
            Dim blueOfs As Integer = (bmData.Stride * x) + (PixelSize * y)
            Dim greenOfs As Integer = blueOfs + 1
            Dim redOfs As Integer = greenOfs + 1

            'Set each component of the pixel
            'There are 3 bytes that make up each pixel (24bpp rgb)
            Marshal.WriteByte(bmData.Scan0, blueOfs, pixels(x, y).B)
            Marshal.WriteByte(bmData.Scan0, greenOfs, pixels(x,y).G)
            Marshal.WriteByte(bmData.Scan0, redOfs, pixels(x,y).R)

        Next
    Next

    'Important!
    bm.UnlockBits(bmData)

    'Save the updated bitmap
    bm.Save("C:\Users\Noah\Desktop\graphics\Grass.bmp", System.Drawing.Imaging.ImageFormat.Bmp)

End Sub

我希望这会有所帮助。

更新:我已更新代码以显示更改像素值。

【讨论】:

  • 我为 x = 0 到 bm.width 做了另一个循环,并为 y = 0 到 bm.height 做了一个嵌入式循环。在 y 循环中,我输入了像素(x,y)= color.red,但是当我显示位图时,它看起来和以前一样?
  • 我做了一个像素(0,0).tostring的消息框,我说颜色[红色]?
  • 改变像素(x,y) 的值是否不会改变位图的实际像素?如果不是,我可以使用您提供的 setpixel 之外的代码来实现吗?
  • 那也超级快?
  • 更改像素数组中的值不会影响原始位图。如果你想改变位图,你必须使用Marshal.WriteByte。我已经更新了我的答案以显示这一点。这与 VB.Net 一样快。它比使用 GetPixel 和 SetPixel 快得多。
【解决方案2】:

不幸的是,Bitmap 类没有一个属性可以返回所有像素颜色的数组/列表,所以你不能一次设置它们。The Microsoft documentation page 实际上提供了获取和设置的示例代码两个嵌套循环中的像素颜色,就像您已经在做的那样。

如果您的最终目标是存储像素信息以传递给另一个Bitmap,我建议the Clone method。与其花费时间和精力将数据提取为您自己的格式,不如使用已经提供的格式。预定义的方法几乎总是最有效的,因此这应该是您最好的性能选择。

如果您确实必须将颜色存储在一个数组中,那么您必须编写一个方法来循环遍历每种颜色并一次使用一个像素SetPixel。这听起来就像你现在正在做的一样,所以这不会节省任何时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-26
    • 2021-05-24
    • 1970-01-01
    • 2019-09-20
    • 1970-01-01
    • 2022-01-26
    • 2019-08-26
    相关资源
    最近更新 更多