Obtaing the ROI in Visual basic errors in code after conversion from C - vb.net

I've been working on obtaining the ROI of an image, I'm trying to get a square shaped box that will hoover around the region an be able to click and get the standard deviation. I'm familiar with c so i used the c to VB converter, but im getting errors that the statement is not valid in namespace. Everything seems to compatible to VB code. I will be grateful for any suggestions on this matter. Thanks
Private Function DrawRoi(Image As Bitmap, rect As RectangleF) As oid
Dim roi As New Rectangle()
roi.X = CInt(CSng(Image.Width) * rect.X)
roi.Y = CInt(CSng(Image.Height) * rect.Y)
roi.Width = CInt(CSng(Image.Width) * rect.Width)
roi.Height = CInt(CSng(Image.Height) * rect.Height)
Dim timer As New Stopwatch()
timer.Start()
' graphics manipulation takes about 240ms on 1080p image
Using roiMaskImage As Bitmap = CreateRoiMaskImage(ImageWithRoi.Width, ImageWithRoi.Height, roi)
Using g As Graphics = Graphics.FromImage(ImageWithRoi)
g.DrawImage(Image, 0, 0)
g.DrawImage(roiMaskImage, 0, 0)
Dim borderPen As Pen = CreateRoiBorderPen(ImageWithRoi)
g.DrawRectangle(borderPen, roi)
End Using
End Using
Debug.WriteLine("roi graphics: {0}ms", timer.ElapsedMilliseconds)
Me.imagePictureBox.Image = ImageWithRoi
End Function
Private Function CreateRoiMaskImage(width As Integer, height As Integer, roi As Rectangle) As Bitmap
Dim image As New Bitmap(width, height, PixelFormat.Format32bppArgb)
Using g As Graphics = Graphics.FromImage(image)
Dim dimBrush As New SolidBrush(Color.FromArgb(64, 0, 0, 0))
g.FillRectangle(dimBrush, 0, 0, width, height)
Dim roiBrush As New SolidBrush(Color.Red)
g.FillRectangle(roiBrush, roi)
image.MakeTransparent(Color.Red)
Return image
End Using
End Function

Related

The cropping area has an x and y offset in the new bitmap, but only if the original has been scaled

