Manipulación de Imágenes BMP en Java: Duplicación y Procesamiento
Clasificado en Informática
Escrito el en español con un tamaño de 9,62 KB
Este documento explica el código Java para la manipulación de imágenes en formato BMP (Bitmap) de 24 bits, con un enfoque en la duplicación de imágenes. Se asume que la altura y la anchura de la imagen son múltiplos de 4 y menores que 127.
Clase ImagenBMP
La clase ImagenBMP
proporciona métodos para leer, duplicar y guardar imágenes BMP.
Atributos
TAM_CABECERAS
: Constante que define el tamaño de la cabecera de un archivo BMP (54 bytes).cabecera
: Array de bytes que almacena la cabecera de la imagen BMP.nombre
: String que representa el nombre del archivo de la imagen.matriz
: Matriz de objetosPixel
que representa la imagen original.imagen
: ObjetoFile
que representa el archivo de la imagen.matrizDoble
: Matriz de objetosPixel
que representa la imagen duplicada.
Constructor ImagenBMP(String nomb)
Inicializa una nueva instancia de la clase ImagenBMP
.
- Recibe el nombre del archivo de imagen como parámetro.
- Lee la cabecera y los datos de píxeles del archivo BMP.
- Almacena la cabecera en el array
cabecera
. - Crea una matriz de objetos
Pixel
con las dimensiones especificadas en la cabecera. - Lee los bytes de datos de píxeles y los convierte en objetos
Pixel
, almacenándolos en la matrizmatriz
. - Maneja las excepciones
FileNotFoundException
eIOException
.
Métodos
getAncho()
Devuelve el ancho de la imagen (número de columnas de la matriz).
getAlto()
Devuelve el alto de la imagen (número de filas de la matriz).
setImagen(String nom)
Establece el archivo de imagen a partir del nombre de archivo proporcionado.
- Recibe el nombre del archivo como parámetro.
- Crea un nuevo objeto
File
con el nombre de archivo dado.
duplicar()
Duplica el tamaño de la imagen almacenada en la matriz matriz
.
- Crea una nueva matriz
matrizDoble
con el doble de ancho y alto que la matriz original. - Copia cada píxel de la matriz original en cuatro posiciones adyacentes en la matriz
matrizDoble
, duplicando efectivamente la imagen. - Actualiza la cabecera para reflejar las nuevas dimensiones.
duplicar2()
Duplica el tamaño de la imagen utilizando un método alternativo más eficiente.
- Crea una nueva matriz
matrizDoble
con el doble de ancho y alto que la matriz original. - Itera sobre cada píxel de la matriz
matrizDoble
y asigna el valor del píxel correspondiente de la matriz original, dividiendo los índices por 2.
volcarImagen(String nomFichero)
Guarda la imagen duplicada en un archivo BMP.
- Recibe el nombre del archivo de salida como parámetro.
- Crea un nuevo objeto
FileOutputStream
. - Crea una nueva cabecera
cabeceraDoble
con las dimensiones actualizadas. - Escribe la cabecera en el archivo de salida.
- Escribe los datos de píxeles de la matriz
matrizDoble
en el archivo de salida. - Cierra el flujo de salida.
- Maneja las excepciones
FileNotFoundException
eIOException
.
Método main
El método main
demuestra el uso de la clase ImagenBMP
.
- Crea una nueva instancia de
ImagenBMP
con el archivo "orig.bmp". - Llama al método
duplicar2()
para duplicar la imagen. - Llama al método
volcarImagen()
para guardar la imagen duplicada en el archivo "doble.bmp".
Código Completo
import java.io.*;
/**
* Clase para duplicar imágenes BMP de 24 bits con altura y anchura múltiplo de 4 menor que 127.
*/
public class ImagenBMP {
private static final int TAM_CABECERAS = 54;
private byte cabecera[];
private String nombre;
private Pixel[][] matriz;
private File imagen;
private Pixel matrizDoble[][];
public ImagenBMP(String nomb) {
cabecera = new byte[TAM_CABECERAS];
imagen = new File(nomb);
try {
FileInputStream in = new FileInputStream(imagen);
int leido1 = 0;
int leido2 = 0;
int leido3 = 0;
int i = 0;
int j = 0;
in.read(cabecera);
matriz = new Pixel[cabecera[18]][cabecera[22]];
while (i < matriz.length && j < matriz[0].length) {
while (((leido1 = in.read()) != -1) && ((leido2 = in.read()) != -1) && ((leido3 = in.read()) != -1)
&& j < matriz[0].length) {
Pixel nuevoPixel = new Pixel(((byte) leido1), ((byte) leido2), ((byte) leido3));
matriz[i][j] = nuevoPixel;
j++;
}
j = 0;
i++;
if ((leido1 != -1) && (leido2 != -1) && (leido3 != -1)) {
Pixel nuevoPixel = new Pixel(((byte) leido1), ((byte) leido2), ((byte) leido3));
matriz[i][j] = nuevoPixel;
j++;
}
}
in.close();
} catch (FileNotFoundException e) {
System.out.println("No existe el fichero");
} catch (IOException e) {
System.out.println("Error E/S lectura");
}
}
public int getAncho() {
return matriz.length;
}
public int getAlto() {
return matriz[0].length;
}
/**
* Carga una imagen bmp del fichero de nombre dado.
*
* @param nom nombre del fichero a cargar
*/
public void setImagen(String nom) {
imagen = new File(nom);
}
/**
* Duplica los datos de la imagen guardada.
*/
public void duplicar() {
int alto = getAncho() * 2;
int ancho = getAlto() * 2;
matrizDoble = new Pixel[alto][ancho];
for (int i = 0; i < getAncho(); i++) {
for (int j = 0; j < getAlto(); j++) {
Pixel valor = matriz[i][j];
for (int m = 0; m < getAncho(); m += 2) {
for (int n = 0; n < getAlto(); n += 2) {
matrizDoble[m][n] = valor;
matrizDoble[m + 1][n] = valor;
matrizDoble[m][n + 1] = valor;
matrizDoble[m + 1][n + 1] = valor;
}
}
}
}
byte cabeceraDoble[] = new byte[TAM_CABECERAS];
cabeceraDoble[18] = ((byte) ancho);
cabeceraDoble[22] = ((byte) alto);
}
public void duplicar2() {
int ancho = getAncho() * 2;
int alto = getAlto() * 2;
matrizDoble = new Pixel[alto][ancho];
for (int i = 0; i < alto; i++) {
for (int j = 0; j < ancho; j++) {
matrizDoble[i][j] = matriz[i / 2][j / 2];
}
}
}
/**
* Guarda en un fichero de nombre dado los datos de la imagen.
*
* @param nomFichero nombre del fichero donde almacenar los datos de la imagen.
*/
public void volcarImagen(String nomFichero) {
try {
byte cabeceraDoble[] = new byte[TAM_CABECERAS];
FileOutputStream out = new FileOutputStream(nomFichero);
for (int i = 0; i < cabecera.length; i++) {
cabeceraDoble[i] = cabecera[i];
}
cabeceraDoble[18] = ((byte) (getAncho() * 2));
cabeceraDoble[22] = ((byte) (getAlto() * 2));
out.write(cabeceraDoble);
for (int i = 0; i < getAlto() * 2; i++) {
for (int j = 0; j < getAncho() * 2; j++) {
out.write(matrizDoble[i][j].getByte1());
out.write(matrizDoble[i][j].getByte2());
out.write(matrizDoble[i][j].getByte3());
}
}
out.close();
} catch (FileNotFoundException e) {
System.out.println("No existe el fichero ");
} catch (IOException e) {
System.out.println("Error E/S escritura ");
}
}
public static void main(String[] args) {
ImagenBMP x = new ImagenBMP("orig.bmp");
x.duplicar2();
x.volcarImagen("doble.bmp");
}
}
Clase Pixel
La clase Pixel
, aunque no se muestra en el código proporcionado, se puede inferir que representa un píxel individual con tres componentes de color (rojo, verde y azul), cada uno almacenado como un byte. Probablemente, tendría métodos para obtener los valores de cada componente (getByte1()
, getByte2()
, getByte3()
) y un constructor para crear un nuevo objeto Pixel
a partir de tres bytes.
Ejemplo de la clase Pixel
public class Pixel {
private byte byte1;
private byte byte2;
private byte byte3;
public Pixel(byte byte1, byte byte2, byte byte3) {
this.byte1 = byte1;
this.byte2 = byte2;
this.byte3 = byte3;
}
public byte getByte1() {
return byte1;
}
public byte getByte2() {
return byte2;
}
public byte getByte3() {
return byte3;
}
}