High DPI screenshot in VB .NET - 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).

Related

Print Bitmap image over multiple pages using PDFSharp, Vb.net

I have a panel which draws a diagram based on user input. Unfortunately the diagrams can get really really big, and when I print them it doesn't entirely fit on a single page without losing readability.
I'm using PDFsharp within VB.net to create the PDF. The current method is the turn the panel in which the diagram is drawn on to a bitmap image, and then place the image in the pdf document.
1 diagram can easily make the panel 1500,3000 in size.
Example of Diagram
Example of Diagram in PDF
Any help is greatly appreciated
Dim pdfdoc As New PdfDocument
Dim page As PdfPage = pdfdoc.AddPage
Dim Bitmap As Bitmap = New Bitmap(pnl_Draw.Width, pnl_Draw.Height)
Dim BXImage As XImage
Dim GFX As XGraphics
Me.pnl_Draw.DrawToBitmap(Bitmap, New Rectangle(0, 0, Bitmap.Width, Height))
Dim pbx As New PictureBox
pbx.Image = Bitmap
BXImage = XImage.FromGdiPlusImage(pbx.Image)
GFX = XGraphics.FromPdfPage(page)
GFX.ScaleTransform(0.82)
GFX.DrawImage(BXImage, 0, 0)
GFX.Dispose()
pdfdoc.Save("G:\test.pdf")
pdfdoc.Close()
Try
Process.Start("G:\test.pdf")
Catch ex As Exception
End Try
Simple solution: in the Adobe Reader Print dialog click on "Poster" to print the image on more than 1 page. Increase the Zoom factor to distribute the poster on as many pages as you need.
You can also increase the page size proportionally to the bitmap size.
BTW: You don't need GFX.ScaleTransform(0.82) if you specify the destination size in the call to GFX.DrawImage.

How to save real PictureBox

I need to save picturebox with real image as displayed.
Help me?
Ex:
Dim myEncoder As Encoder
Dim myImageCodecInfo As ImageCodecInfo
Dim myEncoderParameter As EncoderParameter
Dim myEncoderParameters As EncoderParameters
Dim bmp As Bitmap = CType(imgJpgPng.Image, Bitmap)
Dim bmpt As New Bitmap(640, 640)
Using g As Graphics = Graphics.FromImage(bmpt)
g.DrawImage(bmp, 0, 0, bmpt.Width, bmpt.Height)
End Using
myImageCodecInfo = GetEncoderInfo(ImageFormat.Jpeg)
myEncoder = Encoder.Quality
myEncoderParameters = New EncoderParameters(1)
myEncoderParameter = New EncoderParameter(myEncoder, CType(75L, Int32))
myEncoderParameters.Param(0) = myEncoderParameter
bmpt.Save("d:\ImgTemp\0000.JPG", myImageCodecInfo, myEncoderParameters)
From what I'm getting is that you want to save the picture box image, maybe to a directory or something. So, lets get right into this(It's very simple. By the way, I noticed you have Dim'd the bmpt at 640, 640, maybe that's a problem.
This is how I would save a picture box image
PictureBox1.Image.Save("C:\Users\Owner\Desktop\Webcam Application poctures\Picture.jpg")
Its very self explanatory, Picturebox1.Image.Save(saving the image) and in the quotations, there's the directory, and at the end there' a jpg, you can make it a .png, or any other file format.
If you want to have it being displayed as the original picture in the picture box, you will need to goto the properties of the picture box and make it bigger(size) or use the stretch feature.
Edit: I'm sorry I didn't read your question right, here's an update!
Read this website's information and look into it, this will help you greatly!
http://www.vb-helper.com/howto_resize_picture_save.html

Find Bounds of GDI+ Shape

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

Quality of TIFF image opened on Win XP machine is poor

