Can't set the correct value in this while loop

牧云@^-^@ 提交于 2019-12-13 10:48:04

问题


I have translated this code to VB.NET which is a function to check if a image is grayscale.

private static unsafe bool IsGrayScale(Image image)
{
    using (var bmp = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb))
    {
        using (var g = Graphics.FromImage(bmp))
        {
            g.DrawImage(image, 0, 0);
        }

        var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);

        var pt = (int*)data.Scan0;
        var res = true;

        for (var i = 0; i < data.Height * data.Width; i++)
        {
            var color = Color.FromArgb(pt[i]);

            if (color.A != 0 && (color.R != color.G || color.G != color.B))
            {
                res = false;
                break;
            }
        }

        bmp.UnlockBits(data);

        return res;
    }
}

The C# code is working but is not doing what I need so I did a little modifications trying to make a function which checks if a image has certain RGB color but the most important part is not working:

Dim color__1 = Color.FromArgb(pt(i))

Exception:

Error   1   Expression is not an array or a method, and cannot have an argument list.   C:\Visual Studio Projects\WindowsApplication9\WindowsApplication9\Form1.vb  21  47  WindowsApplication9

Here is the translated code:

Imports System.Drawing.Imaging

Public Class Form1

    Private Shared Function ImageHasColor(ByVal image As Image, ByVal R As Int32, ByVal G As Int32, ByVal B As Int32) As Boolean

        Using bmp = New Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb)

            Using graph = Graphics.FromImage(bmp)
                graph.DrawImage(image, 0, 0)
            End Using

            Dim data = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.[ReadOnly], bmp.PixelFormat)

            Dim pt = CType(data.Scan0, Integer)
            MsgBox(pt)
            Dim res As Boolean

            Dim i = 0
            While i < data.Height * data.Width
                Dim color__1 = Color.FromArgb(pt(i))

                If color__1.A <> 0 AndAlso color__1.R = R AndAlso color__1.G = G AndAlso color__1.B = B Then
                    res = True
                    Exit While
                End If

                System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
            End While

            bmp.UnlockBits(data)

            Return res
        End Using
    End Function


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim bmp = New Bitmap("C:\Users\Administrador\Desktop\PrtScr capture_3.jpg")
        MsgBox(ImageHasColor(bmp, 240, 240, 240))
    End Sub

End Class

UPDATE:

Those codes works only for the first time, if I use it more than one time I get this error:

Attempted to read or write protected memory

1.

Private Shared Function ImageHasColor(ByVal image As Image, ByVal R As Int32, ByVal G As Int32, ByVal B As Int32) As Boolean

    Using bmp = New Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb)

        Using graph = Graphics.FromImage(bmp)
            graph.DrawImage(image, 0, 0)
        End Using
        Dim color__1 As Color
        Dim byt
        Dim data = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.[ReadOnly], bmp.PixelFormat)

        Dim pt = CType(data.Scan0, Integer)

        Dim res As Boolean

        For i = 0 To data.Height * data.Width - 1

            color__1 = Color.FromArgb(Marshal.ReadInt32(pt, i * 4))

            If color__1.A <> 0 AndAlso color__1.R = R AndAlso color__1.G = G AndAlso color__1.B = B Then
                res = True
                Exit For
            End If

            'System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
        Next

        bmp.UnlockBits(data)

        Return res
    End Using
End Function

2.

Private Shared Function ImageHasColor(ByVal image As Image, ByVal R As Int32, ByVal G As Int32, ByVal B As Int32) As Boolean

    Using bmp = New Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb)

        Using graph = Graphics.FromImage(bmp)
            graph.DrawImage(image, 0, 0)
        End Using
        Dim color__1 As Color
        Dim byt
        Dim data = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.[ReadOnly], bmp.PixelFormat)

        Dim pt = CType(data.Scan0, Integer)

        Dim res As Boolean

        Dim i = 0
        While i < data.Height * data.Width


            color__1 = Color.FromArgb(Marshal.ReadInt32(pt, i * 4))

            If color__1.A <> 0 AndAlso color__1.R = R AndAlso color__1.G = G AndAlso color__1.B = B Then
                res = True
                Exit While
            End If

            System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)
        End While

        bmp.UnlockBits(data)

        Return res
    End Using
End Function

UPDATE:

This code seems to be working

Private Shared Function ImageHasColor(ByVal image As Image, ByVal R As Int32, ByVal G As Int32, ByVal B As Int32) As Boolean

    Try
        Using bmp = New Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb)

            Using graph = Graphics.FromImage(bmp) : graph.DrawImage(image, 0, 0) : End Using

            Dim Pixel_Color As Color

            Dim Ditmap_Data = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.[ReadOnly], bmp.PixelFormat)

            Dim pt As IntPtr = CType(Ditmap_Data.Scan0, IntPtr)

            For i = 0 To Ditmap_Data.Height * Ditmap_Data.Width - 1

                Pixel_Color = Color.FromArgb(Marshal.ReadInt32(pt, i * 4))

                If Pixel_Color.A <> 0 AndAlso Pixel_Color.R = R AndAlso Pixel_Color.G = G AndAlso Pixel_Color.B = B Then
                    bmp.UnlockBits(Ditmap_Data)
                    Return True
                End If

            Next

            bmp.UnlockBits(Ditmap_Data)
            Return False

        End Using
    Catch ex As Exception
        MsgBox(ex.Message)
        Return Nothing
    End Try

End Function

回答1:


Now you're just being contrarian. Why these UnlockBits in the loop? Do you see them in the original code? Remove them at once.

Private Shared Function HasColor(ByVal image As Image, ByVal toFind As Color) As Boolean

    Using bmp = New Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb)

        Using graph = Graphics.FromImage(bmp)
            graph.DrawImage(image, 0, 0)
        End Using

        Dim data = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.[ReadOnly], bmp.PixelFormat)

        Dim pt = data.Scan0 'Since we can't use a pointer in VB.Net, we'll stick to IntPtr for now
        Dim res As Boolean = False

        For i=0 To data.Height * data.Width - 1
            Dim foundColor as Int32 = Marshal.ReadInt32(pt, i*4)

            If (foundColor and &HFF000000) <> 0 AndAlso ( (foundColor and &H00FFFFFF) = (toFind.ToArgb() and &H00FFFFFF) ) Then
                res = True
                Exit For
            End If

        Next

        bmp.UnlockBits(data)

        Return res
    End Using
End Function


Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Dim bmp = New Bitmap("C:\Users\Administrador\Desktop\PrtScr capture_3.jpg")
    MsgBox(ImageHasColor(bmp, Color.FromArgb(240, 240, 240)))
End Sub

End Class




回答2:


Try declaring pt as an IntPtr and using the Marshal and BitConverter classes to read the integer there.



来源:https://stackoverflow.com/questions/16605197/cant-set-the-correct-value-in-this-while-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!