0

I am attempting to save an image as modified by graphics tools such as pens and shapes that can be drawn onto the image. I have done this using a panel with background image and trying to set up a bit map that will save changes within this panel:

    private void saveToolStripButton_Click(object sender, EventArgs e)
    {
        //sets panel1 contents as bit map to be saved at set locations
        int width = panel1.Size.Width;
        int height = panel1.Size.Height;

        using (Bitmap bmp = new Bitmap(width, height))
        {
            panel1.DrawToBitmap(bmp, new Rectangle(0, 0, width, height));
            bmp.Save(@"C:\Users\Me\Pics\testBitmap.jpeg", ImageFormat.Jpeg);
        }
        MessageBox.Show("Your image has been saved");
     }

Once the save button is clicked, the image saves ok but the changes made with the graphics tools do not show up. Can anyone suggest a solution?

Here is some code regarding the graphics tool i've set up for use within the panel:

    {
        InitializeComponent();
        //Create graphics object in panel1
        g = panel1.CreateGraphics();
    }

    private void btnExit2_Click(object sender, EventArgs e)
    {
        this.Close();
    }
    Graphics g;
    //set a drawing boolean
    bool draw = false;
    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        draw = true;
        if (drawSq)
        {
            SolidBrush brush = new SolidBrush(Color.FromArgb(128, 255, 0, 0));
            if (toolStripTextBox1.Text != "")
            {
                g.FillRectangle(brush, e.X, e.Y, Convert.ToInt32(toolStripTextBox1.Text), Convert.ToInt32(toolStripTextBox1.Text));
            }
            else if (toolStripTextBox1.Text == "")
            {
               MessageBox.Show("Please enter a shape size");
            }

            draw = false;
            drawSq = false; 
        }
    }

and more:

      private void panel1_MouseUp(object sender, MouseEventArgs e)
    {
        draw = false;
        mouseX = null;
        mouseY = null;
    }
    //null values allow freehand style drawing
    int? mouseX = null;
    int? mouseY = null;
    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        //creates a pen tool and sets properties by mouse location
        if (draw)
        {
            Pen pen = new Pen(btnColor.ForeColor, float.Parse(txtBox1.Text));
            g.DrawLine(pen, new Point(mouseX ?? e.X, mouseY ?? e.Y), new Point(e.X, e.Y));
            mouseX = e.X;
            mouseY = e.Y;
        }
    }
ajm
  • 101
  • 2
  • 3
  • 15
  • "Modified by graphics tools such as pens and shapes..." I think we need to see that code or know how that is being done. Clearly, they are not drawing on the image on the panel. – Andrew Barber Apr 03 '14 at 16:22
  • The graphics tools work fine on the panel. They simply aren't included when saving the image – ajm Apr 03 '14 at 16:24
  • *What graphics tools?* – Andrew Barber Apr 03 '14 at 16:25
  • Pens, brushes, rectangles etc. They all draw to the panel fine – ajm Apr 03 '14 at 16:27
  • So when you say "graphics tools", you actually mean GDI+ graphics objects? Not literal 'tools' that a user uses in a drawing program? – Andrew Barber Apr 03 '14 at 16:29
  • eg SolidBrush brush = new SolidBrush(Color.FromArgb(128, 255, 0, 0)); – ajm Apr 03 '14 at 16:31
  • OK; When you said "tools", that made it sound like something different. Include a short example of code you are using to draw with, then. Not in a comment, but by editing the question. – Andrew Barber Apr 03 '14 at 16:32
  • 1
    Don't use CreateGraphics, and don't store the graphic object. Get the graphic object from the image, draw with it, close it. Use the paint event of the panel to draw the updated image. Now you can save that image, too. – LarsTech Apr 03 '14 at 16:38
  • Can you please explain this further? It took me long enough to get the current graphics system working haha – ajm Apr 03 '14 at 16:40
  • CreateGraphics is a temporary drawing. It doesn't get saved anywhere. Using your CreateGraphics method, draw something, then minimize your form and bring it back. What was drawn will now have vanished. – LarsTech Apr 03 '14 at 16:42
  • What @LarsTech said; [Someone's even tried to tell you that before](http://stackoverflow.com/questions/21677204/z-index-of-drawing-rectangle-c-sharp#comment32768617_21677204). [This answer](http://stackoverflow.com/a/21677407/237838) you got on that same question may be what pointed you in that incorrect direction. – Andrew Barber Apr 03 '14 at 16:42
  • @LarsTech You're right I didn't even notice. I followed a tutorial to create this paint program, which had no save feature. Does this require a complete re work? – ajm Apr 03 '14 at 16:49

2 Answers2

0

Let's try to fix this.

Start by creating your image first:

Bitmap bmp;

protected override void OnLoad(EventArgs e) {
  base.OnLoad(e); 
  bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height);
}

