question

JeanLucCoudret-9280 avatar image
0 Votes"
JeanLucCoudret-9280 asked JeanLucCoudret-9280 commented

How to stick some text on an Image via a Label?

Hi all,

In short: I am trying to add a text via a label on an image placed in a picturebox.
My code below is working in some case, but not always. I am using a weird number (3.16) which help most of the case, but I don't really understand why.

What I am looking for is:
1- To stick the text of the label over my Image
2- The label (coming from the class TGlass) displayed over my Image must appeared exactly as it is displayed on the screen (in my picturebox "pbCheckImage01" 400x266px)
3- My image can change in term of pixels (example: 6016x4000 or 2256x1504 or 317x212 ... with always the same ratio 1.5)
4- The size of the label can change via a personalised and limited FontDialog (size 48 to 108)

Any ideas, corrections, improvements are welcome. Hope my explanations were clear enough.

I tried with the method DrawToBitmap, but it doesn't work as I am losing pixels.
I also tried with the method MeasureString without success, but it is maybe the way to go.

Below is the code I am using to stick my label on my image.

             Dim myBitmap As Bitmap = Nothing
             Using fs As New System.IO.FileStream(myPath, System.IO.FileMode.Open, System.IO.FileAccess.Read)
                 'Dim img2 As Image = Image.FromStream(fs)
                 Dim img2 As Bitmap = CType(Bitmap.FromStream(fs), Bitmap)
                 pbCheckImage01.BackgroundImage = img2
                 Dim g As Graphics = Graphics.FromImage(img2)
                 ' Text position of Label TGlass
                 Dim topleft As Point
                 topleft = New Point(TGlass.Left, TGlass.Top)
                 ' Text content of Label TGlass
                 Dim strCalendar As String = TGlass.Text
                 ' Rectangle layout for the selected font
                 Dim layout As New Rectangle(topleft, TGlass.Size)
                 ' Rectangle position with respect of the image
                 layout.X = CInt(layout.X * (img2.Height / pbCheckImage01.Height))
                 layout.Y = CInt(layout.Y * (img2.Width / pbCheckImage01.Width))
                 ' Text First Page
                 Dim myFontSize As Integer
                 myFontSize = CInt(TGlass.Font.Size * (img2.Width / pbCheckImage01.Width) / 3.16)
                 Dim myFont As New Font(TGlass.Font.FontFamily, myFontSize, TGlass.Font.Style)
                 Dim myBrush As New SolidBrush(TGlass.ForeColor)
                 ' Drawing on Image
                 g.DrawString(strCalendar, myFont, myBrush, layout.X, layout.Y)
                 ' Remove the TextWindow class
                 ckbYear.Checked = False
                 myBitmap = img2
             End Using
             ' Update the new image on FirstPage
             pb00.BackgroundImage = myBitmap
             pb00.BackgroundImageLayout = ImageLayout.Stretch
             pb00.Size = fSizeTransfer(myBitmap.Width, myBitmap.Height, 120)
             ' Save (Replace) the Image in the right folder
             myBitmap.Save(myPath, System.Drawing.Imaging.ImageFormat.Jpeg)

And here the code of the TextWindow class TGlass.

 Public Class cTextWindow
    
     Inherits Label ' Control Text
     ' Variable initialisation
     Dim a As Integer
     Dim b As Integer
     Dim newPoint As Point
     Public bClick As Boolean
    
     Public Sub New()
         ' Initialisation
         Me.Cursor = Cursors.SizeAll
         bClick = True
     End Sub
    
     Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
         ' Draw the border of the label
         Try
             If bClick = True Then
                 e.Graphics.DrawRectangle(New Pen(Brushes.Blue, 4), Me.ClientRectangle)
             Else
                 e.Graphics.DrawRectangle(New Pen(Brushes.Transparent, 4), Me.ClientRectangle)
             End If
             MyBase.OnPaint(e)
         Catch ex As Exception
             MsgBox(ex.Message)
         End Try
     End Sub
    
     Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
         ' Find the position of the label
         Try
             a = MousePosition.X - Me.Location.X
             b = MousePosition.Y - Me.Location.Y
         Catch ex As Exception
             MsgBox(ex.Message)
         End Try
     End Sub
    
     Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
         ' Update the position of the label
         Try
             ' New location
             If e.Button = MouseButtons.Left Then
                 newPoint = MousePosition
                 newPoint.X -= a
                 newPoint.Y -= b
                 Me.Location = newPoint
             End If
             ' Raise the MouseMove event
             MyBase.OnMouseMove(e)
         Catch ex As Exception
             MsgBox(ex.Message)
         End Try
     End Sub
    
     Protected Overrides Sub OnMove(ByVal e As System.EventArgs)
         ' Control the position of the label
         Try
             ' Keep it inside the main PictureBox
             If Me.Location.X < 0 Then Me.Location = New Point(0, Me.Location.Y)
             If Me.Location.Y < 0 Then Me.Location = New Point(Me.Location.X, 0)
             If Me.Location.X + Me.Width > frmECalendar.pbCheckImage01.Width Then Me.Location = New Point(frmECalendar.pbCheckImage01.Width - Me.Width, Me.Location.Y)
             If Me.Location.Y + Me.Height > frmECalendar.pbCheckImage01.Height Then Me.Location = New Point(Me.Location.X, frmECalendar.pbCheckImage01.Height - Me.Height)
             ' Control to be redrawn
             'Me.Invalidate()
             Me.Update()
             ' Raise the Move event
             MyBase.OnMove(e)
         Catch ex As Exception
             MsgBox(ex.Message)
         End Try
     End Sub
    
     Protected Overrides Sub OnMousedoubleClick(e As MouseEventArgs)
         ' Display the label frame with a mouse click 
         Try
             bClick = Not bClick
             ' Raise the MouseClick event
             MyBase.OnMouseDoubleClick(e)
             Refresh()
         Catch ex As Exception
             MsgBox(ex.Message)
         End Try
     End Sub
    
 End Class
dotnet-visual-basic
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.


In which cases it is not working?

0 Votes 0 ·

I am not completely sure, but I think it is when the image size is smaller in pixels (300x200 instead of 6000x4000 for example), then the label is applied to the image but with a smaller size of what I can see on the screen. The proportion of the label seen on the screen in the picturebox 400x266 should be the same on the image independant of the real size of the image.

0 Votes 0 ·

Hi @JeanLucCoudret-9280 ,
I try to make a test based on your code, but I get the following exception:
97647-1.png
Could you provide a complete sample here? It will help us make a test.
Besides, you can also consider sharing your project on onedrive or github.

0 Votes 0 ·
1.png (73.5 KiB)
XingyuZhao-MSFT avatar image
1 Vote"
XingyuZhao-MSFT answered JeanLucCoudret-9280 commented

Hi @JeanLucCoudret-9280 ,

especially about these numbers 3 or 4 depending of the way I do it.

(intRenderer.Width / PictureBox1.Width) * img.Width cannot be used as font size.
In 'Button4_Click', you set TGlass.Font = New Font("Arial", 80, FontStyle.Bold)
So consider :

             Dim WidthRate = img.Width / PictureBox1.Width
             Dim myFontSize = CInt(WidthRate * 80)

Best Regards,
Xingyu Zhao


If the answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Perfect and more simple than I thought.
Thank you.

0 Votes 0 ·
JeanLucCoudret-9280 avatar image
0 Votes"
JeanLucCoudret-9280 answered JeanLucCoudret-9280 commented

Hi,

And thanks for your help.
I did a short version of what I want to achieved in a small Apps, but I was not able to attach the zipped file.
Then, I added the main code I used in my small Apps below. The TGlass class I used is already shared in the previous post.

Note it will create a Test folder on your desktop with the various images.
Click BTN01 or BTN02, BTN04 (you can move the label) and finally BTN05 and check the created images N_img1 and N_img2 in the Test folder.
Target: I would like to have the text on the N_image in the folder as it appeared on the picturebox. It worked a bit (not perfectly) with img1, but not with img2 (text too small).

img1 size: W=6016px, H=4000px
img2 size: W=995px, H=661px

