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

Kev*_*ner 1 .net vb.net graphics gdi+ winforms

我正在尝试执行签名捕获程序并将客户签名保存为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
Run Code Online (Sandbox Code Playgroud)

我想看看签名的图像。

Jim*_*imi 6

永远不要使用[Control].CreateGraphics,除非您需要在特定环境中立即使用此对象。例如,测量在特定图形上下文中绘制时的文本大小。
当你需要绘图坚持,作为控制表面涂装,使用由提供的图形对象PaintEventArgs的中的画图事件(或类似的活动,为DRAWITEM组合框,列表框时,ListView控件的事件)。
您会在 SO(以及一般的 Web)上找到此类建议。

如何进行:

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

此处,存储运动的对象是Dictionary(Of Integer, List(Of Point)),其中Key表示一条曲线,Value表示定义该曲线的点的集合。
每次按下鼠标左键时,Key都会创建一个新的,并且新List(Of Point)的与Key.
移动鼠标/笔时,新的点位置将添加到当前曲线的List(Of Point).

所述的GraphicsPath类可以在转换List(Of Point)集合Bezier曲线的控制点,使用GraphicsPath.AddCurve()方法。
此方法接受一个 Points 数组和一个Tension值作为参数。的Tension是之间的值01定义的连接点时弯曲施加到曲线的量。0.5f这里使用的值。

? 当我们需要在 Bitmap 上绘制绘图以将结果保存到磁盘时,我们将相同的逻辑应用到从 Bitmap 对象派生的 Graphics 对象上。
因此,仅使用一种方法在 Control 的表面和 Bitmap 对象上进行绘制。 此代码中
DrawSignature(g As Graphics)方法。

这是它的工作原理:

签名图

重现所描述程序的代码

Private signatureObject As New Dictionary(Of Integer, List(Of Point))
Private signaturePen As New Pen(Color.Black, 4)
Private currentCurvePoints As List(Of Point)
Private currentCurve As Integer = -1

Private Sub pBoxSignature_MouseDown(sender As Object, e As MouseEventArgs) Handles pBoxSignature.MouseDown
    currentCurvePoints = New List(Of Point)
    currentCurve += 1
    signatureObject.Add(currentCurve, currentCurvePoints)
End Sub

Private Sub pBoxSignature_MouseMove(sender As Object, e As MouseEventArgs) Handles pBoxSignature.MouseMove
    If e.Button <> MouseButtons.Left OrElse currentCurve < 0 Then Return
    signatureObject(currentCurve).Add(e.Location)
    pBoxSignature.Invalidate()
End Sub

Private Sub btnClearSignature_Click(sender As Object, e As EventArgs) Handles btnClearSignature.Click
    currentCurve = -1
    signatureObject.Clear()
    pBoxSignature.Invalidate()
End Sub

Private Sub btnSaveSignature_Click(sender As Object, e As EventArgs) Handles btnSaveSignature.Click
    Dim signatureFileName = txtSignatureFileName.Text.Trim()
    If String.IsNullOrEmpty(signatureFileName) Then Return
    If currentCurve < 0 OrElse signatureObject(currentCurve).Count = 0 Then Return

    Using imgSignature As Bitmap = New Bitmap(pBoxSignature.Width, pBoxSignature.Height, PixelFormat.Format32bppArgb), 
        g As Graphics = Graphics.FromImage(imgSignature)

        DrawSignature(g)
        Dim signaturePath As String = Path.Combine(Application.StartupPath, $"{signatureFileName}.png")
        imgSignature.Save(signaturePath, ImageFormat.Png)
        pBoxSavedSignature.Image = New Bitmap(imgSignature)
    End Using
End Sub

Private Sub pBoxSignature_Paint(sender As Object, e As PaintEventArgs) Handles pBoxSignature.Paint
    If currentCurve < 0 OrElse signatureObject(currentCurve).Count = 0 Then Return
    DrawSignature(e.Graphics)
End Sub

Private Sub DrawSignature(g As Graphics)
    g.CompositingMode = CompositingMode.SourceOver
    g.CompositingQuality = CompositingQuality.HighQuality
    g.SmoothingMode = SmoothingMode.AntiAlias

    For Each curve In signatureObject
        If curve.Value.Count < 2 Then Continue For
        Using gPath As New GraphicsPath()
            gPath.AddCurve(curve.Value.ToArray(), 0.5F)
            g.DrawPath(signaturePen, gPath)
        End Using
    Next
End Sub
Run Code Online (Sandbox Code Playgroud)