简体   繁体   中英

If Image contains specific color then

Exists a easy way to check if a image contains certain rgb color?

For example:

Dim img As Image = Image.FromFile("C:\image.png")

If img.contains color.red(.toRGB) then... 

I think the hard way to check this is by getting the color value of each pixel of the image, excluding the transparency of the pngs... also that technique I think will take a longer amount of time to process the entire image... but anyway I don't know how to do that too.

UPDATE

Tried this, but it sayd i'm trying to read from protected memory access:

' Lock the bitmap's data.
Public Function LockBitmap(ByVal bm As Bitmap) As Byte()
    Dim bmp = New Bitmap("C:\Users\Administrador\Desktop\PrtScr capture_3.jpg")
    Dim bmdata As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)
    Dim buffer(bmdata.Stride * bmdata.Height - 1) As Byte
    Marshal.Copy(bmdata.Scan0, buffer, 0, buffer.Length)
    Dim stride As Integer = bmdata.Stride
    bmp.UnlockBits(bmdata)

    'loop over the pixels
    For y As Integer = 0 To bmp.Height - 1
        For x As Integer = 0 To bmp.Width - 1
            Dim valB As Integer = 255 - Marshal.ReadByte(bmdata.Scan0, (stride * y) + (x * 4))
            Dim valG As Integer = 255 - Marshal.ReadByte(bmdata.Scan0, (stride * y) + (x * 4) + 1)
            Dim valR As Integer = 255 - Marshal.ReadByte(bmdata.Scan0, (stride * y) + (x * 4) + 2)

            MsgBox(valR & "," & valG & "," & valB)
        Next
    Next

End Function

Tried this but can't set the value: Can't set the correct value in this while loop

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

Tried taking an example of this making my modifications: http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/1d04ef14-cffb-4ae1-83d3-3a0cd8255c95

    'get a BitmapDataObject for fast processing and copy the Data of the image to an array
    Dim bmdata As BitmapData = bmp.LockBits(New Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb)
    Dim buffer(bmdata.Stride * bmdata.Height - 1) As Byte
    Marshal.Copy(bmdata.Scan0, buffer, 0, buffer.Length)
    Dim stride As Integer = bmdata.Stride
    bmp.UnlockBits(bmdata)

    'loop over the pixels
    For y As Integer = 0 To bmp.Height - 1
        For x As Integer = 0 To bmp.Width - 1
            'Colors/Bytes stored in sequence BGRA
            'test access of alpha channel
            If buffer((stride * y) + (x * 4) + 3) <> 0 Then
               'do something
            End If
        Next
    Next

' use Marshal.Copy again to put the processed data back to the image.

More time spent trying more examples from here: http://www.vb-helper.com/howto_net_lockbits_image.html

' Title Manipulate image pixels very quickly using LockBits in VB .NET

Public g_RowSizeBytes As Integer
Public g_PixBytes() As Byte

Private m_BitmapData As BitmapData

' Lock the bitmap's data.
Public Sub LockBitmap(ByVal bm As Bitmap)
    ' Lock the bitmap data.
    Dim bounds As Rectangle = New Rectangle( _
        0, 0, bm.Width, bm.Height)
    m_BitmapData = bm.LockBits(bounds, _
        Imaging.ImageLockMode.ReadWrite, _
        Imaging.PixelFormat.Format24bppRgb)
    g_RowSizeBytes = m_BitmapData.Stride

    ' Allocate room for the data.
    Dim total_size As Integer = m_BitmapData.Stride * _
        m_BitmapData.Height
    ReDim g_PixBytes(total_size)

    ' Copy the data into the g_PixBytes array.
    Marshal.Copy(m_BitmapData.Scan0, g_PixBytes, _
        0, total_size)
End Sub

Also tried also an alternative way : https://stackoverflow.com/questions/16598567/transparencykey-and-displayed-images-issue

I don't have the necessary knowledges to make it.

PLEASE, SOMEONE CAN HELP ME?

Well, you can do it easily through the "hard way" as you identified, checking every pixel until a specific color is found. Worst case scenario? Loop the entire image.

Private Function ColorInBitmap(Path As String, Target As Color) As Boolean
    Dim B As New Bitmap(Path)
    For x As Integer = 1 To B.Width
        For y As Integer = 1 To B.Height
            Dim tmpC As Color = B.GetPixel(x - 1, y - 1)
            If tmpC.Equals(Target) Then Return True
        Next
    Next
    Return False
End Function

It took 5,6 seconds to return False on 2048x1536 image, measuring before the Bitmap class loads the JPG

You can use it simply by passing the path to the image and the target color.

ColorInBitmap("c:\test.jpg", Color.FromArgb(109, 109, 109))

Note that this Fromargb overload sets alpha value to the max.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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