Sie sind auf Seite 1von 65

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 ColorModel: IndexColorModel,


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
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 Si los pixels de la fuente y del destino se solapan, sólo


(DST_OVER) 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.

Destination-out Si los pixels de la fuente y del destino se solapan, se


(DST_OUT) 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.

Clear (CLEAR) Si los pixels de la fuente y del destino se solapan, los


pixels del área solapada se borrarán.

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 fijo-
punto, 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 class javax.media.jai.BorderExtenderConstant
o class javax.media.jai.BorderExtenderCopy
o class javax.media.jai.BorderExtenderReflect
o class javax.media.jai.BorderExtenderWrap
o class javax.media.jai.BorderExtenderZero
o class javax.media.jai.util.CaselessStringKey (implements java.lang.Cloneable, java.io.Serializable)
o class javax.media.jai.registry.CIFRegistry
o class javax.media.jai.CollectionImage (implements java.util.Collection, javax.media.jai.ImageJAI)
o class javax.media.jai.AttributedImageCollection
o class javax.media.jai.CollectionOp (implements javax.media.jai.OperationNode,
java.beans.PropertyChangeListener)
o class javax.media.jai.ImageSequence
o class javax.media.jai.ImageStack
o class javax.media.jai.RenderedImageList (implements java.util.List,
java.awt.image.RenderedImage, java.io.Serializable)
o class java.awt.image.ColorModel (implements java.awt.Transparency)
o class java.awt.image.ComponentColorModel

