09 noviembre, 2012

Seleccion de área de una imágen con Java

De vez en cuando se necesita que el usuario seleccione un área de una imágen para darle tratamiento. Por ejemplo supongamos que tenemos un programa que almacena fichas de empleados y queremos que en cada ficha se almacene la foto del empleado.

Puede darse el caso de que las imágenes vengan en distinto tamaño, por lo que es útil proporcionar una herramienta que permita la selección de una determinada área de la imágen para su almacenamiento.

El problema en si no es muy complejo. A grandes rasgos se resume en:

  • Determinar el punto de origen.
  • Determinar el área.
  • Seleccionar el área.


Para ello utilizaremos un JPanel que contendra la imágen, la cual estaŕa a su vez contenida en un BufferedImage, un MouseListener para detectar cuando el usuario presiona y suelta el boton del mouse y un MouseMotionListener para determinar cuando el usuario mueve el mouse para seleccionar el área.

Supongamos que el usuario hace clic en un punto de la imagen que llamaremos pi(xi, yi) y arrastra el mouse hasta un punto que llamaremos pf(xf, yf).

El primer paso consiste en determinar al ancho y alto del área abarcada por el arrastre del mouse.

      ancho = Math.abs(xi - xf);
    alto = Math.abs(yi - yf);


Luego obtenemos una imagen con el área seleccionada. Para ello utilizaremos el metodo getSubimage() de BufferedImage.

     BufferedImage seleccion = imagen.getSubimage(x, y, ancho, alto);

Para crear el efecto de opacidad de fondo y seleccion más clara, dibujaremos primero la imagen aplicando un filtro que reduce en un 50% el color. Para ello usaremos RescaleOp.

BufferedImageOp op = new RescaleOp(new float[]{0.5f, 0.5f, 0.5f}, new float[]{0f, 0f, 0f}, null);

Finalmente sobrecargamos el metodo paintComponent() del JPane para que se dibuje la imagen y el área seleccionada.

@Override
public void paintComponent(Graphics gr) {
   Graphics2D g = (Graphics2D) gr;
   super.paintComponent(g);
   if (imagen == null) {
       return;
   }
   if (puntoInicial != null && puntoFinal != null) {
       g.drawImage(imagen, op, 0, 0);
       g.drawImage(getImagenSeleccionada(), x, y, this);
       g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,         RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
       g.setColor(Color.WHITE);
       g.drawRect(x, y, ancho, alto);
       g.drawString("Área: " + ancho + "x" + alto, 10, 20);
   } else {
       g.drawImage(imagen, 0, 0, this);
   }
}


La verdad, es que el tema quiza sea un poco más complejo, porque debemos cuidarnos de que los puntos esten dentro de la imágen. También podríamos forzar a seleccionar un área siempre cuadrada o bien un rectángulo libre.

El código es largo y la verdad me da flojera escribirlo todo aca, por eso los ejemplos resumidos.

Por lo mismo, en este enlace se puede descargar el código fuente del Selector de Área de Imágen y un Jframe con el ejemplo de uso para que puedas incluirlo en tu programa. Cualquier comentario, observación y correción del código es bienvenida.



24 octubre, 2012

Modulador de Ancho de Pulso (PWM) en Java

javaPWM.png


JavaPWM es una sencilla aplicación que permite convertir cualquier PC con un puerto serial en un modulador de ancho de pulso (PWM).

Existen en internet varios circuitos simples que permiten controlar un relé con el puerto serial. JavaPWM aprovecha esta característica y envia pulsos al puerto serial que pueden servir para controlar un relé u otro dispositivo similar. He aqui un esquemático simple para controlar un relé por medio del puerto serial:

(originalmente publicada en http://www.windmeadow.com/node/4)

Permite configurar el puerto, modo de operacion, ciclo de trabajo y frecuencia. Se puede trabajar con un pulso simple de duracion determinada o bien como un oscilador a la frecuencia indicada.

El ciclo de trabajo (duty cycle) puede variar entre 1 y 99%. 

En modo oscilador (continuo) la frecuencia puede variar entre 1 y 50 Hz.

En modo pulso, el pulso puede durar entre 1 y 100 segundos.

El modo "off/on" invierte el ciclo.

Requiere Java 6 o superior y la biblioteca rxtx correctamente instalada o configurada.

En ciertos casos puede dejar el puerto bloqueado. En linux se desbloquea eliminando el archivo Lock del puerto en /var/lock. En Windows no tengo idea como desbloquear un puerto.

Para descargar la aplicación clic aqui. Es totalmente gratuita!
El codigo fuente se puede descargar desde aca.

Si te sirve, te gusta o tienes alguna sugerencia, tu comentario es bienvenido.