Ir al índice de .NET Cómo... en .NET
 

Trocear una imagen

Parte 1: Usando 9 PictureBox para mostrar los trozos

 
Publicado el 17/Ene/2007
Actualizado el 17/Ene/2007
Autor: Guillermo 'guille' Som

En este artículo te muestro cómo trocear una imagen en otras más pequeñas, de forma que todas juntas forman la imagen original, útil para, por ejemplo hacer un puzzle de imágenes o crear mapas, etc. Como de costumbre, con código tanto para Visual Basic como para C# (válido para .NET 1.1 y superior).


Introducción:

Pues eso, que a raíz de una consulta en mis foros, me decidí a hacer el ejemplo, y así de paso te pongo algo de manipulación de imágenes, que de eso, yo en particular casi no escribo... creo que este es el primer artículo que publico sobre el manejo de imágenes.

Te explico que es lo que hace el código que te voy a mostrar

En esta primera parte, he creado un formulario en el que hay control PictureBox que será el usado para mostrar la imagen que vamos a trocear.

También hay un control GroupBox en el que hay 9 controles de tipo PictureBox, en esos controles será donde mostremos cada uno de los trozos, y como es de suponer, cada trozo es una parte de la imagen original, y por tanto, si los juntamos todos, formarán esa imagen.

Este primer ejemplo, no solo permite trocear la imagen en 9 trozos (3 filas y 3 columnas), sino que puedes trocearla en menos trozos, aunque el máximo será de 3 columnas y 3 filas.
En este otro ejemplo, puedes ver el código para trocear la imagen en el número de filas y columnas que quieras.

El proceso para trocear es el siguiente:

  1. Se calcula el tamaño de cada trozo de la imagen original, para ello se divide el ancho de la imagen original por el número de columnas y el alto de dicha imagen por el número de filas:
' Visual Basic 

Dim tamTrozoW As Integer = Me.picMain.Image.Width \ columnas
Dim tamTrozoH As Integer = Me.picMain.Image.Height \ filas
// C# 

int tamTrozoW = this.picMain.Image.Width / columnas;
int tamTrozoH = this.picMain.Image.Height / filas;
  1. Se calcula cuanto ocupará cada imagen, en este caso, el tamaño de uno de los 9 controles que están en el GroupBox:
' Visual Basic 

' El tamaño de cada trozo
Dim nW As Integer = pic0.Width
Dim nH As Integer = pic0.Height
' El rectángulo de cada nuevo trozo
Dim rectDest As New Rectangle(0, 0, nW, nH)
// C# 

// El tamaño de cada trozo
int nW = pic0.Width;
int nH = pic0.Height;
// El rectángulo que ocupará cada nuevo trozo
Rectangle rectDest = new Rectangle(0, 0, nW, nH);
  1. Creamos un array con los 9 controles, para que resulte más fácil controlarlas:
' Visual Basic 

Dim trozos() As PictureBox = {pic0, pic1, pic2, pic3, pic4, pic5, pic6, pic7, pic8}
// C# 

