UNIVERSIDAD EL BOSQUE FACULTAD DE ING.

ELECTRÒNICA CURSO DE JAVA PRESENTADO A: JUAN CARLOS DÌAZ PRESENTADO POR: JACKSON DAVID NIÑO Cod. 04170037

MANEJO AVANZADO DE IMÁGENES EN JAVA INTRODUCCION: El API de manejo avanzado de imágenes extiende la plataforma de Java (incluso el API de Java 2D ) permitiendo una imagen sofisticada, alto rendimiento que procesa para ser incorporado en los programas de Java. El manejo avanzado de imagen de java es un juego de clases que proporcionan una funcionalidad de imagen más allá de Java 2D y de la Fundación de Java, aunque es compatible con esos API. El API de java avanzado de imagen lleva a cabo un juego de imagen del centro que procesa capacidades incluyendo imagen azulada, regiones de interés, hilando y la ejecución diferido. JAI también ofrece un juego de imagen del centro que procesa a operadores que incluyen a muchos puntos en común, área y operadores del dominio de la frecuencia. JAI encapsula los datos de la estructura de la imagen y las invocaciones del método remoto dentro de los datos de la imagen re-utilizables, permitiendo un archivo de la imagen, un objeto de imagen de red o los datos del real-tiempo que vierten para ser procesados idénticamente. JAI sigue una carrera de tiempo de la biblioteca modelo de java, mientras proporciona la independencia de la plataforma con el paradigma "escriba una vez, ejecute en cualquier parte." El imaging del cliente-servidor se apoya por vía de la plataforma de Java que está conectando a una red de computadoras y tecnologías de ejecución remotas. La ejecución remota es basada en Java RMI (método remoto de invocación). Esto permite que el código de Java en un cliente invoque las llamadas del método en objetos que residen en otra computadora sin tener que mover aquéllos objetos al cliente. JAI sigue un modelo objeto dónde las imágenes y operadores de imagen son definidas como objetos subclasificados fuera de un padre común. Un objeto del operador es el instanciado con uno o más fuentes de la imagen y otros parámetros. Este objeto del operador puede volverse una fuente de la imagen entonces para el próximo objeto del operador. Las conexiones entre los objetos definen el flujo de datos procesados. Pueden definirse los gráficos del editable resultantes de imagen que procesa los funcionamientos e instanciado como necesitado. JAI también proporciona un armazón extensible que permite agregar las soluciones personalizadas al central API. MANEJO AVANZADO DE IMÀGENES

Librería API 2D: El API 2D de Java contiene gráficos avanzados en dos dimensiones, texto, y capacidades de manejo de imágenes para los programas Java a través de la extensión del AWT. Este paquete soporta líneas artísticas, texto e imágenes, siendo flexible potente para desarrollar interfaces de usuario, programas de dibujo sofisticados y editores de imágenes. El API 2D de Java proporciona:
• • • • • •

Un modelo de renderizado uniforme para pantallas e impresoras. Gráficos primitivos geométricos, como curvas, rectángulos, y elipses y un mecanismo para renderizar virtualmente cualquier forma geométrica. Mecanismos para detectar esquinas de formas, texto e imágenes. Un modelo de composición que proporciona control sobre cómo se renderizan los objetos solapados. Soporte de color mejorado que facilita su manejo. Soporte para imprimir documentos complejos.

Las capacidades de procesado de imágenes de Java se encuentran recogidas en el paquete java.awt.image. Entre las mas importantes se pueden destacar: Interfaces: ImageProducer ImageConsumer. ImageObserver

Las clases que implementa el interfaz ImageProducer sirven como fuentes de pixels. Los métodos de estas clases pueden generar los pixels a partir de la pantalla, o puede interpretar cualquier otra fuente de datos, como un fichero GIF. No importa cómo genere los datos, el principal propósito de un productor de imágenes es proporcionar pixels a una clase ImageConsumer. Los productores de imágenes operan como fuentes de imágenes, y el modelo productor/consumidor que se sigue en el tratamiento de imágenes es el mismo que se utiliza en el modelo fuente/receptor de eventos. En particular, los métodos declarados en el interfaz ImageProducer hacen posible que uno o más objetos ImageConsumer se registren para mostrar su interés en una imagen. El productor de la imagen invocará a los métodos declarados en el interfaz ImageConsumer para enviar pixels a los consumidores de imágenes. Un productor de imágenes puede registrar muchos consumidores de sus pixels, de la misma forma que una fuente de eventos puede registrar múltiples receptores de sus eventos. En el interfaz ImageProducer hay varios métodos para manipular la lista de consumidores, por ejemplo para añadir nuevos consumidores interesados en los pixels del productor, o para eliminar consumidores de la lista.

El interfaz ImageConsumer declara métodos que deben ser implementados por las clases que reciben datos desde un productor de imágenes. El principal de estos métodos es setPixels(). void setPixels( int,int,int,int,ColorModel,byte[],int,int ) La clase ColorModel Dependiendo de cómo se quiera representar la imagen en pantalla, un solo pixel puede contener mucha información, o casi ninguna. Por ejemplo, si se quieren dibujar una serie de líneas del mismo color sobre un fondo de un color diferente, la única información que debe contener cada pixel es si debe estar encendido o apagado, es decir, que solamente sería necesario un bit de información para representar al pixel. En el otro extremo de la información que puede recoger un pixel se encuentran los gráficos complejos de los juegos de ordenador, que requieren 32-bits para representar un pixel individual. Estos 32 bits se dividen en grupos de cuatro octetos de bits, o bytes. Tres de estos grupos representan la cantidad de colores fundamentales: rojo, verde y azul, que forman parte del color del pixel; y el cuarto byte, normalmente conocido con byte alpha, se utiliza para representar la transparencia, en un rango de 0 a 255, siendo 0 la transparencia total y 255 la opacidad completa. En teoría, este formato permite la utilización de 16 millones de colores en cada pixel individual, aunque puede ser que el monitor o la tarjeta gráfica no sean capaces de visualizar electrónicamente tal cantidad de colores. Cada uno de los extremos se puede considerar como un modelo de color. En Java, un modelo de color determina cuántos colores se van a representar dentro del AWT. La clase ColorModel es una clase abstracta que se puede extender para poder especificar representaciones de color propias. Un modelo de color es necesario porque hay muchos métodos que reciben un array de bytes y convierten esos bytes en pixeles para su presentación en pantalla, es decir, convierten los bytes de datos en pixels visuales sobre la pantalla. Por ejemplo, con un modelo de color directo simple, cada grupo de cuatro bytes se podría interpretar como la representación de un valor del color de un pixel individual. En un modelo de color indexado simple, cada byte en el array se podría interpretar como un índice a una tabla de enteros de 32 bits donde cada uno de esos enteres representa el valor del color adscrito al pixel. El AWT proporciona tres subclases de ComponentColorModel y PackedColorModel. La clase IndexColorModel: Cuando se utilizan imágenes de alta resolución, se consume gran cantidad de memoria; por ejemplo, una imagen de dimensiones 1024x768, contiene 786.432 pixels individuales. Si se quieren representar estos pixels con sus cuatro bytes en memoria, se necesitarán 3.145.728 bytes de memoria para esta imagen. Para evitar este rápido descenso de memoria, se han incorporado varios esquemas de forma que las imágenes se puedan representar de forma razonable sin comprometer ColorModel: IndexColorModel,

demasiado el uso de memoria. Un esquema muy común consiste en localizar un pequeño número de bits para cada pixel (8 bits por ejemplo) y luego utilizar los valores de los pixels como un índice a una tabla de enteros de 32 bits que contenga el subconjunto de todos los colores que se utilizan en la imagen. Por ejemplo, si se utilizan ocho bits para representar un pixel, el valor del pixel se puede utilizar como índice a una tabla de contenga hasta 256 colores que se utilicen en la imagen. Estos 256 colores se pueden seleccionar entre los millones disponibles, conociéndose a este subconjunto como la paleta de colores de la imagen. La clase DirectColorModel: Esta clase se extiende a la clase PackedColorModel e implementa el formato completo de color de 32-bit, en el que cada pixel está formado por los cuatro bytes, representando el canal alpha y las cantidades de rojo, verde y azul que componen cada pixel La clase FilteredImageSource Esta clase es una implementación del interfaz ImageProducer que toma una imagen y un objeto de tipo ImageFilter para generar una nueva imagen que es una versión filtrada de la imagen original. Las operaciones de filtrado pueden realizar una gran variedad de operaciones, como son el desplazamiento y sustitución de colores, la rotación de imágenes, etc. La clase ImageFilter Esta clase es una implementación del interfaz ImageConsumer. Además de los métodos declarados en el interfaz, hay métodos para implementar un filtro nulo, que no realiza modificación alguna sobre los datos que se le pasan. Hay varias subclases que extienden esta clase base para permitir la manipulación de la imagen, como son RGBImageFilter, CropImageFilter, ReplicateScaleFilter y AreaAveragingScaleFilter. La clase MemoryImageSource Esta clase es una implementación del interfaz ImageProducer que utiliza un array de datos para generar los valores de los pixels de una imagen. Dispone de varios constructores que son:
• • • • • •

Ancho y alto en pixels de la imagen que va a ser creada, Modelo de color que se empleará en la conversión, si el constructor no requiere este parámetro, utilizará el modelo de color RGB por defecto Un array de bytes o enteros conteniendo los valores a ser convertidos en pixel según el modelo de color especificado Un offset para indicar el primer pixel dentro del array El número de pixels por línea en el array Un objeto de tipo Hashtable conteniendo las propiedades asociadas de la imagen, en caso de que la haya

En todos los casos, el constructor genera un objeto ImageProducer que se utiliza como un array de bytes o enteros para generar los datos de un objeto Image. Esta clase puede pasar múltiples imágenes a consumidores interesados en ellas, recordando a la funcionalidad multiframe que ofrece el formato gráfico GIF89a para producir animaciones. La clase PixelGrabber Esta es una clase de utilidad para convertir una imagen en un array de valores que corresponden a sus pixels. Implementa el interfaz ImageConsumer, que puede ser acoplado a un objeto Image o ImageProducer para realizar cualquier manipulación de esa imagen. METODOS PARA MANEJO DE IMÁGENES Métodos de Clipping Clipping es el proceso por el que se define la zona del contexto gráfico en la que se van a realizar las modificaciones de los subsiguientes procesos de dibujo. Cualquier pixel que se encuentre fuera del área de clipping permanecerá inmune a toda modificación. Los métodos que están involucrados son varios, unos que permiten fijar el rectángulo de clipping y otros que permiten obtener la zona de clipping actual. clipRect( int,int,int,int ), realiza la intersección del rectángulo de clipping actual con el formado por los parámetros que se pasan al método. Este método solamente se puede utilizar para reducir el tamaño de la zona de clipping, no para aumentarla. getClip(), devuelve la zona de clipping actual como un objeto de tipo Shape getClipBounds(), devuelve el rectángulo que delimita el borde de la zona de clipping actual. setClip (int,int,int,int ), fija el rectángulo de clipping actual al indicado en las cuatro coordenadas que se pasan como parámetro al método. Hay varias formas distintas para el método drawImage(), que difieren fundamentalmente en las posibilidades de manipulación del método y los parámetros que hay que pasar para realizar esas manipulaciones. La siguiente llamada es solamente representativa del grupo, que se verán posteriormente. drawImage( Image,int,int,int,int,int,int,int,int,Color,ImageObserver ), pinta sobre la zona indicada la imagen que se pasa como parámetro, escalándola sobre la marcha para que rellene completamente el área de destino. No obstante, antes de entrar en el desarrollo de los diferentes métodos drawImage(), quizá sea presentar la clase Color, que es relativamente simple de entender y utilizar. La clase Color

Esta clase es simple, encapsula los colores utilizando el formato RGB. En este formato, los colores se definen por sus componentes Rojo, Verde y Azul, representado cada uno de ellos por un número entero en el rango 0-255. En el caso del API Java2D, el espacio de color que se usa es el sRGB, un estándar del consorcio W3. Hay otro modelo de color llamado HSB (matiz, saturación y brillo). La clase Color proporciona métodos de conveniencia para poder realizar la conversión entre un modelo y otro sin dificultad. La clase Color proporciona variables estáticas finales que permiten el uso de cualquiera de los treinta colores, simplemente especificando su nombre. Para usar estas variables sólo es necesario referencias el color por su nombre de variable, por ejemplo objeto.setBackground( Color.red ); Los valores predefinidos para los colores en esta clase son los que se muestran en la siguiente lista, todos ellos en el espacio sRGB:
• • • • • • • • • • • • •

black, negro blue, azul cyan, azul celeste darkGray, gris oscuro gray, gris green, verde lightGray, gris claro magenta, violeta orange, naranja pink, rosa red, rojo white, blanco yellow, amarillo

Los constructores de esta clase son tres, dos de los cuales permiten instanciar un nuevo objeto de tipo Color indicando las cantidades de rojo, verde y azul que entran en su composición mediante valores enteros en el rango 0 a 255: Color( int,int,int ) El otro de los constructores que permite especificar la contribución de rojo, verde y azul al color final, admite valore flotantes en el rango 0.0 a 1.0: Color( float,float,float ) Y el tercer constructor admite solamente un número entero en el cual se especifica el valor RGB, de forma que la cantidad de color rojo que interviene en el color final está especificada en los bits 16-23 del argumento, la cantidad de verde en los bits 8-15 y la cantidad de azul en los bits 0-7. Color( int )

