Find Bounds of GDI+ Shape - vb.net

Hi I'm trying to get a rectangle that completely surrounds a shape drawn via GDI+ when the pen is thick.
This is my test code to demo which I just added to mybase.load to test out..
Dim bmp As New Bitmap(500, 500)
Dim g As Graphics = Graphics.FromImage(bmp)
g.Clear(Color.Transparent)
g.SmoothingMode = SmoothingMode.HighQuality
g.PixelOffsetMode = PixelOffsetMode.Default
' Setup Matrix
Dim mat As New Matrix
mat.Translate(100, 100)
g.Transform = mat
' Draw Lines and Fill
Dim gp As New GraphicsPath
gp.AddLines({New Point(50, 0), New Point(100, 100), New Point(0, 100)})
gp.CloseAllFigures() ' Closes Open Path (ie join back to origin)
g.FillPath(New SolidBrush(Color.Beige), gp)
' Add Border to Graphics Path
g.DrawPath(New Pen(New SolidBrush(Color.Black), 20), gp)
g.DrawRectangle(New Pen(New SolidBrush(Color.Red), 1), Rectangle.Truncate(gp.GetBounds))
' Tidy Up
g.ResetTransform()
mat.Dispose()
' Set Picturebox Value
PictureBox1.Image = bmp
I'd post the image but the forum doesn't let me.
I want the bounding rectangle to include the pen width too. I used the above triangle to demo that I cant just add penwidth/2.
Any ideas?
Julian

If that is sufficient for your needs you can simply set the pen's .Alignment property to Inset like so:
g.DrawPath(New Pen(New SolidBrush(Color.Black), 20) With {.Alignment = PenAlignment.Inset}, gp)
This basically tells the pen to draw itself on the inside of the path at all times. Default is that it draws itself on the middle which leads to the situation that the outside width at edges is dependant on the angle of the edge.
Result is:

Just in case anyone else struggles like i did trying to find a solution then this is what I did in the end. I gave up trying to do using some form of getbounds method.
My solution in the was to scan the rendered bitmap instead to calculate the bounds based on pixels that were non-transparent (the background of my rendered image(s)). In fact I only need to scan once on the combined image and it takes a fraction of a second to calculate the "true" bounds now.
I used this article Fit a PictureBox to its non-transparent pixels to achieve a starting point that proved the concept and gave me a region that I could do a "getbounds" on. Then I swapped out the slow getpixel method for the lockbits example at Work with bitmaps faster in C# and voila!
Just ran all the code through an online c# to vb convertor and pasted it together to get completely working in less than an hour.
Took a fraction of the time I wasted trying to find a solution on the internet that would work directly on the vector image.
Julian

Related

VB.Net Custom Bitmap

Its a bit complicated and I will try my best to explain what I want to achieve.
I've already worked a bit with bitmaps and copy from screen functions.
This all worked very well. But these bitmaps are always rectangles and I would like to use my own bitmap if possible.
As an example:
Somewhere at position x, y on my screen is a map
This map has several paths and junctions.
There are also houses and things that don't interest me, I only focus on the paths in between.
Now I want to scan this map for Argb Pixels using a bitmap and Copy from screen function. I have already done this and it works great, but instead of only scanning the paths for pixels, the whole map is scanned for pixels. But I only want these paths to be scanned.
I have this map as a template and could make a screenshot of it. Can I now import this map into Photoshop, color the houses and everything that I don't need black and make the paths transparent and import them as bitmap so that the Copy From Screen function only scans the paths or is that even possible? I haven't found anything for vb.net if someone could lead me in a right direction I would be very thankful :)
This is the code I got so far - simple pixelsearch function:
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim xd3 = Color.FromArgb(255, 100, 100, 100) 'Searching for this color on the screen
Dim b As New Bitmap(2210, 1100) 'Position of Bitmap
Dim g As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(b)
g.CopyFromScreen(Me.Left, Me.Top, 0, 0, b.Size) 'Searching on Screen
For i = 0 To (Me.Width - 0) 'searching each pixel
For j = 0 To (Me.Height - 0) 'searching each pixel
If b.GetPixel(i, j) = xd3 Then 'If pixel has same color that im searching for it will show a messagebox true
MessageBox.Show("true")
End If
Next
Next
End Sub

visual studio 2017 form location doesn't match picturebox location:

I want to place a picturebox based on the location of the form, so I can move the form around and the box will stay in the same place.
However, when setting the location of the picturebox to be equal to the location of the form, as I move the form, the picturebox change location within the form.
Image 1
Image 2
You'll notice in the first image, the picturebox is close to the topleft corner of the form. This is what I expect.
When the form moves away from the corner of the screen, the picturebox moves in a similar manner.
The code relevant to this is as follows.
PictureBox2.Location = New Point(Me.Location.X, Me.Location.Y)
How can I set the location of the picturebox to be in the same place on the form.
Further Details:
Before you ask: why not make them definite values, this isn't the actual implementation that I'm after.
I'm running an OCR and using a transparent picturebox as my image capture window. However, it wont line up correctly due to the above issue.
The code used to get the image is
gfx.CopyFromScreen(New Point(Me.Location.X + PictureBox1.Location.X + 100, Me.Location.Y + PictureBox1.Location.Y + 50), New Point(0, 0), pic.Size)
However, as I move the form, the image taken is never the same relative location from the form location.
Edit: Attempt 2
Ignore my previous question as I asked it badly. Hopefully this attempt is better.
Image 3
Image 3 shows ideally what I want the form to look like. The top box of the form is transparent picturebox1. When I click the update button, I want to to take a screen shot of that picturebox1 location, and then fill a second picturebox2 below. This is what the image shows.
However, if I move the form to the around, you get the following.
Image4
You can see here the 'photo' taken that is now in picturebox2 no longer lines up perfectly, but instead the image that has been taken is offset.
I want the image captured to always be in the same location as the picturebox1.
The only code being run when the picture is taken is the following.
gfx.CopyFromScreen(New Point(Me.Location.X + PictureBox1.Location.X + 100, Me.Location.Y + PictureBox1.Location.Y + 50), New Point(0, 0), pic.Size)
PictureBox2.Image = pic
And the code at the start of the project is
Dim pic As Bitmap = New Bitmap(270, 100)
Dim gfx As Graphics = Graphics.FromImage(pic)
As the picturebox1 location is constant due to being a relative value to the form corner, the only values that are changing are me.location.x/y.
Therefore, it seems to me that the actual form moves further than the location.x/y value updates.
Why is that and how can I fix my problem?

