none
Save panel image as .png RRS feed

  • Question

  • Hello, I am trying to create a program that will write text onto a panel and then save that image to a .png file.

    Pressing button1 adds the text from textbox1 onto panel2 at the x and y coordinates specified by numericupdown1 and numericupdown2.  Once I have added all the text I want, pressing button2 is supposed to save the image of panel 2 as a .png file.  However, the .png file is always the blank white rectangle that the panel was before any text was added.  

    I have been struggling and tormented by this for hours!  Can someone please help me?  Thank you!

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Panel1.Location = New Point(0, 0)
            Panel1.Controls.Add(Panel2)
            Panel2.Location = New Point(100, 100)
            Panel2.BackColor = Color.White
        End Sub

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            ' add text to panel
            Dim myGraphics As Graphics = Panel2.CreateGraphics
            Dim myFont As Font
            Dim myBrush As Brush

            myBrush = New Drawing.SolidBrush(Color.Blue)
            myFont = New System.Drawing.Font("Arial", 14)
            myGraphics.DrawString(TextBox1.Text, myFont, myBrush, NumericUpDown1.Value, NumericUpDown2.Value)
            myBrush.Dispose()
            myGraphics.Dispose()
        End Sub

        Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            ' save panel2 as .png
            Dim bmp As New Bitmap(Panel2.Width, Panel2.Height)

            Panel2.DrawToBitmap(bmp, New Rectangle(0, 0, Panel2.Width, Panel2.Height))

            bmp.Save("c:\images\panel2.png", System.Drawing.Imaging.ImageFormat.Png)
        End Sub
    End Class

    Saturday, May 6, 2017 10:56 PM

Answers

  • When you draw on a graphics surface, like the one you make with create graphics, what you draw only lasts until the next time the surface needs updating. At that time the surface is cleared and redrawn. This can happen many times a second when using the mouse and etc.

    That is why controls have a paint event. The paint event is called by vb when the surface needs updating and that event routine is our chance to draw what we want to persist on the control. The paint event is called every time the surface needs updating and thus we draw what we want every time in the paint event.

    Another way to persist the image we draw is draw onto a bitmap that will be a permanent memory image that saves each dot we draw as the bitmap in memory. We can then save the bitmap to disc or show it in another control.

    Probably what you need to do is create a bitmap and draw on that instead of the panel drawing surface. Then you can just save the bitmap to disc.

    So instead of panel.creategraphics, declare a memory bitmap and create a graphics for that. Then you can just bmp.save() or optionally show the bmp in the panel.backgroundimage for screen display.

    Is this for school? Here is a start.

           'declare bitmap in memory the size of the panel
            Dim bmp As New Bitmap(Panel1.ClientSize.Width, Panel1.ClientSize.Height)
    
            'create a graphics drawing surface for the bitmap
            Dim g As Graphics = Graphics.FromImage(bmp)
    

    Sunday, May 7, 2017 12:43 AM