a strange phenomenon occurs.
With my edge detection program, I can transfer the inside of the GraphicsPath to a new image.
It always works great – except when I scale the original image with GIMP and Word (aspect ratio remains, only the dimensions are changed). Then the area is shifted. To the left and up. See attachement. In line 68, I looked what is in rectCutout. Everything OK.
Does this have anything to do with GIMP? The dots per inch are the same (72). The compression quality of the JPEG also (100%).
I just realized: if I scale an image larger, the result is completely black.
The strange thing is: I'm not saying: the picture that is drawn on is larger than the picture that is saved. Then it would be logical that the path is not in the same position. It's about the fact that the loaded image is just smaller.
I would be happy if someone could tell me why. 😄
this is the scaled image which is loaded
Here you see the GUI, ready to save
cropped image, area has x and y offset
#Disable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
Imports System.Drawing.Drawing2D
Imports Microsoft.WindowsAPICodePack.Dialogs
Public NotInheritable Class AllesGrafische
Public Shared Sub Paint_the_Rectangle(ByVal g As Graphics, ByVal recta As Rectangle)
If g IsNot Nothing Then
g.SmoothingMode = SmoothingMode.AntiAlias
g.CompositingQuality = CompositingQuality.HighQuality
g.PixelOffsetMode = PixelOffsetMode.HighQuality
g.InterpolationMode = InterpolationMode.HighQualityBilinear
Using Pen_Hellblau As Pen = New Pen(Color.FromArgb(0, 200, 255), 1.0F)
g.DrawRectangle(Pen_Hellblau, recta)
End Using
End If
End Sub
Public Shared Sub Draw_Curve(ByVal g As Graphics, ByVal theList As List(Of Point))
If theList IsNot Nothing AndAlso theList.Count > 0 AndAlso g IsNot Nothing Then
g.SmoothingMode = SmoothingMode.AntiAlias
g.CompositingQuality = CompositingQuality.HighQuality
g.PixelOffsetMode = PixelOffsetMode.HighQuality
g.InterpolationMode = InterpolationMode.HighQualityBilinear
Dim theList_neu As New List(Of Point)
Using gp As New GraphicsPath
For i As Integer = 1 To theList.Count - 1 Step 1
Dim a As Integer = theList(i).X
Dim b As Integer = theList(i).Y
Dim c As Integer = theList(i - 1).X
Dim d As Integer = theList(i - 1).Y
Dim Entfernungsbetrag As Double = Math.Sqrt(Math.Pow(a, 2) + Math.Pow(b, 2) + Math.Pow(c, 2) + Math.Pow(d, 2) - 2 * a * c - 2 * b * d)
If Entfernungsbetrag < Form1.erlaubte_Entfernung Then
theList_neu.Add(theList(i))
End If
Next
If theList_neu.Count = 0 Then Return
gp.AddLines(theList_neu.ToArray())
Using Pen_hellrosa As Pen = New Pen(Color.FromArgb(255, 64, 239), 1.0F)
g.DrawPath(Pen_hellrosa, gp)
End Using
If Form1.ClosePath Then
gp.CloseFigure()
End If
If Form1.CheckBox1.Checked Then
Dim Speicherpfad As String
Using SFD1 As New CommonSaveFileDialog
SFD1.Title = "Wo soll das Bild gespeichert werden?"
SFD1.Filters.Add(New CommonFileDialogFilter("PNG", ".png"))
If System.IO.Directory.Exists("C:\Users\...\source\repos\VB.NET\Get mouse position and draw rectangle on screen") Then
SFD1.InitialDirectory = "C:\Users\...\source\repos\VB.NET\Get mouse position and draw rectangle on screen"
Else
SFD1.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
End If
If SFD1.ShowDialog = CommonFileDialogResult.Ok Then
Speicherpfad = SFD1.FileName & ".png"
Else
Return
End If
End Using
Using bmpSource As Bitmap = New Bitmap(Form1.Pfad_Bild)
Dim rectCutout As RectangleF = gp.GetBounds()
Using m As Matrix = New Matrix()
m.Translate(-rectCutout.Left, -rectCutout.Top)
gp.Transform(m)
End Using
Using bmpCutout As Bitmap = New Bitmap(CInt(Math.Round(rectCutout.Width, 0)), CInt(Math.Round(rectCutout.Height, 0)))
Using graphicsCutout As Graphics = Graphics.FromImage(bmpCutout)
graphicsCutout.Clip = New Region(gp)
graphicsCutout.DrawImage(bmpSource, CInt(-rectCutout.Left), CInt(-rectCutout.Top))
bmpCutout.Save(Speicherpfad, Imaging.ImageFormat.Png)
Form1.CheckBox1.Checked = False
End Using
End Using
End Using
End If
End Using
End If
End Sub
End Class
#Enable Warning CA1707 ' Bezeichner dürfen keine Unterstriche enthalten
The solution is to use .SetResolution()
Using Original As Bitmap = New Bitmap(Form1.Pfad_Bild)
Dim rectCutout As RectangleF = gp.GetBounds()
Using m As System.Drawing.Drawing2D.Matrix = New System.Drawing.Drawing2D.Matrix()
m.Translate(-rectCutout.Left, -rectCutout.Top)
gp.Transform(m)
End Using
Using bmpCutout As Bitmap = New Bitmap(CInt(Math.Round(rectCutout.Width, 0)), CInt(Math.Round(rectCutout.Height, 0)))
bmpCutout.SetResolution(Original.HorizontalResolution, Original.VerticalResolution)
.
.
.
.
.

vb 2015 GDI+ bitmap placement

I've had little luck trying to find the answer to this either on stackoverflow specifically, or on the internet in general.
I have a form in a vb 2015 Windows Forms project.
On that form, I've placed six controls: four textboxes, a panel, and a button.
When I click the button, it generates a bitmap, like so:
Private Sub btnSetLeft_Click(sender As Object, e As EventArgs) Handles btnSetLeft.Click
Dim R As Integer = CInt(txtRedLeft.Text)
Dim G As Integer = CInt(txtGreenLeft.Text)
Dim B As Integer = CInt(txtBlueLeft.Text)
Dim A As Integer = CInt(txtAlphaLeft.Text)
gcL = Color.FromArgb(A, R, G, B)
Using bm As Bitmap = New Bitmap(9, 9)
Using gBM As Graphics = Graphics.FromImage(bm)
Using br As SolidBrush = New SolidBrush(gcL)
gBM.FillRectangle(br, New Rectangle(0, 0, 8, 8))
End Using
End Using
End Using
End Sub
But, after building the bitmap, I want the button to place the bitmap on the panel and then repaint the panel, thus displaying the new bitmap.
How do I do that?
It's not too hard (I simplified your example):
Dim gcL As Color = Color.Blue
Using bm As New Bitmap(9, 9)
Using gBM As Graphics = Graphics.FromImage(bm)
Using br As New SolidBrush(gcL)
gBM.FillRectangle(br, New Rectangle(0, 0, 8, 8))
End Using
End Using
panel1.BackgroundImage = bm
panel1.BackgroundImageLayout = ImageLayout.Tile
panel1.Update()
End Using

VB Downscaling coordinates

