Add project files.

This commit is contained in:
Miguel 2024-04-11 11:51:12 +02:00
parent 416f2fd561
commit 10ceff7c70
12 changed files with 1090 additions and 0 deletions

9
App.xaml Normal file
View File

@ -0,0 +1,9 @@
<Application x:Class="ROIEditor.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ROIEditor"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

14
App.xaml.cs Normal file
View File

@ -0,0 +1,14 @@
using System.Configuration;
using System.Data;
using System.Windows;
namespace ROIEditor
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

10
AssemblyInfo.cs Normal file
View File

@ -0,0 +1,10 @@
using System.Windows;
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]

113
DatabaseManager.cs Normal file
View File

@ -0,0 +1,113 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text.Json;
using Microsoft.Data.Sqlite;
using System.ComponentModel;
namespace ROIEditor
{
public class DatabaseManager<T>
{
private readonly string connectionString;
private readonly string tableName;
private List<T> data = new List<T>();
public void Add(T item)
{
data.Add(item);
}
public void Clear()
{
data.Clear();
}
public List<T> GetList()
{
return data;
}
public int Count => data.Count;
public DatabaseManager(string dbPath, string tableName)
{
connectionString = $"Data Source={dbPath}";
this.tableName = tableName;
InitializeDatabase();
}
private void InitializeDatabase()
{
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = $@"
CREATE TABLE IF NOT EXISTS {tableName} (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Clave TEXT,
SerializeData TEXT
)";
command.ExecuteNonQuery();
}
}
public void SaveData(string clave)
{
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
var deleteCommand = connection.CreateCommand();
deleteCommand.CommandText = @"DELETE FROM Roi WHERE Clave = $Clave";
deleteCommand.Parameters.AddWithValue("$Clave", clave);
deleteCommand.ExecuteNonQuery();
foreach (var elemento in data)
{
string serializedData = JsonSerializer.Serialize(elemento);
var command = connection.CreateCommand();
command.CommandText = $"INSERT INTO {tableName} (Clave, SerializeData) VALUES ($Clave, $SerializedData)";
command.Parameters.AddWithValue("$Clave", clave);
command.Parameters.AddWithValue("$SerializedData", serializedData);
command.ExecuteNonQuery();
}
}
}
public List<T> LoadData(string clave)
{
var dataList = new List<T>();
using (var connection = new SqliteConnection(connectionString))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = $"SELECT SerializeData FROM {tableName} WHERE Clave = $Clave";
command.Parameters.AddWithValue("$Clave", clave);
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
string serializedData = reader.GetString(0);
List<T> data = JsonSerializer.Deserialize<List<T>>(serializedData);
dataList.AddRange(data);
}
}
}
return dataList;
}
}
}

81
ImagenEstado.cs Normal file
View File

@ -0,0 +1,81 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace ROIEditor
{
public class ImagenEstado
{
public double ZoomScaleX { get; set; }
public double ZoomScaleY { get; set; }
public double HorizontalOffset { get; set; }
public double VerticalOffset { get; set; }
public string NombreImagen;
// Constructor sin parámetros
public ImagenEstado()
{
}
public ImagenEstado(string imageNameActual)
{
NombreImagen = imageNameActual;
}
public string PathPlantillasJson()
{
string jsonPath = Path.ChangeExtension(NombreImagen, ".json");
var imagePath = Path.Combine(Directory.GetCurrentDirectory(), "Plantillas", jsonPath);
return imagePath;
}
public string PathPlantillasPNG()
{
string jsonPath = Path.ChangeExtension(NombreImagen, ".png");
var imagePath = Path.Combine(Directory.GetCurrentDirectory(), "Plantillas", jsonPath);
return imagePath;
}
public void SalvarEstadoJSON()
{
// Cambia la extensión del archivo de imagen a .json
string jsonPath = PathPlantillasJson();
// Serializa el estado de la imagen a JSON
string json = JsonConvert.SerializeObject(NombreImagen, Formatting.Indented);
// Escribe el JSON en un archivo
File.WriteAllText(jsonPath, json);
}
public void CargarEstadoJSON()
{
string jsonPath = PathPlantillasJson();
if (File.Exists(jsonPath))
{
string json = File.ReadAllText(jsonPath);
ImagenEstado estadoCargado = JsonConvert.DeserializeObject<ImagenEstado>(json);
// Usar reflexión para copiar todas las propiedades
foreach (PropertyInfo prop in typeof(ImagenEstado).GetProperties())
{
if (prop.CanRead && prop.CanWrite)
{
prop.SetValue(this, prop.GetValue(estadoCargado, null), null);
}
}
}
}
}
}

