Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net “快速”;对于位图中的每个像素;环_Vb.net_Bitmap - Fatal编程技术网

Vb.net “快速”;对于位图中的每个像素;环

Vb.net “快速”;对于位图中的每个像素;环,vb.net,bitmap,Vb.net,Bitmap,我正在编写一个VisualBasic应用程序,它可以截取桌面的屏幕截图,然后在屏幕中央将其裁剪成200px x 200px的图像。应用程序的一部分将遍历每个像素,并检查该像素的RGB是否为某种颜色(这意味着需要不到一秒的时间才能使其有效),不幸的是,位图。Getpixel对我没有任何好处,无论它是否通过位图加载到内存中。是否锁定 有没有更快(几乎是瞬间)的方法?谢谢。当然有。通常您要做的是: for each pixel Get device contex Read Pixel Re

我正在编写一个VisualBasic应用程序,它可以截取桌面的屏幕截图,然后在屏幕中央将其裁剪成200px x 200px的图像。应用程序的一部分将遍历每个像素,并检查该像素的RGB是否为某种颜色(这意味着需要不到一秒的时间才能使其有效),不幸的是,位图。Getpixel对我没有任何好处,无论它是否通过位图加载到内存中。是否锁定


有没有更快(几乎是瞬间)的方法?谢谢。

当然有。通常您要做的是:

for each pixel
  Get device contex
  Read Pixel
  Release device contex (unless you want memory leak)
要使此功能正常工作,您需要很少的外部windows库调用,例如:

        [DllImport("user32.dll")]
        static extern IntPtr GetDC(IntPtr hwnd);

        [DllImport("user32.dll")]
        static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc);

        [DllImport("gdi32.dll")]
        static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos);

        static public System.Drawing.Color getPixelColor(int x, int y) {
            IntPtr hdc = GetDC(IntPtr.Zero);
            uint pixel = GetPixel(hdc, x, y);
            ReleaseDC(IntPtr.Zero, hdc);
            Color color = Color.FromArgb((int)(pixel & 0x000000FF),
                         (int)(pixel & 0x0000FF00) >> 8,
                         (int)(pixel & 0x00FF0000) >> 16);
            return color;
        }
最好是

GetDC
for each pixel
  read pixel and store value
ReleaseDC
然而,我发现获取像素的方法本身很慢。因此,为了获得更好的性能,只需将整个屏幕抓取到位图中,并从中获取像素

以下是c#中的一些示例代码,如果您想使用联机转换器,可以在VB.net中进行转换:

var maxX=200;
var maxY=200;
var screensize = Screen.PrimaryScreen.Bounds;
var xCenterSub100 = (screensize.X-maxX)/2;
var yCenterSub100 = (screensize.Y-maxY)/2;
Bitmap hc = new Bitmap(maxX, maxY);
using (Graphics gf = Graphics.FromImage(hc)){
    gf.CopyFromScreen(xCenterSub100, yCenterSub100, 0, 0, new Size(maxX, maxY), CopyPixelOperation.SourceCopy);
    //...
    for (int x = 0; x < maxX; x++){
        for (int y = 0; y < maxY; y++){
            var pColor = hc.GetPixel(x, y);
            //do something with the color...
        }
    }
}

在我的旧电脑上使用c#,我获得了大约30 fps的速度,运行时间大约为35毫秒。有更快的方法,但他们开始滥用一些东西来达到这个速度。请注意,您没有使用getPixelColor,这里只是供参考。您可以使用屏幕刮取图像方法。

如果您不想使用p/invoke,可以使用LockBits方法。此代码将PictureBox中位图中心200 x 200区域的每个组件设置为随机值。它在大约100毫秒内运行(不包括PictureBox的刷新)

编辑:我意识到您正在尝试读取像素,所以我添加了一行代码来演示如何读取像素

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

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

    Dim rnd As New Random()

    'This code uses a bitmap that is loaded in a picture box.  
    'Any bitmap should work.
    Dim bm As Bitmap = Me.PictureBox1.Image

    'lock an area of the bitmap for editing that is 200 x 200 pixels in the center.
    Dim bmd As BitmapData = bm.LockBits(New Rectangle((bm.Width - 200) / 2, (bm.Height - 200) / 2, 200, 200), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat)

    'loop through the locked area of the bitmap.
    For y = 0 To bmd.Height - 1
        For x = 0 To bmd.Width - 1
            'Get the various pixel locations  This calculation is for a 32bpp Argb bitmap
            Dim blue As Integer = (bmd.Stride * y) + (PixelSize * x)
            Dim green As Integer = blue + 1
            Dim red As Integer = green + 1
            Dim alpha As Integer = red + 1

            'Set each component of the pixel to a random rgb value.  
            'There are 4 bytes that make up each pixel (32bpp Argb)
            Marshal.WriteByte(bmd.Scan0, red, CByte(rnd.Next(0, 256)))
            Marshal.WriteByte(bmd.Scan0, blue, CByte(rnd.Next(0, 256)))
            Marshal.WriteByte(bmd.Scan0, green, CByte(rnd.Next(0, 256)))
            Marshal.WriteByte(bmd.Scan0, alpha, 255)

            'Use the ReadInt32() method to read back the entire pixel
            Dim intColor As Integer = Marshal.ReadInt32(bmd.Scan0)
            If intColor = Color.Blue.ToArgb() Then
                'The pixel is blue
            Else
                'The pixel is not blue
            End If

        Next
    Next

    'Important!
    bm.UnlockBits(bmd)

    Me.PictureBox1.Refresh()

End Sub

前6行应初始化并使用一次。
Private Sub DoGraphics()
    Dim x As Integer
    Dim y As Integer

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

    Dim rnd As New Random()

    'This code uses a bitmap that is loaded in a picture box.  
    'Any bitmap should work.
    Dim bm As Bitmap = Me.PictureBox1.Image

    'lock an area of the bitmap for editing that is 200 x 200 pixels in the center.
    Dim bmd As BitmapData = bm.LockBits(New Rectangle((bm.Width - 200) / 2, (bm.Height - 200) / 2, 200, 200), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat)

    'loop through the locked area of the bitmap.
    For y = 0 To bmd.Height - 1
        For x = 0 To bmd.Width - 1
            'Get the various pixel locations  This calculation is for a 32bpp Argb bitmap
            Dim blue As Integer = (bmd.Stride * y) + (PixelSize * x)
            Dim green As Integer = blue + 1
            Dim red As Integer = green + 1
            Dim alpha As Integer = red + 1

            'Set each component of the pixel to a random rgb value.  
            'There are 4 bytes that make up each pixel (32bpp Argb)
            Marshal.WriteByte(bmd.Scan0, red, CByte(rnd.Next(0, 256)))
            Marshal.WriteByte(bmd.Scan0, blue, CByte(rnd.Next(0, 256)))
            Marshal.WriteByte(bmd.Scan0, green, CByte(rnd.Next(0, 256)))
            Marshal.WriteByte(bmd.Scan0, alpha, 255)

            'Use the ReadInt32() method to read back the entire pixel
            Dim intColor As Integer = Marshal.ReadInt32(bmd.Scan0)
            If intColor = Color.Blue.ToArgb() Then
                'The pixel is blue
            Else
                'The pixel is not blue
            End If

        Next
    Next

    'Important!
    bm.UnlockBits(bmd)

    Me.PictureBox1.Refresh()

End Sub