I have the need to know when a gdi+ drawn line is clicked on by the mouse.
I have fashioned this function which is used in a loop on all the existing lines and what the function does is:
It makes a buffer of the line's container's size
It makes the whole thing black
It draws the line in green
It gets the pixel at the mouse location
If the pixel is different from black a.k.a green, the line has successfully been clicked and the function should then return true.
This works great, there's no misinterpretations, but I'm afraid that there's a tiny delay (not really noticeable) when my form is in full screen (due to the large buffer).
I'm looking for a way to optimize this, and my first thought is to downscale everything. So what I mean by that is make the buffer like 20x20 and then draw the line in a scaled down version using math. Problem is, I suck at math, so I'm basically asking you how to do this and preferably with an explanation for dummies.
This is the function:
Public Function Contains(ByVal e As Point) As Boolean
Dim Width As Integer = Container.Size.Width
Dim Height As Integer = Container.Size.Height
Dim Buffer As Bitmap = New Bitmap(Width, Height)
Using G As Graphics = Graphics.FromImage(Buffer)
G.Clear(Color.Black)
Dim Start As Point = New Point(ParentNode.Location.X + ParentNode.Size.Width / 2, ParentNode.Location.Y + ParentNode.Size.Height / 2)
Dim [End] As Point = New Point(ChildNode.Location.X + ChildNode.Size.Width / 2, ChildNode.Location.Y + ChildNode.Size.Height / 2)
Dim Control1 As Point
Dim Control2 As Point
Control1.X = Start.X + GetAngle(ChildNode.Location, ParentNode.Location, ChildNode.Location.X - ParentNode.Location.X, ChildNode.Location.Y - ParentNode.Location.Y)
Control1.Y = Start.Y
Control2.X = [End].X
Control2.Y = Start.Y
G.DrawBezier(New Pen(Color.Green, 4), Start, Control1, Control2, [End])
End Using
If Buffer.GetPixel(e.X, e.Y).ToArgb() <> Color.Black.ToArgb() Then
Return True
End If
Return False
End Function
This is one of my attempts to make the function use the idea above:
Public Function Contains(ByVal e As Point) As Boolean
Dim Width As Integer = 20
Dim Height As Integer = 20
Dim Buffer As Bitmap = New Bitmap(Width, Height)
Using G As Graphics = Graphics.FromImage(Buffer)
G.Clear(Color.Black)
Dim Start As Point = New Point(ParentNode.Location.X + ParentNode.Size.Width / 2, ParentNode.Location.Y + ParentNode.Size.Height / 2)
Dim [End] As Point = New Point(ChildNode.Location.X + ChildNode.Size.Width / 2, ChildNode.Location.Y + ChildNode.Size.Height / 2)
Dim Control1 As Point
Dim Control2 As Point
Control1.X = Start.X + GetAngle(ChildNode.Location, ParentNode.Location, ChildNode.Location.X - ParentNode.Location.X, ChildNode.Location.Y - ParentNode.Location.Y)
Control1.Y = Start.Y
Control2.X = [End].X
Control2.Y = Start.Y
G.DrawBezier(New Pen(Color.Green, 4), New Point(Start.X / Width, Start.Y / Height), New Point(Control1.X / Width, Control1.Height / Height), New Point(Control2.X / Width, Control2.Y / Height), New Point([End].X / Width, [End].Y / Height))
End Using
If Buffer.GetPixel(Width, Height).ToArgb() <> Color.Black.ToArgb() Then
Return True
End If
Return False
End Function
Try using a GraphicsPath for drawing and testing with the built-in IsOutlineVisible function:
Public Function Contains(ByVal e As Point) As Boolean
Dim result as Boolean = False
Using gp As New GraphicsPath
gp.AddBezier(your four points)
Using p As New Pen(Color.Empty, 4)
result = gp.IsOutlineVisible(e, p)
End Using
End Using
Return result
End Function
Side note: Bitmaps and Graphic objects need to be disposed when you create them.

Vb.net changing colors of a picture