89
MainWindow.xaml Normal file
View File

@ -0,0 +1,89 @@
<Window x:Class="ROIEditor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ROIEditor"
mc:Ignorable="d"
Title="Editor de ROI" Height="1000" Width="1600">
<Window.Resources>
<Style x:Key="TextBoxPlaceholderStyle" TargetType="TextBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<TextBox IsHitTestVisible="False" Text="{TemplateBinding Tag}" FontStyle="Italic" Foreground="Gray" Background="Transparent" BorderThickness="0" IsReadOnly="True"/>
<ScrollViewer x:Name="PART_ContentHost"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<DockPanel LastChildFill="True">
<!-- Panel izquierdo para la lista de imágenes -->
<ListBox x:Name="ListaImagenes" DockPanel.Dock="Left" Width="200" Margin="5">
<!-- Aquí irán los elementos de la lista de imágenes -->
</ListBox>
<!-- Panel derecho dividido en dos para ROIs y formulario -->
<DockPanel DockPanel.Dock="Right" Width="400" Margin="5">
<!-- Lista de ROIs -->
<ListBox x:Name="ListaROIs" DockPanel.Dock="Top" Height="300" Margin="0,0,0,5"/>
<!-- Formulario para detalles del ROI -->
<StackPanel DockPanel.Dock="Bottom" Margin="0,5,0,0">
<!-- Coordenadas X,Y -->
<Label Content="Coordenadas X,Y:"/>
<TextBox x:Name="ROI_xy" Margin="0,0,0,5"/>
<!-- DX, DY -->
<Label Content="DX, DY:"/>
<TextBox x:Name="ROI_dxdy" Margin="0,0,0,5"/>
<!-- Nombre -->
<Label Content="Nombre:"/>
<TextBox x:Name="ROI_nombre" Margin="0,0,0,5"/>
<!-- Código Numérico -->
<Label Content="Código Numérico:"/>
<TextBox x:Name="ROI_num" Margin="0,0,0,5"/>
<!-- Descripción -->
<Label Content="Descripción:"/>
<TextBox x:Name="ROI_descripcion" Margin="0,0,0,5"/>
<!-- Campo de texto 1 -->
<Label Content="Campo de texto 1:"/>
<TextBox x:Name="ROI_text1" Margin="0,0,0,5"/>
<!-- Campo de texto 2 -->
<Label Content="Campo de texto 2:"/>
<TextBox x:Name="ROI_text2" Margin="0,0,0,5"/>
<!-- Campo de texto 3 -->
<Label Content="Campo de texto 3:"/>
<TextBox x:Name="ROI_text3" Margin="0,0,0,5"/>
<!-- Botones -->
<Button x:Name="Guardar_ROI" Content="Guardar" Margin="0,0,0,5"/>
<Button x:Name="Borrar_ROI" Content="Borrar ROI"/>
</StackPanel>
</DockPanel>
<!-- Centro para la imagen con soporte de paneo y zoom -->
<ScrollViewer x:Name="ImagenEnTrabajoScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas x:Name="ImagenEnTrabajoCanvas" Margin="200">
<!-- El Margin puede ser ajustado según el espacio adicional que quieras proporcionar -->
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="1" ScaleY="1"/>
</Canvas.LayoutTransform>
</Canvas>
</ScrollViewer>
</DockPanel>
</Window>

490
MainWindow.xaml.cs Normal file
View File