Métodos que devuelven un entero representando el valor RGB para un determinado objeto Color. getRed(), devuelve el componente rojo del color como un entero en el rango 0 a 255. getGreen(), devuelve la cantidad de verde que entra en la composición del objeto Color, en el rango 0 a 255. getBlue(), devuelve el componente azul del color con un entero en el rango 0 a 255. getRGB(), devuelve un entero representando el color RGB, utilizando los bits para indicar la cantidad de cada uno de los componentes rojo, verde y azul que entran en su composición. Los bits 24 a 31 del entero que devuelve el método son 0xff, los bits 16 a 23 son el valor rojo, los bits 8 a 15 son el valor verde y los bits 0 a 7 indican el valor del color azul. Siempre en el rango 0 a 255. Los siguiente métodos devuelven un objeto de tipo Color, de forma que se pueden utilizar para crear objetos de este tipo. brighter(), crea una versión más brillante del color. darker(), crea una versión más oscura del color. decode( String ), convierte una cadena a un entero y devuelve el color correspondiente. Los métodos que se indican a continuación, también devuelven un objeto de tipo Color, pero están especializados para trabajar con el sistema a través de la clase Properties. getColor( String ), busca un color entre las propiedades del sistema. El objeto String se utiliza como el valor clave en el esquema clave/valor utilizado para describir las propiedades en Java. El valor es entonces utilizado para devolver un objeto Color. getColor( String,Color ), busca un color entre las propiedades del sistema. El segundo parámetro es el que se devuelve en el caso de que falle la búsqueda de la clave indicada en el objeto String. getColor( String,int ), busca un color entre las propiedades del sistema. El segundo parámetro es utilizado para instanciar y devolver un objeto Color en el caso de que falle la búsqueda de la clave indicada en el objeto String. Los siguientes métodos se utilizan para realizar la conversión entre el modelo de color RGB y el modelo HSB. getHSBColor( float,float,float ), crea un objeto de tipo Color basado en los valores proporcionados por el modelo HSB. HSBtoRGB( float,float,float ), convierte los componentes de un color, tal como se especifican en el modelo HSB, a su conjunto equivalente de valores en el modelo RGB.

RGBtoHSB( int,int,int,float[] ), convierte los componentes de un color, tal como se especifican en el modelo RGB, a los tres componentes del modelo HSB. Y ya, los métodos que quedan son métodos de utilidad general, sin ninguna aplicación específica en lo que al Color respecta. equals( Object ), determina si otro objeto es igual a un color. hashCode(), calcula el código hash para un color. toString(), crea una cadena representando al color, indicando el valor de sus componentes RGB. El método drawImage(): Este método es el que se utiliza para presentar una imagen en pantalla; aunque hay métodos de otras clases que son utilizados para la manipulación de imágenes en Java, lo primero que se necesita es saber cómo se visualiza una imagen, y eso es lo que hace este método drawImage() de la clase Graphics. drawImage( Image,int,int,Color,ImageObserver ), pinta la imagen que se indica situando su esquina superior izquierda en la coordenada que se pasa, en el contexto gráfico actual. Los pixeles transparentes se pintan en el color de fondo que se indica. Esta operación es equivalente a rellenar un rectángulo del ancho y alto de la imagen dada con un color y luego pintar la imagen sobre él, aunque probablemente más eficiente. drawImage( Image,int,int,ImageObserver ), pinta la imagen que se indica situando su esquina superior izquierda en la coordenada que se pasa, en el contexto gráfico actual. Los pixeles transparentes de la imagen no se ven afectados. Este método retorna inmediatamente en todos los casos, incluso aunque la imagen completa no se haya terminado de cargar y no se haya presentado completamente en el dispositivo de salida. drawImage( Image,int,int,int,int,Color,ImageObserver ), pinta la imagen que se pasa dentro del rectángulo que se indica en los parámetros, escalando esa imagen si es necesario. El método retorna inmediatamente, aunque la imagen no se haya cargado completamente. Si la representación de la imagen en el dispositivo de salida no se ha completado, entonces drawImage() devuelve el valor false. drawImage( Image,int,int,int,int,ImageObserver ), pinta la imagen que se pasa dentro del rectángulo que se indica en los parámetros, escalando esa imagen si es necesario. El método retorna inmediatamente, aunque la imagen no se haya cargado completamente. Si la representación de la imagen en el dispositivo de salida no se ha completado, entonces drawImage() devuelve el valor false. El proceso que pinta las imágenes notifica al observador a través de su método imageUpdate(). drawImage( Image,int,int,int,int,int,int,int,int,Color,ImageObserver ). drawImage( Image,int,int,int,int,int,int,int,int,ImageObserver ). Ejemplo llamada a metodo:

public abstract boolean drawImage( Image img, int x, int y, int width, int height, ImageObserver observer ) Los parámetros del método son: img, la imagen que se quiere pintar x e y, coordenadas para posicionar la esquina superior izquierda de la imagen width y height, dimensiones del rectángulo sobre el que se posicionará la imagen observer, objeto que ha de ser notificado tan pronto como la imagen se haya convertido y situado en su posición En esta versión del método, la imagen se pintará dentro del rectángulo que se para en los parámetros y se escalará si es necesario. El método retorna inmediatamente, incluso aunque la imagen no se haya terminado de escalar o convertir al formato que admita el dispositivo de salida. Si esta conversión no se ha completado, drawImage() devuelve false, y como hay parte de imagen que no está procesada, el proceso que pinta la imagen notifica al observador a través de su método imageUpdate() y esa imagen continúa pintándose por trozos. El método imageUpdate() pertenece a la clase Component, cuando es llamado, encola una llamada a repaint(), permitiendo que se pinta un trozo más de imagen sin que se interfiera la tarea o hilo de control principal. Hay también una propiedad, awt.image.incrementaldraw que determina si la imagen puede ser pintada en piezas, tal como se ha indicado antes. El valor por defecto para esta propiedad es true, en cuyo caso el sistema va pintado trozos de imagen según van llegando. Si el valor es false, el sistema esperará a que la imagen esté completamente cargada antes de pintarla. Hay una segunda propiedad, awt.image.redrawrate que determina el período mínimo, en milisegundos, que debe haber entre llamadas a repaint() para imágenes. El valor por defecto es 100, y solamente se aplica cuando la propiedad anterior es true. Tanto esta propiedad como la anterior se pueden modificar, pero solamente sirve esa modificación para la ejecución actual del programa. De los parámetros que se pasan al método drawImage(), todos resultan obvios, excepto quizá, el último de ellos, observer, que se refiere al objeto que debe ser notificado cuando la imagen esté disponible. Cuando se realiza una llamada a drawImage(), se lanza una tarea que carga la imagen solicitada. Hay un observador que monitoriza el proceso de carga; la tarea que está cargando la imagen notifica a ese observador cada vez que llegan nuevos datos. Para este parámetro se puede utilizar perfectamente this como observador en la llamada a drawImage(); es más, se puede decir que cualquier componente puede servir como observador para imágenes que se pintan sobre él. Quizá sea este el momento

de entrar un poco más en detalle en la clase ImageObserver, e incluso antes en la clase Image, porque son los dos parámetros diferentes del típico entero que aparecen en la llamada a drawImage(). La clase Image: La clase Image, como cualquier otra, está formada por una serie de constantes o variables, constructores y métodos. Uno de estos métodos es getScaledInstance(), que devuelve una versión escalada de una imagen. Uno de los parámetros de este método es un valor entero que especifica el algoritmo a utilizar para la realización del escalado. Se puede utilizar cualquiera de ellos, la tabla siguiente muestra su nombre y una pequeña descripción, si el lector necesita más detalles, debe recurrir como siempre se recomienda, a la documentación del JDK. SCALE_AREA_AVERAGING, utiliza el algoritmo Area Averaging SCALE_FAST, utiliza un algoritmo que proporcione mayor rapidez en el escalado, a costa de la suavidad de realización de ese escalado SCALE_SMOOTH, al contrario que el anterior, sacrifica la velocidad por la suavidad de realización del escalado SCALE_REPLICATE, utiliza un algoritmo de los internos de la clase ReplicateScaleFilter SCALE_DEFAULT, utiliza el algoritmo de defecto UndefinedProperty, un objeto de este tipo debe ser retornado siempre que una propiedad no se encuentre definida para una determinada imagen. Esta propiedad no se utiliza para el escalado, sino que es utilizada como valor de retorno del método getProperties() para indicar que la propiedad solicitada no está disponible. Aunque la clase Image dispone de un constructor, es una clase abstracta, por lo que no se puede instanciar ningún objeto llamando directamente a este constructor. Se puede conseguir un objeto Image indirectamente por la invocación del método getImage() de las clases Applet o Toolkit. El método getImage() utiliza un hilo de ejecución, o tarea, separado para cargar la imagen. El resultado práctico de la invocación a getImage(), es la asociación entre una referencia de tipo Image y un fichero localizado en algún lugar que contiene la imagen que interesa. Otra forma de obtener un objeto Image es invocar al método createImage(), de las clases Component y Toolkit. La lista siguiente muestra una pequeña descripción de los métodos de la clase Image: flush(), libera todos los recursos que utiliza el objeto Image getGraphics(), crea un contexto gráfico para pintar una imagen en segundo plano getHeight( ImageObserver ), determina la altura de la imagen getWidth( ImageObserver ), determina la anchura de la imagen getProperty( String,ImageObserver ), obtiene una propiedad de la imagen por su nombre getScaledInstance( int,int,int ), crea una versión escalada de la imagen getSource(), devuelve el objeto que produce los pixeles de la imagen