o class javax.media.jai.FloatDoubleColorModel
o 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)
o class javax.media.jai.CanvasJAI
o class javax.media.jai.widget.ImageCanvas
o class java.awt.Container
o class javax.swing.JComponent (implements java.io.Serializable)

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

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)
o class javax.media.jai.CoordinateImage
o class javax.media.jai.CRIFImpl (implements java.awt.image.renderable.ContextualRenderedImageFactory)
o class javax.media.jai.NullCRIF
o class javax.media.jai.registry.CRIFRegistry
o class java.awt.image.DataBuffer
o class javax.media.jai.DataBufferDouble
o class javax.media.jai.DataBufferFloat
o 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
o 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
o class com.sun.media.jai.codec.FPXDecodeParam (implements
com.sun.media.jai.codec.ImageDecodeParam)
o 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)
o class javax.media.jai.Histogram (implements java.io.Serializable)
o class com.sun.media.jai.codec.ImageCodec
o class com.sun.media.jai.codec.ImageDecoderImpl (implements com.sun.media.jai.codec.ImageDecoder)
o class com.sun.media.jai.codec.ImageEncoderImpl (implements com.sun.media.jai.codec.ImageEncoder)
o class javax.media.jai.ImageLayout (implements java.lang.Cloneable, java.io.Serializable)
o class javax.media.jai.ImageMIPMap (implements javax.media.jai.ImageJAI)
o class javax.media.jai.ImagePyramid
o 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 class com.sun.media.jai.codec.SegmentedSeekableStream
o class javax.media.jai.IntegerSequence
o 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
o class javax.media.jai.JAI
o class com.sun.media.jai.codec.JPEGDecodeParam (implements
com.sun.media.jai.codec.ImageDecodeParam)
o class com.sun.media.jai.codec.JPEGEncodeParam (implements
com.sun.media.jai.codec.ImageEncodeParam)
o class javax.media.jai.KernelJAI (implements java.io.Serializable)
o class javax.media.jai.LookupTableJAI (implements java.io.Serializable)
o class javax.media.jai.ColorCube
o class javax.media.jai.MultiResolutionRenderableImage (implements
java.awt.image.renderable.RenderableImage, java.io.Serializable, javax.media.jai.WritablePropertySource)
o class javax.media.jai.remote.NegotiableCapabilitySet (implements java.io.Serializable)
o class javax.media.jai.remote.NegotiableCollection (implements javax.media.jai.remote.Negotiable)
o class javax.media.jai.remote.NegotiableNumeric (implements javax.media.jai.remote.Negotiable)
o class javax.media.jai.remote.NegotiableNumericRange (implements javax.media.jai.remote.Negotiable)
o 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)
o 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 class javax.media.jai.operator.ExpDescriptor
o class javax.media.jai.operator.ExtremaDescriptor
o class javax.media.jai.operator.FileLoadDescriptor
o class javax.media.jai.operator.FileStoreDescriptor
o class javax.media.jai.operator.FilteredSubsampleDescriptor
o class javax.media.jai.operator.FormatDescriptor
o class javax.media.jai.operator.FPXDescriptor
o class javax.media.jai.operator.GIFDescriptor
o class javax.media.jai.operator.GradientMagnitudeDescriptor
o class javax.media.jai.operator.HistogramDescriptor
o class javax.media.jai.operator.IDCTDescriptor
o class javax.media.jai.operator.IDFTDescriptor
o class javax.media.jai.operator.IIPDescriptor
o class javax.media.jai.operator.IIPResolutionDescriptor
o class javax.media.jai.operator.ImageFunctionDescriptor
o class javax.media.jai.operator.InvertDescriptor
o class javax.media.jai.operator.JPEGDescriptor
o class javax.media.jai.operator.LogDescriptor
o class javax.media.jai.operator.LookupDescriptor
o class javax.media.jai.operator.MagnitudeDescriptor
o class javax.media.jai.operator.MagnitudeSquaredDescriptor
o class javax.media.jai.operator.MatchCDFDescriptor
o class javax.media.jai.operator.MaxDescriptor
o class javax.media.jai.operator.MaxFilterDescriptor
o class javax.media.jai.operator.MeanDescriptor
o class javax.media.jai.operator.MedianFilterDescriptor
o class javax.media.jai.operator.MinDescriptor
o class javax.media.jai.operator.MinFilterDescriptor
o class javax.media.jai.operator.MosaicDescriptor
o class javax.media.jai.operator.MultiplyComplexDescriptor
o class javax.media.jai.operator.MultiplyConstDescriptor
o class javax.media.jai.operator.MultiplyDescriptor
o class javax.media.jai.operator.NotDescriptor
o class javax.media.jai.operator.NullDescriptor
o class javax.media.jai.operator.OrConstDescriptor
o class javax.media.jai.operator.OrderedDitherDescriptor
o class javax.media.jai.operator.OrDescriptor
o class javax.media.jai.operator.OverlayDescriptor
o class javax.media.jai.operator.PatternDescriptor
o class javax.media.jai.operator.PeriodicShiftDescriptor
o class javax.media.jai.operator.PhaseDescriptor
o class javax.media.jai.operator.PiecewiseDescriptor
o class javax.media.jai.operator.PNGDescriptor
o class javax.media.jai.operator.PNMDescriptor
o class javax.media.jai.operator.PolarToComplexDescriptor
o class javax.media.jai.operator.RenderableDescriptor
o class javax.media.jai.operator.RescaleDescriptor
o class javax.media.jai.operator.RotateDescriptor
o class javax.media.jai.operator.ScaleDescriptor
o class javax.media.jai.operator.ShearDescriptor
o class javax.media.jai.operator.StreamDescriptor
o class javax.media.jai.operator.SubsampleAverageDescriptor
o class javax.media.jai.operator.SubsampleBinaryToGrayDescriptor
o class javax.media.jai.operator.SubtractConstDescriptor
o class javax.media.jai.operator.SubtractDescriptor
o class javax.media.jai.operator.SubtractFromConstDescriptor
o class javax.media.jai.operator.ThresholdDescriptor
o class javax.media.jai.operator.TIFFDescriptor
o class javax.media.jai.operator.TranslateDescriptor
o class javax.media.jai.operator.TransposeDescriptor
o class javax.media.jai.operator.UnsharpMaskDescriptor
o class javax.media.jai.operator.URLDescriptor
o class javax.media.jai.operator.WarpDescriptor
o class javax.media.jai.operator.XorConstDescriptor
o class javax.media.jai.operator.XorDescriptor
o class javax.media.jai.OperationNodeSupport (implements java.io.Serializable)
o class javax.media.jai.OperationRegistry (implements java.io.Externalizable)
o class java.io.OutputStream
o class com.sun.media.jai.codec.SeekableOutputStream
o class javax.media.jai.PackedImageData
o class java.awt.image.renderable.ParameterBlock (implements java.lang.Cloneable, java.io.Serializable)
o class javax.media.jai.ParameterBlockJAI (implements javax.media.jai.ParameterList)
o class javax.media.jai.ParameterListDescriptorImpl (implements javax.media.jai.ParameterListDescriptor,
java.io.Serializable)
o 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
o class javax.media.jai.PerspectiveTransform (implements java.lang.Cloneable, java.io.Serializable)
o class javax.media.jai.PixelAccessor
o 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)
o class com.sun.media.jai.codec.PNGDecodeParam (implements
com.sun.media.jai.codec.ImageDecodeParam)
o 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
o class com.sun.media.jai.codec.PNGSuggestedPaletteEntry (implements java.io.Serializable)
o class com.sun.media.jai.codec.PNMEncodeParam (implements
com.sun.media.jai.codec.ImageEncodeParam)
o class java.beans.PropertyChangeSupport (implements java.io.Serializable)
o class javax.media.jai.PropertyChangeSupportJAI
o class javax.media.jai.PropertySourceImpl (implements javax.media.jai.PropertySource, java.io.Serializable)
o class javax.media.jai.WritablePropertySourceImpl (implements
javax.media.jai.WritablePropertySource)
o class javax.media.jai.iterator.RandomIterFactory
o class javax.media.jai.util.Range (implements java.io.Serializable)
o class javax.media.jai.RasterAccessor
o class javax.media.jai.RasterFactory
o class javax.media.jai.RasterFormatTag
o class javax.media.jai.registry.RCIFRegistry
o class javax.media.jai.iterator.RectIterFactory
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
o class javax.media.jai.registry.RemoteCRIFRegistry
o class javax.media.jai.remote.RemoteDescriptorImpl (implements javax.media.jai.remote.RemoteDescriptor)
o class javax.media.jai.remote.JAIRMIDescriptor
o class javax.media.jai.remote.RemoteJAI
o class javax.media.jai.registry.RemoteRIFRegistry
o class javax.media.jai.RenderableImageAdapter (implements java.awt.image.renderable.RenderableImage,
javax.media.jai.WritablePropertySource)
o 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
o class javax.media.jai.registry.RIFRegistry
o class javax.media.jai.ROI (implements java.io.Serializable)
o class javax.media.jai.ROIShape
o class javax.media.jai.iterator.RookIterFactory
o class java.awt.image.SampleModel
o class java.awt.image.ComponentSampleModel
o class javax.media.jai.ComponentSampleModelJAI
o class javax.media.jai.SequentialImage
o class javax.media.jai.remote.SerializableRenderedImage (implements java.awt.image.RenderedImage,
java.io.Serializable)
o class javax.media.jai.remote.SerializerFactory
o class com.sun.media.jai.codec.StreamSegment
o 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 class javax.media.jai.remote.RemoteImagingException
o class com.sun.media.jai.codec.TIFFDecodeParam (implements
com.sun.media.jai.codec.ImageDecodeParam)
o class com.sun.media.jai.codec.TIFFDirectory (implements java.io.Serializable)
o class com.sun.media.jai.codec.TIFFEncodeParam (implements
com.sun.media.jai.codec.ImageEncodeParam)
o class com.sun.media.jai.codec.TIFFField (implements java.lang.Comparable, java.io.Serializable)
o 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
o class javax.media.jai.tilecodec.TileDecoderImpl (implements javax.media.jai.tilecodec.TileDecoder)
o class javax.media.jai.registry.TileDecoderRegistry
o class javax.media.jai.tilecodec.TileEncoderImpl (implements javax.media.jai.tilecodec.TileEncoder)
o class javax.media.jai.registry.TileEncoderRegistry
o class javax.media.jai.UnpackedImageData
o 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)