@ -0,0 +1,490 @@
using Newtonsoft.Json;
using System.Diagnostics.Eventing.Reader;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Path = System.IO.Path;
namespace ROIEditor
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private ImagenEstado EstadoImagenActual = new ImagenEstado();
private Point? clickPosition = null;
private bool _isDrawing = false;
private Point _startPosition;
private Rectangle _currentRect = null;
private Image imagenDeFondo;
private bool _isDragging = false;
private Point _lastMousePosition;
public dbROIs ListaDeROIs = new dbROIs();
// Constructor de MainWindow
public MainWindow()
{
InitializeComponent();
CargarImagenes();
ListaImagenes.SelectionChanged += ListaImagenes_SelectionChanged;
ImagenEnTrabajoCanvas.MouseLeftButtonDown += ImagenEnTrabajoCanvas_MouseLeftButtonDown;
ImagenEnTrabajoCanvas.MouseRightButtonDown += ImagenEnTrabajoCanvas_MouseRightButtonDown;
ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown;
ImagenEnTrabajoCanvas.MouseMove += Canvas_MouseMove;
ImagenEnTrabajoScrollViewer.PreviewMouseWheel += ImagenEnTrabajoCanvas_MouseWheel;
// En el constructor de MainWindow o un método de inicialización
ImagenEnTrabajoCanvas.MouseDown += Canvas_MouseDown_Panning;
ImagenEnTrabajoCanvas.MouseMove += Canvas_MouseMove_Panning;
ImagenEnTrabajoCanvas.MouseUp += Canvas_MouseUp_Panning;
// Agrega este manejador en el inicializador de tu ventana o control
ListaROIs.SelectionChanged += ListaROIs_SelectionChanged;
// Agrega este manejador en el inicializador de tu ventana o control
Guardar_ROI.Click += Guardar_ROI_Click;
// Suscripción a los eventos LostFocus
ROI_xy.LostFocus += GuardarCambiosRoi;
ROI_dxdy.LostFocus += GuardarCambiosRoi;
ROI_nombre.LostFocus += GuardarCambiosRoi;
ROI_num.LostFocus += GuardarCambiosRoi;
ROI_descripcion.LostFocus += GuardarCambiosRoi;
ROI_text1.LostFocus += GuardarCambiosRoi;
ROI_text2.LostFocus += GuardarCambiosRoi;
ROI_text3.LostFocus += GuardarCambiosRoi;
}
private void ListaROIs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ListaROIs.SelectedItem is Roi selectedRoi)
{
CargarDatosROI(selectedRoi);
}
}
private void Guardar_ROI_Click(object sender, RoutedEventArgs e)
{
if (ListaROIs.SelectedItem is Roi selectedRoi)
{
ActualizarDatosROI(selectedRoi);
}
}
private void CargarDatosROI(Roi selectedRoi)
{
ROI_xy.Text = $"{selectedRoi.X}, {selectedRoi.Y}";
ROI_dxdy.Text = $"{selectedRoi.Width}, {selectedRoi.Height}";
ROI_nombre.Text = selectedRoi.Nombre;
ROI_num.Text = selectedRoi.CodigoNumerico.ToString();
ROI_descripcion.Text = selectedRoi.Descripcion;
ROI_text1.Text = selectedRoi.CampoTexto1;
ROI_text2.Text = selectedRoi.CampoTexto2;
ROI_text3.Text = selectedRoi.CampoTexto3;
}
private void ActualizarDatosROI(Roi selectedRoi)
{
try
{
// Suponiendo que se validen y parseen adecuadamente los valores
var xy = ROI_xy.Text.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var dxdy = ROI_dxdy.Text.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
selectedRoi.X = int.Parse(xy[0].Trim());
selectedRoi.Y = int.Parse(xy[1].Trim());
selectedRoi.Width = int.Parse(dxdy[0].Trim());
selectedRoi.Height = int.Parse(dxdy[1].Trim());
selectedRoi.Nombre = ROI_nombre.Text;
selectedRoi.CodigoNumerico = int.TryParse(ROI_num.Text, out int codigo) ? codigo : 0;
selectedRoi.Descripcion = ROI_descripcion.Text;
selectedRoi.CampoTexto1 = ROI_text1.Text;
selectedRoi.CampoTexto2 = ROI_text2.Text;
selectedRoi.CampoTexto3 = ROI_text3.Text;
// Aquí podrías llamar a un método que realice el guardado específico, si es necesario
// Por ejemplo, actualizar la visualización del ROI o guardar en un archivo JSON
}
catch (Exception ex)
{
// Manejar posibles errores de parseo o validación
MessageBox.Show($"Error al actualizar los datos del ROI: {ex.Message}");
}
}
private void GuardarCambiosRoi(object sender, RoutedEventArgs e)
{
if (ListaROIs.SelectedItem is Roi selectedRoi)
{
ActualizarDatosROI(selectedRoi);
}
}
private void CargarImagenes()
{
// Asumiendo que las imágenes están en una carpeta "Imagenes" dentro del directorio de salida de tu aplicación
string folderPath = Path.Combine(Directory.GetCurrentDirectory(), "Plantillas");
if (Directory.Exists(folderPath))
{
var archivosImagen = Directory.GetFiles(folderPath, "*.png"); // Asumiendo que buscas archivos .png
foreach (var archivo in archivosImagen)
{
// Aquí simplemente añadimos el nombre del archivo a la lista, pero podrías querer añadir un objeto más complejo
ListaImagenes.Items.Add(Path.GetFileName(archivo));
}
}
else
{
MessageBox.Show("No se encontró la carpeta de imágenes.");
}
}
private void Canvas_MouseDown_Panning(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && !_isDrawing)
{
// Indica que se inicia el panning
_isDragging = true;
// Guarda la posición actual del ratón
_lastMousePosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
//ImagenEnTrabajoScrollViewer.CaptureMouse(); // Importante para capturar el movimiento
}
}
private void Canvas_MouseMove_Panning(object sender, MouseEventArgs e)
{
if (_isDragging && !_isDrawing)
{
// Calcula el nuevo desplazamiento basado en el movimiento del ratón
var currentPosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
var dx = currentPosition.X - _lastMousePosition.X;
var dy = currentPosition.Y - _lastMousePosition.Y;
// Ajusta el desplazamiento del ScrollViewer
ImagenEnTrabajoScrollViewer.ScrollToHorizontalOffset(ImagenEnTrabajoScrollViewer.HorizontalOffset - dx);
ImagenEnTrabajoScrollViewer.ScrollToVerticalOffset(ImagenEnTrabajoScrollViewer.VerticalOffset - dy);
// Actualiza la posición del ratón para el próximo movimiento
_lastMousePosition = currentPosition;
}
}
private void Canvas_MouseUp_Panning(object sender, MouseButtonEventArgs e)
{
if (_isDragging)
{
_isDragging = false;
ImagenEnTrabajoScrollViewer.ReleaseMouseCapture(); // Finaliza la captura del ratón
}
}
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
// Verifica si el botón derecho del ratón fue el que se presionó
if (e.ChangedButton == MouseButton.Right)
{
if (!_isDrawing)
{
_startPosition = e.GetPosition(ImagenEnTrabajoCanvas);
_isDrawing = true;
// Inicializar un nuevo rectángulo
_currentRect = new Rectangle
{
Stroke = Brushes.Red,
StrokeThickness = 2,
Fill = Brushes.Transparent
};
Canvas.SetLeft(_currentRect, _startPosition.X);
Canvas.SetTop(_currentRect, _startPosition.Y);
ImagenEnTrabajoCanvas.Children.Add(_currentRect);
}
else
{
// Finaliza el dibujo del rectángulo
_isDrawing = false;
// Calcula las dimensiones finales y posición del ROI
var endPosition = e.GetPosition(ImagenEnTrabajoCanvas);
var x = Math.Min(_startPosition.X, endPosition.X);
var y = Math.Min(_startPosition.Y, endPosition.Y);
var width = Math.Abs(endPosition.X - _startPosition.X);
var height = Math.Abs(endPosition.Y - _startPosition.Y);
// Crea el nuevo objeto Roi con la información recopilada
Roi newRoi = new Roi(EstadoImagenActual.NombreImagen, (int)x, (int)y, (int)width, (int)height);
// Agrega el nuevo Roi a la lista de ROIs
ListaDeROIs.Add(newRoi);
// Elimina el rectángulo temporal del Canvas
ImagenEnTrabajoCanvas.Children.Remove(_currentRect);
_currentRect = null;
// Actualiza la interfaz de usuario con el nuevo ROI
ActualizarUIConROIs();
}
}
}
private void ActualizarUIConROIs()
{
// Aquí actualizas los controles de la interfaz de usuario que muestran los ROIs
// Por ejemplo, si tienes una ListBox para los ROIs, actualízala así:
ListaROIs.ItemsSource = null;
if (ListaDeROIs.Count() > 0)
{
ListaROIs.ItemsSource = ListaDeROIs.rois;
}
DibujarROIsEnCanvas();
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (_isDrawing)
{
var currentPosition = e.GetPosition(ImagenEnTrabajoCanvas);
var width = Math.Abs(currentPosition.X - _startPosition.X);
var height = Math.Abs(currentPosition.Y - _startPosition.Y);
_currentRect.Width = width;
_currentRect.Height = height;
// Ajusta la posición si el dibujo se hace hacia arriba o hacia la izquierda
if (currentPosition.X < _startPosition.X)
{
Canvas.SetLeft(_currentRect, currentPosition.X);
}
if (currentPosition.Y < _startPosition.Y)
{
Canvas.SetTop(_currentRect, currentPosition.Y);
}
}
}
private void ImagenEnTrabajoCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
{
var st = (ScaleTransform)ImagenEnTrabajoCanvas.LayoutTransform;
double zoomFactor = e.Delta > 0 ? 1.1 : 0.9;
Point cursorPosition = e.GetPosition(ImagenEnTrabajoScrollViewer);
// Calcular el punto focal del zoom relativo al contenido del ScrollViewer
var absoluteX = ImagenEnTrabajoScrollViewer.HorizontalOffset + cursorPosition.X;
var absoluteY = ImagenEnTrabajoScrollViewer.VerticalOffset + cursorPosition.Y;
// Aplicar el zoom
st.ScaleX *= zoomFactor;
st.ScaleY *= zoomFactor;
// Calcular el nuevo desplazamiento para que el zoom se centre en la posición del cursor
ImagenEnTrabajoScrollViewer.UpdateLayout(); // Asegurarse de que el layout del ScrollViewer esté actualizado
var newHorizontalOffset = absoluteX * zoomFactor - cursorPosition.X;
var newVerticalOffset = absoluteY * zoomFactor - cursorPosition.Y;
// Aplicar el nuevo desplazamiento
ImagenEnTrabajoScrollViewer.ScrollToHorizontalOffset(newHorizontalOffset);
ImagenEnTrabajoScrollViewer.ScrollToVerticalOffset(newVerticalOffset);
e.Handled = true; // Evita el procesamiento adicional del evento
}
private void ImagenEnTrabajoCanvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
var mousePos = e.GetPosition(ImagenEnTrabajoCanvas);
// Verificar si mousePos está dentro de algún ROI y mostrar el formulario de comentario si es así
}
private void ImagenEnTrabajoCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var mousePos = e.GetPosition(ImagenEnTrabajoCanvas);
// Aquí puedes inicializar la creación de un nuevo ROI basándote en mousePos
}
private void CargarImagenEnTrabajo(string imagePath)
{
BitmapImage bitmap = new BitmapImage(new Uri(imagePath, UriKind.Absolute));
if (imagenDeFondo == null)
{
imagenDeFondo = new Image();
ImagenEnTrabajoCanvas.Children.Add(imagenDeFondo);
}
imagenDeFondo.Source = bitmap;
RenderOptions.SetBitmapScalingMode(imagenDeFondo, BitmapScalingMode.HighQuality);
// Elimina solo los ROIs, no la imagen de fondo
for (int i = ImagenEnTrabajoCanvas.Children.Count - 1; i >= 0; i--)
{
if (ImagenEnTrabajoCanvas.Children[i] is Rectangle)
{
ImagenEnTrabajoCanvas.Children.RemoveAt(i);
}
}
// Ajusta el tamaño del Canvas a la imagen, si es necesario
ImagenEnTrabajoCanvas.Width = bitmap.Width;
ImagenEnTrabajoCanvas.Height = bitmap.Height;
// Posiciona la imagen correctamente dentro del Canvas
Canvas.SetLeft(imagenDeFondo, 0);
Canvas.SetTop(imagenDeFondo, 0);
}
private void ListaImagenes_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ListaImagenes.SelectedItem != null)
{
if (EstadoImagenActual.NombreImagen != null)
{
SalvarEstadoImagen();
}
if (ListaDeROIs.Count()>0)
{
ListaDeROIs.GuardarRois();
}
EstadoImagenActual = new ImagenEstado();
EstadoImagenActual.NombreImagen = ListaImagenes.SelectedItem.ToString();
ListaDeROIs = new dbROIs(EstadoImagenActual.NombreImagen);
var imagePath = EstadoImagenActual.PathPlantillasPNG();
CargarImagenEnTrabajo(imagePath);
CargarEstadoImagen();
}
}
private void CargarEstadoImagen()
{
string jsonPath = EstadoImagenActual.PathPlantillasJson();
if (File.Exists(jsonPath))
{
string json = File.ReadAllText(jsonPath);
EstadoImagenActual = JsonConvert.DeserializeObject<ImagenEstado>(json);
var st = (ScaleTransform)ImagenEnTrabajoCanvas.LayoutTransform;
st.ScaleX= EstadoImagenActual.ZoomScaleX ;
st.ScaleY = EstadoImagenActual.ZoomScaleY;
// Aplicar el nuevo desplazamiento
ImagenEnTrabajoScrollViewer.ScrollToHorizontalOffset(EstadoImagenActual.HorizontalOffset);
ImagenEnTrabajoScrollViewer.ScrollToVerticalOffset(EstadoImagenActual.VerticalOffset);
DibujarROIsEnCanvas();
} else
{
var st = (ScaleTransform)ImagenEnTrabajoCanvas.LayoutTransform;
EstadoImagenActual.ZoomScaleX = st.ScaleX;
EstadoImagenActual.ZoomScaleY = st.ScaleY;
EstadoImagenActual.HorizontalOffset = EstadoImagenActual.HorizontalOffset;
EstadoImagenActual.VerticalOffset = EstadoImagenActual.VerticalOffset;
}
}
private void SalvarEstadoImagen()
{
// Cambia la extensión del archivo de imagen a .json
string jsonPath = EstadoImagenActual.PathPlantillasJson();
var st = (ScaleTransform)ImagenEnTrabajoCanvas.LayoutTransform;
EstadoImagenActual.ZoomScaleX = st.ScaleX;
EstadoImagenActual.ZoomScaleY = st.ScaleY;
EstadoImagenActual.HorizontalOffset = ImagenEnTrabajoScrollViewer.HorizontalOffset;
EstadoImagenActual.VerticalOffset = ImagenEnTrabajoScrollViewer.VerticalOffset;
// Serializa el estado de la imagen a JSON
string json = JsonConvert.SerializeObject(EstadoImagenActual, Formatting.Indented);
// Escribe el JSON en un archivo
File.WriteAllText(jsonPath, json);
}
private void DibujarROIsEnCanvas()
{
// Elimina solo los ROIs, no la imagen de fondo
for (int i = ImagenEnTrabajoCanvas.Children.Count - 1; i >= 0; i--)
{
if (ImagenEnTrabajoCanvas.Children[i] is Rectangle)
{
ImagenEnTrabajoCanvas.Children.RemoveAt(i);
}
}
// Dibuja los ROIs
foreach (var roi in ListaDeROIs.rois)
{
Rectangle rect = roi.DibujarRoiEnCanvas(ImagenEnTrabajoCanvas);
// Eventos
rect.MouseEnter += Rect_MouseEnter;
rect.MouseLeave += Rect_MouseLeave;
rect.MouseDown += Rect_MouseDown;
}
}
private void Rect_MouseEnter(object sender, MouseEventArgs e)
{
if (sender is Rectangle rect)
{
rect.StrokeThickness = 4; // Aumenta el grosor
}
}
private void Rect_MouseLeave(object sender, MouseEventArgs e)
{
if (sender is Rectangle rect)
{
rect.StrokeThickness = 2; // Restaura el grosor
}
}
private void Rect_MouseDown(object sender, MouseButtonEventArgs e)
{
if (sender is Rectangle rect && rect.Tag is Roi roi)
{
int index = ListaDeROIs.rois.IndexOf(roi);
if (index != -1)
{
ListaROIs.SelectedIndex = index; // Selecciona el ROI en la lista
e.Handled = true; // Evita la propagación del evento
}
}
}
}
}