PictureBox[] trozos = { pic0, pic1, pic2, pic3, pic4, pic5, pic6, pic7, pic8 };
  1. Usamos un bucle para obtener cada trozo, inicialmente el primer trozo estará en la posición 0,0,
    (fíjate que en C#, a diferencia de Visual Basic, hay que inicializar las variables):
' Visual Basic 

' Para contar cada columna
Dim c As Integer
' La posición X e Y en la imagen original
Dim pX, pY As Integer
For i As Integer = 0 To trozos.Length - 1
// C# 

// Para contar cada columna
int c = 0;
// La posición X e Y en la imagen original
int pX = 0, pY = 0;
for (int i = 0; i < trozos.Length; i++)
  1. En cada repetición del bucle troceamos una imagen, y la vamos asignando al elemento del array que corresponda. Para realizar el recorte y asignarlo a la imagen de destino, usamos un objeto de tipo Graphics obtenido de la imagen de destino, la imagen la dibujamos usando el método DrawImage en el que le indicamos que trozo queremos de la imagen original, trozo que indicamos con un objeto Rectangle (rectOrig) al que le asignamos los valores X e Y además del ancho y alto que anteriormente calculamos y que tenemos guardado en las variables tamTrozoW y tamTrozoH respectivamente. La posición en la que queremos insertar la nueva imagen la indicamos con el rectángulo de destino (rectDest), que siempre es el mismo, por eso esa asignación la hacemos fuera del bucle:
' Visual Basic 

' El trozo de la imagen original
rectOrig = New Rectangle(pX, pY, tamTrozoW, tamTrozoH)
' La imagen de destino
bmpDest = New Bitmap(tamTrozoW, tamTrozoW)
g = Graphics.FromImage(bmpDest)
' Obtenemos un trozo de la imagen original
' y lo dibujamos en la imagen de destino
g.DrawImage(picMain.Image, rectDest, rectOrig, GraphicsUnit.Pixel)

' Asignamos la nueva imagen al picture correspondiente
trozos(i).Image = bmpDest
// C# 

// El trozo de la imagen original
rectOrig = new Rectangle(pX, pY, tamTrozoW, tamTrozoH);
// La imagen de destino
bmpDest = new Bitmap(tamTrozoW, tamTrozoW);
g = Graphics.FromImage(bmpDest);
// Obtenemos un trozo de la imagen original
// y lo dibujamos en la imagen de destino
g.DrawImage(picMain.Image, rectDest, rectOrig, GraphicsUnit.Pixel);

// Asignamos la nueva imagen al picture correspondiente
trozos[i].Image = bmpDest;
  1. Incrementamos el valor de la posición horizontal (pX) e incrementamos el número de columna, si hemos llegado al número de columnas indicadas, es que estamos en la siguiente fila, por tanto ponemos a cero el valor de la posición X e incrementamos la posición Y (pY):
' Visual Basic 

    c += 1
    pX += tamTrozoW
    ' Cuando hayamos recorrido las columnas,
    ' pasamos a la siguiente fila
    If c >= columnas Then
        c = 0
        pX = 0
        pY += tamTrozoH
    End If
Next
// C# 

    c += 1;
    pX += tamTrozoW;
    // Cuando hayamos recorrido las columnas,
    // pasamos a la siguiente fila
    if (c >= columnas)
    {
        c = 0;
        pX = 0;
        pY += tamTrozoH;
    }
}

 

Y eso es todo.

Aquí tienes una captura del formulario en tiempo de diseño y más abajo tienes el código completo, tanto para Visual Basic .NET como para C#.
En el caso de C#, tendrás que asociar los eventos de los controles con los métodos mostrados, en Visual Basic no hace falta, ya que con la instrucción Handles se asocia automáticamente.

Figura 1. El formulario en tiempo de diseño
Figura 1. El formulario en tiempo de diseño

 

 

Espero que te sea de utilidad.

Nos vemos.
Guillermo

Aquí tienes otro ejemplo, pero usando un número dinámico de filas y columnas.

 


Código para Visual Basic.NET (VB.NET)El código para Visual Basic .NET (cualquier versión)

'------------------------------------------------------------------------------
' Trocear una imagen                                                (17/Ene/07)
'
' ©Guillermo 'guille' Som, 2007
'------------------------------------------------------------------------------
Option Strict On

Imports Microsoft.VisualBasic
Imports System
Imports System.Windows.Forms
Imports System.Drawing

Public Class Form1

    Private Sub btnExaminar_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles btnExaminar.Click
        Dim oFD As New OpenFileDialog
        oFD.Title = "Seleccionar imagen"
        oFD.Filter = "Imágenes|*.jpg;*.gif;*.png;*.bmp|Todos (*.*)|*.*"
        oFD.FileName = Me.txtImagen.Text
        If oFD.ShowDialog = Windows.Forms.DialogResult.OK Then
            Me.txtImagen.Text = oFD.FileName
            Me.picMain.Image = Image.FromFile(Me.txtImagen.Text)
        End If
    End Sub

    Private Sub btnTrocear_Click(ByVal sender As Object, ByVal e As EventArgs) _
                Handles btnTrocear.Click
        ' Trocear una imagen en trozos más pequeños
        Const columnas As Integer = 3
        Const filas As Integer = 3
        '
        ' El tamaño proporcional del ancho y alto
        ' correspondientes a los trozos a usar
        Dim tamTrozoW As Integer = Me.picMain.Image.Width \ columnas
        Dim tamTrozoH As Integer = Me.picMain.Image.Height \ filas
        ' El tamaño de cada trozo
        Dim nW As Integer = pic0.Width
        Dim nH As Integer = pic0.Height
        ' El rectángulo de cada nuevo trozo
        Dim rectDest As New Rectangle(0, 0, nW, nH)
        ' Estas variables se usan en el bucle
        Dim bmpDest As Bitmap
        Dim g As Graphics
        Dim rectOrig As Rectangle
        '
        ' Array con los pictures que hay en el formulario
        Dim trozos() As PictureBox = {pic0, pic1, pic2, pic3, pic4, pic5, pic6, pic7, pic8}
        ' Para contar cada columna
        Dim c As Integer
        ' La posición X e Y en la imagen original
        Dim pX, pY As Integer
        For i As Integer = 0 To trozos.Length - 1
            ' El trozo de la imagen original
            rectOrig = New Rectangle(pX, pY, tamTrozoW, tamTrozoH)
            ' La imagen de destino
            bmpDest = New Bitmap(tamTrozoW, tamTrozoW)
            g = Graphics.FromImage(bmpDest)
            ' Obtenemos un trozo de la imagen original
            ' y lo dibujamos en la imagen de destino
            g.DrawImage(picMain.Image, rectDest, rectOrig, GraphicsUnit.Pixel)
            ' Asignamos la nueva imagen al picture correspondiente
            trozos(i).Image = bmpDest
            c += 1
            pX += tamTrozoW
            ' Cuando hayamos recorrido las columnas,
            ' pasamos a la siguiente fila
            If c >= columnas Then
                c = 0
                pX = 0
                pY += tamTrozoH
            End If
        Next
    End Sub
