Reputation: 1
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
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