o 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)
o interface javax.media.jai.CollectionImageFactory
o interface javax.media.jai.ColorModelFactory
o interface java.util.EventListener
o interface javax.media.jai.TileComputationListener
o interface javax.media.jai.widget.ImageCanvas.PaintListener
o interface com.sun.media.jai.codec.ImageDecoder
o interface com.sun.media.jai.codec.ImageEncoder
o interface javax.media.jai.ImageFunction
o interface javax.media.jai.util.ImagingListener
o interface com.sun.media.jai.remote.JAIServerConfigurationSpi
o interface javax.media.jai.OperationRegistrySpi
o interface javax.media.jai.ParameterList
o interface javax.media.jai.ParameterListDescriptor
o 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 interface javax.media.jai.ImageJAI
o 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
o interface javax.media.jai.iterator.RandomIter
o interface javax.media.jai.iterator.WritableRandomIter
o 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)
o interface javax.media.jai.iterator.WritableRectIter
o interface javax.media.jai.iterator.WritableRookIter (also extends
javax.media.jai.iterator.RookIter)
o 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
o interface javax.media.jai.remote.RemoteRIF
o interface javax.media.jai.remote.RemoteCRIF
o interface javax.media.jai.RenderableCollectionImageFactory
o interface java.awt.image.RenderedImage
o interface javax.media.jai.remote.RemoteRenderedImage
o interface java.io.Serializable
o interface com.sun.media.jai.codec.ImageDecodeParam (also extends java.lang.Cloneable)
o 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
o interface javax.media.jai.remote.Serializer
o interface com.sun.media.jai.codec.StreamSegmentMapper
o interface javax.media.jai.TileCache
o interface javax.media.jai.tilecodec.TileDecoder
o interface javax.media.jai.tilecodec.TileDecoderFactory
o interface javax.media.jai.tilecodec.TileEncoder
o interface javax.media.jai.tilecodec.TileEncoderFactory
o interface javax.media.jai.TileFactory
o interface javax.media.jai.TileRecycler
o interface javax.media.jai.TileRequest
o interface javax.media.jai.TileScheduler
o 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) );
}
}

Das könnte Ihnen auch gefallen