High DPI screenshot in VB .NET

I'm trying to create a little application that would take screenshots of the Windows desktop.
Now i've got this code which is pretty classic :
Private Function TakeScreenShot() As Bitmap
Dim screenSize As Size = New Size(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height)
Dim screenGrab As New Bitmap(My.Computer.Screen.Bounds.Width, My.Computer.Screen.Bounds.Height)
screenGrab.SetResolution(2400, 2400)
Dim g As Graphics = Graphics.FromImage(screenGrab)
g.CompositingQuality = CompositingQuality.HighQuality
g.InterpolationMode = InterpolationMode.HighQualityBicubic
g.SmoothingMode = SmoothingMode.HighQuality
g.CopyFromScreen(New Point(0, 0), New Point(0, 0), screenSize)
Return screenGrab
End Function
But I'd like to have a very good quality screenshot. I don't know if it is possible, so I'm asking, but could I maybe get a higher resolution screenshot by modifying the DPI (like I did) or maybe by increasing the initial size of the bitmap ? I don't know at all so I ask...
Thank you in advance
You can't do that. Pixels are something like the atoms of computer graphics.
You can't go deeper.
(Yes I know we actually can in the real world or in some hollywood movies with Leonardo DiCaprio, but let's just say atoms are the smallest possible unit. This isn't Physics Exchange, and for a reason I don't have an account there ;S).

Capture image of webbrowser control

I want to capture the image of my webbrowser, or actually just a part of it.
I already achieved it, but it just takes a screenshot of it instead of capturing the bitmap itself.
So when i use this technique and you drag another window above it, the window is also captured. (this is what I don't want.)
My code:
' 1. Get the WebBrowsers bitmap.
Dim bmp As New Bitmap(WebBrowser1.Width, WebBrowser1.Height)
Dim BMPEndResult As Bitmap
Dim graph As Graphics = Graphics.FromImage(bmp)
Dim p As Point = Me.PointToScreen(WebBrowser1.Location)
graph.CopyFromScreen(p.X, p.Y, 0, 0, bmp.Size)
picDest.Image = bmp
So I need to get the image of the webbrowser:
- without the scrollbars if possible
- Even if the window is minimized or in the task bar
- Full webbrowser
- and also if possible just a part of it, where I can specify the top, left, width and height
WebBrowser.DrawToBitmap(bitmap, rectangle)

Larger Image to fit in picturebox

As you'll can see the first image is the size of (1024*768) and it is correctly displayed in the picturebox and in the second case the image size is (1600*900) and it is displayed to half of the picturebox and the remaining is missing .So No I would like to fir that image in the picturebox no matter what the size is and even though it is greater than the size of the picturebox.I need to scale that Image.So how do I do that?And one more thing is that I need to resize the picturebox automatically when the image loads to it just as we see in the lightbox effect..
http://www.lokeshdhakar.com/projects/lightbox2/ -------->example.
Any help will be appreciated!
Here is what I am getting.
If it's a winforms app, you can set the SizeMode property of the PictureBox to PictureBoxSizeMode.Zoom. Note that this will increase the size of smaller images to fill the frame, so you might want to measure the image first, in order to check if either edge is too long, and then setting SizeMode to either PictureBoxSizeMode.Zoom or PictureBoxSizeMode.Normal.
I know this is marked answered, but I wrote this for one of my own apps. Hope it helps somebody..
Private Sub ScaleImage(ByVal p As PictureBox, ByRef i As Bitmap)
If i.Height > p.Height Then
Dim diff As Integer = i.Height - p.Height
Dim Resized As Bitmap = New Bitmap(i, New Size(i.Width - diff, i.Height - diff))
i = Resized
End If
If i.Width > p.Width Then
Dim diff As Integer = i.Width - p.Width
Dim Resized As Bitmap = New Bitmap(i, New Size(i.Width - diff, i.Height - diff))
i = Resized
End If
End Sub
The two Easiest Ways to Fit an Image to Any Size of PictureBox is:
-to set the Image as Background Image
OR
-to set it as picturebox image then set sizemode to StretchImage
1.Background Image
-use the BackgroundImage property of the PictureBox
picturebox.BackgroundImage = Image.FromStream(New IO.MemoryStream(CType(data, Byte())))
-Then Set its BackgroundImageLayout to stretch Like This:
picturebox.BackgroundImageLayout = ImageLayout.Stretch
Image
-use the Image property of the PictureBox
picturebox.Image = Image.FromStream(New IO.MemoryStream(CType(data, Byte())))
-Then Set its' sizeMode to StretchImage Like This:
picturebox.SizeMode = PictureBoxSizeMode.StretchImage
This will make any Picture / Image / Canvas Stroke (converted to Byte Array) fit according to the height and width of the picturebox
Hope This Helps :)