You are on page 1of 14

Graficacin

UNIDAD I.- INTRODUCCIN A LOS AMBIENTES DE GRAFICACIN


___________________________________________________________________
LECCIN 1.3.- Formatos Grficos de Almacenamiento
___________________________________________________________________
1.3.6.- Cdigo para leer la estructura de un BMP
Clase Archivo
package util;
public class Archivo {
/**
* Mtodo para pegar bytes leidos separadamente
* Por ejemplo si se usa pegarBytes(bi,2,4)
*
* |7
0|7
0|7
0|7
0|
* |--------|--------|--------|--------|
* |-bi[5]--|-bi[4]--|-bi[3]--|-bi[2]--|
*
* El ltimo byte leido es el mas significativo de la secuencia
*
* @param bi - arreglo de bytes
* @param inicio - la posicin donde se inicia la lectura
* @param numero - el nmero de bytes a pegar
* @return el valor entero resultado de pegar los bytes
*/

public static int pegarBytes(byte bi[],int inicio, int numero) {


/* Se inicia desde el ltimo byte (numero - 1)
hasta el primer byte
*/
int j = numero - 1;
long valor = ((int) bi[inicio + j]) & 0xff;
for (int i = j - 1; i >= 0; i--) {
valor = (valor << 8) | ((int) (bi[inicio + i]) & 0xff);
}
return (int) valor;
}

Rafael Rivera Lpez

Graficacin
Clase BMP
package bmp;
import java.awt.*;
import java.io.*;
public class BMP{
private CabeceraBMP cabeceraBMP;
private PaletaBMP paletaBMP;
private ImagenBMP imagenBMP;
public void cargarBMP(String nombre) {
FileInputStream archivo = null;
try {
archivo = new FileInputStream(nombre);
cabeceraBMP = new CabeceraBMP(archivo);
imprimirCabecera(cabeceraBMP);
paletaBMP = new PaletaBMP(archivo, this);
imagenBMP = new ImagenBMP(archivo, this);
} catch (IOException ex) {
System.out.println("Error "+ex);
System.exit(-1);
}
}
public void dibujar(Graphics g) {
if (imagenBMP != null) {
g.drawImage(imagenBMP.getImagen(), 0, 0, null);
}
}
public static void imprimirCabecera(CabeceraBMP cabecera) {
System.out.println("BMP? " + cabecera.isBmp());
System.out.println("Tamano =" + cabecera.getFileSize());
System.out.println("Offset = " + cabecera.getOffset());
System.out.println("Ancho = " + cabecera.getWidth());
System.out.println("Alto = " + cabecera.getHeight());
System.out.println("Bits por pixel = " + cabecera.getBits());
System.out.println("Compresion = " + cabecera.getCompression());
System.out.println("Size = " + cabecera.getImageSize());
System.out.println("XR = " + cabecera.getxResolution());
System.out.println("YR = " + cabecera.getyResolution());
System.out.println("Colores =" + cabecera.getnColours());
}
public CabeceraBMP getCabeceraBMP() {
return cabeceraBMP;
}
public void setCabeceraBMP(CabeceraBMP cabeceraBMP) {

Rafael Rivera Lpez

Graficacin
this.cabeceraBMP = cabeceraBMP;
}
public PaletaBMP getPaletaBMP() {
return paletaBMP;
}
public void setPaletaBMP(PaletaBMP paletaBMP) {
this.paletaBMP = paletaBMP;
}
public ImagenBMP getImagenBMP() {
return imagenBMP;
}

public void setImagenBMP(ImagenBMP imagenBMP) {


this.imagenBMP = imagenBMP;
}

Clase CabeceraBMP.java
package bmp;
import java.io.*;
import static util.Archivo.*;
public class CabeceraBMP {
/* Bits 0-14 HEADER
* 0- 1 MagicNumber :
* 2- 5 fileSize
:
6- 7 reserved1
:
8- 9 reserved2
:
* 10-13 offset
:
*/
private boolean bmp;
private int fileSize;
private int offset;

Tipo de Archivo ("BM")


Tamao total del archivo (cabecera + imagen)
No utilizado
No utilizado
bit donde inicia la imagen en el archivo.
// bits 0-1
// bits 2-3-4-5
// bits 10-11-12-13

/* Bits 15-54 INFOHEADER


15-18 size
: Tamao del infoHeader (siempre es 40 bytes)
* 19-22 width
: Ancho de la imagen (nmero de pixeles)
* 23-26 height
: alto de la imagen (nmero de pixeles)
27-28 planes
: Nmero de planos de color (siempre es 1)
* 29-30 bits
: Nmero de bits por color: 1, 4, 8 24
31-34 compression : Tipo de Compresin:
0 (sin compresion), 1 (8-bit RLE), or 2 (4-bit RLE)
35-38 imageSize
: Nmero de bytes de la imagen (pixeles+relleno)
Si es cero debe ser calculado
39-42 xResolution : Resolucin horizontal de la imagen (pixel por metro)
43-46 yResolution : Resolucin vertical de la imagen (pixel por metro)

Rafael Rivera Lpez

Graficacin
47-50

: Nmero de colores utilizados


Si es cero debe ser calculado
importantColours : Nmero de colores importantes.
Estos aparecen al principio en la paleta
Si es cero, todos son importantes

51-54

nColours

*/
private
private
private
private
private
private
private
private
private
private
private

int
int
int
int
int
int
int
int
int
int
int

size;
width;
height;
planes;
bits;
compression;
imageSize;
xResolution;
yResolution;
nColours;
importantColours;

//
//
//
//
//
//
//
//
//
//
//

15-16-17-18
19-20-21-22
23-24-25-26
27-28
29-30
31-32-33-34
35-36-37-38
39-40-41-42
43-44-45-46
47-48-49-50
51-52-53-54

public CabeceraBMP(FileInputStream archivo) throws IOException {


byte bf[] = new byte[54];
archivo.read(bf, 0, 54);

bmp = new String(bf, 0, 2).equals("BM");


if (bmp) {
fileSize
= pegarBytes(bf, 2, 4);
offset
= pegarBytes(bf, 10, 4);
// se usa i=14 para respetar las estructuras conocidas
int i = 14;
size
= pegarBytes(bf, i + 0, 4);
width
= pegarBytes(bf, i + 4, 4);
height
= pegarBytes(bf, i + 8, 4);
planes
= pegarBytes(bf, i + 12, 2);
bits
= pegarBytes(bf, i + 14, 2);
compression = pegarBytes(bf, i + 16, 4);
imageSize
= pegarBytes(bf, i + 20, 4);
xResolution = pegarBytes(bf, i + 24, 4);
yResolution = pegarBytes(bf, i + 28, 4);
nColours
= pegarBytes(bf, i + 32, 4);
importantColours = pegarBytes(bf, i + 36, 4);
}

public boolean isBmp() {


return bmp;
}
public void setBmp(boolean bmp) {
this.bmp = bmp;
}
public int getFileSize() {
return fileSize;

Rafael Rivera Lpez

Graficacin
}
public void setFileSize(int fileSize) {
this.fileSize = fileSize;
}
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getPlanes() {
return planes;
}
public void setPlanes(int planes) {
this.planes = planes;
}
public int getBits() {
return bits;
}
public void setBits(int bits) {
this.bits = bits;

Rafael Rivera Lpez

Graficacin
}
public int getCompression() {
return compression;
}
public void setCompression(int compression) {
this.compression = compression;
}
public int getImageSize() {
return imageSize;
}
public void setImageSize(int imageSize) {
this.imageSize = imageSize;
}
public int getxResolution() {
return xResolution;
}
public void setxResolution(int xResolution) {
this.xResolution = xResolution;
}
public int getyResolution() {
return yResolution;
}
public void setyResolution(int yResolution) {
this.yResolution = yResolution;
}
public int getnColours() {
return nColours;
}
public void setnColours(int nColours) {
this.nColours = nColours;
}
public int getImportantColours() {
return importantColours;
}
public void setImportantColours(int importantColours) {
this.importantColours = importantColours;
}
}

Rafael Rivera Lpez

Graficacin
Clase PaletaBMP
package bmp;
import java.io.*;
import static util.Archivo.*;
public class PaletaBMP
private byte[] r;
private byte[] g;
private byte[] b;

{
// Vector de rojos de la paleta
// Vector de verdes de la paleta
// Vector de azules de la paleta

/**
* Se crea la paleta de colores de una imagen de 256 colores
* Los colores de la paleta estan almacenados en 4 bytes en el archivo
* |7
0|7
0|7
0|7
0|
* |-blue---|-green--|-red----|--------|
*/
public PaletaBMP(FileInputStream archivo, BMP bmp) throws IOException {
CabeceraBMP cabecera = bmp.getCabeceraBMP();
if (cabecera.isBmp()) {
int nColores = cabecera.getnColours();

if (nColores <= 0) {
nColores = (1 & 0xff) << cabecera.getBits();
}
if (cabecera.getBits() != 24) {
byte bitsPaleta[] = new byte[nColores * 4];
archivo.read(bitsPaleta, 0, nColores * 4);
r = new byte[nColores];
g = new byte[nColores];
b = new byte[nColores];
int indice = 0;
for (int n = 0; n < nColores; n++) {
r[n] = (byte) pegarBytes(bitsPaleta, indice + 2, 1);
g[n] = (byte) pegarBytes(bitsPaleta, indice + 1, 1);
b[n] = (byte) pegarBytes(bitsPaleta, indice, 1);
indice += 4;
}
}

}
public byte[] getR() {
return r;
}
public void setR(byte[] r) {
this.r = r;
}
public byte[] getG() {

Rafael Rivera Lpez

Graficacin
return g;
}
public void setG(byte[] g) {
this.g = g;
}
public byte[] getB() {
return b;
}

public void setB(byte[] b) {


this.b = b;
}

Clase ImagenBMP
package bmp;
import
import
import
import

java.awt.*;
java.awt.image.*;
java.io.*;
static util.Archivo.*;

public class ImagenBMP {


private Image imagen;
private byte[] bPixeles;
private int[] iPixeles;
private int tamaoLinea;
private int relleno;
private ColorModel cm;

//
//
//
//
//
//
//
//
//
//

La imagen producida
Pixeles de una imagen 256 colores
Almacena los indices de la paleta
Pixeles de una imagen de 24 bits
Almacena el cdigo del color XRGB
Nmero de bytes de cada renglon
mltiplos de 4 (ancho*bitsPorColor
+ relleno)
bytes de relleno de una linea
Modelo de color de la imagen

/**
* La imagen esta almacenada de izquierda a derecha
* y de la ltima linea a la primera
* Lnea n, lnea n-1, lnea n-2, ...., lnea 3, lnea 2, lnea 1
* @param archivo Stream asociado al archivo que contiene al imagen
* @param bmp
Objeto BMP que contiene los elementos del archivo
* @throws java.io.IOException
*/
public ImagenBMP(FileInputStream archivo, BMP bmp) throws IOException {
CabeceraBMP cabecera = bmp.getCabeceraBMP();
PaletaBMP paleta = bmp.getPaletaBMP();
MemoryImageSource mImagen;
int alto = cabecera.getHeight();

Rafael Rivera Lpez

Graficacin
int ancho = cabecera.getWidth();
//Se debe leer el ancho de la imagen en multiplos de 4
//Si el ancho no es multiplo de 4, se le completa con un relleno
tamaoLinea = (ancho * cabecera.getBits() + 31) / 32 * 4;
relleno = tamaoLinea - ancho * cabecera.getBits() / 8;
// Contiene los bytes almacenados de la imagen
byte bBMP[] = new byte[tamaoLinea * alto];
archivo.read(bBMP, 0, bBMP.length);
int iImagen = 0; // Contador de pixeles
int mascara = 0xff;
// el offset apunta al inicio de la ltima lnea
int offset = (alto-1) * tamaoLinea;
if (cabecera.getBits() != 24) {
// Imagen de 256 colores
bPixeles = new byte[ancho * alto];
for (int j = 0; j < alto; j++) {
int iDatos=0;
for (int i = 0; i < ancho; i++) {
bPixeles[iImagen] =
(byte) (bBMP[offset+iDatos] & mascara);
iDatos++;
iImagen++;
}
// Se regresa a la lnea anterior
offset -= tamaoLinea;
}
// El modelo de color carga la paleta de colores del bmp
cm =
new IndexColorModel(cabecera.getBits(),cabecera.getnColours(),
paleta.getR(),paleta.getG(),paleta.getB());
// Se crea la imagen
mImagen = new MemoryImageSource(ancho, alto, cm, bPixeles, 0, ancho);
} else {
// Imagen de 24 bits
iPixeles = new int[ancho * alto];
for (int j = 0; j < alto; j++) {
int iDatos = 0;
for (int i = 0; i < ancho; i++) {
iPixeles[iImagen] = 0xff000000 |
pegarBytes(bBMP, offset+iDatos, 3);
// El pixel esta almacenado en tres bytes
iDatos += 3;
iImagen++;
}
// Se regresa a la lnea anterior
offset -= tamaoLinea;
}
// El modelo de color es el predefinido
cm = ColorModel.getRGBdefault();
// Se crea la imagen
mImagen = new MemoryImageSource(ancho, alto, cm, iPixeles, 0, ancho);
}

Rafael Rivera Lpez

Graficacin
imagen = Toolkit.getDefaultToolkit().createImage(mImagen);
}
public Image getImagen() {
return imagen;
}
public void setImagen(Image imagen) {
this.imagen = imagen;
}
public byte[] getbPixeles() {
return bPixeles;
}
public void setbPixeles(byte[] bPixeles) {
this.bPixeles = bPixeles;
}
public int[] getiPixeles() {
return iPixeles;
}
public void setiPixeles(int[] iPixeles) {
this.iPixeles = iPixeles;
}
public int getTamaoLinea() {
return tamaoLinea;
}
public void setTamaoLinea(int tamaoLinea) {
this.tamaoLinea = tamaoLinea;
}
public int getRelleno() {
return relleno;
}
public void setRelleno(int relleno) {
this.relleno = relleno;
}
public ColorModel getCm() {
return cm;
}

public void setCm(ColorModel cm) {


this.cm = cm;
}

Rafael Rivera Lpez

Graficacin
Ejemplo del uso de las clases para menejar BMP
Clase VistaBMP
package vistabmp;
import bmp.*;
public class VistaBMP {

public static void main(String[] args) {


BMP bmp = new BMP(); //MODELO
VentanaBMP f = new VentanaBMP();
PanelBMP panel = new PanelBMP(bmp);
OyenteBMP oyente = new OyenteBMP(bmp,f);
f.setSize(800, 600);
f.setLocation(100, 50);
f.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
f.addEventos(oyente);
f.setContentPane(panel);
f.setVisible(true);
}

Clase VentanaBMP
package vistabmp;
public class VentanaBMP extends javax.swing.JFrame {
public VentanaBMP() {
initComponents();
}
public void addEventos(OyenteBMP oyente){
opcionAbrir.addActionListener(oyente);
opcionSalir.addActionListener(oyente);
}
private void initComponents() {
barraMenu =
menuArchivo
opcionAbrir
separador =
opcionSalir

new javax.swing.JMenuBar();
= new javax.swing.JMenu();
= new javax.swing.JMenuItem();
new javax.swing.JPopupMenu.Separator();
= new javax.swing.JMenuItem();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
menuArchivo.setMnemonic('A');

Rafael Rivera Lpez

Graficacin
menuArchivo.setText("Archivo");
opcionAbrir.setAccelerator(
javax.swing.KeyStroke.getKeyStroke(
java.awt.event.KeyEvent.VK_O,
java.awt.event.InputEvent.CTRL_MASK));
opcionAbrir.setIcon(new javax.swing.ImageIcon(
getClass().getResource(
"/imagenes/Folder-document-open-icon.png"))); // NOI18N
opcionAbrir.setMnemonic('A');
opcionAbrir.setText("Abrir");
opcionAbrir.setName("abrir"); // NOI18N
menuArchivo.add(opcionAbrir);
menuArchivo.add(separador);
opcionSalir.setAccelerator(
javax.swing.KeyStroke.getKeyStroke(
java.awt.event.KeyEvent.VK_Q,
java.awt.event.InputEvent.CTRL_MASK));
opcionSalir.setIcon(new javax.swing.ImageIcon(
getClass().getResource(
"/imagenes/Actions-session-exit-icon.png"))); // NOI18N
opcionSalir.setMnemonic('S');
opcionSalir.setText("Salir");
opcionSalir.setName("salir"); // NOI18N
menuArchivo.add(opcionSalir);
barraMenu.add(menuArchivo);
setJMenuBar(barraMenu);
pack();
}// </editor-fold>
// Variables declaration - do not modify
private javax.swing.JMenuBar barraMenu;
private javax.swing.JMenu menuArchivo;
private javax.swing.JMenuItem opcionAbrir;
private javax.swing.JMenuItem opcionSalir;
private javax.swing.JPopupMenu.Separator separador;
// End of variables declaration
}

Clase PanelBMP
package vistabmp;
import bmp.*;
import java.awt.*;

Rafael Rivera Lpez

Graficacin
import javax.swing.*;
public class PanelBMP extends JPanel{
private final BMP bmp;
public PanelBMP(BMP bmp){
this.bmp = bmp;
setBackground(Color.CYAN);
}

@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
bmp.dibujar(g);
}

Clase OyenteBMP
package vistabmp;
import
import
import
import

bmp.BMP;
java.awt.event.*;
javax.swing.*;
javax.swing.filechooser.*;

public class OyenteBMP implements ActionListener {


private BMP bmp;
private final JFrame frame;
public OyenteBMP(BMP bmp,JFrame frame){
this.bmp = bmp;
this.frame = frame;
}
@Override
public void actionPerformed(ActionEvent e) {
String origen = ((JComponent) e.getSource()).getName();
switch (origen) {
case "abrir":
abrirArchivo();
break;
case "salir":
System.exit(0);
}
}

Rafael Rivera Lpez

Graficacin

public void abrirArchivo() {


JFileChooser seleccion = new JFileChooser();
FileNameExtensionFilter filtro =
new FileNameExtensionFilter("Archivos BMP","BMP");
seleccion.setFileFilter(filtro);
int opcion = seleccion.showOpenDialog(frame);
if (opcion == JFileChooser.APPROVE_OPTION) {
String nombreBMP = "" + seleccion.getSelectedFile();
bmp.cargarBMP(nombreBMP);
frame.repaint();
}
}

Rafael Rivera Lpez

You might also like