如何绘制签名并将其作为位图保存到光盘?

时间:2019-07-17 17:22:24

标签: vb.net winforms gdi+

我正在尝试执行签名捕获程序,并将客户签名保存为PNGBMP格式。我的Picturebox代码运行良好,结果看起来比使用draw更好。我无法保存图像。

Imports System.Drawing
Public Class Form1

Dim color As System.Drawing.Pen = Pens.Black
Dim bmp As Bitmap

Private Sub form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    bmp = New Bitmap(PictureBox1.Width, PictureBox1.Height)
    PictureBox1.Image = bmp
End Sub

Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
    Static last As New Point
    If e.Button = Windows.Forms.MouseButtons.Left Then
        PictureBox1.CreateGraphics.DrawLine(color, last.X, last.Y, e.X, e.Y)
    End If
    last = e.Location
End Sub

Private Sub CmdClear_Click(sender As Object, e As EventArgs) Handles cmdClear.Click
    bmp = New Bitmap(PictureBox1.Width, PictureBox1.Height)
    PictureBox1.Image = bmp
End Sub

Private Sub CmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click
    If PictureBox1.Image IsNot Nothing Then
        bmp = PictureBox1.Image
        bmp.Save("c:\temp\test1.bmp")
    End If
End Sub

End Class

我想看签名的图像。 谢谢

3 个答案:

答案 0 :(得分:2)

请勿使用 [Control].CreateGraphics ,除非您需要此对象在特定环境中立即使用。例如,测量一个字符串。
当需要保留图形时,就像在控件表面上进行绘制一样,请使用PaintEventArgs事件(或类似事件,如Paint事件)的DrawItem提供的Graphics对象ComboBox,ListBox,ListView控件)。
您会在整个SO(以及整个Web)上找到这种建议。

如何进行:

  1. 我们需要一个对象,该对象可以存储定义手工曲线的鼠标/笔运动。
  2. 每次释放鼠标左键(或丢失并重新获取笔触摸)时,对象都需要存储新的曲线定义。
  3. 我们需要一个Graphics对象,该对象可以将Mouse / Pen运动定义的点转换为Bezier curves(在矢量图形中,曲线的组合通常称为路径)。

在这里,存储运动的对象是 Dictionary(Of Integer, List(Of Point)) ,其中 Key 代表曲线,而 {{ 1}} 代表定义该曲线的点的集合。
每次按下鼠标左键,都会创建一个新的Value并将一个新的KeyList(Of Point)关联。
移动鼠标/笔时,新的Point位置将添加到当前曲线的Key中。

GraphicsPath类可以使用GraphicsPath.AddCurve()方法将List(Of Point)集合转换为贝塞尔曲线的控制点。
此方法接受点数组和 List(Of Point) 值作为参数。 Tension是介于Tension0之间的一个值,它定义了在连接点时应用于曲线的弯曲量。这里使用1的值。

当需要在位图上绘制图形以将结果保存到磁盘时,我们对从位图对象派生的Graphics对象应用相同的逻辑。
因此,仅使用一种方法既可以在控件的表面上绘制,也可以在位图对象上绘制。
这段代码中的 0.5f 方法。

这是它的工作方式:

Signature Drawing

用于复制所描述过程的代码:

DrawSignature(g As Graphics)

答案 1 :(得分:0)

当要另存为BMP时,背景必须为白色,因为BMP不支持透明性。话虽如此,我在DrawPath调用上方添加了这两行。

List

但是,现在我不再能够拿起笔触,否则以前的所有笔触都会被清除/清除。 (意思是名字和姓氏,无需拿起笔就可以写出来)可能对图像有更多了解的人可能会看到这种情况的原因,并指出解决方案的方向吗?

更新: 工作代码

代码如下:

Dim Brsh As SolidBrush = New SolidBrush(Color.White)
g.FillRectangle(Brsh, 0, 0, pBoxSignature.Width, pBoxSignature.Height)
g.DrawPath(signaturePen, gPath)

答案 2 :(得分:0)

感谢吉米。

万一有人在C#中需要它:

public partial class FSignature : Form
{
    private Dictionary<int, List<Point>> signatureObject = new Dictionary<int, List<Point>>();
    private Pen signaturePen = new Pen(Color.Black, 4);
    private List<Point> currentCurvePoints;
    private int currentCurve = -1;

    public FSignature()
    {
        InitializeComponent();
    }





    private void pBoxSignature_MouseDown(object sender, MouseEventArgs e)
    {
        currentCurvePoints = new List<Point>();
        currentCurve += 1;
        signatureObject.Add(currentCurve, currentCurvePoints);
    }

    private void pBoxSignature_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.Button != MouseButtons.Left || currentCurve < 0)
            return;
        signatureObject[currentCurve].Add(e.Location);
        pBoxSignature.Invalidate();
    }

    private void btnClearSignature_Click(object sender, EventArgs e)
    {
        currentCurve = -1;
        signatureObject.Clear();
        pBoxSignature.Invalidate();
    }

    private void btnSaveSignature_Click(object sender, EventArgs e)
    {
        var signatureFileName = txtSignatureFileName.Text.Trim();
        if (string.IsNullOrEmpty(signatureFileName))
            return;
        if (currentCurve < 0 || signatureObject[currentCurve].Count == 0)
            return;
        using (Bitmap imgSignature = new Bitmap(pBoxSignature.Width, pBoxSignature.Height, PixelFormat.Format32bppArgb))
        {
            using (Graphics g = Graphics.FromImage(imgSignature))
            {
                DrawSignature(g);
                string signaturePath = Path.Combine(Application.StartupPath, $"{signatureFileName}.png");
           
                imgSignature.Save(signaturePath, ImageFormat.Png);
                pBoxSavedSignature.Image = new Bitmap(imgSignature);
            }
        }
    }

    private void pBoxSignature_Paint(object sender, PaintEventArgs e)
    {
        if (currentCurve < 0 || signatureObject[currentCurve].Count == 0)
            return;
        DrawSignature(e.Graphics);
    }

    private void DrawSignature(Graphics g)
    {
        g.CompositingMode = CompositingMode.SourceOver;
        g.CompositingQuality = CompositingQuality.HighQuality;
        g.SmoothingMode = SmoothingMode.AntiAlias;
        foreach (var curve in signatureObject)
        {
            if (curve.Value.Count < 2)
                continue;
            using (GraphicsPath gPath = new GraphicsPath())
            {
                gPath.AddCurve(curve.Value.ToArray(), 0.5F);
                g.DrawPath(signaturePen, gPath);
            }
        }
    }


}