Algunos de estos métodos se utilizarán en los ejemplos que se presentan. No obstante, el interés no debe centrarse solamente en la clase Image, sino también en las otras clases que se necesitan para instanciar los parámetros de llamada a estos métodos, e incluso, algunas otras clases de soporte general. Por ello, aún a costa de resultar un poco ladrillo, se presenta a continuación una pequeña revisión de las clases más interesantes, MediaTracker e ImageProducer, ya que sobre las clases String, ImageObserver, Graphics y Object, que son las que intervienen en los métodos de la clase Image, El interfaz ImageProducer: Se trata de un interfaz para objeto que pueden producir imágenes para la clase Image. Cada imagen contiene un ImageProducer que se utiliza en la reconstrucción de esa imagen cuando es necesario; por ejemplo, cuando se escala la imagen, o cuando se cambia la imagen de tamaño La clase MediaTracker: Esta es una clase de utilidad general diseñada para controlar el estado de los objetos de tipo media, que en teoría pueden ser tanto clips de sonido como cualquier otro objeto media, como es el caso de una imagen. Un objeto MediaTracker se utiliza a través de una instancia de la clase MediaTracker sobre el objeto Component que se quiere monitorizar, e invocando al método addImage() para cada una de las imágenes que se quiere controlar. A cada una de estas imágenes se puede asignar un identificador único, o también se puede asignar el mismo identificador a un grupo de imágenes. Este identificador controla el orden de prioridad en que se cargarán las imágenes, de forma que imágenes con un identificador bajo tienen preferencia sobre otras con identificador más alto. El identificador también se puede utilizar para identificar un conjunto único de imágenes. En otras palabras, asignando el mismo identificador a varias imágenes, se las puede manejar a la vez. Se puede determinar el estado de una imagen (o grupo de imágenes) invocando alguno de los distintos métodos sobre el objeto MediaTracker, pasándole como parámetro el identificador de la imagen (o grupo de imágenes). El objeto MediaTracker también se puede utilizar para bloquear la ejecución a la espera de la carga completa de una imagen (o grupo de imágenes. La clase MediaTracker proporciona cuatro constantes, que se utilizan como valores de retorno de algunos de los métodos de la clase y, tal como su nombre sugiere, indican el estado en que se encuentra una imagen dada. Estas constantes son las siguientes. ABORTED, la carga de la imagen (o cualquier media) ha sido abortada COMPLETE, realizara satisfactoriamente la carga completa ERRORED, se ha encontrado algún tipo de error en la carga LOADING, se está cargando la imagen (o cualquier media) Para esta clase solamente hay un constructor que pueda ser invocado a la hora de instanciar objetos que controlen el estado de algunas, o todas, las imágenes sobre un determinado componente.

MediaTracker( Component ): Un objeto MediaTracker tiene la posibilidad de controlar el estado de algunas, o todas, las imágenes que están siendo cargadas para el objeto Component que se ha pasado como parámetro a la hora de instanciar ese objeto MediaTracker. Los métodos siguientes se utilizan para crear y mantener esta lista de imágenes. Cuando se añade una imagen a la lista, hay que proporcionar un identificador numérico para esa imagen, que será luego el que sea utilizado por otros métodos para poder indicar el estado en que se encuentra una imagen determinada. addImage( Image,int ), incorpora una nueva imagen a la lista de imágenes que está siendo controlada por el objeto MediaTracker. addImage( Image,int,int,int ), incorpora una imagen escalada a la lista. removeImage( Image ), elimina la imagen indicada de la lista. removeImage( Image,int ), elimina la imagen que corresponde al identificador que se pasa como parámetro de la lista. removeImage( Image,int,int,int ), elimina la imagen que corresponde al ancho, alto e identificador, de la lista de imágenes. El objeto MediaTracker se puede utilizar para hacer que la tarea, o hilo de ejecución, se bloquee hasta que una o más imágenes de su lista haya completado su carga. Esto se consigue con los siguientes métodos. waitForAll(), inicia la carga de todas la imágenes controladas por el objeto MediaTracker; devuelve void. waitForAll( long ), inicia la carga de todas la imágenes, devolviendo true si todas las imágenes se han cargado y false en cualquier otro caso. waitForID( int ), inicia la carga de las imágenes que corresponden al identificador que se pasa; devuelve void. waitForID( int,long ), inicia la carga de las imágenes que corresponden al identificador que se pasa; devuelve true si todas las imágenes se han cargado y false en cualquier otro caso. Por supuesto, es posible utilizar métodos que no bloquean la tarea que carga las imágenes para comprobar el estado de una o más imágenes de la lista. Esto permite continuar haciendo el trabajo mientras las imágenes siguen cargándose. Estos métodos devuelven true o false para indicar si la carga es completa. La versión con el parámetro booleano comenzará la carga de cualquier imagen que no se esté cargando, en caso de que ese parámetro booleano sea true. La otra versión no iniciará la carga de ninguna imagen. Esta interpretación también es válida para el parámetro booleano de otros métodos de la clase que disponen de él.

checkAll() y checkAll( boolean ), comprueban si todas las imágenes que están siendo controladas por el objeto MediaTracker han finalizado la carga. checkID( int ) y checkID( int,boolean ), comprueban si todas las imágenes que corresponden al identificador especificado han concluido su carga. El hecho de que los métodos anteriores indiquen que la carga de las imágenes ha sido completa, no garantiza que esa carga esté libre de errores. Los siguiente métodos se utilizan para determinar si se ha producido algún problema durante la carga de las imágenes. getErrorsAny(), devuelve una lista de todas las imágenes (o cualquier media) en los que se ha producido un error en la carga. getErrorsAny( int ), devuelve una lista de todas las imágenes correspondientes a un determinado identificador, en los que se ha producido un error en la carga. isErrorAny(), comprueba el estado de error de todas las imágenes. isErrorID( int ), comprueba el estado de error de todas las imágenes correspondientes a un determinado identificador. Los dos siguientes métodos devuelven un valor entero formado por la operación OR entre los valores de estado de todas las imágenes que se requieren; en el primero de todas las que controla el objeto MediaTracker, y en el segundo de las que corresponden al identificador que se especifica. statusAll( boolean ) statusID( int,boolean )

GRAFICOS CON JAVA 2D

Imágenes El API 2D de Java implementa un nuevo modelo de imagen que soporta la manipulación de imágenes de resolución fija almacenadas en memoria. Una nueva clase Image en el paquete java.awt.image, se puede usar BufferedImage, para manipular datos de una imagen recuperados desde un fichero o una URL. Por ejemplo, se puede usar un BufferedImage para implementar doble buffer -- los elementos gráficos son dibujados fuera de la pantalla en el BufferedImage y luego son copiados a la pantalla a través de llamadas al método drawImage de Graphics2D. Las clases BufferedImage y

BufferedImageOp también permiten realizar una gran variedad de operaciones de filtrado de imágenes como blur. El modelo de imagen productor/consumidor proporcionado en las versiones anteriores del JDK sigue siendo soportado por razones de compatibilidad Sistema de Coordenadas El sistema 2D de Java mantiene dos espacios de coordenadas:
• •

El espacio de usuario es el espacio en que se especifican los gráficos primitivos. El espacio de dispositivo es el sistema de coordenadas para un diopositivo de salida, como una pantalla, una ventana o una impresora.

El espacio de usuario es un sistema de coordenadas lógicas independiente del dispositivo: el espacio de coordenas que usan nuestros programas. Todos los geométricos pasados a las rutinas Java 2D de renderizado se especifican en coordenadas de espacio de usuario. Cuando se utiliza la transformación por defecto desde el espacio de usuario al espacio de dispositivo, el origen del espacio de usuario es la esquina superior izquierda del área de dibujo del componente. La coordena X se incrementa hacia la derecha, y la coordena Y hacia abajo. El espacio de dispositivo es un sistema de coordenadas dependiente del dispositivo que varía de acuerdo a la fuente del dispositivo. Aunque el sistema de coordenas para una ventana o una pantalla podría ser muy distinto que para una impresora, estas diferencias son invisibles para los programas Java. Las conversiones necesarias entre el espacio de usuario y el espacio de dispositivo se realizan automáticamente durante el dibujado. Construir Formas Complejas desde Geométricos Primitivos Construir un área geométrica (CAG) es el proceso de crear una nueva forma geométrica realizando operaciones con las ya existentes. En el API Java 2D un tipo especial de Shape llamado Area soporta operaciones booleanas. Podemos construir un Area desde cualquier Shape . Area soporta la siguientes operaciones booleanas: Unión Subtracción

Intersección

Or-Exclusivo (XOR)

Ejemplo: Areas En este ejemplo, los objetos Area construyen una forma de pera partiendo de varias elipses.

Gráficos en 2 Dimensiones: El API 2D de Java permite fácilmente:
• • • •

Dibujar líneas de cualquier anchura Rellenar formas con gradientes y texturas Mover, rotar, escalar y recortar texto y gráficos. Componer texto y gráficos solapados.

Por ejemplo, se podria mostrar gráficos y charts complejos que usan varios estilos de línea y de relleno para distinguir conjuntos de datos, como se muestra en la siguiente figura:

El API 2D de Java también permite almacenar datos de imágenes--por ejemplo, se puede realizar fácilmente filtros de imágenes, como blur o recortado, como se muestra en la siguiente figura:

Formas 2D

Las clases del paquete java.awt.geom definen gráficos primitivos comunes, como puntos, líneas, curvas, arcos, rectángulos y elipses. Clases en el paquete java.awt.geom Arc2D Ellipse2D QuadCurve2D Area GeneralPath Rectangle2D CubicCurve2D Line2D RectangularShape Dimension2D Point2D RoundRectangle2D Excepto para Point2D y Dimension2D, cada una de las otras clases geométricas implementa el interface Shape, que proporciona un conjunto de métodos comunes para describir e inspeccionar objetos geométricos bi-dimensionales. Con estas clases se puede crear de forma virtual cualquier forma geométrica y dibujarla a través de Graphics2D llamando al método draw o al método fill. Por ejemplo, las formas geométricas del siguiente applet están definidas usando los geométricos básicos de Java 2D.

Formas Rectangulares Los primitivos Rectangle2D, RoundRectangle2D, Arc2D, y Ellipse2D descienden del RectangularShape, que define métodos para objetos Shape que pueden ser descritos por una caja rectángular. La geometría de un RectangularShape puede ser extrapolada desde un rectángulo que encierra completamente el exterior de la Shape.

QuadCurve2D y CubicCurve2D La clase QuadCurve2D nos permite crear segmentos de curvas cuadráticos. Una curva cuadrática está definida por dos puntos finales y un punto de control.

La clase CubicCurve2D nos permite crear segmentos de curvas cúbicos. Una curva cúbica está definida por dos puntos finales y dos puntos de control. Las siguientes figuras muestran ejemplos de curvas cuadráticas y cúbicas.

GeneralPath La clase GeneralPath permite crear una curva arbitraria especificando una serie de posiciones a lo largo de los límites de la forma. Estas posiciones pueden ser conectadas por segmentos de línea, curvas cuadráticas o curvas cúbicas. La siguiente figura puede ser creada con 3 segmentos de línea y una curva cúbica.

Areas Con la clase Area se realiza operaciones boolenas, como uniones, intersecciones y substracciones, sobre dos objetos Shape cualesquiera. Esta técnica, permite crear rápidamente objetos Shape complejos sin tener que describir cada línea de segmento o cada curva. Controlar la Calidad del Dibujo: Se puede usar el atributo 'rendering hint' de Graphics2D para especificar que los objetos sean dibujados tan rápido como sea posible o que se dibujen con la mayor calidad posible. Para seleccionar o configurar el atributo 'rendering hint' en el contexto, Graphics2D se puede construir un objeto RenderingHints y pasarlo dentro de Graphics2D.setRenderingHints. Si sólo se quiere seleccionar un hint, se llama a

Graphics2D. setRenderingHint y especificar la pareja clave-valor para el hint que se desea seleccionar. RenderingHints soporta los siguientes tipos de hints.
• • • • • • • •

Alpha interpolation--por defecto, calidad, o velocidad. Antialiasing--por defecto, on, u off Color rendering-por defecto, calidad, o velocidad Dithering--por defecto, activado o desactivado Fractional metrics--por defecto, on u off Interpolation--vecino más cercano, bilinear, o bicúbico Rendering--por defecto, calidad, o velocidad Text antialiasing--por defecto, on u off.

Renderizado en Java 2D El mecanismo de renderizado básico es el mismo que en las versiones anteriores del JDK, el sistema de dibujo controla cuándo y cómo dibuja un programa. Cuando un componente necesita ser mostrado, se llama automáticamente a su método paint o update dentro del contexto Graphics apropiado. El API 2D de Java presenta java.awt.Graphics2D, un nuevo tipo de objeto Graphics. Graphics2D desciende de la clase Graphics para proporcionar acceso a las características avanzadas de renderizado del API 2D de Java. Para usar las características del API 2D de Java, se forza el objeto Graphics pasado al método de dibujo de un componente a un objeto Graphics2D. public void Paint (Graphics g) { Graphics2D g2 = (Graphics2D) g; ... } Contexto de Renderizado de Graphics2D Al conjunto de atributos de estado asociados con un objeto Graphics2D se le conoce como Contexto de Renderizado de Graphics2D. Para mostrar texto, formas o imágenes, se configura este contexto y luego se llama a uno de los métodos de renderizado de la clase Graphics2D, como draw o fill . Cómo muestra la siguiente figura, el contexto de renderizado de Graphics2D contiene varios atributos. El estilo de lápiz que se aplica al exterior de una forma. Este atributo stroke nos permite dibujar líneas con cualquier tamaño de punto y patrón de sombreado y aplicar finalizadores y decoraciones a la línea.

El estilo de relleno que se aplica al interior de la forma. Este atributo paint nos permite rellenar formas con cólores sólidos, gradientes o patrones.

El estilo de composición se utiliza cuando los objetos dibujados se solapan con objetos existentes.

La transformación que se aplica durante el dibujado para convertir el objeto dibujado desde el espacio de usuario a las coordenadas de espacio del dispositivo. También se pueden aplicar otras transformaciones opcionales como la traducción, rotación escalado, recortado, a través de este atributo. El Clip que restringe el dibujado al área dentro de los bordes de la Shape se utiliza para definir el ára de recorte. Se puede usar cualquier Shape para definir un clip.

La fuente se usa para convertir cadenas de texto.

Punto de Renderizado que especifican las preferencias en cuanto a velocidad y calidad. Por ejemplo, podemos especificar si se debería usar antialiasing, si está disponible.

Para configurar un atributo en el contexto de renderizado de Graphics2D, se usan los métodos set Attribute.

setStroke

• • • • • •

setPaint setComposite setTransform setClip setFont setRenderingHints

Cuando se configura un atributo, se le pasa al objeto el atributo apropiado. Por ejemplo, para cambiar el atributo paint a un relleno de gradiente azul-gris, se debería construir el objeto GradientPaint y luego llamar a setPaint. gp = new GradientPaint(0f,0f,blue,0f,30f,green); g2.setPaint(gp); Graphics2D contiene referencias a sus objetos atributos -- no son clonados. Si modificamos un objeto atributo que forma parte del contexto Graphics2D, necesitamos llamar al método set para notificarlo al contexto. La modificación de un atributo de un objeto durante el renderizado puede causar comportamientos impredecibles. Métodos de renderizado de Graphics2D Graphics2D proporciona los siguientes métodos generales de dibujado que pueden usarser para dibujar cualquier primitivo geométrico, texto o imagen.
• • •

draw--dibuja el exterior de una forma geométrica primitiva usando los atributos stroke y paint. fill--dibuja cualquier forma geométrica primitiva rellenado su interior con el color o patrón especificado por el atributo paint. drawString--dibuja cualquier cadena de texto. El atributo font se usa para convertir la fuente a glyphs que luego se rellenan con el color o patrón especificados por el atributo paint. drawImage--dibuja la imagen especificada.

Además, Graphics2D soporta los métodos de renderizado de Graphics para formas particulares, como drawOval y fillRect. Componer Gráficos: La clase AlphaComposite encapsula varios estilos de composición, que determinan cómo se dibujan los objetos solapados. Un AlphaComposite también puede tener un valor alpha que especifica el grado de transparencia: alpha = 1.0 es totalmente opaco, alpha = 0.0 es totalmente transparente. AlphaComposite soporta la mayoría de los estándares de composición como se muestra en la siguiente tabla. Source-over (SRC_OVER) Si los pixels del objeto que está siendo renderizado (la fuente) tienen la misma posición que los pixels renderizados préviamente (el destino), los pixels de la fuente se renderizan sobre los pixels del destino.

Source-in (SRC_IN)

Si los pixels de la fuente y el destino se solapan, sólo se renderizarán los pixels que haya en el área solapada.

Source-out (SRC_OUT)

Si los pixels de la fuente y el destino se solapan, sólo se renderizarán los pixels que haya fuera del área solapada. Los pixels que haya en el área solapada se borrarán.

Destination-over (DST_OVER)

Si los pixels de la fuente y del destino se solapan, sólo se renderizarán los pixels de la fuente que haya fuera del área solapada. Los pixels que haya en el área solapada no se cambian.

Destination-in (DST_IN)

Si los pixels de la fuente y del destino se solapan, el alpha de la fuente se aplica a los pixels del área solapada del destino. Si el alpha = 1.0, los pixels del área solapada no cambian; si alpha es 0.0 los pixels del área solapada se borrarán. Si los pixels de la fuente y del destino se solapan, se aplica el alpha de la fuente a los pixels del área solapada del destino. Si el alpha = 1.0, los pixels del área solapada no cambian; si alpha es 0.0 los pixels del área solapada se borrarán. Si los pixels de la fuente y del destino se solapan, los pixels del área solapada se borrarán.

Destination-out (DST_OUT)

Clear (CLEAR)

Para cambiar el estilo de composición usado por Graphics2D, se crea un objeto AlphaComposite y se pasa al método setComposite.

Ejemplo: Composite Este programa ilustra los efectos de varias combinaciones de estilos de composición y valores de alpha.

Se ha construido un nuevo objeto AlphaComposite ac llamando a AlphaComposite. getInstance y especificando las reglas de composición deseadas. AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC); Cuando se selecciona una regla de composición o un valor alpha, se llama de nuevo a AlphaComposite.getInstance, y el nuevo AlphaComposite se asigna a ac. El alpha seleccionado se aplica al valor alpha de cada pixel y se le pasa un segundo parámetro a AlphaComposite.getInstance. ac = AlphaComposite.getInstance(getRule(rule), alpha); El atributo composite se modifica pasando el objeto AlphaComposite a Graphics 2D setComposite. Los objetos son renderizados dentro de un BufferedImage y más tarde se copian en la pantalla, por eso el atributo composite se configura con el contexto Graphics2D para el BufferedImage. BufferedImage buffImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D gbi = buffImg.createGraphics();. gbi.setComposite(ac);

Mostrar y Manipular Imágenes Esta lección muestra cómo realizar operaciones de filtrado con BufferedImages y cómo usar un BufferedImage como un buffer fuera de pantalla. Modo Inmediato con BufferedImage Esta sección describe el modelo de modo inmediato implementado en el API Java 2D y explica como BufferedImage permite la manipulación de datos de imágenes. Filtrado y BufferedImage Esta sección muestra cómo usar las clases BufferedImageOp para realizar operaciones de filtrado sobre BufferedImage. Usar un BufferedImage para doble buffer Esta sección nos enseña cómo usar un BufferedImage como un buffer fuera de pantalla para aumentar el rendimiento de las imágenes. Modo Inmediato con BufferedImage El modelo de imágenes "modo inmediato" permite manipular y mostrar imágenes de pixels mapeados cuyos datos están almacenados en memoria. Se puede acceder a los datos de la imagen en una gran variedad de formatos y usar varios tipos de operaciones de filtrado para manipular los datos. BufferedImage es la clase clave del API del modo-inmediato. Esta clase maneja una imagen en memoria y proporciona métodos para almacenar, interpretar y dibujar cada dato de pixel. Un BufferedImage puede ser renderizado en un contexto Graphics o on un contexto Graphics2D. Un BufferedImage es esencialmente un Image un buffer de datos accesible. Un BufferedImage tiene un ColorModel y un Raster de los datos de la imagen.

