C sharp - Seleccionar trozos de una imagen en un PictureBox

 
Vista:

Seleccionar trozos de una imagen en un PictureBox

Publicado por kalixe985 (26 intervenciones) el 13/11/2007 18:39:21
Hola!!!

Resulta que estoy haciendo una aplicación en la que se carga una imagen, y en la que debo poder seleccionar trozos de ella, poderlos guardar o poder aplicar operaciones sobre ellos (por ejemplo si hago click con el botón derecho sobre uno, que me aparezaca un menú). Todo lo que es cargar la imagen y guardar imágenes lo sé hacer (Image.Save(...). También sé hacer que se quede dibujado una especie de rectángulo de selección (al estilo MSPAINT) sobre la imagen del pictureBox (lo hago controlando los eventos MouseMove, MouseUp y MouseDown). El problema viene cuando he dibujado el rectángulo de selección. En lo que necesito ayuda es:

-Que el trozo imagen se quede "marcada" o que se muestre (¿quizá pasándosela a un nuevo PictureBox y que se muestre sobre el original?).

-Me gustaría que poder guardar cada trozo que vaya marcando.

-Después de haber marcado trozos, que pueda aplicar acciones sobre ellos, como que aparezca un menú cuando hago botón derecho o mouseHover, por ejemplo.

-Creo que la clave estaría en saber cómo obtener una imagen nueva, a partir del trozo de la imagen original que quede "seleccionado".


Ya sé que pido mucho, espero que alguien me pueda ayudar. Gracias de antemano y saludos!!!
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

RE:Seleccionar trozos de una imagen en un PictureB

Publicado por El Dr. Gusman (2 intervenciones) el 15/11/2007 17:46:55
Buenas.

Para conseguir lo que quieres tienes varios métodos.

El mas sencillo tal y como tu has dicho es crear otro picturebox encima del original y copiar el trozo a un nuevo bitmap y asignar este bitmap como imagen al nuevo picturebox.

Para conseguir esto haz lo siguiente:

-Almacena las coordenadas del rectángulo dentro de la imagen original.

-Crea un Bitmap utilizando el tamaño del recuadro y usando el formato de imagen de la imagen original. Suponiendo que tu picturebox original se llamase pb1 y que las dimensiones del recuadro seleccionado se hubiesen guardado como Width y Height el código sería:

Bitmap newBMP = new Bitmap(Width, Height, pb1.Image.PixelFormat);

-Ahora que tienes la nueva imagen de destino, obtienes un objeto Graphics del nuevo Bitmap y dibujas el rectangulo seleccionado. Como tienes las coordenadas X e Y del rectángulo y el alto y el ancho aprovechamos para crear un Rectangle con dichas propiedades. Vamos a llamar X e Y a las coordenadas y Width y Height a los tamaños, quedando este código:

Rectangle rectSrc = new Rectangle(X, Y, Width, Height); //Recuadro de origen
Rectangle rectDest = new Rectangle(0, 0, Width, Height); //Recuadro de destino
Graphics g = Graphics.FromImage(newBMP);
g.DrawImage(pb1.Image, rectDest, rectSrc, GraphicsUnit.Pixel);
g.Dispose();

-Ya tenemos la imagen, ahora hay que crear el nuevo PictureBox y añadirlo dentro del PictureBox original:

PictureBox newPB = new PictureBox();
newPB.Image = newBMP;
newPB.BorderStyle = BorderStyle.None;
pb1.Controls.Add(newPB);
newPB.Left = X;
newPB.Top = Y;
newPB.Width = Width;
newPB.Height = Height;

-En este punto ya tienes el nuevo picturebox, dentro del original, y con el trozo de imagen cargado. Si ahora quieres disparar eventos (por ejemplo el Click) solo has de engancharte a ellos (ah, de paso metemos en el tag una ID única para poder identificar el picturebox que dispara el evento):

newPB.Tag = VariableDeID; //El Tag es un object, así que puedes
//poner el tipo de variable que quieras
newPB.Click += new EventHandler(recuadros_Click);

Creo que con esto ya tienes lo que buscabas, una cosa que si te debo recordar es que si quieres destruir los pictureboxes primero los debes de eliminar de la colección Controls del picturebox original antes de hacer el dispose si no quieres generar una excepción.

Otra cosa que te recomendaría es que te crees un List<T> o un Dictionary<TKey, TValue> con los pictureboxes para poder acceder a ellos facilmente.

Bueno, pues eso es todo, como te he dicho hay mas métodos de hacer esto (podrias hacerlo con un solo picturebox, creando controles sin ventana que capten los clicks dentro de otro control dentro de un área definida (tienes un ejemplo de esto en mi web: http://www.drgusman.info) y guardando los Bitmaps de los trozos en una lista y redibujándolos según te haga falta) pero este es el más sencillo.

Espero haberte sido de ayuda.

Un saludo.

El Dr. Gusman.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Seleccionar trozos de una imagen en un PictureB

Publicado por kalixe985 (26 intervenciones) el 15/11/2007 21:41:40
Hola!!!!
Muchísimas gracias por responder y dedicarle un buen tiempo al post. Intentaré hacerlo como dices y ya te diré algo.
Infinitas gracias y saludos!!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Seleccionar trozos de una imagen en un PictureB

Publicado por kalixe985 (26 intervenciones) el 19/11/2007 12:18:07
Hola!!!
He intentado hacerlo como me has dicho y me ha funcionado a medias. Me explico: cuando hago el MouseDown, arrastro y luego MouseUp, se dibuja el rectángulo de selección y también se dibuja el pictureBox, pero la imagen que me carga sale desplazada. Es como si no cojiera bien las coordenadas del puntero. Yo las coordenadas las calculo respecto del pictureBox con MouseEventArgs, no respecto al formulario. Es por esto que si estoy con el puntero dentro del pictureBox, me marca una coordenadas y si salgo fuera del pictureBox, me marca otras coordenadas totalmente diferentes. ¿Sabes por qué puede ser esto?

A continuación te pongo mi código que dibuja un rectángulo (ver http://www.megaupload.com/?d=FZHW8Z52), a ver si me puedes ayudar:

private bool seleccionar = false;
private Rectangle RectanguloSeleccion = new Rectangle(new Point(0, 0), new Size(0, 0));
private Point PuntoInicio;
private Point PuntoFin;
private int alturaRectanguloSeleccion;
private int anchoRectanguloSeleccion;
private float[] valoresLineaDiscontinua ={ 3, 2, 3, 2 };


private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{ this.Click_Raton(e); }


private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{ this.Levantar_Raton(e); }

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{ this.Mover_Raton(e); }


private void Click_Raton(MouseEventArgs e)
{
if (seleccionar & e.Button == MouseButtons.Left)
{
PuntoInicio = new Point(e.X, e.Y);
}
}

private void Levantar_Raton(MouseEventArgs e)
{
if (seleccionar)
{
RectanguloSeleccion = new Rectangle(PuntoInicio.X, PuntoInicio.Y, anchoRectanguloSeleccion, alturaRectanguloSeleccion);
this.Cursor = System.Windows.Forms.Cursors.Cross;
Graphics objGrafico = this.pictureBoxPrincipal.CreateGraphics();
Pen pen = new Pen(Color.Red, 1);
pen.DashPattern = valoresLineaDiscontinua;
objGrafico.DrawRectangle(pen, RectanguloSeleccion);
}
}


private void Mover_Raton(MouseEventArgs e)
{
if (seleccionar & e.Button == MouseButtons.Left)
{
PuntoFin = new Point(e.X, e.Y);
anchoRectanguloSeleccion = PuntoFin.X - PuntoInicio.X;
alturaRectanguloSeleccion = PuntoFin.Y - PuntoInicio.Y;
}
}

Y este el el código de mezclar lo que tu me dijiste con lo que yo tenía, y que dibuja los picturesBoxes, pero con las imágenes desplazadas (ver http://www.megaupload.com/?d=VPM0VDDX):

private bool seleccionar = false;
private Rectangle RectanguloSeleccion = new Rectangle(new Point(0, 0), new Size(0, 0));
private Point PuntoInicio;
private Point PuntoFin;
private int alturaRectanguloSeleccion;
private int anchoRectanguloSeleccion;
private float[] valoresLineaDiscontinua ={ 3, 2, 3, 2 };

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{ this.Click_Raton(e); }


private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{ this.Levantar_Raton(e); }

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{ this.Mover_Raton(e); }

private void Click_Raton(MouseEventArgs e)
{
if (seleccionar & e.Button == MouseButtons.Left)
{
PuntoInicio = new Point(e.X, e.Y);
}
}

private void Levantar_Raton(MouseEventArgs e)
{
if (seleccionar)
{
RectanguloSeleccion = new Rectangle(PuntoInicio.X, PuntoInicio.Y, anchoRectanguloSeleccion, alturaRectanguloSeleccion);
Bitmap imagenPequeña = new Bitmap(anchoRectanguloSeleccion, alturaRectanguloSeleccion, this.pictureBoxPrincipal.Image.PixelFormat);
Rectangle rectDest = new Rectangle(0, 0, anchoRectanguloSeleccion, alturaRectanguloSeleccion);
Graphics g = Graphics.FromImage(imagenPequeña);
g.DrawImage(this.pictureBoxPrincipal.Image, rectDest, RectanguloSeleccion2, GraphicsUnit.Pixel);
g.Dispose();
PictureBox newPB = new PictureBox();
newPB.Image = imagenPequeña;
newPB.BorderStyle = BorderStyle.Fixed3D;
this.pictureBoxPrincipal.Controls.Add(newPB);
newPB.Left = PuntoInicio.X;
newPB.Top = PuntoInicio.Y;
newPB.Width = anchoRectanguloSeleccion;
newPB.Height = alturaRectanguloSeleccion;
this.Cursor = System.Windows.Forms.Cursors.Cross;
Graphics objGrafico = this.pictureBoxPrincipal.CreateGraphics();
Pen pen = new Pen(Color.Red, 1);
pen.DashPattern = valoresLineaDiscontinua;
objGrafico.DrawRectangle(pen, RectanguloSeleccion);
}
}

private void Mover_Raton(MouseEventArgs e)
{
if (seleccionar & e.Button == MouseButtons.Left)
{
PuntoFin = new Point(e.X, e.Y);
anchoRectanguloSeleccion = PuntoFin.X - PuntoInicio.X;
alturaRectanguloSeleccion = PuntoFin.Y - PuntoInicio.Y;
}
}

A ver si me puedes echar una mano. He mirado tu web, pero no encontré el ejemplo que decías de la otra forma de hacerlo. Gracias y saludos!!!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:NUEVO: Seleccionar trozos de una imagen ....

Publicado por kalixe985 (26 intervenciones) el 22/11/2007 00:54:33
Hola!!!

Al final lo he intentado de 20000 formas diferentes, y me sigue pasando básicamente lo mismo, la imagen que me pone en el pictureBox es de una zona diferente a la que yo he seleccionado. Intenté con lo de RectangleToClient, pero sólo me sirvió en parte. Ahora mismo, lo estoy intentando hacer sobre un pictureBox, que está dentro de una tabPage, estos dentro de un formulario. Adjunto el código y un video a ver alguien si me puede ayudar: http://www.megaupload.com/?d=IN3T0YC0 (660KB)

private bool seleccionar = false;
private Rectangle RectanguloSeleccion;
private Point PuntoInicio;
private Point PuntoFin;
private int anchoSeleccion;
private int alturaSeleccion;


private void MouseDown_PictureBox(object sender, MouseEventArgs e)
{ this.Click_Raton(sender,e);
}


private void MouseUp_PictureBox(object sender, MouseEventArgs e)
{ this.Levantar_Raton(sender,e);
}


private void MouseMove_PictureBox(object sender, MouseEventArgs e)
{ this.Mover_Raton(sender,e);
}


private void Click_Raton(object sender,MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
seleccionar = true;
}
Control control = (Control)sender;
PuntoInicio = control.PointToScreen(new Point(e.X, e.Y));
}


private void Mover_Raton(object sender,MouseEventArgs e)
{
if (seleccionar)
{
ControlPaint.DrawReversibleFrame(RectanguloSeleccion,Color.Silver, FrameStyle.Dashed);
PuntoFin = ((Control)sender).PointToScreen(new Point(e.X, e.Y));
anchoSeleccion = PuntoFin.X - PuntoInicio.X;
alturaSeleccion = PuntoFin.Y - PuntoInicio.Y;
RectanguloSeleccion = new Rectangle(PuntoInicio.X, PuntoInicio.Y, anchoSeleccion, alturaSeleccion);
ControlPaint.DrawReversibleFrame(RectanguloSeleccion,Color.Silver, FrameStyle.Dashed);
}

}


private void Levantar_Raton(object sender, MouseEventArgs e)
{
seleccionar = false;
ControlPaint.DrawReversibleFrame(RectanguloSeleccion,Color.Blue, FrameStyle.Thick);
Rectangle r1 = this.pictureBoxPrincipal.RectangleToClient(RectanguloSeleccion);
Bitmap imagenPequeña = new Bitmap(anchoSeleccion, alturaSeleccion, this.pictureBoxPrincipal.Image.PixelFormat);
Rectangle rectDest = new Rectangle(0, 0, anchoSeleccion, alturaSeleccion);
Graphics g = Graphics.FromImage(imagenPequeña);
g.DrawImage(this.pictureBoxPrincipal.Image, rectDest, r1, GraphicsUnit.Pixel);
g.Dispose();
PictureBox newPB = new PictureBox();
newPB.Image = imagenPequeña;
newPB.BorderStyle = BorderStyle.Fixed3D;
this.pictureBoxPrincipal.Controls.Add(newPB);
newPB.Location = new System.Drawing.Point(r1.X, r1.Y);
newPB.Size = new System.Drawing.Size(anchoSeleccion, alturaSeleccion);
newPB.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Normal;
}


Espero que alguien me pueda ayudar. Gracias y saludos!!!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar