Descrizione :
Una mia tecnica per disegnare su Bitmap di sfondo e salvare il risultato finale nel formato immagine desiderato.
+ Articolo :
"Disegnare in una PictureBox" è un task piuttosto comune e richiesto in svariate applicazioni.
Qui si tratta di disegnare "a mano", ovvero con il Mouse :
Per ottenere questo risultato occorre naturalmente una Form "FormMain", con una PictureBox "PBX" e un paio di Button : "cmd_salva" e "cmd_reset".
Inoltre ho aggiunto anche un NumericUpDown "num_tratto" e una ColorPickerCombo "CPC".
La "ColorPickerCombo" ovviamente non fa parte del FrameWork 4.0, ma è una speciale ComboBox per la scelta rapida dei Known Colors, il cui articolo completo di codice è qui :
http://marcoggblog.blogspot.com/2011/11/vbnet-un-color-picker-per-known-colors.html
La disponibilità di una scelta sia sullo spessore del tratto, sia sul colore, permette già una certa varietà.
In questo articolo disegno su una Bitmap in memoria ( che ha le stesse dimensioni in pixels della PBX... ), e chiaramente le coordinate del Mouse sono prese nell'area della PBX.
L'immagine base di partenza usata per questo articolo è chiaramente la semplice pianta in bianco e nero dell'immagine precedente :
Con un semplice PBX.Refresh() mi assicuro che l'immagine visualizzata nella PBX sia sempre aggiornata, quindi, all'atto pratico sembra proprio che stia "disegnando nella PBX"...
Qui di seguito la figura che mostra FormMain in Design e relativi controlli :
Faccio uso di due Bmp in memoria, una per l'immagine di sfondo ( caricamento da disco una volta sola ), e una ( copia ) su cui disegnare e salvare.
L'operazione di Reset elimina ogni disegno precedente creando una nuova Bmp Corrente dalla Bmp di Sfondo.
--> Codice FormMain :
Public Class FormMain Private drawOn As Boolean Private drawColor As Color Private drawWidth As Single Private P As New Pen(drawColor, drawWidth) Private B As New SolidBrush(drawColor) Private prevX As Integer Private prevY As Integer Private X As Integer Private Y As Integer Private bmpSfondo As Bitmap Private bmpCorrente As Bitmap Private percorsoImgs As String = Application.StartupPath & "\" Private Function GetBitmap(ByVal nomeFile As String) As Bitmap Using FS As New System.IO.FileStream(nomeFile, IO.FileMode.Open, IO.FileAccess.Read) Return Bitmap.FromStream(FS) End Using End Function Private Sub FormMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load With num_tratto .Minimum = 1 .Maximum = 10 .Value = 2 End With bmpSfondo = GetBitmap(percorsoImgs & "background.jpg") bmpCorrente = New Bitmap(bmpSfondo) PBX.Image = bmpCorrente drawWidth = num_tratto.Value drawColor = CPC.PickedColor P = New Pen(drawColor, drawWidth) End Sub Private Sub PBX_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PBX.MouseDown If e.Button = Windows.Forms.MouseButtons.Left Then drawOn = True PBX.Cursor = Cursors.Cross X = e.X - drawWidth / 2 Y = e.Y - drawWidth / 2 prevX = e.X prevY = e.Y Using G As Graphics = Graphics.FromImage(bmpCorrente) G.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias G.FillEllipse(B, X, Y, drawWidth, drawWidth) End Using PBX.Refresh() End If End Sub Private Sub PBX_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PBX.MouseUp If e.Button = Windows.Forms.MouseButtons.Left Then drawOn = False PBX.Cursor = Cursors.Default End If End Sub Private Sub PBX_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PBX.MouseMove If drawOn = False Then Exit Sub X = e.X - drawWidth / 2 Y = e.Y - drawWidth / 2 Using G As Graphics = Graphics.FromImage(bmpCorrente) G.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias G.DrawLine(P, prevX, prevY, e.X, e.Y) G.FillEllipse(B, X, Y, drawWidth, drawWidth) End Using prevX = e.X prevY = e.Y PBX.Refresh() End Sub Private Sub cmd_salva_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_salva.Click bmpCorrente.Save(percorsoImgs & "output.gif", Imaging.ImageFormat.Gif) End Sub Private Sub cmd_reset_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd_reset.Click bmpCorrente = New Bitmap(bmpSfondo) PBX.Image = bmpCorrente End Sub Private Sub num_tratto_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles num_tratto.ValueChanged drawWidth = num_tratto.Value P.Width = drawWidth End Sub Private Sub CPC_OnPickedColorChanged() Handles CPC.OnPickedColorChanged drawColor = CPC.PickedColor P.Color = drawColor B.Color = drawColor End Sub End Class
Note :
--> Il metodo di disegno tiene traccia delle coordinate Mouse precedenti e integra il semplice disegno del "pennello" ( in questo caso una Ellipse ) con una linea, per assicurare un'ottima continuità al tratto. Le possibilità di definire pennelli e tratti sono infinite...
--> Grazie alla straordinaria varietà di GDI+, non ci vuole molto per capirne le possibilità di upgrade...
+ Fine Articolo.
0 commenti:
Posta un commento