mich krumskas
mich krumskas

Reputation: 1

finding the color of any pixel of a picture box which has some drawn shapes in different colors by scanning it (in VB.Net 2015)

I used the following code (in VB.Net 2105) for picking the color of the pixel at curser point on a picture box which a rectangle has been drawn on that with white color of the boundary and filled by red color.

Private Sub PictureBox1_mosevnt(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
       
 Dim bmp_dumy As Bitmap = New Bitmap(1, 1)
        
        'For x_pix As Integer = 0 To Me.Width - 1
        '    For y_pix As Integer = 0 To Me.Height - 1
       
        '    Next
        'Next
        
        Using gr_new = Graphics.FromImage(bmp_dumy)
            gr_new.CopyFromScreen(Me.Cursor.Position, New Point(0, 0), New Size(1, 1))
        End Using
        
        Dim pixel As Drawing.Color = bmp_dumy.GetPixel(0, 0)
        
        If pixel.A.ToString = 255 And pixel.R.ToString = 255 And pixel.G.ToString = 255 And pixel.B.ToString = 255 Then
            MsgBox("White color pixel is detected" & pixel.ToString(), MessageBoxButtons.OK)
           
            PictureBox1.BackColor = pixel
            
            Label1.Text$ = bmp_dumy.GetPixel(0, 0).ToString

            Dim p As New Point

            p.X = (Me.Width / 2) - (Label1.Width / 2)

            p.Y = Label1.Top

            Label1.Location = p
            
            Me.Invalidate()
        End if
End sub

Problem:
However when I wanted to put two for--next loops and scan the surface area of picture box (Me.Cursor.Position ---> new point(x_pix,y_pix) it doesn't works.
The IF condition isn't reached, as follows:

Private Sub PictureBox1_mosevnt(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseClick
       
 Dim bmp_dumy As Bitmap = New Bitmap(1, 1)
        
        For x_pix As Integer = 0 To Me.Width - 1
            For y_pix As Integer = 0 To Me.Height - 1
       Using gr_new = Graphics.FromImage(bmp_dumy)
            gr_new.CopyFromScreen(new point(x_pix,y_pix), New Point(0, 0), New Size(1, 1))
        End Using
        
        Dim pixel As Drawing.Color = bmp_dumy.GetPixel(0, 0)
        
        If pixel.A.ToString = 255 And pixel.R.ToString = 255 And pixel.G.ToString = 255 And pixel.B.ToString = 255 Then
            MsgBox("White color pixel is detected" & pixel.ToString(), MessageBoxButtons.OK)
           
            PictureBox1.BackColor = pixel
            
            Label1.Text$ = bmp_dumy.GetPixel(0, 0).ToString

            Dim p As New Point

            p.X = (Me.Width / 2) - (Label1.Width / 2)

            p.Y = Label1.Top

            Label1.Location = p
            
            Me.Invalidate()
            Next
        Next
      End if  
End sub

Upvotes: 0

Views: 50

Answers (1)

Daniel
Daniel

Reputation: 526

I hope I understood your goal correctly. I've written a program for you where you can select an image and draw a rectangle on the PictureBox. Additionally, a copy of the original image is saved, with the rectangle at the corresponding position. The colors within this rectangle are stored in a List(of Color) (allColors). I wasn't sure what to do with it, so for now, the list is just sitting there doing nothing ^^.

The point is, you need to consider the image dimensions and geometry. For example, an image might be 2700×1800 pixels. If you displayed it in its original size, it would extend beyond the screen edges of a 1920×1080 monitor. So my PictureBox displays the image scaled down (still maintaining the aspect ratio, so no side is distorted). One has to use proportional calculations (rule of three) to determine the true coordinates on the original image when the mouse pointer is over a pixel in the PictureBox.

I've built a new PictureBox and slightly modified it so it doesn't trigger too many events. Build the project, save, and you need to place it on the GUI, using the toolbar.

Imports System.Windows.Forms
Public Class PictureBoxEx : Inherits PictureBox
    Public Sub New()
        SetStyle(ControlStyles.Selectable Or ControlStyles.UserMouse, True) 
    End Sub
End Class

By the way, I took one of my old projects and stripped it down (into a new project); it originally had more features. I hope you're okay with that.

Option Strict On
Imports System
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Collections.Generic
Public NotInheritable Class FormMain
    Private loadedImage As Bitmap
    Private mouseStartPointForRectangle As Point
    Private mouseUpMustFollow As Boolean
    Private mouseEndPointForRectangle As Point
    Private allowedToDrawUsersRectangle As Boolean
    Private drawnRectangle As Rectangle
    Private imageRect As RectangleF = RectangleF.Empty
    Private currentZoomFactor As Double = 1.0
    Private imageIsMoved As Boolean = False
    Private saveImage As Boolean = False

    Private Sub ButtonLoadImage_Click(sender As Object, e As EventArgs) Handles ButtonLoadImage.Click
        Using openFileDialog As New OpenFileDialog()
            openFileDialog.Filter = "images|*.bmp;*.jpeg;*.jpg;*.png"
            openFileDialog.Multiselect = False
            If openFileDialog.ShowDialog() = DialogResult.OK Then
                If PictureBoxEx1.Image IsNot Nothing Then
                    PictureBoxEx1.Image.Dispose()
                    PictureBoxEx1.Image = Nothing
                    loadedImage = Nothing
                End If
                loadedImage = New Bitmap(openFileDialog.FileName)
                Dim size As Size = GetImageSize(openFileDialog.FileName)
                ResizePictureBox(size)
                PictureBoxEx1.Image = loadedImage
                currentZoomFactor = 1.0
                imageRect = RectangleF.Empty
                imageRect.Location = New PointF(PictureBoxEx1.Location.X, PictureBoxEx1.Location.Y)
            End If
        End Using
    End Sub

    Private Shared Function GetImageSize(path As String) As Size
        Using bmp As New Bitmap(path)
            Return bmp.Size
        End Using
    End Function

    Private Sub ResizePictureBox(imageSize As Size)
        Dim currentWidth As Integer = imageSize.Width
        Dim currentHeight As Integer = imageSize.Height
        Dim maxPossibleWidth As Integer = 925
        Dim maxPossibleHeight As Integer = 925

        If currentWidth > maxPossibleWidth OrElse currentHeight > maxPossibleHeight Then
            PictureBoxEx1.SizeMode = PictureBoxSizeMode.StretchImage
            PictureBoxEx1.Size = If(
                                  currentWidth * maxPossibleHeight / currentHeight > maxPossibleWidth,
                                  New Size(maxPossibleWidth, CInt(currentHeight * maxPossibleWidth / currentWidth)),
                                  New Size(CInt(currentWidth * maxPossibleHeight / currentHeight), maxPossibleHeight)
                                  )
        Else
            PictureBoxEx1.SizeMode = PictureBoxSizeMode.Normal
            PictureBoxEx1.Size = imageSize
        End If
    End Sub

    Private Sub PictureBoxEx1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBoxEx1.MouseDown
        If loadedImage Is Nothing Then
            Return
        End If

        Select Case e.Button
            Case MouseButtons.Left
                mouseStartPointForRectangle = e.Location
                mouseUpMustFollow = True
                allowedToDrawUsersRectangle = True
                PictureBoxEx1.Invalidate()
                Exit Select
            Case MouseButtons.Right
                drawnRectangle = PointsToRectangle(New Point(0, 0), New Point(0, 0))
                PictureBoxEx1.Invalidate()
                Exit Select
        End Select
    End Sub

    Private Sub PictureBoxEx1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBoxEx1.MouseMove
        If loadedImage Is Nothing Then
            Return
        End If

        If e.Button = MouseButtons.Left AndAlso mouseUpMustFollow Then
            mouseEndPointForRectangle = e.Location
            allowedToDrawUsersRectangle = True
            drawnRectangle = PointsToRectangle(mouseStartPointForRectangle, mouseEndPointForRectangle)
            PictureBoxEx1.Invalidate()
        End If
    End Sub

    Private Sub PictureBoxEx1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBoxEx1.MouseUp
        If loadedImage Is Nothing Then
            Return
        End If

        If e.Button = MouseButtons.Left AndAlso mouseUpMustFollow Then
            mouseEndPointForRectangle = e.Location
            allowedToDrawUsersRectangle = True
            drawnRectangle = PointsToRectangle(mouseStartPointForRectangle, mouseEndPointForRectangle)
            saveImage = True
            PictureBoxEx1.Invalidate()
            mouseUpMustFollow = False
        End If
    End Sub

    Private Sub PictureBoxEx1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBoxEx1.Paint
        If loadedImage Is Nothing Then
            Return
        End If

        If allowedToDrawUsersRectangle Then
            Dim rectanglePictureBox As RectangleF = CalculateZoomedAndOrMovedRect()
            DrawRectangleOnScreen(e.Graphics, rectanglePictureBox)

            If saveImage Then
                Dim drawnRectangleOnOriginalImage As Rectangle = BuildBigRectangle(rectanglePictureBox)
                DrawRectangleOnOriginalImage(e.Graphics,
                                             drawnRectangleOnOriginalImage)
                saveImage = False
            End If

        End If
    End Sub

    Private Sub DrawRectangleOnScreen(g As Graphics, rectanglePictureBox As RectangleF)
        If g Is Nothing Then
            Return
        End If

        g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
        g.CompositingQuality = Drawing2D.CompositingQuality.HighQuality
        g.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
        g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBilinear
        Using penBlue As New Pen(Color.FromArgb(0, 200, 255), 1.0F)
            g.DrawImage(loadedImage, rectanglePictureBox)
            g.DrawRectangle(penBlue, drawnRectangle)
        End Using
    End Sub

    Private Function BuildBigRectangle(rectanglePictureBox As RectangleF) As Rectangle
        Dim x1 As Double = (drawnRectangle.X - rectanglePictureBox.X) / rectanglePictureBox.Width * loadedImage.Width
        Dim y1 As Double = (drawnRectangle.Y - rectanglePictureBox.Y) / rectanglePictureBox.Height * loadedImage.Height
        Dim x2 As Double = ((drawnRectangle.X + drawnRectangle.Width) - rectanglePictureBox.X) / rectanglePictureBox.Width * loadedImage.Width
        Dim y2 As Double = ((drawnRectangle.Y + drawnRectangle.Height) - rectanglePictureBox.Y) / rectanglePictureBox.Height * loadedImage.Height

        Dim rect As New Rectangle(CInt(Math.Round(x1, 0)),
                                  CInt(Math.Round(y1, 0)),
                                  CInt(Math.Round(x2 - x1, 0)),
                                  CInt(Math.Round(y2 - y1, 0)))

        Dim allColors As New List(Of Color)
        For x As Integer = CInt(Math.Round(x1, 0)) To CInt(Math.Round(x2, 0)) Step 1
            For y As Integer = CInt(Math.Round(y1, 0)) To CInt(Math.Round(y2, 0)) Step 1
                allColors.Add(loadedImage.GetPixel(x, y))
            Next
        Next

        Return rect
    End Function

    Private Function CalculateZoomedAndOrMovedRect() As RectangleF
        imageRect.Width = PictureBoxEx1.Width
        imageRect.Height = PictureBoxEx1.Height

        Dim newLocation As PointF
        If imageIsMoved Then
            newLocation = imageRect.Location
        Else
            newLocation = New PointF(
                (PictureBoxEx1.Size.Width / 2.0F) - imageRect.Width * CSng(currentZoomFactor) / 2.0F,
                (PictureBoxEx1.Size.Height / 2.0F) - imageRect.Height * CSng(currentZoomFactor) / 2.0F)
        End If

        Diagnostics.Debug.WriteLine("x = " & Math.Round(newLocation.X, 1).ToString() & "; y = " & Math.Round(newLocation.Y, 1).ToString())
        Return New RectangleF(
            newLocation,
            New SizeF(imageRect.Width * CSng(currentZoomFactor), imageRect.Height * CSng(currentZoomFactor)))
    End Function

    Private Shared Function PointsToRectangle(p1 As Point, p2 As Point) As Rectangle
        Return New Rectangle With {
            .Width = Math.Abs(p1.X - p2.X),
            .Height = Math.Abs(p1.Y - p2.Y),
            .X = Math.Min(p1.X, p2.X),
            .Y = Math.Min(p1.Y, p2.Y)
        }
    End Function

    Private Sub DrawRectangleOnOriginalImage(g As Drawing.Graphics, r As Drawing.Rectangle)
        If g Is Nothing Then
            Return
        End If

        If r.Width > 0 Then
            Using penOrange As New Pen(Color.FromArgb(255, 170, 0), 2.0F)
                Using bmp As New Bitmap(loadedImage)
                    Using gr As Graphics = Graphics.FromImage(bmp)
                        gr.DrawRectangle(penOrange, r)
                        bmp.Save(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) & $"\{Date.Now.ToString("G", New Globalization.CultureInfo("de-DE")).Replace(":"c, "."c)}.png", Imaging.ImageFormat.Png)
                    End Using
                End Using
            End Using
        End If
    End Sub
End Class

Upvotes: 0

Related Questions