I am struggling with the following problem: I have a small picture with is painted in red. This color must be changed to another color (users'choice). I used msdn and some googling did the following:
Private Function GetPicture(Iterator As Integer, tempfile As String) As String
Dim Rstring = ""
If Colors.Count = 0 OrElse Iterator >= Colors.Count Then
Rstring = tempfile
Else
Dim NewPicture = My.Computer.FileSystem.GetTempFileName()
My.Computer.FileSystem.CopyFile(tempfile, NewPicture, True)
Dim mypict = New Bitmap(NewPicture)
Dim ColorList As New List(Of Color)
For x = 0 To mypict.Width - 1
For y = 0 To mypict.Height - 1
Dim mypixel = mypict.GetPixel(x, y)
If ColorList.Contains(mypixel) = False Then
ColorList.Add(mypixel)
End If
Next
Next
Dim NewColor = Color.FromArgb(255, 0, 0, 255)
Dim ListOfColorMaps As New List(Of ColorMap)
For Each elem In ColorList
Dim newcolormap = New ColorMap
newcolormap.OldColor = elem
newcolormap.NewColor = NewColor
ListOfColorMaps.Add(newcolormap)
Next
Dim imageAttributes As New ImageAttributes()
Dim width As Integer = mypict.Width
Dim height As Integer = mypict.Height
Dim colorMap As New ColorMap()
'colorMap.OldColor = Color.FromArgb(255, 0, 0, 0) ' opaque red
'colorMap.NewColor = Color.FromArgb(255, 0, 0, 255) ' opaque blue
Dim remapTable As ColorMap() = ListOfColorMaps.ToArray
imageAttributes.SetRemapTable(remapTable, ColorAdjustType.Bitmap)
Dim tempBmp = New Bitmap(width, height)
Dim g = Graphics.FromImage(tempBmp)
g.DrawImage(tempBmp, New Rectangle(0, 0, width, height), 0, 0, width, height, GraphicsUnit.Pixel, imageAttributes)
g.Save()
g.Dispose()
mypict.Dispose()
Dim NewFileName = NewPicture.Remove(NewPicture.IndexOf("."c) - 1) & ".png"
tempBmp.Save(NewFileName, Imaging.ImageFormat.Png)
My.Computer.FileSystem.DeleteFile(NewPicture)
tempBmp.Dispose()
Rstring = NewPicture
End If
Return Rstring
The Code runs without exceptions, and it seems to find the desired colors but the saved tempbmp contains no picture. Does this happen because the code runs in a dll without graphic?
You can pretty much ignore the "IF" part - that has something to do with another usecase.
Greetings and sincere thanks
Christian Sauer
You are getting no picture displayed because you are drawing an empty bitmap.
Your problem starts here:
Dim tempBmp = New Bitmap(width, height)
Dim g = Graphics.FromImage(tempBmp)
g.DrawImage(tempBmp, New Rectangle(0, 0, width, height), 0, 0, width, height, _
GraphicsUnit.Pixel, imageAttributes)
You create a new bitmap (probably with a white background).
Then you create a new Graphics object from your empty bitmap.
Then you draw the empty bitmap onto itself.
What you should be doing is drawing the mypict object (which is the bitmap whose colors you want to change). Thus your third line should be as follows:
g.DrawImage(mypict, New Rectangle(0, 0, width, height), 0, 0, width, height, _
GraphicsUnit.Pixel, imageAttributes)
Since the Graphics object g is associated with tempBmp (which is empty prior to the DrawImage operation) drawing mypict will draw to it with your parameters.
One other recommendation is that you remove the g.Save() line. You save a graphics object when you plan to restore it later. Doing a Graphics.Save() does not save a picture. What really saves the changes you have made is the tempBmp.Save() line.

Creating listview icons on the fly on VB.NET?

Is that possible? I want to pass my custom color as a parameter and I want to receive an Image (rectangle for example).
Public Function createIcon(ByVal c As Color) As Bitmap
Dim g As Graphics
Dim Brush As New SolidBrush(c)
g.FillRectangle(Brush, New Rectangle(0, 0, 20, 20))
Dim bmp As New Bitmap(20, 20, g)
Return bmp
End Function
I tried this way and couldn't success.
Bitmap: A canvas (in memory) that contains an image.
Graphics: A tool set that allows you to draw on an associated canvas.
With this in mind, here is the solution:
Public Function CreateIcon(ByVal c As Color, ByVal x As Integer, ByVal y As Integer) As Bitmap
Dim icon As New Bitmap(x, y)
Using g = Graphics.FromImage(icon)
Using b As New SolidBrush(c)
g.FillRectangle(b, New Rectangle(0, 0, 20, 20))
End Using
End Using
Return icon
End Function
The Using blocks here merely serve the purpose of disposing the graphics resources properly (by automatically calling their Dispose method at the end of the block). You need to do this, otherwise you will leak graphics resources.
Okay, got it. I am going to share what I did just in case.
Public Function createIcon(ByVal c As Color, ByVal x As Integer, ByVal y As Integer) As Bitmap
createIcon = New Bitmap(x, y)
For i = 0 To x - 1
For j = 0 To y - 1
If i = 0 Or j = 0 Or i = x - 1 Or j = y - 1 Then
createIcon.SetPixel(i, j, Color.Black)
Else
createIcon.SetPixel(i, j, c)
End If
Next
Next
Return createIcon
End Function
This function will give you a colored rectangle with black border.