Imports System.IO Imports System.Collections.ObjectModel Imports EgtWPFLib5 Public Class ImagePreviewV Private m_OrigImagPath As String Private m_ImagPath As String Private m_Name As String Private bFirstSave As Boolean = True Private m_bIsModified As Boolean = False Private m_CurrentPoint As New Windows.Point(0, 0) Private m_StartCurvePolyLine As New Windows.Point(0, 0) Private m_bActive As Boolean = False Private m_bPolyLine As Boolean = False Private m_bLine As Boolean = False Private m_bRubber As Boolean = False Private m_bDrawCenterScaleCircle As Boolean = False Private m_PolyLine As Polyline Private m_PolyLineRubber As Polyline Private m_CenterScaleCircle As Ellipse Private m_Radius As Double = 50 Private m_BitMap As BitmapImage Private m_Scale As Double = 1 Private m_ScaleTransform As New ScaleTransform(m_Scale, m_Scale) Private m_TraslateTrasform As New TranslateTransform() Private m_bActivePan As Boolean = False Private m_Origin As New Windows.Point(0, 0) Private m_StartVectorPan As New Windows.Vector(0, 0) Private m_VectorPan As New Windows.Vector(0, 0) Private m_DeltaX As Double = 0 Private m_DeltaY As Double = 0 Private m_ImageWidthOrig As Double = 1920 Private m_ImageHeightOrig As Double = 1080 Private m_PolyLineIndex As Integer = 0 Private m_LineIndex As Integer = 0 Private m_RubberIndex As Integer = 0 Private m_NewImagePath As String = String.Empty Private m_NewImageTxt As String = String.Empty Private m_RubberColor As Brush = New SolidColorBrush(Colors.White) Private m_LineColor As Brush = New SolidColorBrush(Colors.Black) Sub New() InitializeComponent() ' carico la posizione della finestra WinPosFromIniToWindow("General", "WinDraw", Me) ' nascondo la visualizzazione delle coordinate stCoordinates.Visibility = Visibility.Hidden ' creo una copia dell'immagine corrente m_OrigImagPath = PhotoMap.refProjectVM.SelSlab.ImagePath m_Name = PhotoMap.refProjectVM.SelSlab.Id If Not CreateCopyFile() Then Return SetTitlePage() StackPanelBorder.CornerRadius = New CornerRadius(3) bgBorder.CornerRadius = New CornerRadius(3) LoadImageInCanvas() End Sub #Region "Manage file JPG" ' creo la copia della foto partendo dal file attuale nel DB (carico il percorso nella variabile m_ImagePath) Private Function CreateCopyFile() As Boolean Dim bOk As Boolean = False Dim CurrentDirectory As String = Path.GetDirectoryName(m_OrigImagPath) Dim CurrFileName As String = Path.GetFileNameWithoutExtension(m_OrigImagPath) Dim TempFilePath As String = CurrentDirectory & "\" & CurrFileName & "_Copy" & ".jpg" Try ' creo la copia dell'immagine File.Copy(m_OrigImagPath, TempFilePath) File.Copy(CurrentDirectory & "\" & CurrFileName & ".txt", CurrentDirectory & "\" & CurrFileName & "_Copy" & ".txt") m_ImagPath = TempFilePath bOk = True Catch ex As Exception EgtUILib.EgtOutLog("Errore in fase di crezione immagine copia: " & ex.Message) MessageBox.Show("Impossibile aprire l'immagine corrente: il file è in modifica da un altro utente", "Error", MessageBoxButton.OK, MessageBoxImage.Asterisk) bOk = False End Try Return bOk End Function ' creo la copia della foto partendo dal file origina ".Back" nel DB (carico il percorso nella variabile m_ImagePath) Private Function CreateCopyFileFromBack() As Boolean Dim bOk As Boolean = False Dim CurrentDirectory As String = Path.GetDirectoryName(m_OrigImagPath) Dim CurrFileName As String = Path.GetFileNameWithoutExtension(m_OrigImagPath) Dim TempFilePath As String = CurrentDirectory & "\" & CurrFileName & "_Copy" & ".jpg" Dim BackFilePath As String = CurrentDirectory & "\" & CurrFileName & ".Back" & ".jpg" Try File.Copy(BackFilePath, TempFilePath) File.Copy(CurrentDirectory & "\" & CurrFileName & ".txt", CurrentDirectory & "\" & CurrFileName & "_Copy" & ".txt") m_ImagPath = TempFilePath bOk = True Catch ex As Exception EgtUILib.EgtOutLog("Errore in fase di crezione immagine copia: " & ex.Message) bOk = False End Try Return bOk End Function ' creo il file ".back" solo se non esiste Private Function CreateFileBack() As Boolean If String.IsNullOrEmpty(m_ImagPath) Then Return False Dim CurrentDirectory As String = Path.GetDirectoryName(m_OrigImagPath) Dim CurrFileName As String = Path.GetFileNameWithoutExtension(m_OrigImagPath) ' ricostruisco il nome del file sorgente Dim OrigImagePath As String = CurrentDirectory & "\" & CurrFileName & ".back" & ".jpg" ' se non esiste il file ".back.jpg" significa che sto per eseguire la prima modifica If Not File.Exists(OrigImagePath) Then Try File.Copy(m_OrigImagPath, OrigImagePath) Catch ex As Exception EgtUILib.EgtOutLog("Errore in fase di creazione file back dell'immagine: " & ex.Message) Return False End Try End If Return True End Function ' elimino il file "_Copy" utilizzato solo all'interno della canavas Private Function DeleteCopyFile() As Boolean Dim bOk As Boolean = False Dim CurrentDirectory As String = Path.GetDirectoryName(m_OrigImagPath) Dim CurrFileName As String = Path.GetFileNameWithoutExtension(m_OrigImagPath) Dim TempFilePath As String = CurrentDirectory & "\" & CurrFileName & "_Copy" & ".jpg" Try File.Delete(TempFilePath) File.Delete(CurrentDirectory & "\" & CurrFileName & "_Copy" & ".txt") bOk = True Catch ex As Exception EgtUILib.EgtOutLog("Errore in fase di eleiminzione immagine copia: " & ex.Message) bOk = False End Try Return bOk End Function #End Region ' Manage file JPG ' carico l'immagine all'interno della Canvas Private Sub LoadImageInCanvas() ' se non è stata creata l'immagine allora esco If String.IsNullOrEmpty(m_ImagPath) Then Return SlabImage.Source = Nothing Dim bi3 As New BitmapImage() bi3.BeginInit() bi3.CacheOption = BitmapCacheOption.None bi3.UriCachePolicy = New Net.Cache.RequestCachePolicy(Net.Cache.RequestCacheLevel.BypassCache) bi3.CacheOption = BitmapCacheOption.OnLoad bi3.CreateOptions = BitmapCreateOptions.IgnoreImageCache bi3.UriSource = New Uri(m_ImagPath, UriKind.RelativeOrAbsolute) bi3.EndInit() SlabImage.Source = bi3 m_ImageWidthOrig = SlabImage.Source.Width m_ImageHeightOrig = SlabImage.Source.Height End Sub ' adatto la dimensione della alla dimensione della finestra Private Sub PostInit() Handles Me.ContentRendered If String.IsNullOrEmpty(m_ImagPath) Then ' chiudo la finestra e stampo messaggio di errore Me.Close() End If ' adatto la dimensione dell'immagine all'area di lavoro m_Scale = Math.Min(MainPaintSurface.ActualWidth / m_ImageWidthOrig, MainPaintSurface.ActualHeight / m_ImageHeightOrig) m_ScaleTransform.ScaleX = m_Scale m_ScaleTransform.ScaleY = m_Scale m_ScaleTransform.CenterX = 0 m_ScaleTransform.CenterY = 0 ' posizione l'immagine in alto a sinistra MainPaintSurface.RenderTransform = m_ScaleTransform m_TraslateTrasform.X = 0 m_TraslateTrasform.Y = 0 PaintSurface.RenderTransform = m_TraslateTrasform m_Origin.X = 0 m_Origin.Y = 0 PaintSurface.RenderTransformOrigin = m_Origin ' da abilitare tramite variabile locale (m_bDrawCenterScaleCircle) DrawCenterScaleCircle() End Sub ' disegna un cerchio nella in corrispondenza delle coordinarte del centro di scalatura Private Sub DrawCenterScaleCircle() If Not m_bDrawCenterScaleCircle Then Return If IsNothing(m_CenterScaleCircle) Then m_CenterScaleCircle = New Ellipse() m_CenterScaleCircle.Name = "CenterScale" m_Radius = 50 m_CenterScaleCircle.Height = m_Radius * 2 m_CenterScaleCircle.Width = m_Radius * 2 m_CenterScaleCircle.Fill = m_LineColor PaintSurface.Children.Add(m_CenterScaleCircle) End If m_CenterScaleCircle.SetValue(Canvas.LeftProperty, m_ScaleTransform.CenterX - m_Radius) m_CenterScaleCircle.SetValue(Canvas.TopProperty, m_ScaleTransform.CenterY - m_Radius) End Sub ' imposta il titolo della pagina ("*" se file modificato) Private Sub SetTitlePage() Dim Titile As String = "Draw - " & m_Name If m_bIsModified Then Titile &= "*" End If Me.Title = Titile End Sub #Region "CANVAS" ' recupero il click all'interno della fotografia Private Sub Canvas_MouseDown_1(sendere As Object, e As MouseEventArgs) Handles PaintSurface.MouseDown If e.RightButton = MouseButtonState.Pressed Or e.MiddleButton = MouseButtonState.Pressed Then Dim MainPaintSurfacePosition As Windows.Point = e.GetPosition(MainPaintSurface) m_StartVectorPan = MainPaintSurfacePosition Return End If If e.LeftButton <> MouseButtonState.Pressed Then Return m_bActive = True m_CurrentPoint = e.GetPosition(PaintSurface) If m_bPolyLine Then ' crea una polilinea If IsNothing(m_PolyLine) Then m_PolyLine = New Polyline() m_PolyLineIndex += 1 m_PolyLine.Name = "PolyLine_" & m_PolyLineIndex.ToString m_PolyLine.Stroke = m_RubberColor m_PolyLine.StrokeThickness = 10 PaintSurface.Children.Add(m_PolyLine) m_StartCurvePolyLine = e.GetPosition(PaintSurface) End If ' aggiungo un punto alla polilinea m_CurrentPoint = e.GetPosition(PaintSurface) m_PolyLine.Points.Add(m_CurrentPoint) End If End Sub Private Sub Canvas_MouseMove_1(sendre As Object, e As MouseEventArgs) Handles PaintSurface.MouseMove GetCurrentPosition(sendre, e) ' se pulsante destro premuto sopra l'immagine If e.RightButton = MouseButtonState.Pressed Or e.MiddleButton = MouseButtonState.Pressed Then m_bActivePan = True Dim MainPaintSurfacePosition As Windows.Point = e.GetPosition(MainPaintSurface) m_VectorPan = MainPaintSurfacePosition m_TraslateTrasform.X = (m_VectorPan.X - m_StartVectorPan.X) + m_Origin.X m_TraslateTrasform.Y = (m_VectorPan.Y - m_StartVectorPan.Y) + m_Origin.Y PaintSurface.RenderTransform = m_TraslateTrasform Return End If If Not m_bActive AndAlso Not m_bPolyLine Then Return If m_bLine Then ' crea una linea libera Dim m_Line As Line = New Line() m_LineIndex += 1 m_Line.Name = "Line_" & m_LineIndex.ToString m_Line.Stroke = m_LineColor m_Line.X1 = m_CurrentPoint.X m_Line.Y1 = m_CurrentPoint.Y m_Line.X2 = e.GetPosition(PaintSurface).X m_Line.Y2 = e.GetPosition(PaintSurface).Y m_CurrentPoint = e.GetPosition(PaintSurface) PaintSurface.Children.Add(m_Line) m_bIsModified = True ElseIf m_bPolyLine Then If IsNothing(m_PolyLine) Then Return ' mostro la previw della linea If m_PolyLine.Points.Count > 1 Then m_PolyLine.Points.RemoveAt(m_PolyLine.Points.Count - 1) End If Dim ActualPosition As Windows.Point = e.GetPosition(PaintSurface) m_PolyLine.Points.Add(ActualPosition) m_bIsModified = True ElseIf m_bRubber Then ' crea una polilinea If IsNothing(m_PolyLineRubber) Then m_PolyLineRubber = New Polyline() m_RubberIndex += 1 m_PolyLineRubber.Name = "Rubber_" & m_RubberIndex.ToString m_PolyLineRubber.Stroke = m_RubberColor m_PolyLineRubber.StrokeThickness = 50 PaintSurface.Children.Add(m_PolyLineRubber) End If m_CurrentPoint = e.GetPosition(PaintSurface) m_PolyLineRubber.Points.Add(m_CurrentPoint) m_bIsModified = True End If SetTitlePage() End Sub ' rilascio il mouse Private Sub Canvas_MouseUp_1(sender As Object, e As MouseEventArgs) Handles PaintSurface.MouseUp, bgBorder.MouseUp MouseUp_Left() MouseUp_Right() GetCurrentPosition(sender, e) End Sub Private Sub MouseUp_Left() If m_bRubber Then m_PolyLineRubber = Nothing End If m_bActive = False End Sub Private Sub MouseUp_Right() If m_bActivePan Then m_Origin.X = m_TraslateTrasform.X m_Origin.Y = m_TraslateTrasform.Y PaintSurface.RenderTransformOrigin = m_Origin End If m_bActivePan = False End Sub Private Sub Canvas_MouseWheel(sender As Object, e As MouseWheelEventArgs) Handles MainPaintSurface.MouseWheel GetCurrentPosition(sender, e) If e.Delta > 0 And m_Scale < 1.01 Then m_Scale = m_Scale + 0.01 ElseIf e.Delta < 0 And m_Scale > 0.1 Then m_Scale = m_Scale - 0.01 End If m_ScaleTransform.ScaleX = m_Scale m_ScaleTransform.ScaleY = m_Scale MainPaintSurface.RenderTransform = m_ScaleTransform m_ScaleTransform.CenterX = (e.GetPosition(PaintSurface).X) * m_Scale m_ScaleTransform.CenterY = (e.GetPosition(PaintSurface).Y) * m_Scale MainPaintSurface.RenderTransform = m_ScaleTransform End Sub ' stampo a video le coordinate del muse Private Sub GetCurrentPosition(sender As Object, e As MouseEventArgs) DrawCenterScaleCircle() Dim MainPaintSurfacePosition As Windows.Point = e.GetPosition(MainPaintSurface) Dim PaintSurfacePosition As Windows.Point = e.GetPosition(PaintSurface) bgCursor.Text = "MainPaintSurface: " & Math.Round(MainPaintSurfacePosition.X, 3).ToString & "; " & Math.Round(MainPaintSurfacePosition.Y, 3).ToString pnCursor.Text = "PaintSurface: " & Math.Round(PaintSurfacePosition.X, 3).ToString & "; " & Math.Round(PaintSurfacePosition.Y, 3).ToString pnScale.Text = "Orig: " & Math.Round(m_ScaleTransform.CenterX, 3).ToString & "; " & Math.Round(m_ScaleTransform.CenterY, 3).ToString End Sub #End Region ' Canvas #Region "COMMAND" #Region "Exit Polyline" Private Sub ExitPolyline(sender As Object, e As KeyEventArgs) Handles Me.KeyDown If e.Key <> Key.Escape Then Return UsePolyLine.IsChecked = False ToggleButton_PolyLine() End Sub #End Region ' Exit Polyline #Region "Draw Polyline" Private Sub ToggleButton_PolyLine() Handles UsePolyLine.Click m_bPolyLine = UsePolyLine.IsChecked m_bLine = False UseLine.IsChecked = m_bLine m_bRubber = False UseRubber.IsChecked = m_bRubber If Not m_bPolyLine Then ' deve esistere If IsNothing(m_PolyLine) Then Return ' deve essere almeno un triangolo If m_PolyLine.Points.Count <= 3 Then m_bPolyLine = True Button_UnDo() m_bPolyLine = False m_StartCurvePolyLine = Nothing m_PolyLine = Nothing Return End If m_PolyLine.Points.RemoveAt(m_PolyLine.Points.Count - 1) ' chiudo la linea m_PolyLine.Points.Add(m_StartCurvePolyLine) ' coloro la regione indicata m_PolyLine.Fill = m_RubberColor m_StartCurvePolyLine = Nothing m_PolyLine = Nothing End If End Sub #End Region ' Draw Polyline #Region "Use Rubber" Private Sub ToggleButton_Rubber() Handles UseRubber.Click m_bRubber = UseRubber.IsChecked m_bLine = False UseLine.IsChecked = m_bLine m_bPolyLine = False UsePolyLine.IsChecked = m_bPolyLine End Sub #End Region ' Use Rubber #Region "Use Line" Private Sub ToggleButton_Line() Handles UseLine.Click m_bLine = UseLine.IsChecked m_bPolyLine = False UsePolyLine.IsChecked = m_bPolyLine m_bRubber = False UseRubber.IsChecked = m_bRubber End Sub #End Region ' Use Line #Region "DeZoom" Private Sub Buttom_DeZoom() Handles DeZoom.Click ' ricolloco l'immagine al centro della pagina PostInit() End Sub #End Region ' DeZoom #Region "Cancel" ' elimina l'ultimo elemento selezionato Private Sub Button_UnDo() Handles Cancel.Click If m_bPolyLine Then For i = 0 To PaintSurface.Children.Count - 1 Dim Child As UIElement = PaintSurface.Children(i) If TypeOf Child Is Polyline Then Dim CurrPolyLine As Polyline = DirectCast(Child, Polyline) If CurrPolyLine.Name = "PolyLine_" & m_PolyLineIndex.ToString Then PaintSurface.Children.Remove(Child) m_PolyLineIndex -= 1 Exit For End If End If Next ElseIf m_bLine Then For i = 0 To PaintSurface.Children.Count - 1 Dim Child As UIElement = PaintSurface.Children(i) If TypeOf Child Is Line Then Dim CurrLine As Line = DirectCast(Child, Line) If CurrLine.Name = "Line_" & m_LineIndex.ToString Then PaintSurface.Children.Remove(Child) m_LineIndex -= 1 Exit For End If End If Next ElseIf m_bRubber Then For i = 0 To PaintSurface.Children.Count - 1 Dim Child As UIElement = PaintSurface.Children(i) If TypeOf Child Is Polyline Then Dim CurrPolyLine As Polyline = DirectCast(Child, Polyline) If CurrPolyLine.Name = "Rubber_" & m_RubberIndex.ToString Then PaintSurface.Children.Remove(Child) m_RubberIndex -= 1 Exit For End If End If Next End If End Sub ' elimina tutti gli elementi Private Sub ReselAllShape() Dim Count As Integer = PaintSurface.Children.Count - 1 While Count > 0 Dim Child As UIElement = PaintSurface.Children(Count) If TypeOf Child Is Polyline Then Dim CurrPolyLine As Polyline = DirectCast(Child, Polyline) If CurrPolyLine.Name = "PolyLine_" & m_PolyLineIndex.ToString Then PaintSurface.Children.Remove(Child) m_PolyLineIndex -= 1 End If End If Count -= 1 End While Count = PaintSurface.Children.Count - 1 While Count > 0 Dim Child As UIElement = PaintSurface.Children(Count) If TypeOf Child Is Line Then Dim CurrLine As Line = DirectCast(Child, Line) If CurrLine.Name = "Line_" & m_LineIndex.ToString Then PaintSurface.Children.Remove(Child) m_LineIndex -= 1 End If End If Count -= 1 End While Count = PaintSurface.Children.Count - 1 While Count > 0 Dim Child As UIElement = PaintSurface.Children(Count) If TypeOf Child Is Polyline Then Dim CurrPolyLine As Polyline = DirectCast(Child, Polyline) If CurrPolyLine.Name = "Rubber_" & m_RubberIndex.ToString Then PaintSurface.Children.Remove(Child) m_RubberIndex -= 1 End If End If Count -= 1 End While End Sub #End Region ' Cancel #Region "RESET" Private Sub Button_Reset() Handles Reset.Click ' carico l'immagine originale If Not GetFileSource() Then Return LoadImageInCanvas() PostInit() m_PolyLineIndex = 0 m_LineIndex = 0 m_RubberIndex = 0 ' annullo tutte le modifiche m_bIsModified = False SetTitlePage() End Sub Private Function GetFileSource() As Boolean If String.IsNullOrEmpty(m_ImagPath) Then Return False Dim CurrentDirectory As String = Path.GetDirectoryName(m_OrigImagPath) Dim CurrFileName As String = Path.GetFileNameWithoutExtension(m_OrigImagPath) ' ricostruisco il nome del file sorgente Dim OrigImagePath As String = CurrentDirectory & "\" & CurrFileName & ".back" & ".jpg" ' se esiste il file ".back.jpg" significa che il file attuale è già stato modificato If File.Exists(OrigImagePath) Then ' elimino la copia attuale in uso DeleteCopyFile() ' carico nella canvas l'immagine usata nella texture (l'originale) m_ImagPath = m_OrigImagPath ' rimuovo tutti gli elementi aggiunti nella canvas ReselAllShape() ' creo la copia a partire dal file ".back" CreateCopyFileFromBack() ' carcio nella texture l'immagine di copia dell'originale ".back" PhotoMap.refProjectVM.SelSlab.NewPhotoPath(m_ImagPath) ' copio sull'originale l'immagine recuperata dal file ".back" Try ' elimino il file in uso in precedenza nella texture File.Delete(m_OrigImagPath) ' creo la copia dell'immagine sull'oroginale File.Copy(m_ImagPath, m_OrigImagPath) Catch ex As Exception EgtUILib.EgtOutLog("Errore in fase reset e copia immagine: " & ex.Message) Return False End Try ' ricarico l'immagine PhotoMap.refProjectVM.SelSlab.NewPhotoPath(m_OrigImagPath) Return True End If Return False End Function #End Region ' Reset #Region "SAVE" Private Sub Button_Save() Handles Save.Click SaveImage() m_bIsModified = False SetTitlePage() End Sub Private Sub SaveImage() ' riposiziono l'immagine in alto a sinistra m_TraslateTrasform.X = 0 m_TraslateTrasform.Y = 0 PaintSurface.RenderTransform = m_TraslateTrasform ' imposto la scalatura originale dell'immagine m_ScaleTransform.ScaleX = 1 m_ScaleTransform.ScaleY = 1 MainPaintSurface.RenderTransform = m_ScaleTransform ' se la creazione del file back fallisce allora non procedo con il salvataggio If Not CreateFileBack() Then Return ' carico l'immagine copia come texture (Image_Copy.jpg) If Not PhotoMap.refProjectVM.SelSlab.NewPhotoPath(m_ImagPath) Then Return ' converto l'immagine in Bitmap Dim bmp As New RenderTargetBitmap(CInt(m_ImageWidthOrig), CInt(m_ImageHeightOrig), 96, 96, PixelFormats.Pbgra32) bmp.Render(MainPaintSurface) Dim Encoder As New JpegBitmapEncoder Encoder.Frames.Add(BitmapFrame.Create(bmp)) Dim ms As New MemoryStream() ' salvo l'immagine nel file originale (che non è in uso dalla texture) Try Encoder.Save(ms) ms.Close() File.WriteAllBytes(m_OrigImagPath, ms.ToArray()) Catch ex As Exception EgtUILib.EgtOutLog("Errore in fase di salvataggio immagine: " & ex.Message) End Try ' reimposta la scalatura attuale m_ScaleTransform.ScaleX = m_Scale m_ScaleTransform.ScaleY = m_Scale MainPaintSurface.RenderTransform = m_ScaleTransform ' riposiziono l'immagine m_TraslateTrasform.X = m_Origin.X m_TraslateTrasform.Y = m_Origin.Y PaintSurface.RenderTransform = m_TraslateTrasform ' reimposto l'immagine originale come texture (originale e copy sono uguali) PhotoMap.refProjectVM.SelSlab.NewPhotoPath(m_OrigImagPath) End Sub #End Region ' Save #Region "CLOSE" Private Sub ExitWindow(sender As Object, e As EventArgs) Handles Me.Closing ' se l'immagine non è stata caricata allora esco If String.IsNullOrEmpty(m_ImagPath) Then Return WinPosFromWindowToIni(Me, "General", "WinDraw") If m_bIsModified Then Dim MsgResult As MessageBoxResult = MessageBox.Show("Vuoi salvare le modifiche", "Question", MessageBoxButton.YesNo, MessageBoxImage.Question) If MsgResult = MessageBoxResult.Yes Then SaveImage() End If End If End Sub Private Sub ResetWindow(sender As Object, e As EventArgs) Handles Me.Closed ' se l'immmagine non è stata caricata allora esco If String.IsNullOrEmpty(m_ImagPath) Then Return DeleteCopyFile() End Sub #End Region ' CLose #End Region ' Command End Class