All replies

  • When you draw on a graphics surface, like the one you make with create graphics, what you draw only lasts until the next time the surface needs updating. At that time the surface is cleared and redrawn. This can happen many times a second when using the mouse and etc.

    That is why controls have a paint event. The paint event is called by vb when the surface needs updating and that event routine is our chance to draw what we want to persist on the control. The paint event is called every time the surface needs updating and thus we draw what we want every time in the paint event.

    Another way to persist the image we draw is draw onto a bitmap that will be a permanent memory image that saves each dot we draw as the bitmap in memory. We can then save the bitmap to disc or show it in another control.

    Probably what you need to do is create a bitmap and draw on that instead of the panel drawing surface. Then you can just save the bitmap to disc.

    So instead of panel.creategraphics, declare a memory bitmap and create a graphics for that. Then you can just bmp.save() or optionally show the bmp in the panel.backgroundimage for screen display.

    Is this for school? Here is a start.

           'declare bitmap in memory the size of the panel
            Dim bmp As New Bitmap(Panel1.ClientSize.Width, Panel1.ClientSize.Height)
    
            'create a graphics drawing surface for the bitmap
            Dim g As Graphics = Graphics.FromImage(bmp)
    

    Sunday, May 7, 2017 12:43 AM
  • However, the .png file is always the blank white rectangle that the panel was before any text was added.

    Graphics objects do not persist.  You need to re-draw the text when you create the panel image.   Insert this after you draw the panel to the bitmap:

            Dim myGraphics As Graphics = Graphics.FromImage(bmp)
            Dim myFont As Font
            Dim myBrush As Brush
    
            myBrush = New Drawing.SolidBrush(Color.Blue)
            myFont = New System.Drawing.Font("Arial", 14)
            myGraphics.DrawString(TextBox1.Text, myFont, myBrush, NumericUpDown1.Value, NumericUpDown2.Value)
            myBrush.Dispose()
    Sunday, May 7, 2017 12:47 AM
  • Thank you for that clear and helpful explanation!  Working with that as my starting point, here is what I did to solve the problem: Each time the add text button is pushed, I draw it to the panel and I save the properties to a datagridview -- the text, the font, the brush color, the x position, the y position.  Then, once I have all the text on the panel the way I want it, I push a save button.  The save button uses a for/next loop to add each item from the datagridview to a bitmap.  I then save the bitmap as a .png file.  This works!  However, it seems like there should be a cleaner way?  

    You asked if this is for school.  No, I am trying to add text to .png images for an app I am working on.  I am a novice programmer and it has been a challenge.  Often fun but sometimes very frustrating!  

    Thank you again for your time and generosity!

    Sunday, May 7, 2017 7:07 AM
  • Thank you for the time you spent in addressing my problem.  I was able to solve it! Thanks again!
    Sunday, May 7, 2017 7:10 AM
  • Each time the add text button is pushed, I draw it to the panel and I save the properties to a datagridview -- the text, the font, the brush color, the x position, the y position.

    A datagridview is not a suitable form of storage for the drawing instructions. A better option is to create a custom class with fields to store the required properties, and use a collection (eg, List(Of...)) class instances to accumulate them.  Iterate over the collection to do the completed image.  Use the same collection for the visible panel, the bitmap and (if required) a listbox (or datagridview, or whatever) to show what the list looks like from time to time.

    Since you are creating a bitmap for the Save operation, you could simplify things by using a picturebox instead of a panel, drawing directly to the bitmap, and simply showing the bitmap in the picturebox whenever it changes.  Your focus should be on the objects you need to manipulate (bitmap, collection of drawing instructions) rather than the controls used to display things (panel, datagridview).

    Sunday, May 7, 2017 7:39 AM
  • Thank you for that clear and helpful explanation!  Working with that as my starting point, here is what I did to solve the problem: Each time the add text button is pushed, I draw it to the panel and I save the properties to a datagridview -- the text, the font, the brush color, the x position, the y position.  Then, once I have all the text on the panel the way I want it, I push a save button.  The save button uses a for/next loop to add each item from the datagridview to a bitmap.  I then save the bitmap as a .png file.  This works!  However, it seems like there should be a cleaner way?  

    You asked if this is for school.  No, I am trying to add text to .png images for an app I am working on.  I am a novice programmer and it has been a challenge.  Often fun but sometimes very frustrating!  

    Thank you again for your time and generosity!

    Mich,

    Yes. Well there is normally a better way when we first do something. The second or third time we do better. We have the problem better defined. We know the goods and bads of this and that.

    But it is hard for us to give you a "better" way as we dont know still exactly what you want to accomplish.

    Are you making plain white bitmaps with text on them to show in your app? Or are you drawing text on photographs or what do you mean exactly?

    Here is the code I made yesterday. I did not post it as we try not to just give a student code.

    It just makes a bitmap and draws on it. Then shows it in the panel which you dont have to do just to draw and save the bitmap.

    But how do you enter the text you want on the bitmap? Using the DGV? And how many are you going to do? 10? 10,000?

    If you decribe in more detail what you have and what you plan then we can make more suggestions. Otherwise we are just writing our own application. Not helping you with yours.

    So Acamar has a good suggestion for you in making a class to store your data with instead of storing it in a dgv.

    If you show and tell us more of what you have done and exactly what to do we may have more ideas. For example it is not clear to me why you make bitmaps to show text. Why not just show text? Is there more to the bitmap?

    Option Strict On
    
    Public Class Form9
        Private Sub Form9_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
            'declare bitmap in memory the size of the panel
            Dim bmp As New Bitmap(Panel1.ClientSize.Width, Panel1.ClientSize.Height)
    
            'create a graphics drawing surface for the bitmap
            Dim g As Graphics = Graphics.FromImage(bmp)
    
            'now draw the text on the bitmap
            g.DrawString("Hello World", Font, Brushes.Black, 20, 20)
    
            'save the bitmap
            bmp.Save("c:\test\test.png")
    
            'copy a copy of bitmap to the panel (optional for just saving the drawing)
            Panel1.BackgroundImage = CType(bmp.Clone, Image)
    
            'dispose of the drawing surface and the memory bitmap
            g.Dispose()
            bmp.Dispose()
    
    
        End Sub
    End Class

    Sunday, May 7, 2017 10:22 AM
  • Can you please share the final code you came up with. 
    Sunday, May 7, 2017 11:49 AM