krikara
krikara

Reputation: 2445

Draw on Panel, save as Bitmap

I'm trying to make a simple application where the user can draw on the Panel and save it to their computer as a bitmap. When I proceed to the save part, however, all I get is an empty (white) bitmap.

I've been browsing many other solutions and I am pretty sure I am saving the bitmap the correct way, so I am starting to wonder if my drawing process is incorrect. What exactly is wrong here?

public partial class Form1 : Form
{

    SolidBrush brush;
    Pen pen;
    Point[] points = new Point[3];
    Graphics display;
    Bitmap bmap;

    public Form1()
    {
        InitializeComponent();
        display = panel1.CreateGraphics();
        bmap = new Bitmap(panel1.Width, panel1.Height);
    }


    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        brush = new SolidBrush(Color.Black);
        pen = new Pen(Color.Black);


        display.FillEllipse(brush, e.X, e.Y, 10, 10);
        panel1.DrawToBitmap(bmap, new Rectangle(0, 0, panel1.Width, panel1.Height));

        //this.Invalidate();
    }



    private void clearToolStripMenuItem_Click(object sender, EventArgs e)
    {
        Graphics display = panel1.CreateGraphics();
        display.Clear(panel1.BackColor);

    }

    private void saveToolStripMenuItem_Click(object sender, EventArgs e)
    {



        bmap.Save(@"C:\Temp\Test.bmp");

    }
}

EDIT With this revision, I just get a black bmp and I don't even see elipses being created anymore on my screen. Although I did notice that if I put invalidate and Draw to bitmap back in the mousedown event, then the save button will save the last ellipse, while there is still nothing appearing on my screen.

private void panel1_MouseDown(object sender, MouseEventArgs e)
        {

            mousedown = true;
            x = e.X;
            y = e.Y;

        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            //Graphics g = e.Graphics;
            if(mousedown==true)

            {
            brush = new SolidBrush(Color.Black);
            pen = new Pen(Color.Black);

            Graphics.FromImage(bmap).FillEllipse(brush, x, y, 10, 10);
            panel1.Invalidate();
           //panel1.DrawToBitmap(bmap, new Rectangle(0, 0, panel1.Width, panel1.Height));


            //panel1.Invalidate();

            }
        }

Upvotes: 2

Views: 16105

Answers (2)

Nishantha
Nishantha

Reputation: 93

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);
        }


    }
}

Upvotes: 0

LarsTech
LarsTech

Reputation: 81675

As Hans did most of the work in his comment, here is how your code should probably look:

public partial class Form1 : Form {
  Bitmap bmap;

  public Form1() {
    InitializeComponent();

    bmap = new Bitmap(panel1.ClientWidth, panel1.ClientHeight);
    panel1.MouseDown += panel1_MouseDown;
    panel1.Paint += panel1_Paint;
  }

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

  void panel1_MouseDown(object sender, MouseEventArgs e) {
    using (Graphics g = Graphics.FromImage(bmap)) {
      g.FillEllipse(Brushes.Black, e.X, e.Y, 10, 10);
    }
    panel1.Invalidate();
  }

  private void clearToolStripMenuItem_Click(object sender, EventArgs e) {
    using (Graphics g = Graphics.FromImage(bmap)) {
      g.Clear(Color.White);
    }
    panel1.Invalidate();
  }

  private void saveToolStripMenuItem_Click(object sender, EventArgs e) {
    bmap.Save(@"c:\temp\bmap.bmp");
  }
}

CreateGraphics is just a temporary canvas, so you rarely, if ever, use that for drawing purposes, especially since you are trying to save an image.

Upvotes: 4

Related Questions