End Class

 


Código para C Sharp (C#)El código para C# (cualquier versión)

//-----------------------------------------------------------------------------
// Trocear una imagen                                               (17/Ene/07)
//
// ©Guillermo 'guille' Som, 2007
//-----------------------------------------------------------------------------
using System;
using System.Windows.Forms;
using System.Drawing;

namespace trocearImagen_cs
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnExaminar_Click(object sender, EventArgs e)
        {
            OpenFileDialog oFD = new OpenFileDialog();
            oFD.Title = "Seleccionar imagen";
            oFD.Filter = "Imágenes|*.jpg;*.gif;*.png;*.bmp|Todos (*.*)|*.*";
            oFD.FileName = this.txtImagen.Text;
            if (oFD.ShowDialog() == DialogResult.OK)
            {
                this.txtImagen.Text = oFD.FileName;
                this.picMain.Image = Image.FromFile(this.txtImagen.Text);
            }
        }

        private void btnTrocear_Click(object sender, EventArgs e)
        {
            // Trocear una imagen en trozos más pequeños
            const int columnas = 3;
            const int filas = 3;
            //
            // El tamaño proporcional del ancho y alto
            // correspondientes a los trozos a usar
            int tamTrozoW = this.picMain.Image.Width / columnas;
            int tamTrozoH = this.picMain.Image.Height / filas;
            // El tamaño de cada trozo
            int nW = pic0.Width;
            int nH = pic0.Height;
            // El rectángulo que ocupará cada nuevo trozo
            Rectangle rectDest = new Rectangle(0, 0, nW, nH);
            // Estas variables se usan en el bucle
            Bitmap bmpDest;
            Graphics g;
            Rectangle rectOrig;
            //
            // Array con los pictures que hay en el formulario
            PictureBox[] trozos = { pic0, pic1, pic2, pic3, pic4, pic5, pic6, pic7, pic8 };
            // Para contar cada columna
            int c = 0;
            // La posición X e Y en la imagen original
            int pX = 0, pY = 0;
            for (int i = 0; i < trozos.Length; i++)
            {
                // El trozo de la imagen original
                rectOrig = new Rectangle(pX, pY, tamTrozoW, tamTrozoH);
                // La imagen de destino
                bmpDest = new Bitmap(tamTrozoW, tamTrozoW);
                g = Graphics.FromImage(bmpDest);
                // Obtenemos un trozo de la imagen original
                // y lo dibujamos en la imagen de destino
                g.DrawImage(picMain.Image, rectDest, rectOrig, GraphicsUnit.Pixel);
                // Asignamos la nueva imagen al picture correspondiente
                trozos[i].Image = bmpDest;
                c += 1;
                pX += tamTrozoW;
                // Cuando hayamos recorrido las columnas,
                // pasamos a la siguiente fila
                if (c >= columnas)
                {
                    c = 0;
                    pX = 0;
                    pY += tamTrozoH;
                }
            }
        }
    }
}

 


Espacios de nombres usados en el código de este artículo:

System.Windows.Forms
System.Drawing
 

Compatibilidad:

Este código funciona con cualquier versión de .NET
Windows Vista ready! ;-)))

 


Código de ejemplo (comprimido):

 

No hay código para bajar

 


Ir al índice principal de el Guille

Valid XHTML 1.0 Transitional ¡CSS Válido!