229
ROI.cs Normal file
View File

@ -0,0 +1,229 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using Microsoft.Data.Sqlite;
using System;
using System.Collections.Generic;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace ROIEditor
{
public class dbROIs
{
public List<Roi> rois { get; set; }
const string dbPath = "Data Source=roiseditor.db";
public string NombreImagen;
public void Add(Roi r)
{
rois.Add(r);
}
public int Count() { return rois.Count; }
public dbROIs()
{
rois = new List<Roi>();
}
public dbROIs(string nombreImagen)
{
NombreImagen = nombreImagen;
rois = new List<Roi>();
CrearBaseDeDatosSiNoExiste();
CargarROIs();
}
private void CrearBaseDeDatosSiNoExiste()
{
using (var connection = new SqliteConnection(dbPath))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText =
@"
CREATE TABLE IF NOT EXISTS Roi (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
X INTEGER NOT NULL,
Y INTEGER NOT NULL,
Width INTEGER NOT NULL,
Height INTEGER NOT NULL,
Nombre TEXT,
NombreImagen TEXT,
CodigoNumerico INTEGER,
Descripcion TEXT,
CampoTexto1 TEXT,
CampoTexto2 TEXT,
CampoTexto3 TEXT
);
";
command.ExecuteNonQuery();
}
}
public void CargarROIs()
{
rois.Clear();
using (var connection = new SqliteConnection(dbPath))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = @"SELECT * FROM Roi WHERE NombreImagen = $NombreImagen";
command.Parameters.AddWithValue("$NombreImagen", NombreImagen);
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
rois.Add(new Roi
{
X = reader.GetInt32(reader.GetOrdinal("X")),
Y = reader.GetInt32(reader.GetOrdinal("Y")),
Width = reader.GetInt32(reader.GetOrdinal("Width")),
Height = reader.GetInt32(reader.GetOrdinal("Height")),
Nombre = reader.IsDBNull(reader.GetOrdinal("Nombre")) ? null : reader.GetString(reader.GetOrdinal("Nombre")),
NombreImagen = reader.GetString(reader.GetOrdinal("NombreImagen")),
CodigoNumerico = reader.GetInt32(reader.GetOrdinal("CodigoNumerico")),
Descripcion = reader.IsDBNull(reader.GetOrdinal("Descripcion")) ? null : reader.GetString(reader.GetOrdinal("Descripcion")),
CampoTexto1 = reader.IsDBNull(reader.GetOrdinal("CampoTexto1")) ? null : reader.GetString(reader.GetOrdinal("CampoTexto1")),
CampoTexto2 = reader.IsDBNull(reader.GetOrdinal("CampoTexto2")) ? null : reader.GetString(reader.GetOrdinal("CampoTexto2")),
CampoTexto3 = reader.IsDBNull(reader.GetOrdinal("CampoTexto3")) ? null : reader.GetString(reader.GetOrdinal("CampoTexto3")),
});
}
}
}
}
public void GuardarRois()
{
using (var connection = new SqliteConnection(dbPath))
{
connection.Open();
var deleteCommand = connection.CreateCommand();
deleteCommand.CommandText = @"DELETE FROM Roi WHERE NombreImagen = $NombreImagen";
deleteCommand.Parameters.AddWithValue("$NombreImagen", NombreImagen);
deleteCommand.ExecuteNonQuery();
}
using (var connection = new SqliteConnection(dbPath))
{
connection.Open();
foreach (var roi in rois)
{
var insertCommand = connection.CreateCommand();
insertCommand.CommandText =
@"INSERT INTO Roi (X, Y, Width, Height, Nombre, NombreImagen, CodigoNumerico, Descripcion, CampoTexto1, CampoTexto2, CampoTexto3)
VALUES ($X, $Y, $Width, $Height, $Nombre, $NombreImagen, $CodigoNumerico, $Descripcion, $CampoTexto1, $CampoTexto2, $CampoTexto3)";
insertCommand.Parameters.AddWithValue("$X", roi.X);
insertCommand.Parameters.AddWithValue("$Y", roi.Y);
insertCommand.Parameters.AddWithValue("$Width", roi.Width);
insertCommand.Parameters.AddWithValue("$Height", roi.Height);
insertCommand.Parameters.AddWithValue("$Nombre", roi.Nombre ?? (object)DBNull.Value);
insertCommand.Parameters.AddWithValue("$NombreImagen", roi.NombreImagen);
insertCommand.Parameters.AddWithValue("$CodigoNumerico", roi.CodigoNumerico);
insertCommand.Parameters.AddWithValue("$Descripcion", roi.Descripcion ?? (object)DBNull.Value);
insertCommand.Parameters.AddWithValue("$CampoTexto1", roi.CampoTexto1 ?? (object)DBNull.Value);
insertCommand.Parameters.AddWithValue("$CampoTexto2", roi.CampoTexto2 ?? (object)DBNull.Value);
insertCommand.Parameters.AddWithValue("$CampoTexto3", roi.CampoTexto3 ?? (object)DBNull.Value);
insertCommand.ExecuteNonQuery();
}
}
}
public void EliminarRoi( string nombre)
{
using (var connection = new SqliteConnection(dbPath))
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = @"DELETE FROM Roi WHERE NombreImagen = $NombreImagen AND Nombre = $Nombre";
command.Parameters.AddWithValue("$NombreImagen", NombreImagen);
command.Parameters.AddWithValue("$Nombre", nombre);
command.ExecuteNonQuery();
}
}
}
public class Roi
{
public int X { get; set; }
public int Y { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public string Nombre { get; set; }
public string NombreImagen { get; set; }
public int CodigoNumerico { get; set; }
public string Descripcion { get; set; }
public string CampoTexto1 { get; set; }
public string CampoTexto2 { get; set; }
public string CampoTexto3 { get; set; }
// Constructor sin parámetros para facilitar la deserialización
public Roi() { }
// Puedes agregar un constructor con parámetros si lo necesitas,
// para facilitar la creación de instancias de Roi con información específica.
public Roi(string nombreImagen, int x, int y, int width, int height, string nombre, int codigoNumerico, string descripcion, string campoTexto1, string campoTexto2, string campoTexto3)
{
X = x;
Y = y;
Width = width;
Height = height;
Nombre = nombre;
NombreImagen = nombreImagen;
CodigoNumerico = codigoNumerico;
Descripcion = descripcion;
CampoTexto1 = campoTexto1;
CampoTexto2 = campoTexto2;
CampoTexto3 = campoTexto3;
}
public Roi(string nombreImagen, int x, int y, int width, int height)
{
X = x;
Y = y;
Width = width;
Height = height;
NombreImagen = nombreImagen;
}
public Rectangle DibujarRoiEnCanvas(System.Windows.Controls.Canvas ImagenEnTrabajoCanvas)
{
Rectangle rect = new Rectangle
{
Stroke = Brushes.Red,
StrokeThickness = 2, // Grosor normal
Width = Width, // No ajustar aquí por el zoom; ajustar al aplicar el zoom si es necesario
Height = Height, // No ajustar aquí por el zoom; ajustar al aplicar el zoom si es necesario
Fill = Brushes.Transparent, // Permite la detección de eventos MouseEnter en todo el rectángulo
Tag = this // Almacena el Roi en el Tag para identificarlo después
};
Canvas.SetLeft(rect, X);
Canvas.SetTop(rect, Y);
ImagenEnTrabajoCanvas.Children.Add(rect); // Asegúrate de que esto se refiere al Canvas, no al ScrollViewer
return rect;
}
}
}