If you prefer, I can share it on Google Drive, but I will need your email address.

 Public Class Form1
    
     Private ReadOnly TGlass As New cTextWindow
     Private myPath As String
    
     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
         myPath = System.IO.Path.Combine(System.IO.Path.Combine(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop))), "Test")
         If (Not (System.IO.Directory.Exists(myPath))) Then
             System.IO.Directory.CreateDirectory(myPath)
             My.Resources.img1.Save(myPath & "\img1.jpg", System.Drawing.Imaging.ImageFormat.Jpeg)
             My.Resources.img2.Save(myPath & "\img2.jpg", System.Drawing.Imaging.ImageFormat.Jpeg)
         End If
     End Sub
    
     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
         PictureBox1.BackgroundImage = Nothing
         Dim bmp As Bitmap = New Bitmap(My.Resources.img1, PictureBox1.Size)
         PictureBox1.BackgroundImage = bmp
         'PictureBox1.Image = My.Resources.img1
         PictureBox1.BackgroundImageLayout = ImageLayout.Stretch
         Label1.Text = "W: " & My.Resources.img1.Width & " x H: " & My.Resources.img1.Height
         Label2.Text = "img1"
     End Sub
    
     Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
         PictureBox1.BackgroundImage = Nothing
         Dim bmp As Bitmap = New Bitmap(My.Resources.img2, PictureBox1.Size)
         PictureBox1.BackgroundImage = bmp
         'PictureBox1.Image = My.Resources.img2
         PictureBox1.BackgroundImageLayout = ImageLayout.Stretch
         Label1.Text = "W: " & My.Resources.img2.Width & " x H: " & My.Resources.img2.Height
         Label2.Text = "img2"
     End Sub
    
     Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
         PictureBox1.Controls.Remove(TGlass)
         TGlass.BackColor = Color.Transparent
         TGlass.ForeColor = Color.Red
         TGlass.AutoSize = True
         TGlass.Text = "Hello"
         TGlass.Font = New Font("Arial", 76, FontStyle.Bold)
         TGlass.Location = New Point(5, 75)
         PictureBox1.Controls.Add(TGlass)
     End Sub
    
     Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
         Dim myBitmap As Bitmap = Nothing
         Using fs As New System.IO.FileStream(myPath & "\" & Label2.Text & ".jpg", System.IO.FileMode.Open, System.IO.FileAccess.Read)
             Dim img As Bitmap = CType(Bitmap.FromStream(fs), Bitmap)
             PictureBox1.BackgroundImage = img
             Dim g As Graphics = Graphics.FromImage(img)
             ' Text position of Label TGlass
             Dim topleft As Point
             topleft = New Point(TGlass.Left, TGlass.Top)
             ' Text content of Label TGlass
             Dim strCalendar As String = TGlass.Text
             ' Rectangle layout for the selected font
             Dim layout As New Rectangle(topleft, TGlass.Size)
             ' Rectangle position with respect of the image
             layout.X = CInt(layout.X * (img.Height / PictureBox1.Height))
             layout.Y = CInt(layout.Y * (img.Width / PictureBox1.Width))
    
    
             ' Text First Page
             Dim myFontSize As Integer
             myFontSize = CInt(TGlass.Font.Size * (img.Width / PictureBox1.Width) / 3.16)
    
    
             Dim myFont As New Font(TGlass.Font.FontFamily, myFontSize, TGlass.Font.Style)
             Dim myBrush As New SolidBrush(TGlass.ForeColor)
             ' Drawing on Image
             g.DrawString(strCalendar, myFont, myBrush, layout.X, layout.Y)
             myBitmap = img
         End Using
         ' Save (Replace) the Image in the right folder
         myBitmap.Save(myPath & "\N_" & Label2.Text & ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg)
         PictureBox1.Controls.Remove(TGlass)
     End Sub
    
 End Class

Thanks,
Jean-Luc

· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi @JeanLucCoudret-9280 ,
It works when the image is small, could you share the img1 here? It will help us make a test. We are waiting for your update.

0 Votes 0 ·

The image img1 is 5.85MB (6016x4000px), then I can't upload it.!
But the image img2 is only 115KB (see attachment), I also attached N_img2 (text too small, compared to the picturebox) and N2_img2 (size almost what I expect), N2_img2 is what I obtain when I remove the number 3.16. Note for the img1, I obtain N_img1 (almost the size I expect) and N2_img1 (text far too big, I can see only half of the H), N2_img1 is what I obtain when I remove the number 3.16.

99186-img2.jpg99239-n-img2.jpg99220-n2-img2.jpg


0 Votes 0 ·
img2.jpg (115.6 KiB)
n-img2.jpg (116.0 KiB)
n2-img2.jpg (106.7 KiB)

Hi @JeanLucCoudret-9280 ,

N_img2 (text too small, compared to the picturebox) and N2_img2 (size almost what I expect)

Thanks for your feedback. I have a question to confirm with you.
The img2's size is 'W=995px, H=661px', and the fontsize of TGlass is '76'.
What do you expect the fontsize of TGlass in N2_img2?
0 Votes 0 ·
Show more comments
XingyuZhao-MSFT avatar image
1 Vote"
XingyuZhao-MSFT answered XingyuZhao-MSFT edited

Hi @JeanLucCoudret-9280 ,
You can consider drawing a string directly on a PictureBox image.
For example:

         Dim bmp As Bitmap = New Bitmap("image path")
         Using g As Graphics = Graphics.FromImage(bmp)
             TextRenderer.DrawText(g, "Hello", New Font("Arial", 76, FontStyle.Bold), New Point(5, 75), Color.Red)
         End Using
         bmp.Save("image path")

Result of my test:
99697-img4.jpg
Also check:

  1. Custom AntiAliasing with GDI+

  2. Drawing smooth text and pictures on the extended glass area of your WinForm in Windows Vista

Hope them could be helpful.

Best Regards,
Xingyu Zhao


If the answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



img4.jpg (118.3 KiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

JeanLucCoudret-9280 avatar image
0 Votes"
JeanLucCoudret-9280 answered JeanLucCoudret-9280 commented

Hi,

I followed your advice (also with the help of this link).
It is much better, but not perfect. But I don't think now it is possible to have something perfect because of the conversion pixels to points, need to consider dpi, screen resolution... (or maybe I am wrong).
Anyway, below is the code I am using now. Note there is still something I don't understand as I need to divide by 3 or 4 (depending of the code I used) in the formula calculating myFontSize. If someone understand why, do not hesitate to tell me.

     Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
         Dim myBitmap As Bitmap = Nothing
         Using fs As New System.IO.FileStream(myPath & "\" & Label2.Text & ".jpg", System.IO.FileMode.Open, System.IO.FileAccess.Read)
             Dim img As Bitmap = CType(Bitmap.FromStream(fs), Bitmap)
             PictureBox1.BackgroundImage = img
             Dim g As Graphics = Graphics.FromImage(img)
    
             ' Text position of Label TGlass
             Dim topleft As Point
             topleft = New Point(TGlass.Left, TGlass.Top)
             ' Text content of Label TGlass
             Dim strCalendar As String = TGlass.Text
             ' Text ForeColor
             Dim myColor As Color
             myColor = TGlass.ForeColor
             ' Rectangle layout for the selected font
             Dim layout As New Rectangle(topleft, TGlass.Size)
             ' Rectangle position with respect of the image
             layout.X = CInt(layout.X * (img.Height / PictureBox1.Height))
             layout.Y = CInt(layout.Y * (img.Width / PictureBox1.Width))
    
             ' Text First Page
             Dim intRenderer As SizeF
             Dim myFontSize As Integer
             'intRenderer = TextRenderer.MeasureText(strCalendar, New Font(TGlass.Font.FontFamily, TGlass.Font.Size, TGlass.Font.Style, GraphicsUnit.Pixel))
             'myFontSize = CInt((intRenderer.Width / PictureBox1.Width) * img.Width / 3)
             intRenderer = TextRenderer.MeasureText(strCalendar, TGlass.Font)
             myFontSize = CInt((intRenderer.Width / PictureBox1.Width) * img.Width / 4)
             ' New Font for Text applied on Image
             Dim myFont As New Font(TGlass.Font.FontFamily, myFontSize, TGlass.Font.Style)
             ' Drawing on Image
             TextRenderer.DrawText(g, strCalendar, myFont, New Point(layout.X, layout.Y), myColor)
    
             myBitmap = img
         End Using
         ' Save (Replace) the Image in the right folder
         myBitmap.Save(myPath & "\N_" & Label2.Text & ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg)
         PictureBox1.Controls.Remove(TGlass)
     End Sub





· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi @JeanLucCoudret-9280 ,
Unfortunately, I get the following exception after testing the code.
100213-2.png
Could you share your project on github or onedrive? It will help us make a test.

0 Votes 0 ·
2.png (21.0 KiB)

Ok, I finally found the way to share a link via Google Drive.
Link: https://drive.google.com/drive/folders/1kvfmhIQIGECxufO85nwvajRRgq6KbDJD?usp=sharing

Please let me know what you think, especially about these numbers 3 or 4 depending of the way I do it.
But I got the result I wanted (not perfectly, but close enough). Maybe I should test more image of various size to be sure.

0 Votes 0 ·