El ColorModel proporciona una interpretación de color de los datos de los pixels de la imagen. El Raster representa las coordenadas rectangulares de la imagen, mantiene los datos de la imagen en memoria, y proporciona un mecanismo para crear múltiples subimagenes de un sólo buffer de imagen. El Raster también proporciona métodos para acceder a pixels específicos dentro de la imagen. Filtrar un BufferedImage

El API Java 2D define varias operaciones de filtrado para objetos BufferedImage . Cada operación de proceso de imágenes está incluida en una clase que implementa el interface BufferedImageOp. La manipulación de imágenes se realiza en el método filter. La clase BufferedImageOp en el API Java 2D soporta:
• • • • • •

Tranformación afin. Escalado. Modificación de Aspecto. Combinación Linear de Bandas. Conversión de color. Convolución.

Para filtrar un BufferedImage usando una de las clases de operación de imagen, se debe: 1. Constuir un ejemplar de una de las clases BufferedImageOp: AffineTransformOp, BandCombineOp, ColorConvertOp, ConvolveOp, LookupOp , o RescaleOp. 2. Llamar al método de operación filter, pasando en el BufferedImage que queremos filtrar y el BufferedImage donde queremos almacenar el resultado. Ejemplo: ImageOps El siguiente applet ilustra el uso de cuatro operaciones de filtrado de imagenes: low-pass, sharpen, lookup, y rescale.

El filtro sharpen se realiza usando un ConvolveOp. Convolución es el proceso de hacer más pesado el valor de cada pixel en una imagen con los valores de los pixels vecinos. La mayoría de los algoritmos de filtrado espacial están basados en las operaciones de convolución. Para construir y aplicar este tipo de filtrado al BufferedImage, este ejemplo usa un código similar al del siguiente fragmento. public static final float[] SHARPEN3x3 = { 0.f, -1.f, 0.f, -1.f, 5.0f, -1.f, 0.f, -1.f, 0.f}; BufferedImage dstbimg = new BufferedImage(iw,ih,BufferedImage.TYPE_INT_RGB);

Kernel kernel = new Kernel(3,3,SHARPEN3x3); ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); cop.filter(srcbimg,dstbimg); El objeto Kernel define matemáticamente cómo se ve afectada la salida de cada pixels en su área inmediata. La definición del Kernel determina el resultado del filtro. Soportar Interacción con el Usuario: Para permitir que el usuario interactúe con los graficos que se dibujan, se requiere poder determinar cuando el usuario pulsa sobre uno de ellos. El método hit de Graphics2D proporciona una forma para determinar fácilmente si ha ocurrido una pulsación de ratón sobre una Shape particular. De forma alternativa podemos obtener la posición del click de ratón y llamar a contains sobre la Shape para determinar si el click ocurrió dentro de los límites de la Shape. Si estamos usando texto primitvo, podemos realizar una simple comprobación obteniendo la línea exterior de la Shape que corresponde al texto y luego llamando a hit o contains con esa Shape. El soporte de edición de texto requiere una comprobación mucho más sofisticada. Si queremos permitir que el usuario edite el texto, generalmente deberíamos usar uno de los componentes de texto editable de Swing. Si estamos trabajando con texto primitivo y estamos usando TextLayout para manejar la forma y posición del texto, también podemos usar TextLayout para realizar la comprobación para la edición de texto. Ejemplo: ShapeMover Este applet permite al usuario arrastrar la Shape por la ventana del applet. La Shape se redibuja en cada nueva posición del ratón para proporcionar información al usuario mientras la arrastra.

