6.- APLICACIÓN DESARROLLADA

Anuncio
6.- APLICACIÓN DESARROLLADA
A lo largo de este capítulo se procederá a realizar la descripción
de la aplicación desarrollada. El objetivo principal es desarrollar un
programa que se ejecute en el cliente, intentando adaptarlo lo máximo
posible al servidor de vídeo ya existente, para facilitar el trabajo. La
explicación se ha estructurado en varias partes: una primera parte en la
que se va a explicar la estructura con la que se diseñó el servidor de
video (necesario para entender el funcionamiento del conjunto), una
segunda parte donde se va a comentar la programación de la interfaz de
usuario del servidor, una tercera parte correspondiente a la realización
de la captura de imágenes y finalmente la parte correspondiente al
cliente del servidor de video, que establecerá conexiones y mostrará las
imágenes por pantalla.
6.1.- Estructura del servidor
La programación del servidor de video se ha realizado utilizando el
lenguaje de programación Java, y con una estructura orientada a
objetos. En el diseño del servidor, se distinguieron cuatro partes
fundamentales y claramente diferenciadas entre ellas:
•
La programación de la interfaz gráfica de usuario (GUI), que se ha
realizado utilizando AWT y Swing.
•
La programación de un servidor web que esté a la escucha de
peticiones de conexión, sirva una pagina web desde la que el
cliente decida que es lo que quiere hacer, y le proporcione al
servidor los datos necesarios para la transmisión.
•
La programación de la parte correspondiente a la captura,
preparación y transmisión de las imágenes video hasta el cliente.
•
La parte correspondiente a la captura de imágenes en diferentes
formatos utilizando la API JIMI, proporcionada por Sun
Microsystems.
Para nuestro proyecto sólo utilizaremos tres de ellas; la interfaz
gráfica, necesaria para poder configurar y poner en marcha el
servidor de vídeo; el servidor web, al que haremos las peticiones
mediante conexiones HTTP (no mediante un navegador específico,
sino
realizando
conexiones
independientes)
y
la
parte
correspondiente a la captura de imágenes usando JIMI. Esto es así
porque sólo llevaremos a cabo la transmisión de imágenes estáticas
(y no de vídeo en tiempo real). Además, será necesario un programa
que se ejecutará en el cliente, que establecerá dichas conexiones
compatibles con este servidor y que mostrará por pantalla las
imágenes capturadas y recibidas.
A través de la interfaz gráfica de usuario (GUI) se tiene el control
del servidor y se muestra una interfaz más amigable para el usuario del
servidor que una interfaz de texto. Desde la misma, tendremos que
configurar algunos aspectos, como el dispositivo de captura, el
directorio de trabajo, etc. Además, podremos poner en marcha o detener
el servidor desde estos menús que comentaremos más adelante.
Como se ha comentado, el servidor va a estar esperando
conexiones desde un navegado Web, para lo se ha tenido que
implementar un servidor Web para que esté a la escucha de las
distintas peticiones y las atienda sirviéndoles un página Web desde la
que el cliente podrá seleccionar la operación que desea realizar
(visualización del video o captura de imágenes en distintos formatos).
Figura 6-1: Conexiones HTTP cliente / servidor
Esta es la idea inicial de este servidor, ya que estaba pensado
para funcionar con PC's como clientes; de hecho, podríamos haberlo
usado así también y acceder al servidor a través de un navegador web
desde nuestro dispositivo portátil compatible con CDC. Sin embargo,
hemos optado por variar el planteamiento y establecer conexiones HTTP
independientes desde el programa que se ejecutará en el cliente.
Cuando el cliente solicita una captura de imagen, en el servidor
entra en funcionamiento la parte correspondiente a Jimi, realizando
una captura del la imagen de video y procesándola; el cliente establece
una conexión HTTP con la URL correspondiente a dicha captura, lee la
imagen del flujo HTTP y la almacena en un fichero local que
posteriormente se usará por el applet para mostrar la imagen
correspondiente por pantalla en nuestro dispositivo móvil.
Además, también es posible solicitar la transmisión de una
imagen almacenada en el sistema de ficheros del servidor, en cualquier
formato de los admitidos.
6.2.- La interfaz gráfica de Usuario (GUI)
La interfaz gráfica de usuario ha sido programada utilizando
Swing y AWT, y consta de una ventana principal que nos muestra tres
menús desplegables desde los que se controla todo el servidor de video.
Cuando el servidor está sin iniciar su funcionamiento, se verá
esto:
Figura 6-2: Servidor antes de su funcionamiento
Cuando se inicia el funcionamiento del servidor, aparece una
ventana en la que se muestra la imagen de video que se obtiene del
dispositivo (en nuestro caso una cámara web) y desde la cual se van a
realizar las capturas de las imágenes solicitadas por el cliente.
Figura 6-3: Servidor en funcionamiento
Los menús desplegables que se encuentran son:
•
Menú Configuración, en el que se muestra una única opción, que
es la de configurar el servidor de video. Se puede seleccionar esta
opción con la combinación de teclas Ctrl-C.
Figura 6-4: Menú configuración
Los parámetros que debemos configurar en el servidor de
video, para su correcto funcionamiento, son cinco:
o Dispositivo de Video, donde se debe seleccionar el dispositivo
de video que vamos a utilizar para capturar el video que
queremos transmitir.
o Puerto, donde se debe indicar el número de puerto por el que
va a estar escuchando el servidor Web las peticiones de
conexión.
o Formato de Video, donde se debe indicar el formato en el que
queremos que esté el video que vamos a transmitir. Los
formatos permitidos, así como sus características se
encuentran en la tabla x.
o Directorio de trabajo, donde se debe indicar el directorio de
trabajo del servidor. En este directorio deberá estar la página
Web que se va a servir a los clientes, así como el applet que se
ejecutará en el cliente cuando se solicite la transmisión de
video.
o Nombre del archivo que contiene la página Web que se va a
mostrar a los clientes.
Formato
Tipo de
Contenido
Calidad de
Imagen
Requisitos
de CPU
Ancho de
Banda
Necesario
RGB
AVI
Alta
Medio
Alto
Medio
Medio
Bajo
Alto
Alto
Alto
QuickTime
RTP
AVI
H.263
QuickTime
RTP
AVI
JPEG
QuickTime
RTP
Tabla 6-1: Formatos de imágenes
La figura siguiente nos muestra una captura del diálogo de
configuración del servidor.
Figura 6-5: Configuración del servidor
•
Menú Acciones, en el que se muestran tres posibles acciones,
Iniciar, Detener y Salir.
Figura 6-6: Menú acciones
o Iniciar, que si se pincha sobre ella, el servidor comenzará a
escuchar las peticiones de conexión, así como a mostrar la
señal de video que se transmitirá. Si el servidor de video no fue
configurado con anterioridad, al seleccionar esta acción, se
mostrará un mensaje de error, indicando que primero se debe
configurar el servidor. Se puede seleccionar esta opción con la
combinación de teclas Ctrl-I.
Figura 6-7: Error por no configuración
o Detener, con la que se detiene el funcionamiento del servidor.
Se puede seleccionar esta opción con la combinación de teclas
Ctrl-D.
o Salir, con la que se cierra la aplicación. Se puede seleccionar
esta opción con la combinación de teclas Ctrl-S.
•
Menú Ayuda, en el que se encuentra la información del servidor
en dos posibles acciones.
Figura 6-8: Menú ayuda
o Ayuda Servidor, con la que se muestra un pequeño diálogo con
información básica del funcionamiento del servidor de video.
Se puede seleccionar esta opción con la combinación de teclas
Ctrl-A.
Figura 6-9: Ayuda del servidor de video
o Sobre..., con la que se muestra un diálogo con los créditos del
servidor de video (desarrollado por un compañero en un PFC
anterior):
Figura 6-10: Créditos
6.3.- Descripción del servido Web utilizado
El servidor para captura de imágenes y video, va a constar de un
servidor Web estándar que acepte peticiones de los clientes desde un
navegador Web. El servidor Web se ha implementado de forma que
cumpla el protocolo HTTP, aunque se le ha añadido una funcionalidad
más para aceptar las peticiones de captura de imágenes por parte de los
clientes.
El servidor Web implementado, estará ejecutando en un hilo
distinto al principal e irá atendiendo las peticiones de los distintos
clientes.
No se considera importante ahondar en la implementación del
mismo; simplemente comentar que el programa cliente realizará
peticiones con el formato adecuado (que se explica en el siguiente
apartado) que establecerán conexiones con el servidor Web para "leer"
las imágenes del flujo HTTP.
Figura 6-11: Servidor Web utilizado
6.4.- Captura y tratamiento de imágenes
6.4.1.- El formato de las peticiones
Como ya se ha comentado en puntos anteriores, las peticiones de
captura de imágenes se realizan mediante peticiones que atiende el
servidor Web que se ha implementado. En concreto estableceremos
conexiones HTTP con el mismo, por lo que es necesario establecer un
formato específico para dichas peticiones y hacer posible la
comunicación cliente / servidor.
Dentro de la petición se pueden indicar los parámetros de la
imágen con los que se quiere que se realice la captura. Los parámetros
que se pueden modificar son:
•
Formato de la imagen. Se le puede indicar el formato en el que
se desea que se desea que se reciba la imagen. Según el formato
pedido, se tendrán parámetros adicionales que se permiten
modificar. Los formatos que se permiten son:
o JPEG, en el que se puede configurar la calidad que se
desea que tenga la imagen.
o PNG, en el que se puede configurar el nivel de compresión
que se desea que tenga la imagen.
o BMP, que no tiene ningún otro parámetro configurable.
•
Escala de grises. Se le puede indicar al servidor si se desea una
captura de imagen en escala de grises.
•
Tamaño de la imagen.
Para que el servidor Web implementado acepte estas peticiones,
deben tener un formato determinado. La petición de la captura de la
imagen debe comenzar por un signo de interrogación cerrado y a
continuación se deben indicar los parámetros que se quieren modificar
en la captura de la imagen separados por signos de interrogación
cerrados.
http://direcciónIP:puerto/?parámetro1?parámetro2?...?
Los parámetros que se quieren modificar tienen que indicarse con
el siguiente formato:
•
Formato de la imagen. Para indicar el formato de la captura de la
imagen se debe utilizar el comando “format=” seguido del valor
que se desee, siendo los valores posibles:
o “jpg” o “jpeg” para indicar que se desea una imagen en
formato JPEG.
o “png” para indicar que se desea una imagen en formato
PNG.
o “bmp”para indicar que se desea una imagen en formato
BMP.
•
Escala de grises. Para indicar que se desea una imagen en escala
de grises se debe utilizar el comando “gray”.
•
Tamaño de la imagen. Para indicar que se desea cambiar el
tamaño de la imagen pedida, se debe utilizar el comando
“resize=” seguido de los valores nuevos valores para el tamaño de
la imagen separados por un asterisco.
•
Calidad de la imagen en formato JPEG. Para indicar la calidad se
debe utilizar el comando “quality=” mas un valor entre cero y
cien. Si no se especifica, tendrá un valor por defecto de cincuenta.
•
Nivel de compresión de la imagen en formato PNG. Para indicar el
nivel de compresión se debe utilizar el comando “comp=” seguido
del valor de compresión. Tendremos tres valores posibles:
o “none” que indica que no se desea compresión.
o “max” que indica que se desea el nivel de compresión máximo.
o “def” que indicar que se use el nivel de compresión por defecto.
Si no se indica este parámetro no se comprimirá la imagen.
Unos ejemplos de peticiones pueden ser:
•
?format=jpeg?, que proporciona una imagen en formato JPEG y
con los valores con los que se realizó la captura.
•
?format=png?resize=800*600?comp=none?, que proporciona una
imagen en formato PNG con un tamaño de 800x600 y sin
compresión.
•
?format=bmp?resize=220*260?gray?, que proporciona una imagen
en formato BMP con un tamaño de 220x260 y en escala de grises.
6.5.- El cliente de vídeo
Se trata de la aplicación propiamente dicha de este Proyecto Fin
de Carrera. Está programado usando el Personal Profile de la
configuración CDC de la plataforma de Java J2ME. Consta de dos
partes principales: el programa que establece la conexión con el
servidor y recibe la imagen solicitada, y la applet que muestra la imagen
capturada por pantalla. A continuación comentaremos ambos subprogramas por separado.
6.5.1.- La Clase Client
Es la clase que incluye el método principal main(String argc[]), que
comprueba que la petición proporcionada por la línea de comandos es
correcta, y si es así llama primero al método que establecen la URL
adecuada a la que pedir la imagen, y luego al que establece la conexión
con dicha dirección y lee la imagen del flujo HTTP, almacenándola en
un fichero local.
Clase Client
package pfc;
import java.io.*;
public class Client{
public static void main(String args[]) {
Connection con = new Connection();
Petition pet = new Petition();
String url = null;
String param[] = null;
String format = null;
// Comprobamos que la ejecución por línea de comandos es correcta;
// si no es así, se indica la forma correcta.
if(args.length!=5){
System.out.println("Forma de uso: ./cvm pfc/Client 1_IP
2_fichero(o_'cam')
3_formato_img('jpeg','png','bmp')
4_gris(si/no)
5_resolucion(x*y/no)");
//Si es correcta, creamos la URL y establecemos la conexión
}else{
format = args[2];
param = args;
url=pet.createURL(param);
System.out.println("Estableciendo conexion con el servidor para
obtener imagen de formato ."+format);
System.out.println(url);
con.stablishConnection(url);
}
}
}
Los atributos de esta clase son los siguientes:
•
con, que es un objeto de la clase Connection, para llamar al
método que establecerá la conexión HTTP.
•
pet, que es un objeto de la clase Petition, para llamar al método
que creará la URL adecuada según la petición obtenida por la
línea de comandos.
•
url, que es un objeto de la clase String para almacenar la URL
devuelta por el método anterior.
•
param, que es un array de objetos de la clase String, que será
una copia de los parámetros obtenidos por la línea de comandos
para poder manejarlos para crear la URL.
Atributos de la clase Client
Connection con = new Connection();
Petition pet = new Petition();
String url = null;
String param[] = null;
El formato de la ejecución por la línea de comandos, por tanto,
es el siguiente:
./cvm pfc/Client 1_IP 2_fichero(o_'cam') 3_formato_img('jpeg','png','bmp')
4_gris(si/no) 5_resolucion(x*y/no)
donde cada uno de los parámetros representa lo siguiente:
•
./cvm pfc/Client -> es la ejecución bajo la C virtual machine de
la clase Client dentro del paquete pfc.
•
1_IP -> dirección IP del servidor Web al que vamos a solicitar las
imágenes.
•
2_fichero(o_'cam') -> nombre del archivo del sistema de ficheros
del servidor que queremos obtener, o bien la palabra cam si lo
que deseamos es una captura del dispositivo de vídeo conectado
al mismo (en nuestro caso, una web cam).
•
3_formato_img('jpeg','png','bmp') -> formato deseado de la
imagen que estamos solicitando, a elegir entre los 3 que se
indican.
•
4_gris(si/no) -> para decir si queremos que la imagen obtenida
sea en escala de grises o no.
•
5_resolución(x*y/no) -> indicar una resolución determinada
(800*600, por ejemplo) si queremos un redimensionado de la
imagen, o la palabra no si queremos el tamaño predeterminado.
Una vez comprobado que el número de parámetros es el correcto,
se pasa al procesado de la URL correspondiente en función de dichos
elementos y a establecer la conexión.
6.5.2.- La Clase Petition
Se trata de la clase que, en función de los parámetros
proporcionados por el usuario por la línea de comandos, crea y devuelve
una URL con el formato adecuado para que sea interpretada por el
servido Web que usaremos.
Los parámetros de esta clase son los siguientes:
•
IP, una cadena de caracteres donde se almacena la IP del servidor
y que es proporcionada por la línea de comandos.
•
name, otra cadena que guarda el nombre del archivo, en caso de
que no queramos una captura de la web cam.
•
format, un tercer String que almacenará el formato de la imagen
solicitada.
•
http, una cadena de caracteres auxiliar para crear la URL final.
•
gray, un objeto de la clase String que almacenará la petición del
usuario respecto a la obtención de la imagen en escala de grises o
no.
•
size, una cadena para almacenar el valor de las dimensiones de
la imagen solicitada por el usuario.
•
size_aux, un nuevo String auxiliar para conformar la URL.
•
url, cadena de caracteres que almacenará la dirección completa a
la que debemos conectarnos.
Atributos de la clase petition
String
String
String
String
String
String
String
String
IP = null;
name = null;
format = null;
http = "http://";
gray = null;
size = null;
size_aux = "resize=";
url = null;
6.5.2.1.- El método createURL(String param[])
Es un método que recibe un array de cadenas de caracteres que
no es más que una copia del array que obtiene el método main por la
línea de caracteres. Lee cada uno de dichas cadenas y en función de
sus valores establece la URL con el formato adecuado a las peticiones
que admite nuestro servidor Web.
Método createURL(String param[])
public String createURL(String param[]){
IP = param[0];
name = param[1];
format = param[2];
gray = param[3];
size = param[4];
if (name.compareTo("cam")==0){
name="?format=";
format=format.concat("?");
if (gray.compareTo("si")==0){
gray="gray?";
}else{
gray="";
}
if (size.compareTo("no")!=0){
size=size_aux.concat(size.concat("?"));
}else{
size="";
}
}
else{
name=name.concat(".");
gray="";
size="";
}
url = http.concat(IP).concat("/").concat(name).concat(format) /
.concat(gray).concat(size);
return(url);
}
6.5.3.- La Clase Connection
Es la clase que va a establecer la conexión con el servidor Web, va
a leer la imagen solicitada del flujo HTTP y la almacenará en un fichero
para su posterior visionado mediante una applet.
Los atributos de esta clase son los siguientes:
•
hc, un objeto de la clase HttpConnection, que será el encargado
de abrir la conexión con la URL determinada.
•
in, objeto de la clase DataInputStream, para leer los bytes que
contienen la información de la imagen del flujo HTTP.
•
fos, objeto de la clase FileOutputStream, para almacenar dichos
bytes en un fichero.
•
file, una cadena de caracteres que almacena el nombre del
archivo en el que se guardará la imagen.
Atributos de la clase Connection
HttpConnection hc = null;
DataInputStream in = null;
FileOutputStream fos=null;
String file = new String("prueba");
6.5.3.1.- El método stablishConnection(String url)
Método que recibe como parámetro el String que almacena una
determinada url, establece la conexión http con la misma, lee la imagen
y la almacena en un fichero.
Lo primero que hace este método es abrir la conexión, definir un
array de bytes y se obtiene la longitud en bytes de la imagen:
Establecimiento de la conexión
public void stablishConnection(String url){
try {
hc = (HttpConnection)Connector.open(url);
int length = (int)hc.getLength();
byte[] data = null;
A continuación, lee la imagen byte a byte mediante el objeto de la
clase DataInputStream, y almacena dichos bytes en el array data:
Lectura de la imagen en bytes
if (length != -1) {
data = new byte[length];
in = new DataInputStream(hc.openInputStream());
for (int i = 0, n = length; i<n; i++)
{
data[i] = (byte)in.read();
}
}
else {
// Si no es dada la longitud, leemos los datos a trozos.
int chunkSize = 512;
int index = 0;
int readLength = 0;
in = new DataInputStream(hc.openInputStream());
data = new byte[chunkSize];
do {
if (data.length < index + chunkSize) {
byte[] newData = new byte[index + chunkSize];
System.arraycopy(data, 0, newData, 0, data.length);
data = newData;
}
readLength = in.read(data, index, chunkSize);
index += readLength;
} while (readLength == chunkSize);
length = index;
}
Se informa por pantalla del éxito de la transmisión y se almacena
la imagen en un fichero:
Almacenamiento de los datos en un archivo
System.out.println("Fin de la transmision");
fos = new FileOutputStream(file);
fos.write(data);
Finalmente, se cierran los flujos abiertos una vez los dejamos de
usar:
Cierre de flujos
finally {
try {
if (in != null) in.close();
if (hc != null) hc.close();
if (fos!= null) fos.close();
}catch (IOException ioe) {}
}
6.5.4.- La Clase ImageLoader
Por ultimo, tenemos la clase que muestra la imagen por pantalla,
que no es más que una simple applet que crea la imagen desde el
archivo almacenado anteriormente:
Los atributos de esta clase:
•
toolkit, objeto de la clase Toolkit para crear la imagen a partir del
archivo correspondiente.
•
image, objeto de la clase Image que será la imagen creada a
partir de los datos obtenidos en la conexión anterior.
•
tracker, objeto de la clase MediaTracker, para controlar el
procesado de cada imagen.
Atributos de la clase ImageLoader
Toolkit toolkit;
Image image;
MediaTracker tracker = new MediaTracker(this);
6.5.4.1.- El método start()
Método que genera la imagen a mostrar por pantalla, comprueba
que su procesado es correcto con ayuda del objeto tracker, y llama a
repaint() para poder visionarla.
El método start() del applet
public void start() {
//crea la imagen desde el fichero "prueba"
toolkit = Toolkit.getDefaultToolkit();
image = toolkit.getImage("prueba");
// controla la correcta creación de la imagen y manda "pintar"
tracker.addImage(image,1);
try {
tracker.waitForID(1);
}catch (InterruptedException ie) {
System.out.println(ie);
}
repaint();
}
6.5.4.2.- El método paint(Graphics g)
Método que muestra la imagen creada por pantalla, además de
pintar el fondo de la misma de líneas rojas horizontales.
El método paint(Graphics g) del applet
public void paint(Graphics g) {
Dimension d = getSize();
// Dimensiones de la imagen a dibujar
int w = image.getWidth(this);
int h = image.getHeight(this);
//Fondo de líneas rojas horizontales
g.setColor(Color.red);
for (int i = 2; i < d.height; i += 4) {
g.drawLine(0,i,d.width,i);
}
// Dibuja la imagen
g.drawImage(image,0,0,w,h,0,0,w,h,this);
}
6.5.4.3.- Archivo HTML necesario para visionar el Applet
El applet anterior tiene que estar contenido en un archivo HTML
para poder ser visionado, bien mediante un navegador web, bien
mediante un AppletViewer. El código HTML de dicho archivo es el
siguiente:
Archivo HTML que contiene el Applet
<html>
<head>
<meta name="Author" content = "David Alvarez Suarez">
<title>Applet que muestra la captura de la imagen</title>
</head>
<body>
<applet code="ImageLoader.class" width="800" height="300">
</applet>
</body>
</html>
Descargar