I've searched lots of webpages, forums and other resources over the web and these two simple lines of code still drive me crazy:
Dim ImageFile As FileStream = File.Open("C:\Programowanie\Indeksowanie\01.tif", FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite)
ImageBox.Image = CType(Bitmap.FromStream(ImageFile), Bitmap)
When run on Win 7 or 8 it works perfectly fine. The picture box displays full 32bit colors. When run on Win XP the image quality goes dramatically down (only black and white) what is unacceptable. Any ideas for workaround? I cannot convert to jpegs as I need to handle multipage scanned document (business requirement).
Eventually I've got it. The results are not 100% what I expected but are acceptable and the effect displayed on the screen is much more better than previously. Here's a piece of code:
Dim fs As FileStream = File.Open("C:\Programowanie\Indeksowanie\01.tif", FileMode.Open, FileAccess.Read)
Dim bm As Bitmap = CType(Bitmap.FromStream(fs), Bitmap)
Dim temp As New Bitmap(bm.Width, bm.Height)
Dim g As Graphics = Graphics.FromImage(temp)
Dim ScaledWidth As Integer = CInt(Math.Round((ImageBox.Height / bm.Height) * bm.Width))
g.InterpolationMode = InterpolationMode.HighQualityBicubic
g.CompositingQuality = CompositingQuality.HighQuality
g.DrawImage(bm, 0, 0, ScaledWidth, ImageBox.Height)
ImageBox.Image = temp

Scaling form controls according to screen resolution

I am trying to write program in vb 2010 that is independent of screen resolution.
I am designing the program in 1920*1080 and when I change the resolution to e.g. 800*600 everything blows up and the program won't fit the screen. How can I fix this?
I have tried three different approaches:
loop through all controls and scale their position and dimensions
Friend Sub ResizeControl(ByRef ctl As Control)
'---------------------------- GET SCALES -------------------------
Dim DesignScreenWidth As Integer = 1920
Dim DesignScreenHeight As Integer = 1080
Dim CurrentScreenWidth As Integer = Screen.PrimaryScreen.Bounds.Width
Dim CurrentScreenHeight As Integer = Screen.PrimaryScreen.Bounds.Height
'Ratios
Dim ratioX As Double = CurrentScreenWidth / DesignScreenWidth ' e.g. 800/1920
Dim ratioY As Double = CurrentScreenHeight / DesignScreenHeight
With ctl
Dim height As Integer = Math.Min(.Height, CurrentScreenHeight)
Dim width As Integer = Math.Min(.Width, CurrentScreenWidth)
'Position
If (.GetType.GetProperty("Top").CanRead) Then .Top = CInt(.Top * ratioY)
If (.GetType.GetProperty("Left").CanRead) Then .Left = CInt(.Left * ratioX)
'Size
If (.GetType.GetProperty("Width").CanRead) Then .Width = CInt(width * ratioX)
If (.GetType.GetProperty("Height").CanRead) Then .Height = CInt(height * ratioY)
End With
'---------------------- RESIZE SUB CONTROLS -------------------------------
For Each subCtl As Control In ctl.Controls
ResizeControl(subCtl)
Next subCtl
End Sub
Anchor each control to the main Form and only resize the main form
tried to AutoScale Mode
Dim factorX As Double = ratioX * 96.0F
Dim factorY As Double = ratioY * 96.0F
Dim newSize As SizeF = New SizeF(factorX, factorY)
AutoScaleDimensions = newSize
AutoScaleMode = AutoScaleMode.Dpi
Scale(newSize)
Font = New Font(Font.FontFamily, Font.Size * factorX)
None of these methods has worked for me. What am I doing wrong?
One thing I figured out was that my main form is larger than 800*600 pixels so when I run the designer in 800*600 resolution VS cut down the with to 812px so my calculations of with and thus scaling ratio becomes wrong. This error goes applies for all three methods.
Please advise on the best method and if I am doing something wrong.
As an expansion to my first comment, take a look at some best practices from the UX (user experience) world. There is a lot of science and and deliberation put into UIs that work.
There's a great SE site - ux.stackexchange.com that you may find can answer your questsions better than SO.
Here's some questions you may find helpful:
https://ux.stackexchange.com/questions/3414/desktop-software-design-patterns (see MS & Apple have their own guidelines incl. things like button widths)
https://ux.stackexchange.com/questions/11361/responsive-web-design-technique-in-desktop-application
Responsive web design seems to parallel what you're doing. The idea behind it is to have your website be able to handle any client device - which is becoming very important because of the mobile explosion.
I suggest doing some studying in these areas to come up with a good solution.