Se llama al método contains para determinar si el cursor está dentro de los límites del rectángulo cuando se pulsa el botón. Si es así, se actualiza la posición del rectángulo. public void mousePressed(MouseEvent e){ last_x = rect.x - e.getX(); last_y = rect.y - e.getY(); if(rect.contains(e.getX(), e.getY())) updateLocation(e); ... public void updateLocation(MouseEvent e){ rect.setLocation(last_x + e.getX(), last_y + e.getY()); ... repaint(); Al redibujar la Shape en cada posición del ratón es muy lento, porque el rectángulo relleno es renderizado cada vez que se mueve, Usando el doble buffer podemos eliminar este problema. Si estamos usando Swing, el dibujo usará doble buffer automáticamente; si no es así tendremos que cambiar todo el código de renderizado. Si no estamos usando Swing, el Ejemplo: BufferedShapeMover en la siguiente lección nos muestra cómo podemos implementar el doble buffer usando un BufferedImage. Podemos dibujar en un BufferedImage y luego copiar la imagen en la pantalla. Ejemplo: HitTestSample Esta aplicación ilustra la comprobación de pulsaciones dibujando el cursor por defecto siempre que el usuario pulse sobre el TextLayout, como se muestra en la siguiente figura.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecerá en una nueva ventana del navegador. HitTestSample.java contiene el código completo de este applet. El método mouseClicked usa TextLayout.hitTestChar para devolver un objeto java.awt.font.TextHitInfo que contiene la posición del click (el índice de inserción) en el objeto TextLayout. La información devuelta por los métodos de TextLayout, getAscent, getDescent y getAdvance se utiliza para calcular la posición del origen del objeto TextLayout para que esté centrado tanto horizontal como verticalmente. ... private Point2D computeLayoutOrigin() { Dimension size = getPreferredSize(); Point2D.Float origin = new Point2D.Float();

origin.x = (float) (size.width - textLayout.getAdvance()) / 2; origin.y = (float) (size.height - textLayout.getDescent() + textLayout.getAscent())/2; return origin; }

... public void paintComponent(Graphics g) { super.paintComponent(g); setBackground(Color.white); Graphics2D graphics2D = (Graphics2D) g; Point2D origin = computeLayoutOrigin();

graphics2D.translate(origin.getX(), origin.getY());

// Draw textLayout. textLayout.draw(graphics2D, 0, 0);

// Retrieve caret Shapes for insertionIndex. Shape[] carets = textLayout.getCaretShapes(insertionIndex);

// Draw the carets. carets[0] is the strong caret and // carets[1] is the weak caret. graphics2D.setColor(STRONG_CARET_COLOR); graphics2D.draw(carets[0]); if (carets[1] != null) { graphics2D.setColor(WEAK_CARET_COLOR); graphics2D.draw(carets[1]); } }

... private class HitTestMouseListener extends MouseAdapter {

/** * Compute the character position of the mouse click. */ public void mouseClicked(MouseEvent e) {

Point2D origin = computeLayoutOrigin();

// Compute the mouse click location relative to // textLayout's origin. float clickX = (float) (e.getX() - origin.getX()); float clickY = (float) (e.getY() - origin.getY());

// Get the character position of the mouse click. TextHitInfo currentHit = textLayout.hitTestChar(clickX, clickY); insertionIndex = currentHit.getInsertionIndex();

// Repaint the Component so the new caret(s) will be displayed. hitPane.repaint(); } Recortar la Región de Dibujo Cualquier Shape puede usarse como un path de recortado que restringe las porciones del área de dibujo que serán renderizadas. El path de recortado forma parte del contexto Graphics2D; para seleccionar el atributo clip, se llama a Graphics2D.setClip y se pasa a la Shape que define el path de recortado que queramos usar. Podemos reducir el path de recortado llamando al método clip y pasándolo en otra Shape; el atributo clip se configura a la intersección entre el clip actual y el Shape especificado. Ejemplo: ClipImage Este ejemplo anima un path de recortado para revelar diferentes porciones de una imagen:

. El path de recortado está definido por la intersección de una elipse y un rectángulo cuyas dimensiones son aleatorias. La elipse se pasa al método setClip , y luego se llama al método clip para seleccionar el path de recortado a la intersección entre la elipse y el rectángulo. private Ellipse2D ellipse = new Ellipse2D.Float(); private Rectangle2D rect = new Rectangle2D.Float(); ... ellipse.setFrame(x, y, ew, eh); g2.setClip(ellipse); rect.setRect(x+5, y+5, ew-10, eh-10); g2.clip(rect); Ejemplo: Starry Un área de recortado también puede crearse desde una cadena de texto existente. El siguiente ejemplo crea un TextLayout con la cadena The Starry Night. Luego, obtiene una línea exterior del TextLayout. El método TextLayout.getOutline devuelve un objeto Shape y un Rectangle creado a partir de los límites del objeto Shape. Los límites contienen todos los pixels que layout puede dibujar. El color en el contexto gráfico se selecciona a azul y se dibuja la figura exterior de la forma, como ilustran la siguiente imagen y el fragmento de código.

FontRenderContext frc = g2.getFontRenderContext(); Font f = new Font("Helvetica", 1, w/10);

String s = new String("The Starry Night"); TextLayout tl = new TextLayout(s, f, frc); AffineTransform transform = new AffineTransform(); Shape outline = textTl.getOutline(null); Rectangle r = outline.getBounds(); transform = g2.getTransform(); transform.translate(w/2-(r.width/2), h/2+(r.height/2)); g2.transform(transform); g2.setColor(Color.blue); g2.draw(outline); Luego, se selecciona un área de recortado en el contexto gráfico usando el objeto Shape creado a partir de getOutline. La imagen starry.gif, que es una pintura famosa de Van Gogh, The Starry Night, se dibuja dentro de área de recortado que empieza en la esquina inferior izquierda del objeto Rectangle. g2.setClip(outline); g2.drawImage(img, r.x, r.y, r.width, r.height, this);

Punteado y Relleno de Gráficos Primitivos Cambiando el punteado y los atributos de dibujo en el contexto de Graphics2D, antes del dibujo, podemos fácilmente aplicar estilos divertidos de líneas y patrones de relleno para gráficos primitivos. Por ejemplo, podemos dibujar una línea punteada creando el objeto Stroke apropiado y llamando a setStroke para añadirlo al contexto Graphics2D antes de dibujar la línea. De forma similar, podemos aplicar un relleno de gradiente a un Shape creando un objeto GradientPaint y añadiendo al contexto Graphics2D llamando a setPaint antes de dibujar la Shape. El siguiente applet demuestra cómo podemos dibujar formas geométricas usando los métodos Graphics2D draw y fill.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecerá en una nueva ventana del navegador. ShapesDemo2D.java contiene el código completo de este applet. Cada una de las formas dibujadas por el applet está construida de geometrías y está dibujada a través de Graphics2D. Las variables rectHeight y rectWidth de este ejemplo definen las dimensiones del espacio en que se dibuja cada forma, en pixels. La variables x e y cambian para cada forma para que sean dibujadas en formación de parrilla. // draw Line2D.Double g2.draw(new Line2D.Double(x, y+rectHeight-1, x + rectWidth, y)); // draw Rectangle2D.Double g2.setStroke(stroke); g2.draw(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); // draw RoundRectangle2D.Double g2.setStroke(dashed); g2.draw(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight,

10, 10)); // draw Arc2D.Double g2.setStroke(wideStroke); g2.draw(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); // draw Ellipse2D.Double g2.setStroke(stroke); g2.draw(new Ellipse2D.Double(x, y, rectWidth, rectHeight)); // draw GeneralPath (polygon) int x1Points[] = {x, x+rectWidth, x, x+rectWidth}; int y1Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polygon = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x1Points.length); polygon.moveTo(x1Points[0], y1Points[0]);

for (int index = 1; index < x1Points.length; index++) {

polygon.lineTo(x1Points[index], y1Points[index]); };

polygon.closePath(); g2.draw(polygon); // draw GeneralPath (polyline) int x2Points[] = {x, x+rectWidth, x, x+rectWidth}; int y2Points[] = {y, y+rectHeight, y+rectHeight, y}; GeneralPath polyline = new GeneralPath(GeneralPath.WIND_EVEN_ODD, x2Points.length);

polyline.moveTo (x2Points[0], y2Points[0]);

for (int index = 1; index < x2Points.length; index++) { polyline.lineTo(x2Points[index], y2Points[index]); };

g2.draw(polyline); // fill Rectangle2D.Double (red)

g2.setPaint(red); g2.fill(new Rectangle2D.Double(x, y, rectWidth, rectHeight)); // fill RoundRectangle2D.Double g2.setPaint(redtowhite); g2.fill(new RoundRectangle2D.Double(x, y, rectWidth, rectHeight, 10, 10)); // fill Arc2D g2.setPaint(red); g2.fill(new Arc2D.Double(x, y, rectWidth, rectHeight, 90, 135, Arc2D.OPEN)); // fill Ellipse2D.Double g2.setPaint(redtowhite); g2.fill (new Ellipse2D.Double(x, y, rectWidth, rectHeight)); // fill and stroke GeneralPath int x3Points[] = {x, x+rectWidth, x, x+rectWidth}; int y3Points[] = {y, y+rectHeight, y+rectHeight, y};

GeneralPath filledPolygon = new

GeneralPath(GeneralPath.WIND_EVEN_ODD, x3Points.length); filledPolygon.moveTo(x3Points[0], y3Points[0]);

for (int index = 1; index < x3Points.length; index++) {

filledPolygon.lineTo(x3Points[index], y3Points[index]);

}; filledPolygon.closePath(); g2.setPaint(red); g2.fill(filledPolygon); Observa que este ejemplo usa implementaciones de doble precision de las clases geométricas. Donde sea posible, las implementaciones de los float y doble precisión de cada geométrico están proporcionados por clases internas. Dibujar Curvas Los applets Cubic y Quad demuestran como crear curvas cúbicas y cuadráticas usando CubicCurve2D y QuadCurve2D. Estos applets también demuestran como se dibujan las curvas con respecto al posicionamiento de los puntos de control permitiendonos mover interactivamente tanto los puntos de control como los puntos finales. Ejemplo: Quad El applet Quad demuestra una curva cuadrática, que es un segmento de curva que tiene dos puntos finales y un único punto de control. El punto de control determina la forma de la curva controlando tanto el punto de control como los vectores tangenciales de los puntos finales.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecerá en una nueva ventana del navegador. Quad.java contiene el código completo de este applet. Primero se crea una nueva curva cuadrática con dos puntos finales y un punto de control y las posiciones de los puntos se seleccionan con respecto al tamaño de la ventana. QuadCurve2D.Double quad = new QuadCurve2D.Double();

Point2D.Double start, end, control; start = new Point2D.Double(); one = new Point2D.Double(); control = new Point2D.Double();

quad.setCurve(start, one, control);

start.setLocation(w/2-50, h/2); end.setLocation(w/2+50, h/2); control.setLocation((int)(start.x)+50, (int)(start.y)-50); Cada vez que el usuario mueva uno de los puntos, la curva se reseteará.

quad.setCurve(start, control, end); Ejemplo: Cubic El ejemplo Cubic muestra una curva cúbica, que es un segmento de curva que tiene dos puntos finales y dos puntos de control. Cada punto de control determina la forma de la curva mediante el control de uno de los vectores tangenciales de un punto final. En el ejemplo Cubic, las cruces coloreadas se dibujan donde se encuentran los puntos de control y los puntos finales. El punto de control azul controla el punto final rojo y el punto de control verde controla el punto final magenta.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecerá en una nueva ventana del navegador. Cubic.java contiene el código completo de este applet. Una curva cúbica se crea con dos puntos finales y dos puntos de control y las localizaciones de los puntos se seleccionan con respecto al tamaño de la ventana. CubicCurve2D.Double cubic = new CubicCurve2D.Double();

Point2D.Double start, end, one, two; start = new Point2D.Double(); one = new Point2D.Double(); two = new Point2D.Double();

end = new Point2D.Double();

cubic.setCurve(start, one, two, end);

... start.setLocation(w/2-50, h/2); end.setLocation(w/2+50, h/2); one.setLocation((int)(start.x)+25, (int)(start.y)-25); two.setLocation((int)(end.x)-25, (int)(end.y)+25); Como en el ejemplo Quad, la curva es reseteada cada vez que se mueven los puntos. cubic.setCurve(start, one, two, end); Dibujar formas arbitrarias El ejemplo ShapesDemo usa GeneralPath para hacer polígonos en forma de cristales, pero tambien podemos usar GeneralPath para hacer formas arbitrarias tanto con líneas rectas como curvas. Ejemplo: Odd_Shape El ejemplo Odd_Shape usa GeneralPath para crear formas arbitrarias en la sección Formas.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecerá en una nueva ventana del navegador. Odd_Shape.java contiene el código completo de este applet. El siguiente código crea un nuevo GeneralPath y añade el primer punto al path. GeneralPath oddShape = new GeneralPath(); ... x = w/2 + 50; y = h/2 - 25;

x2 = x; y2 = y;

oddShape.moveTo(x, y); Después de añadir el primer punto al path, se añaden tres líneas rectas. x -= 100; oddShape.lineTo(x, y); y += 50; oddShape.lineTo(x, y); x += 100; oddShape.lineTo(x, y); Finalmente, se añade una curva cúbica. x += 10; y -= 10; x1 = x - 20; y1 = y - 20; oddShape.curveTo(x, y, x1, y1, x2, y2);

Definir Estilos de línea divertidos y Patrones de relleno. Probablemente habrás observado en el ejemplo anterior algunas de las formas tienen líneas punteadas o están rellenas con gradientes de dos colores. Usando las clases Stroke y Paint de Java 2D, podemos fácilmente definir estilos de línea divertidos y patrones de relleno. Estilos de Línea Los estilos de línea están definidos por el atributo stroke en el contexto Graphics2D. Para seleccionar el atributo stroke podemos crear un objeto BasicStroke y pasarlo dentro del método Graphics2D setStroke. Un objeto BasicStroke contiene información sobre la anchura de la línea, estilo de uniones, estilos finales, y estilo de punteado. Esta información se usa cuando se dibuja un Shape con el método draw. La anchura de línea es la longitud de la línea medida perpendicularmente a su trayectoria. La anchura de la línea se especificada como un valor float en las unidades de coordenadas de usuario, que es equivalente a 1/72 pulgadas cuando se utiliza la transformación por defecto. El estilo de unión es la decoración que se aplica cuando se encuentran dos segmentos de línea. BasicStroke soporta tres estilos de unión:. JOIN_BEVEL JOIN_MITER JOIN_ROUND El estilo de finales es la decoración que se aplica cuando un segmento de línea termina. BasicStroke soporta tres estilos de finalización: CAP_BUTT CAP_ROUND CAP_SQUARE El estilo de punteado define el patrón de las secciones opacas y transparentes aplicadas a lo largo de la longitud de la línea. Este estilo está definido por un array de punteado y una fase de punteado. El array de punteado define el patrón de punteado. Los elementos alternativos en el array representan la longitud del punteado y el espacio entre punteados en unidades de coordenadas de usuario.. El elemento 0 representa el primer punteado, el elemento 1 el primer espacio, etc. La fase de punteado es un desplazamiento en el patrón de punteado, también especificado en unidades de coordenadas de usuario. La fase de punteado indica que parte del patrón de punteado se aplica al principio de la línea.

Patrón de Relleno Los patrones de rellenos están definidos por el atributo paint en el contexto Graphics2D. Para seleccionar el atributo paint, se crea un ejemplar de un objeto que implemente el interface Paint y se pasa dentro del método Graphics2D setPaint. Tres clases implementan el interface Paint: Color, GradientPaint, y TexturePaint . GradientPaint y TexturePaint son nuevas en el JDK 1.2. Para crear un GradientPaint, se especifica una posición inicial y un color y una posición final y otro color. El gradiente cambia proporcionalmente desde un color al otro a lo largo de la línea que conecta las dos posiciones.

El patrón para una TexturePaint esta definido por un BufferedImage. Para crear un TexturePaint, se especifica una imagen que contiene el patrón y un rectángulo que se usa para replicar y anclar el patrón.

Ejemplo: StrokeAndFill El applet StrokeAndFill permite al usuario seleccionar un gráfico primitivo, un estilo de línea, un estilo de dibujo y o bien puntear el exterior del objeto, rellenarlo con el dibujo seleccionado, o puntear el objeto en blanco y rellenar el dibujo con el dibujo seleccionado.

Esta es una imagen del GUI del applet. Para ajecutar el applet, pulsa sobre ella. El applet aparecerá en una nueva ventana del navegador. StrokeAndFill.java contiene el código completo de este applet. Los primitivos son inicializados e introducidos en un array de objetos Shape. El siguiente código crea un Rectangle y un Ellipse2D.Double y los introduce en el array shapes. shapes[0] = new Rectangle(0, 0, 100, 100); shapes[1] = new Ellipse2D.Double(0.0, 0.0, 100.0, 100.0); Para crear un objeto Shape desde una cadena de texto, primero debemos crear un objeto TextLayout desde el texto de la cadena. TextLayout textTl = new TextLayout("Text", new Font("Helvetica", 1, 96), new FontRenderContext(null, false, false)); Las siguientes líneas transforman el TextLayout para que sea centrado en el origen y luego introduce el objeto Shape resultante de la llamda a getOutline dentro del array shapes. AffineTransform textAt = new AffineTransform(); textAt.translate(0, (float)textTl.getBounds().getHeight()); shapes[2] = textTl.getOutline(textAt);

Podemos elegir un primitivo accediendo al índice apropiado dentro del array shapes. Shape shape = shapes[Transform.primitive.getSelectedIndex()]; Cómo se realiza el dibujo dependen de las opciones elegidas.

• •

Cuando el usuario elige stroke, se llama a Graphics2D.draw para realizar el dibujo, Si se elige text como primitivo, las líneas son recuperadas y el dibujo se hace con el método draw. Cuando el usuario elige fill, se llama a Graphics2D.fill o Graphics2D.drawString para realizar el dibujado. Cuando el usuario elige stroke and fill, se llama a fill o drawString para rellenar el Shape, y luego se llama a draw para dibujar la línea exterior.

Nota: Para rellenar y puntear un gráfico primitivo, necesitamos hacer dos llamadas separadas a métodos: fill o drawString para rellenar el interior, y draw para dibujar el exterior. Los tres estilos de línea usados en este ejemplo -- ancho, estrecho y punteado -- son ejemplares de BasicStroke. // Sets the Stroke. ... case 0 : g2.setStroke(new BasicStroke(3.0f)); break; case 1 : g2.setStroke(new BasicStroke(8.0f)); break; case 2 : float dash[] = {10.0f}; g2.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f)); break; El estilo de punteado de este ejemplo tiene 10 unidades de punteado alternados con 10 unidades de espacio. El principio del patrón del punteado se aplica al principio de la línea -- la fase de punteado es 0.0.

En este ejemplo se usan tres estilos de dibujo -- sólido, gradiente y polka. El dibujo de color sólido es un ejemplar de Color, el gradiente un ejemplar de GradientPaint, y el patrón un ejemplar de TexturePaint. // Sets the Paint. ... case 0 : g2.setPaint(Color.blue); break; case 1 : g2.setPaint(new GradientPaint(0, 0, Color.lightGray, w-250, h, Color.blue, false)); break; case 2 : BufferedImage bi = new BufferedImage(5, 5, BufferedImage.TYPE_INT_RGB); Graphics2D big = bi.createGraphics(); big.setColor(Color.blue); big.fillRect(0, 0, 5, 5); big.setColor(Color.lightGray); big.fillOval(0, 0, 5, 5); Rectangle r = new Rectangle(0,0,5,5); g2.setPaint(new TexturePaint(bi, r)); break;

OPERADORES ARITMETICOS: El soporte de JAI es provisto de operadores aritméticos monadic y diádicos. En el monadic los funcionamientos aritméticos incluyen suma del por cada banda, substracción, multiplicación y división entre una imagen de la fuente y un valor constante que produce la imagen de destino. Los funcionamientos aritméticos diádicos incluyen suma del por cada banda, substracción, multiplicación y división entre dos imágenes fuente para producir una imagen de destino. También es posible tomar el valor absoluto de pixeles en la imagen de la fuente y guardar los resultados en una imagen de destino. Exponenciacion también se proporciona. Las operaciones aritméticas requieren que las imágenes fuente y la imagen del destino tengan los mismos tipos de datos y número de bandas. El tamaño de las dos imágenes (altura y anchura), sin embargo, no necesita ser el mismo. Cuando las operaciones son realizadas, se alinean situaciones del origen para cada imagen o la sola imagen para las operaciones del monadic. Por ejemplo, para la suma de la imagen el valor a situación 0,0 en uno la imagen de la fuente se agrega a situación 0,0 de la segunda imagen de la fuente y el resultado se guarda en situación 0,0 de la imagen del destino. Este procedimiento se repite para cada píxel. Las operaciones aritméticas para imágenes onmulti-banda son realizadas con respecto a la banda de la imagen fuente. Se usan las operaciones aritméticas para realizar una combinación píxel a píxel de dos imágenes o de una imagen con un valor constante COMPUESTO: El JAI del funcionamiento compuesto requiere seis parámetros. Dos imágenes de la fuente, dos imágenes del alfa (segundo uno puede ser nulo), una bandera del boolean que indica si o no el alfa se ha multiplicado a fuentes y destino y una bandera del "alphaFirst" dónde verdadero indica que el cauce del alfa es la primera banda de la imagen del destino. Por ejemplo, pb = new ParameterBlock()

pb.addSource(source1); pb.addSource(source2); pb.add(alpha1); pb.add(null); pb.add(new Boolean(false)); destination = JAI.create("composite", pb, null); El funcionamiento compuesto combina dos imágenes basadas en sus valores del alfa a cada píxel. Esto se hace en una base por cada banda, y se espera que las dos imágenes de la fuente tengan el mismo número de bandas y el mismo tipo de datos. La imagen del destino tiene los mismos tipos de datos de las dos imágenes de la fuente, pero con una banda extra que representa el cauce de alfa resultante. Los valores de píxel de destino pueden verse como una representación fraccional de cada pixel o como un factor de transparencia. especifica los instrumentos compuestos el Porter-Duff "encima de" la regla en que el color del rendimiento de un pixel con el triple de valor/alpha de fuente (A, a) y (B, b) se da por el a*A + (1 - a)*(b*B). El valor de alfa de rendimiento se da por a + (1 - a)*b. Para el triple de fuentes de premultiplicado ( a*A, a) y ( b*B, b), el valor de rendimiento de premultiplicado simplemente es ( a*A) + (1 a)*(b*B). Los canales de color de las dos imágenes fuente son provistos vía source1 y source2. Las dos fuentes deben ser cualquiera los dos pre-multiplicados por el alfa o no. El cauce del alfa no debe ser incluido en el source1 y source2. El canal del alfa de las primeras imágenes de la fuente debe proporcionarse vía parámetro del source1Alpha. Este parámetro no puede ser nulo. El canal del alfa de la segunda imagen fuente puede proporcionarse vía parámetro del source2Alpha. Este parámetro puede ser nulo en el caso en que la segunda fuente es considerada completamente opaca. Las imágenes del alfa deben solo-atarse, y tiene los mismos tipos de datos así como las dimensiones de sus imágenes fuente correspondientes. El parámetro del alphaPremultiplied indica si o no la imagen del alfa proporcionada es el premultiplied a ambas imágenes fuente. También indica si la imagen destino los canales de color tienen los valores del alfa multiplicados a los valores de color de pixel. La imagen del destino es la combinación de las dos imágenes de la fuente. Tiene los canales de color y un canal del alfa adicional (el índice de la banda depende del parámetro del alphaFirst). Si el valor del alfa también se pre-multiplica a los canales de color este también depende del valor de alphaPremultiplied (pre-multiplicó si verdadero). CONVOLUCION: El pseudocodigo para el funcionamiento de la convolución en un ejemplo singular dst[x] [y] es como sigue, asumiendo el objeto es de tamaño anchura x altura y se ha girado a través de 180 grados. El elemento del Origen del objeto se localiza a la posición (xOrigin, yOrigin): dst[x][y] = 0; for( int i = - xOrigin; i <- xOrigin + weight; i++) {

for ( int j = - yOrigin; j <- yOrigin + hieght ; j++) { dst[x][y] + = src[x+i][y+j] * kernel[xOrigin+i][yOrigin+j]; } } La convolución, deja una banda de pixeles alrededor de los bordes indefinido. Por ejemplo, para un objeto 3x3 sólo cuatro elementos del objeto y cuatro pixeles de la fuente contribuyen al pixel de la convolución en las esquinas de la imagen de la fuente. Pixeles que no permiten aplicar el objeto lleno a la fuente no son incluidos en la imagen del destino. Un funcionamiento Fronterizo puede usarse para agregar una frontera apropiada a la imagen de la fuente para evitar encogimiento de los límites de la imagen. El objeto no puede ser más grande en cualquier dimensión que los datos de la imagen. Un Kernel se caracteriza por su anchura, altura, y origen, o el elemento importante. El elemento importante es el elemento que se pone encima del pixel de la fuente actual para realizar convolución o difusión del error. En el caso de temblar pedir una serie de objetos de Kernel se requiere realmente que sea un Kernel por la banda de la imagen cambiada. Para cambiar se pide la situación del elemento importante que de hecho no pertinente. La convolución es un funcionamiento espacial que computa cada muestra del rendimiento multiplicando elementos de un grano con las muestras que rodean una muestra de la fuente particular. Para cada muestra del destino, el objeto se gira 180 grados y su elemento" importante, u origen, se pone encima del pixel de la fuente que corresponde con el pixel del destino. Los elementos del grano se multiplican con los pixeles de la fuente bajo ellos, y los productos resultantes se suman para producir el valor de muestra de destino. HISTOGRAMA: Las tareas primarias necesitadas para obtener un histograma son como sigue: 1. cree un objeto del Histograma que especifica el tipo de histograma a ser generado. 2. cree un funcionamiento del Histograma con los parámetros requeridos o crea un ParameterBlock con los parámetros y páselo al funcionamiento del Histograma. 3. lea los datos del histograma guardados en el objeto. Un histograma proporciona una vista del perfil de intensidad de una imagen básicamente y normalmente se despliega como un mapa de la barra. Los valores del pixel son ordenadas y contados con la suma para cada intensidad puesta en su propia caja. Las intensidades del pixel se trazan a lo largo del x-eje horizontal mientras el número de ocurrencias para cada intensidad se traza a lo largo del y-eje vertical. El histograma puede considerarse como la estimación de las probabilidades que un nivel de intensidad particular ocurrira.

Para una imagen de 8 bits, hay 255 posibles valores de intensidad. Así, dada una imagen de 8 bits que es 128 por 128 con los valores todo el juego para poner a cero el histograma resultante a una sola banda tendría un solo valor a las 0 con un valor de 16384 con todas las otras cajas que contienen el valor de 0. La suma de todos los resultados en cada caja debe tener magnitud para el número total de pixeles en la imagen. CAPAS: En JAI, las colecciones contienen imágenes del renderable o colecciones que incluyen colecciones de imágenes. Pilas de imagen, pirámides o mapas mip, por ejemplo. El funcionamiento de AddCollection usado en esta demostración toma una colección de imágenes dadas y agrega cada juego de pixeles, uno de cada imagen de la fuente de la posición correspondiente y banda. Desde que los funcionamientos de la colección se realizan en conjunto, los funcionamientos individuales de las imágenes requieren extracción, reinserción de la imagen. La clase de la colección es principalmente un mecanismo usado para grupos de imágenes donde un funcionamiento es igualmente aplicado al grupo entero.

LOOKUT TABLE: El funcionamiento de Lookup toma una imagen dada o renderada imagen y una mesa del lookup, y realiza el lookup de la mesa general pasando la imagen de la fuente a través de la mesa. La imagen fuente puede ser mono o multi-banda de tipos de datos, ushort, short, o int. El lookuptable puede ser mono o multi-banda y de cualquier JAI soportando los tipos de los datos. La imagen destino debe tener los mismos tipos de datos como la mesa del lookup, y su número de bandas es determinado basado en el número de bandas de la fuente y la mesa. Si la fuente se mono-banda, el destino tiene el mismo número de bandas como la mesa del lookup; por otra parte, el destino tiene el mismo número de bandas como la fuente. Si la fuente 0 del table es mono-banda y el otro es multi-banda, entonces la mono banda se aplica a cada banda del objeto multi-banda. Si los dos son multi-banda, entonces sus bandas correspondiendo se aparean. El table puede tener un juego de valores del desplazamiento, uno para cada banda. Este valor se substrae del pixel de la fuente valorada antes de poner en un índice en la serie de datos del table. Es la responsabilidad del usuario hacer cierto el lookuptable proporcionado, conveniente para la imagen fuente. Específicamente, los datos del table cubre el rango entero de los datos de la fuente. Por otra parte, el resultado de este funcionamiento es indefinido.

Por la naturaleza de este funcionamiento, el destino puede tener un número diferente de bandas y/o tipos de datos de la fuente. El SampleModel del destino se crea de acuerdo con el lookuptable real usada en un caso específico. Los valores de pixel de destino se definen por el pseudocodigo: Si la imagen de la fuente se mono-banda y el lookuptable es mono o multi-banda, entonces la imagen del destino tiene el mismo número de bandas como el lookuptable: dst[x][y][b] = table[b][src[x][y][0] - offsets[b]] Si la imagen de la fuente es multi-banda y el lookuptable es mono-banda, entonces la imagen del destino tiene el mismo número de bandas como la imagen de la fuente: dst[x][y][b] = table[0][src[x][y][b] - offsets[0]] Si la imagen de la fuente es multi-banda y el lookuptable es multi-banda, entonces con el mismo número de bandas como la imagen fuente, la imagen destino tendrá el mismo número de bandas como la imagen fuente: dst[x][y][b] = table[b][src[x][y][b] - offsets[b]] La modificación del lookuptable proporciona una transformación de amplitud non-lineal. La Non-liniear amplitud transformación es útil para una variedad de efectos. El brillo, contraste, corrección gamma, color pseudo y reducción colorida son unos ejemplos de aplicaciones de lookuptable. El valor del pixel de la imagen esta diseccionado dentro del lookuptable. El valor del pixel se reemplaza por los volúmenes a esa dirección. RENDEREABLE: Esta demostración utiliza el JAI.createRenderable () JAI.createScaledRendering (), métodos para realizar la balanza y funcionamientos de imaging de invertido. El funcionamiento del Invertido invierte los valores del pixel de una imagen. Para las imágenes de la fuente con los tipos de datos firmados, el valor de pixel de la imagen destino se define por el pseudocodigo: dst[x][y][b] = - src[x][y][b] Para los tipos de los datos sin firmar, los valores del destino se definen por: dst[x][y][b] = MAX_VALUE - src[x][y][b] donde MAX_VALUE es el valor máximo apoyado por el sistema del tipo de los datos del pixel de la fuente. La arquitectura de API de renderable integra un modelo de independencia con un paralelo, dispositivo-dependiente (dado) modelo. La porción dar-independiente de la arquitectura es un superset del modelo tradicional de imaging dispositivo-dependiente.

La capa del renderable proporciona fuentes de la imagen que pueden reusarse múltiples veces en los contextos diferentes, como la pantalla despliegue o imprimiendo. Los operadores del renderable toman los parámetros dar-independientes y pueden encadenarse juntos (el funcionamiento encadena) a para dirigir-acyclic-graphs(DAGS). Cualquier clase que lleva a cabo la interfaz de RenderableImage es una fuente del renderable y debe adaptar a RenderContexts. Las imágenes de Renderable son los referenciados a través del usuario con los sistemas de la coordenada definidos RENDERABLE SCALE: La operación de escala traduce y redimensiona una imagen. Para cada pixel (x, y) del destino, el valor de la fuente a la posición del subpixel fraccionaria ((x - xTrans)/xScale, (y - yTrans)/yScale) se construye por medio de un objeto de la Interpolación y escrito al destino. Cuando aplica a una escala un factor de escala scale_x, scale_y a una imagen fuente con la anchura de src_width y altura de src_height, la imagen resultante se define para tener las dimensiones siguientes: dst_width = src_width * scale_x dst_height = src_height * scale_y Cuando se especifican interpolaciones que requieren la fuente al relleno como Bilinear o interpolación de Bicubic, la fuente necesita ser extendida tal como los pixeles extras se necesitó computar todos los pixeles del destino. Esta extensión es realizada vía la clase de BorderExtender. El tipo de Extensión Fronteriza puede especificarse como un RenderingHint al método de JAI.create. Si ninguna Extensión Fronteriza se especifica, la fuente no se extenderá. El tamaño de la imagen escalada todavía es calculado según la fórmula especificada anteriormente. No hay bastante fuente sin embargo subsecuentemente para computar todos los pixeles del destino, sólo ese subconjunto de los pixeles de la imagen del destino que pueden computarse se escribirá en el destino. El resto del destino no se escribirá. Especificando un factor de escala mayor a 1 aumenta el tamaño de la imagen, especificando un factor de escala entre 0 y 1 (non-inclusivo) las disminuciones el tamaño de una imagen. Un IllegalArgumentException se tirará si los factores de la escala especificados son negativos o igual a cero. La balanza define un PropertyGenerator que realiza una transformación idéntica en la propiedad de "ROI" de la imagen de la fuente que puede recuperarse llamando el método del getProperty con "ROI" como el nombre de propiedad. Las operaciones renderable de escala tiene en cuenta las imágenes de la multi-resolución para encontrar la imagen con el próximo factor de escala más grande. Esta imagen se usa para escalar el tamaño del rendimiento deseado.

UMBRAL: El funcionamiento del Umbral toma uno imagen dada, y traza todos los pixeles de esta imagen cuyo valor se queda dentro de un rango especificado a una constante especificada. El rango se especifica por un valor bajo y un valor alto. Si el número de elementos proporcionara vía el "alto", "baja", y las series de las "constantes" son menores del número de bandas de la imagen de la fuente, entonces el elemento de entrada 0 se aplica a todas las bandas. Por otra parte, el elemento de una entrada diferente se aplica a su banda correspondiendo. Thresholding, también conocido como la "mejora del contraste binario", proporciona un medios simples de definir los límites de objetos que aparecen en un fondo contrastante. El funcionamiento del umbral traza todo el valor del pixel de una imagen que otoño dentro de un rango dado a uno de un juego de constantes del por-banda. El valor de pixel de la imagen del destino byte define con el pseudocodigo siguiente: if ( src[x][y][b] >= low[b] && src[x][y][b] <= high[b] ) { dst[x][y][b] = constants[b]; } else { dst[x][y][b] = src[x][y][b]; } WARP: Para torcerse la imagen, pueden seleccionarse juegos de puntos usando el botón del ratón izquierdo. Por ejemplo, para el affine apriete el botón del ratón y arrástrelo a una nueva situación. Una línea de venda de caucho mostrará el camino. Cuando el ratón se suelta, un par de puntos se mostrará conectado por una línea recta. Repita este dos más veces. Un mensaje al fondo de la ventana contará el número de juegos seleccionado. Pueden arrastrarse los puntos a las nuevas situaciones, o los puntos de sumas agregaron qué quiere de nuevo, tuérzase la imagen. Java Advanced Imaging proporciona una clase de la transformación, warp que se usa para la transformación de coordenada nolineal de imagen. El pixel posiciona en la clase de la Urdimbre se representa usando el fijo-punto coordina, la exactitud del subpixel productiva pero todavía permitiendo el uso de aritmética del entero. El grado de precisión es fijo por las funciones de JAI apropiadas en el método del warpRect. El método importante de esta clase es warpRect que proporciona las situaciones de los pixeles en el espacio de la fuente que el mapa a una región del rendimiento rectangular dada. La región del rendimiento que usa las coordenadas del entero normales se especifica. Se especifican las posiciones de la fuente vueltas por el método en el fijopunto, las coordenadas del subpixel. Java Advanced Imaging apoya 8 funciones de alabeo:

Polinómico El polinomio general La reja Cuadrático Cúbico En perspectiva Affine OpImage Más allá del affine transforma, el imagen torcerse es un tipo de transformación geométrica que introduce la curvatura en el proceso de la cartografía. La introducción de curvatura es importante cuando una imagen se ha torcido a través de las aberraciones de la lente y otros procesos non-lineales. También puede usarse para la registración de la imagen. Las transformaciones torciéndose, también conocido como las transformaciones de hoja de caucho, pueden estirar una imagen arbitrariamente sobre los puntos definidos. Este tipo de funcionamiento proporciona una transformación del nonlinear entre la fuente y coordenadas del destino. ARBOL DE HERENCIA NOTA: Este árbol es sacado directamente de la página del API, Aunque identifico algunas de las funciones utilizadas para el procesamiento de imágenes, no comprendo la gran mayoria de secciones del arbol.
o
class java.lang.Object o class com.sun.media.jai.codec.BMPEncodeParam (implements com.sun.media.jai.codec.ImageEncodeParam) o class javax.media.jai.BorderExtender (implements java.io.Serializable)

o o o

class javax.media.jai.BorderExtenderZero class javax.media.jai.util.CaselessStringKey (implements java.lang.Cloneable, java.io.Serializable) class javax.media.jai.registry.CIFRegistry class javax.media.jai.CollectionImage (implements java.util.Collection, javax.media.jai.ImageJAI)

o o o o o

class javax.media.jai.BorderExtenderConstant class javax.media.jai.BorderExtenderCopy class javax.media.jai.BorderExtenderReflect class javax.media.jai.BorderExtenderWrap

o o o o o o

class javax.media.jai.AttributedImageCollection class javax.media.jai.CollectionOp (implements javax.media.jai.OperationNode, java.beans.PropertyChangeListener) class javax.media.jai.ImageSequence class javax.media.jai.ImageStack

o

class javax.media.jai.RenderedImageList (implements java.util.List, java.awt.image.RenderedImage, java.io.Serializable) class java.awt.image.ColorModel (implements java.awt.Transparency) class java.awt.image.ComponentColorModel

o

o class javax.media.jai.FloatDoubleColorModel class java.awt.color.ColorSpace (implements java.io.Serializable) o class javax.media.jai.ColorSpaceJAI o
class javax.media.jai.IHSColorSpace

o

class java.awt.Component (implements java.awt.image.ImageObserver, java.awt.MenuContainer, java.io.Serializable) o class java.awt.Canvas (implements javax.accessibility.Accessible) class javax.media.jai.widget.ImageCanvas class java.awt.Container

o

o o o

class javax.media.jai.CanvasJAI

class javax.swing.JComponent (implements java.io.Serializable)

o

class javax.swing.JPanel (implements javax.accessibility.Accessible)

o o o o o

o

o o

o o o o o o o

class com.sun.media.jai.widget.DisplayJAI (implements java.awt.event.MouseListener, java.awt.event.MouseMotionListener) o class java.awt.ScrollPane (implements javax.accessibility.Accessible) o class javax.media.jai.widget.ScrollingImagePanel (implements java.awt.event.AdjustmentListener, java.awt.event.ComponentListener, java.awt.event.MouseListener, java.awt.event.MouseMotionListener) class javax.media.jai.CoordinateImage class javax.media.jai.CRIFImpl (implements java.awt.image.renderable.ContextualRenderedImageFactory) o class javax.media.jai.NullCRIF class javax.media.jai.registry.CRIFRegistry class java.awt.image.DataBuffer o class javax.media.jai.DataBufferDouble o class javax.media.jai.DataBufferFloat class javax.media.jai.EnumeratedParameter (implements java.io.Serializable) o class javax.media.jai.operator.ColorQuantizerType o class javax.media.jai.operator.CompositeDestAlpha o class javax.media.jai.operator.DFTDataNature o class javax.media.jai.operator.DFTScalingType o class javax.media.jai.operator.MaxFilterShape o class javax.media.jai.operator.MedianFilterShape o class javax.media.jai.operator.MinFilterShape o class javax.media.jai.operator.MosaicType o class javax.media.jai.operator.ShearDir o class javax.media.jai.operator.TransposeType class java.util.EventObject (implements java.io.Serializable) o class java.beans.PropertyChangeEvent o class javax.media.jai.PropertyChangeEventJAI o class javax.media.jai.CollectionChangeEvent o class javax.media.jai.PropertySourceChangeEvent o class javax.media.jai.RenderingChangeEvent class com.sun.media.jai.codec.FPXDecodeParam (implements com.sun.media.jai.codec.ImageDecodeParam) class java.awt.Graphics o class java.awt.Graphics2D o class javax.media.jai.GraphicsJAI o class javax.media.jai.RenderableGraphics (implements java.awt.image.renderable.RenderableImage) class javax.media.jai.Histogram (implements java.io.Serializable) class com.sun.media.jai.codec.ImageCodec class com.sun.media.jai.codec.ImageDecoderImpl (implements com.sun.media.jai.codec.ImageDecoder) class com.sun.media.jai.codec.ImageEncoderImpl (implements com.sun.media.jai.codec.ImageEncoder) class javax.media.jai.ImageLayout (implements java.lang.Cloneable, java.io.Serializable) class javax.media.jai.ImageMIPMap (implements javax.media.jai.ImageJAI) o class javax.media.jai.ImagePyramid class java.io.InputStream o class com.sun.media.jai.codec.SeekableStream (implements java.io.DataInput) o class com.sun.media.jai.codec.ByteArraySeekableStream o class com.sun.media.jai.codec.FileCacheSeekableStream o class com.sun.media.jai.codec.FileSeekableStream o class com.sun.media.jai.codec.ForwardSeekableStream o class com.sun.media.jai.codec.MemoryCacheSeekableStream

o

o o

o o o o o o o o o o o

o

o class com.sun.media.jai.codec.SegmentedSeekableStream class javax.media.jai.IntegerSequence class javax.media.jai.Interpolation (implements java.io.Serializable) o class javax.media.jai.InterpolationBilinear o class javax.media.jai.InterpolationNearest o class javax.media.jai.InterpolationTable o class javax.media.jai.InterpolationBicubic o class javax.media.jai.InterpolationBicubic2 class javax.media.jai.JAI class com.sun.media.jai.codec.JPEGDecodeParam (implements com.sun.media.jai.codec.ImageDecodeParam) class com.sun.media.jai.codec.JPEGEncodeParam (implements com.sun.media.jai.codec.ImageEncodeParam) class javax.media.jai.KernelJAI (implements java.io.Serializable) class javax.media.jai.LookupTableJAI (implements java.io.Serializable) o class javax.media.jai.ColorCube class javax.media.jai.MultiResolutionRenderableImage (implements java.awt.image.renderable.RenderableImage, java.io.Serializable, javax.media.jai.WritablePropertySource) class javax.media.jai.remote.NegotiableCapabilitySet (implements java.io.Serializable) class javax.media.jai.remote.NegotiableCollection (implements javax.media.jai.remote.Negotiable) class javax.media.jai.remote.NegotiableNumeric (implements javax.media.jai.remote.Negotiable) class javax.media.jai.remote.NegotiableNumericRange (implements javax.media.jai.remote.Negotiable) class java.util.Observable o class javax.media.jai.DeferredData (implements java.io.Serializable) o class javax.media.jai.DeferredProperty (implements java.beans.PropertyChangeListener) o class javax.media.jai.RecyclingTileFactory (implements javax.media.jai.TileFactory, javax.media.jai.TileRecycler) class javax.media.jai.OperationDescriptorImpl (implements javax.media.jai.OperationDescriptor, java.io.Serializable) o class javax.media.jai.operator.AbsoluteDescriptor o class javax.media.jai.operator.AddCollectionDescriptor o class javax.media.jai.operator.AddConstDescriptor o class javax.media.jai.operator.AddConstToCollectionDescriptor o class javax.media.jai.operator.AddDescriptor o class javax.media.jai.operator.AffineDescriptor o class javax.media.jai.operator.AndConstDescriptor o class javax.media.jai.operator.AndDescriptor o class javax.media.jai.operator.AWTImageDescriptor o class javax.media.jai.operator.BandCombineDescriptor o class javax.media.jai.operator.BandMergeDescriptor o class javax.media.jai.operator.BandSelectDescriptor o class javax.media.jai.operator.BinarizeDescriptor o class javax.media.jai.operator.BMPDescriptor o class javax.media.jai.operator.BorderDescriptor o class javax.media.jai.operator.BoxFilterDescriptor o class javax.media.jai.operator.ClampDescriptor o class javax.media.jai.operator.ColorConvertDescriptor o class javax.media.jai.operator.ColorQuantizerDescriptor o class javax.media.jai.operator.CompositeDescriptor o class javax.media.jai.operator.ConjugateDescriptor o class javax.media.jai.operator.ConstantDescriptor o class javax.media.jai.operator.ConvolveDescriptor o class javax.media.jai.operator.CropDescriptor o class javax.media.jai.operator.DCTDescriptor o class javax.media.jai.operator.DFTDescriptor o class javax.media.jai.operator.DilateDescriptor o class javax.media.jai.operator.DivideByConstDescriptor o class javax.media.jai.operator.DivideComplexDescriptor o class javax.media.jai.operator.DivideDescriptor o class javax.media.jai.operator.DivideIntoConstDescriptor o class javax.media.jai.operator.EncodeDescriptor o class javax.media.jai.operator.ErodeDescriptor o class javax.media.jai.operator.ErrorDiffusionDescriptor

o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o

class javax.media.jai.operator.ExpDescriptor class javax.media.jai.operator.ExtremaDescriptor class javax.media.jai.operator.FileLoadDescriptor class javax.media.jai.operator.FileStoreDescriptor class javax.media.jai.operator.FilteredSubsampleDescriptor class javax.media.jai.operator.FormatDescriptor class javax.media.jai.operator.FPXDescriptor class javax.media.jai.operator.GIFDescriptor class javax.media.jai.operator.GradientMagnitudeDescriptor class javax.media.jai.operator.HistogramDescriptor class javax.media.jai.operator.IDCTDescriptor class javax.media.jai.operator.IDFTDescriptor class javax.media.jai.operator.IIPDescriptor class javax.media.jai.operator.IIPResolutionDescriptor class javax.media.jai.operator.ImageFunctionDescriptor class javax.media.jai.operator.InvertDescriptor class javax.media.jai.operator.JPEGDescriptor class javax.media.jai.operator.LogDescriptor class javax.media.jai.operator.LookupDescriptor class javax.media.jai.operator.MagnitudeDescriptor class javax.media.jai.operator.MagnitudeSquaredDescriptor class javax.media.jai.operator.MatchCDFDescriptor class javax.media.jai.operator.MaxDescriptor class javax.media.jai.operator.MaxFilterDescriptor class javax.media.jai.operator.MeanDescriptor class javax.media.jai.operator.MedianFilterDescriptor class javax.media.jai.operator.MinDescriptor class javax.media.jai.operator.MinFilterDescriptor class javax.media.jai.operator.MosaicDescriptor class javax.media.jai.operator.MultiplyComplexDescriptor class javax.media.jai.operator.MultiplyConstDescriptor class javax.media.jai.operator.MultiplyDescriptor class javax.media.jai.operator.NotDescriptor class javax.media.jai.operator.NullDescriptor class javax.media.jai.operator.OrConstDescriptor class javax.media.jai.operator.OrderedDitherDescriptor class javax.media.jai.operator.OrDescriptor class javax.media.jai.operator.OverlayDescriptor class javax.media.jai.operator.PatternDescriptor class javax.media.jai.operator.PeriodicShiftDescriptor class javax.media.jai.operator.PhaseDescriptor class javax.media.jai.operator.PiecewiseDescriptor class javax.media.jai.operator.PNGDescriptor class javax.media.jai.operator.PNMDescriptor class javax.media.jai.operator.PolarToComplexDescriptor class javax.media.jai.operator.RenderableDescriptor class javax.media.jai.operator.RescaleDescriptor class javax.media.jai.operator.RotateDescriptor class javax.media.jai.operator.ScaleDescriptor class javax.media.jai.operator.ShearDescriptor class javax.media.jai.operator.StreamDescriptor class javax.media.jai.operator.SubsampleAverageDescriptor class javax.media.jai.operator.SubsampleBinaryToGrayDescriptor class javax.media.jai.operator.SubtractConstDescriptor class javax.media.jai.operator.SubtractDescriptor class javax.media.jai.operator.SubtractFromConstDescriptor class javax.media.jai.operator.ThresholdDescriptor class javax.media.jai.operator.TIFFDescriptor class javax.media.jai.operator.TranslateDescriptor class javax.media.jai.operator.TransposeDescriptor class javax.media.jai.operator.UnsharpMaskDescriptor

o o o o o o o o o o

o o

o o o o o o o o o o o

class javax.media.jai.operator.URLDescriptor class javax.media.jai.operator.WarpDescriptor class javax.media.jai.operator.XorConstDescriptor class javax.media.jai.operator.XorDescriptor class javax.media.jai.OperationNodeSupport (implements java.io.Serializable) class javax.media.jai.OperationRegistry (implements java.io.Externalizable) class java.io.OutputStream o class com.sun.media.jai.codec.SeekableOutputStream class javax.media.jai.PackedImageData class java.awt.image.renderable.ParameterBlock (implements java.lang.Cloneable, java.io.Serializable) o class javax.media.jai.ParameterBlockJAI (implements javax.media.jai.ParameterList) class javax.media.jai.ParameterListDescriptorImpl (implements javax.media.jai.ParameterListDescriptor, java.io.Serializable) class javax.media.jai.ParameterListImpl (implements javax.media.jai.ParameterList, java.io.Serializable) o class javax.media.jai.remote.NegotiableCapability (implements java.io.Serializable) o class javax.media.jai.tilecodec.TileCodecParameterList class javax.media.jai.PerspectiveTransform (implements java.lang.Cloneable, java.io.Serializable) class javax.media.jai.PixelAccessor class javax.media.jai.PlanarImage (implements javax.media.jai.ImageJAI, java.awt.image.RenderedImage) o class javax.media.jai.OpImage o class javax.media.jai.AreaOpImage o class javax.media.jai.GeometricOpImage o class javax.media.jai.ScaleOpImage o class javax.media.jai.WarpOpImage o class javax.media.jai.PointOpImage o class javax.media.jai.ColormapOpImage o class javax.media.jai.NullOpImage o class javax.media.jai.SourcelessOpImage o class javax.media.jai.StatisticsOpImage o class javax.media.jai.UntiledOpImage o class javax.media.jai.remote.PlanarImageServerProxy (implements javax.media.jai.remote.RemoteRenderedImage) o class javax.media.jai.RemoteImage o class javax.media.jai.RenderedImageAdapter o class javax.media.jai.AttributedImage o class javax.media.jai.WritableRenderedImageAdapter (implements java.awt.image.WritableRenderedImage) o class javax.media.jai.RenderedOp (implements javax.media.jai.OperationNode, java.beans.PropertyChangeListener, java.io.Serializable) o class javax.media.jai.remote.RemoteRenderedOp (implements javax.media.jai.remote.RemoteRenderedImage) o class javax.media.jai.SnapshotImage (implements java.awt.image.TileObserver) o class javax.media.jai.TiledImage (implements java.beans.PropertyChangeListener, java.awt.image.WritableRenderedImage) class com.sun.media.jai.codec.PNGDecodeParam (implements com.sun.media.jai.codec.ImageDecodeParam) class com.sun.media.jai.codec.PNGEncodeParam (implements com.sun.media.jai.codec.ImageEncodeParam) o class com.sun.media.jai.codec.PNGEncodeParam.Gray o class com.sun.media.jai.codec.PNGEncodeParam.Palette o class com.sun.media.jai.codec.PNGEncodeParam.RGB class com.sun.media.jai.codec.PNGSuggestedPaletteEntry (implements java.io.Serializable) class com.sun.media.jai.codec.PNMEncodeParam (implements com.sun.media.jai.codec.ImageEncodeParam) class java.beans.PropertyChangeSupport (implements java.io.Serializable) o class javax.media.jai.PropertyChangeSupportJAI class javax.media.jai.PropertySourceImpl (implements javax.media.jai.PropertySource, java.io.Serializable) o class javax.media.jai.WritablePropertySourceImpl (implements javax.media.jai.WritablePropertySource) class javax.media.jai.iterator.RandomIterFactory class javax.media.jai.util.Range (implements java.io.Serializable) class javax.media.jai.RasterAccessor class javax.media.jai.RasterFactory class javax.media.jai.RasterFormatTag class javax.media.jai.registry.RCIFRegistry class javax.media.jai.iterator.RectIterFactory

o o o o

o

o o o o o o o o o o o o o o o

class javax.media.jai.RegistryMode o class javax.media.jai.registry.CollectionRegistryMode o class javax.media.jai.registry.RemoteRenderableRegistryMode o class javax.media.jai.registry.RemoteRenderedRegistryMode o class javax.media.jai.registry.RenderableCollectionRegistryMode o class javax.media.jai.registry.RenderableRegistryMode o class javax.media.jai.registry.RenderedRegistryMode o class javax.media.jai.registry.TileDecoderRegistryMode o class javax.media.jai.registry.TileEncoderRegistryMode class javax.media.jai.registry.RemoteCRIFRegistry class javax.media.jai.remote.RemoteDescriptorImpl (implements javax.media.jai.remote.RemoteDescriptor) o class javax.media.jai.remote.JAIRMIDescriptor class javax.media.jai.remote.RemoteJAI class javax.media.jai.registry.RemoteRIFRegistry class javax.media.jai.RenderableImageAdapter (implements java.awt.image.renderable.RenderableImage, javax.media.jai.WritablePropertySource) class javax.media.jai.RenderableOp (implements javax.media.jai.OperationNode, java.awt.image.renderable.RenderableImage, java.io.Serializable, javax.media.jai.WritablePropertySource) o class javax.media.jai.remote.RemoteRenderableOp class javax.media.jai.registry.RIFRegistry class javax.media.jai.ROI (implements java.io.Serializable) o class javax.media.jai.ROIShape class javax.media.jai.iterator.RookIterFactory class java.awt.image.SampleModel o class java.awt.image.ComponentSampleModel o class javax.media.jai.ComponentSampleModelJAI class javax.media.jai.SequentialImage class javax.media.jai.remote.SerializableRenderedImage (implements java.awt.image.RenderedImage, java.io.Serializable) class javax.media.jai.remote.SerializerFactory class com.sun.media.jai.codec.StreamSegment class java.lang.Throwable (implements java.io.Serializable) o class java.lang.Exception o class java.lang.RuntimeException o class javax.media.jai.util.ImagingException

o o o o o

o o o o o o

o class javax.media.jai.remote.RemoteImagingException class com.sun.media.jai.codec.TIFFDecodeParam (implements com.sun.media.jai.codec.ImageDecodeParam) class com.sun.media.jai.codec.TIFFDirectory (implements java.io.Serializable) class com.sun.media.jai.codec.TIFFEncodeParam (implements com.sun.media.jai.codec.ImageEncodeParam) class com.sun.media.jai.codec.TIFFField (implements java.lang.Comparable, java.io.Serializable) class javax.media.jai.tilecodec.TileCodecDescriptorImpl (implements javax.media.jai.tilecodec.TileCodecDescriptor) o class javax.media.jai.tilecodec.GZIPTileCodecDescriptor o class javax.media.jai.tilecodec.JPEGTileCodecDescriptor o class javax.media.jai.tilecodec.RawTileCodecDescriptor class javax.media.jai.tilecodec.TileDecoderImpl (implements javax.media.jai.tilecodec.TileDecoder) class javax.media.jai.registry.TileDecoderRegistry class javax.media.jai.tilecodec.TileEncoderImpl (implements javax.media.jai.tilecodec.TileEncoder) class javax.media.jai.registry.TileEncoderRegistry class javax.media.jai.UnpackedImageData class javax.media.jai.Warp (implements java.io.Serializable) o class javax.media.jai.WarpGrid o class javax.media.jai.WarpPerspective o class javax.media.jai.WarpPolynomial o class javax.media.jai.WarpAffine o class javax.media.jai.WarpCubic o class javax.media.jai.WarpGeneralPolynomial o class javax.media.jai.WarpQuadratic

Interface Hierarchy

o

interface javax.media.jai.CachedTile

o

interface java.lang.Cloneable o interface com.sun.media.jai.codec.ImageDecodeParam (also extends java.io.Serializable) interface com.sun.media.jai.codec.ImageEncodeParam (also extends java.lang.Cloneable, java.io.Serializable) o interface com.sun.media.jai.codec.ImageEncodeParam (also extends com.sun.media.jai.codec.ImageDecodeParam, java.io.Serializable) interface javax.media.jai.CollectionImageFactory interface javax.media.jai.ColorModelFactory interface java.util.EventListener o interface javax.media.jai.TileComputationListener interface javax.media.jai.widget.ImageCanvas.PaintListener interface com.sun.media.jai.codec.ImageDecoder interface com.sun.media.jai.codec.ImageEncoder interface javax.media.jai.ImageFunction interface javax.media.jai.util.ImagingListener interface com.sun.media.jai.remote.JAIServerConfigurationSpi interface javax.media.jai.OperationRegistrySpi interface javax.media.jai.ParameterList interface javax.media.jai.ParameterListDescriptor interface javax.media.jai.PropertyChangeEmitter o interface javax.media.jai.OperationNode (also extends javax.media.jai.PropertySource) o interface javax.media.jai.WritablePropertySource (also extends javax.media.jai.PropertySource)

o

o o o o o o o o o o o o o

o

o interface javax.media.jai.ImageJAI interface javax.media.jai.PropertySource o interface javax.media.jai.OperationNode (also extends javax.media.jai.PropertyChangeEmitter) o interface javax.media.jai.WritablePropertySource (also extends javax.media.jai.PropertyChangeEmitter) o interface javax.media.jai.ImageJAI interface javax.media.jai.iterator.RandomIter o interface javax.media.jai.iterator.WritableRandomIter interface javax.media.jai.iterator.RectIter o interface javax.media.jai.iterator.RookIter o
interface javax.media.jai.iterator.WritableRookIter (also extends javax.media.jai.iterator.WritableRectIter) interface javax.media.jai.iterator.WritableRectIter

o o

o

o

o o o o

o interface javax.media.jai.iterator.WritableRookIter (also extends javax.media.jai.iterator.RookIter) interface javax.media.jai.RegistryElementDescriptor o interface javax.media.jai.OperationDescriptor o interface javax.media.jai.remote.RemoteDescriptor o interface javax.media.jai.tilecodec.TileCodecDescriptor interface javax.media.jai.remote.RemoteRIF o interface javax.media.jai.remote.RemoteCRIF interface javax.media.jai.RenderableCollectionImageFactory interface java.awt.image.RenderedImage o interface javax.media.jai.remote.RemoteRenderedImage interface java.io.Serializable o interface com.sun.media.jai.codec.ImageDecodeParam (also extends java.lang.Cloneable)
interface com.sun.media.jai.codec.ImageEncodeParam (also extends java.lang.Cloneable, java.io.Serializable) o interface com.sun.media.jai.codec.ImageEncodeParam (also extends java.lang.Cloneable, com.sun.media.jai.codec.ImageDecodeParam) o interface javax.media.jai.remote.Negotiable o interface javax.media.jai.PropertyGenerator o interface javax.media.jai.remote.SerializableState interface javax.media.jai.remote.Serializer interface com.sun.media.jai.codec.StreamSegmentMapper interface javax.media.jai.TileCache interface javax.media.jai.tilecodec.TileDecoder interface javax.media.jai.tilecodec.TileDecoderFactory interface javax.media.jai.tilecodec.TileEncoder interface javax.media.jai.tilecodec.TileEncoderFactory

o

o o o o o o o

o o o o o

interface javax.media.jai.TileFactory interface javax.media.jai.TileRecycler interface javax.media.jai.TileRequest interface javax.media.jai.TileScheduler interface javax.media.jai.widget.ViewportListener

APLICACIÓN Nota: Aunque el tema de procesamiento de imágenes se entiende y son claros los conceptos y además de que todo eso es aplicable con java, no estuvo en saber el poder realizar un programa que mostrara todo lo anteriormente mencionado, debido a que esto implica una nivel de manejo de java muy alto o avanzado, en cambio lo que si pude hacer fue investigar varios ejemplos relacionados con el tema y que pueden mostrar claramente como funcionan las aplicaciones de java para el procesamiento avanzado de imagen. Ejemplo de histograma:
import java.io.File; import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.FlowLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.image.renderable.ParameterBlock; import java.awt.image.DataBuffer; import java.awt.event.*; import java.awt.Color; import javax.swing.JPanel; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.border.EtchedBorder; import javax.swing.border.LineBorder; import javax.swing.event.*; import javax.media.jai.JAI; import javax.media.jai.PlanarImage; import javax.media.jai.Histogram; import javax.media.jai.LookupTableJAI; import javax.media.jai.RenderedOp; import java.net.URL; import java.net.MalformedURLException;

public class HistogramDemo extends JPanel implements ActionListener { private PlanarImage source = null; private PlanarImage target = null; private Panner panner; private JButton reset; private JButton equal; private JButton norm; private JButton piece; private ImageDisplay canvas; private XYPlot graph;

public HistogramDemo(String filename) { try { source = JAI.create("url", new URL (filename) ); } catch ( MalformedURLException e) { return; } canvas = new ImageDisplay(source); canvas.setLayout(new FlowLayout(FlowLayout.RIGHT, 2, 2)); panner = new Panner(canvas, source, 128); panner.setBackground(Color.red); panner.setBorder(new EtchedBorder()); canvas.add(panner); Font font = new Font("SansSerif", Font.BOLD, 12); JLabel title = new JLabel(" Histogram"); title.setFont(font); title.setLocation(0, 32); setOpaque(true); setLayout(new BorderLayout()); setBackground(Color.white); graph = new XYPlot(); graph.setBackground(Color.black); graph.setBorder(new LineBorder(new Color(0,0,255), 1)); Colorbar cbar = new Colorbar(); cbar.setBackground(Color.black); cbar.setPreferredSize(new Dimension(256, 25)); cbar.setBorder(new LineBorder(new Color(255,0,255),2)); JPanel hist_panel = new JPanel(); hist_panel.setLayout(new BorderLayout()); hist_panel.setBackground(Color.white); hist_panel.add(graph, BorderLayout.CENTER); hist_panel.add(cbar, BorderLayout.SOUTH); JPanel panel = new JPanel(); panel.setLayout(new GridLayout(2,1,5,5)); panel.setBackground(Color.white); panel.add(canvas); panel.add(hist_panel); JPanel controlPanel = new JPanel(); controlPanel.setLayout(new FlowLayout()); reset = new JButton("Reset"); equal = new JButton("Equalize"); norm = new JButton("Normalize"); piece = new JButton("Piecewise"); reset.addActionListener(this); equal.addActionListener(this);

norm.addActionListener(this); piece.addActionListener(this); controlPanel.add(reset); controlPanel.add(equal); controlPanel.add(norm); controlPanel.add(piece); add(title, BorderLayout.NORTH); add(panel, BorderLayout.CENTER); add(controlPanel, BorderLayout.SOUTH); // original histogram (remains unmodified) graph.plot( getHistogram(source) ); } public int[] getHistogram(PlanarImage image) { // set up the histogram int[] bins = { 256 }; double[] low = { 0.0D }; double[] high = { 256.0D }; Histogram histogram = new Histogram(bins, low, high); ParameterBlock pb = new ParameterBlock(); pb.addSource(image); pb.add(histogram); pb.add(null); pb.add(1); pb.add(1); RenderedOp op = JAI.create("histogram", pb, null); histogram = (Histogram) op.getProperty("histogram"); // get histogram contents int[] local_array = new int[histogram.getNumBins(0)]; for ( int i = 0; i < histogram.getNumBins(0); i++ ) { local_array[i] = histogram.getBinSize(0, i); } return local_array; } // one way to do this (old style) // this could also be done with matchcdf public PlanarImage equalize() { int sum = 0; byte[] cumulative = new byte[256]; int array[] = getHistogram(source); float scale = 255.0F / (float) (source.getWidth() * source.getHeight()); for ( int i = 0; i < 256; i++ ) { sum += array[i]; cumulative[i] = (byte)((sum * scale) + .5F); } LookupTableJAI lookup = new LookupTableJAI(cumulative);

ParameterBlock pb = new ParameterBlock(); pb.addSource(source); pb.add(lookup); return JAI.create("lookup", pb, null); } // for a single band public PlanarImage normalize() { double[] mean = new double[] { 128.0 }; double[] stDev = new double[] { 34.0 }; float[][] CDFnorm = new float[1][]; CDFnorm[0] = new float[256]; double mu = mean[0]; double twoSigmaSquared = 2.0*stDev[0]*stDev[0]; CDFnorm[0][0] = (float)Math.exp(-mu*mu/twoSigmaSquared); for ( int i = 1; i < 256; i++ ) { double deviation = i - mu; CDFnorm[0][i] = CDFnorm[0][i-1] + (float)Math.exp(-deviation*deviation/twoSigmaSquared); } double CDFnormLast = CDFnorm[0][255]; for ( int i = 0; i < 256; i++ ) { CDFnorm[0][i] /= CDFnormLast; } int[] bins = { 256 }; double[] low = { 0.0D }; double[] high = { 256.0D }; Histogram hstgrm = new Histogram(bins, low, high); RenderedOp fmt = JAI.create("histogram", source, hstgrm, null, new Integer(1), new Integer(1)); return JAI.create("matchcdf", fmt, CDFnorm); } public PlanarImage piecewise() { float[][][] bp = new float[1][2][]; bp[0][0] = new float[] { 0.0F, 32.0F, 64.0F, 255.0F }; bp[0][1] = new float[] { 0.0F, 128.0F, 112.0F, 255.0F }; return JAI.create("piecewise", source, bp); } public void actionPerformed(ActionEvent e) { JButton b = (JButton)e.getSource(); if ( b == reset ) { target = source; } else if ( b == equal ) { target = equalize(); } else if ( b == norm ) { target = normalize(); } else if ( b == piece ) { target = piecewise();

} canvas.set(target); graph.plot( getHistogram(target) ); } }

Sign up to vote on this title
UsefulNot useful