16
ROIEditor.csproj Normal file
View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
</Project>

25
ROIEditor.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34714.143
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ROIEditor", "ROIEditor.csproj", "{C65863DA-ED9E-4603-BEE3-BED19A267C0C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C65863DA-ED9E-4603-BEE3-BED19A267C0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C65863DA-ED9E-4603-BEE3-BED19A267C0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C65863DA-ED9E-4603-BEE3-BED19A267C0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C65863DA-ED9E-4603-BEE3-BED19A267C0C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F5432400-54BE-443D-B3B3-2AA32382F2BF}
EndGlobalSection
EndGlobal

BIN
roiseditor.db Normal file

Binary file not shown.

14
roiseditor.sqbpro Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?><sqlb_project><db path="roiseditor.db" readonly="0" foreign_keys="1" case_sensitive_like="0" temp_store="0" wal_autocheckpoint="1000" synchronous="2"/><attached/><window><main_tabs open="structure browser pragmas query" current="2"/></window><tab_structure><column_width id="0" width="300"/><column_width id="1" width="0"/><column_width id="2" width="100"/><column_width id="3" width="1711"/><column_width id="4" width="0"/><expanded_item id="0" parent="1"/><expanded_item id="0" parent="0"/><expanded_item id="1" parent="1"/><expanded_item id="2" parent="1"/><expanded_item id="3" parent="1"/></tab_structure><tab_browse><table title="Roi" custom_title="0" dock_id="1" table="4,3:mainRoi"/><dock_state state="000000ff00000000fd0000000100000002000005bb00000386fc0100000001fb000000160064006f0063006b00420072006f00770073006500310100000000000005bb0000011900ffffff000002590000000000000004000000040000000800000008fc00000000"/><default_encoding codec=""/><browse_table_settings><table schema="main" name="Roi" show_row_id="0" encoding="" plot_x_axis="" unlock_view_pk="_rowid_" freeze_columns="0"><sort/><column_widths><column index="1" value="29"/><column index="2" value="29"/><column index="3" value="29"/><column index="4" value="42"/><column index="5" value="45"/><column index="6" value="52"/><column index="8" value="73"/><column index="9" value="85"/><column index="10" value="85"/><column index="11" value="85"/></column_widths><filter_values/><conditional_formats/><row_id_formats/><display_formats/><hidden_columns/><plot_y_axes/><global_filter/></table></browse_table_settings></tab_browse><tab_sql><sql name="SQL 1*">CREATE TABLE IF NOT EXISTS Roi (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
X INTEGER NOT NULL,
Y INTEGER NOT NULL,
Width INTEGER NOT NULL,
Height INTEGER NOT NULL,
Nombre TEXT,
CodigoNumerico INTEGER,
Descripcion TEXT,
CampoTexto1 TEXT,
CampoTexto2 TEXT,
CampoTexto3 TEXT
);
</sql><current_tab id="0"/></tab_sql></sqlb_project>