Now when you want to draw on it:

void panel1_MouseMove(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Left) {
    using (Graphics g = Graphics.FromImage(bmp)) {
      g.FillEllipse(Brushes.Red, new Rectangle(e.X - 4, e.Y - 4, 8, 8));
    }
    panel1.Invalidate();
  }
}

And display the results:

void panel1_Paint(object sender, PaintEventArgs e) {
  e.Graphics.DrawImage(bmp, Point.Empty);
}

To save, just use your bitmap:

bmp.Save(@"c:\filename.png", ImageFormat.Png);

Use Double buffering with Panel to avoid the flickering.

Community
  • 1
  • 1
LarsTech
  • 80,625
  • 14
  • 153
  • 225
  • The panels image is set in its .BackgroundImage property, how does this tie in to the answer? – ajm Apr 03 '14 at 17:24
  • @ajm Draw the image into your bitmap. Use the code from the MouseMove example, but instead of `g.FillEllipse`, use `g.DrawImage`. – LarsTech Apr 03 '14 at 17:28
0

This will works fine. I tested it and worked well........

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace drawing
{
    public partial class Form2 : Form
    {
        Graphics g;
        bool startPaint = false;
        int? initX = null;
        int? initY = null;

        bool drawSquare = false;
        bool drawRectangle = false;
        bool drawCircle = false;
        public Form2()
        {
            InitializeComponent();

            bmp = new Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height);

        }
        Bitmap bmp;

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

        }
        void panel1_MouseMove(object sender, MouseEventArgs e)
        {
            if (startPaint)
            {
                using ( g = Graphics.FromImage(bmp))
                {
                  //  g.FillEllipse(Brushes.Black, new Rectangle(e.X, e.Y , 5, 5));

                    Pen p = new Pen(btn_PenColor.BackColor, float.Parse(cmb_PenSize.Text));
                    g.DrawLine(p, new Point(initX ?? e.X, initY ?? e.Y), new Point(e.X, e.Y));
                    initX = e.X;
                    initY = e.Y;
                    //g.DrawImage(bmp, new Rectangle(e.X - 4, e.Y - 4, 8, 8));
                }
                panel1.Invalidate();
            }
        }
        private void pnl_Draw_MouseDown(object sender, MouseEventArgs e)
        {
            startPaint = true;
             if (drawSquare)
             {
                 //Use Solid Brush for filling the graphic shapes
                 SolidBrush sb = new SolidBrush(btn_PenColor.BackColor);
                 //setting the width and height same for creating square.
                 //Getting the width and Heigt value from Textbox(txt_ShapeSize)
                 g.FillRectangle(sb, e.X, e.Y, int.Parse(txt_ShapeSize.Text), int.Parse(txt_ShapeSize.Text));
                 //setting startPaint and drawSquare value to false for creating one graphic on one click.
                 startPaint = false;
                 drawSquare = false;
             }
             if (drawRectangle)
             {
                 SolidBrush sb = new SolidBrush(btn_PenColor.BackColor);
                 //setting the width twice of the height
                 g.FillRectangle(sb, e.X, e.Y, 2 * int.Parse(txt_ShapeSize.Text), int.Parse(txt_ShapeSize.Text));
                 startPaint = false;
                 drawRectangle = false;
             }
             if (drawCircle)
             {
                 SolidBrush sb = new SolidBrush(btn_PenColor.BackColor);
                 g.FillEllipse(sb, e.X, e.Y, int.Parse(txt_ShapeSize.Text), int.Parse(txt_ShapeSize.Text));
                 startPaint = false;
                 drawCircle = false;
             }
        }
         private void pnl_Draw_MouseUp(object sender, MouseEventArgs e)
        {
            startPaint = false;
            initX = null;
            initY = null;
        }
        void panel1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(bmp, Point.Empty);
        }


        private void button1_Click(object sender, EventArgs e)
        {
            bmp.Save("D://filename.jpg", ImageFormat.Png);
        }


    }
}
Nishantha
  • 93
  • 1
  • 1
  • 10