Sugiero consultar la API de Java Advanced Imaging (JAI). Probablemente esté utilizando BufferedImage ahora mismo, lo que mantiene todo en la memoria: las imágenes de origen y las de salida. Esto se conoce como procesamiento de "modo inmediato". Cuando llamas a un método para cambiar el tamaño de la imagen, sucede de inmediato. Como resultado, todavía conserva las imágenes en la memoria.
Con JAI, hay dos ventajas que puede aprovechar.
- Procesamiento en modo diferido.
- cálculo de azulejos.
El modo diferido significa que las imágenes de salida no se calculan correctamente cuando llama a los métodos en las imágenes. En cambio, una llamada para cambiar el tamaño de una imagen crea un pequeño objeto de "operador" que puede hacer el cambio de tamaño más tarde. Esto le permite construir cadenas, árboles o tuberías de operaciones. Por lo tanto, su trabajo crearía un árbol de operaciones como "recorte, cambio de tamaño, compuesto" para cada imagen de stock.Lo bueno es que las operaciones son solo objetos de comando, así que no estás consumiendo toda la memoria mientras construyes tus comandos.
Esta API está basada en el tirón. Se difiere el cálculo hasta que alguna acción de salida extraiga píxeles de los operadores. Esto ayuda a ahorrar tiempo y memoria al evitar operaciones de píxeles innecesarias.
Por ejemplo, suponga que necesita una imagen de salida de 2048 x 2048 píxeles, ampliada a partir de un recorte de 512x512 de una imagen de origen que tiene 1600x512 píxeles. Obviamente, no tiene sentido escalar toda la imagen fuente de 1600x512, solo para tirar 2/3 de los píxeles. En cambio, el operador de escala tendrá una "región de interés" (ROI) en función de sus dimensiones de salida. El operador de escalado proyecta el retorno de la inversión en la imagen de origen y solo calcula esos píxeles.
Los comandos deben eventualmente ser evaluados. Esto sucede en algunas situaciones, principalmente relacionadas con la salida de la imagen final. Por lo tanto, pedir que una Imagen Buffered muestre la salida en la pantalla obligará a todos los comandos a evaluar. Del mismo modo, escribir la imagen de salida en el disco forzará la evaluación.
En algunos casos, puede mantener el segundo beneficio de JAI, que es la representación basada en mosaico. Mientras que BufferedImage hace todo su trabajo de inmediato, en todos los píxeles, la representación de mosaico solo funciona en secciones rectangulares de la imagen a la vez.
Utilizando el ejemplo de antes, la imagen de salida de 2048x2048 se dividirá en mosaicos. Supongamos que son 256x256, y luego la imagen completa se divide en 64 mosaicos. Los objetos del operador JAI saben cómo trabajar una ficha en una ficha. Por lo tanto, escalar la sección de 512x512 de la imagen de origen realmente sucede 64 veces en píxeles de origen de 64x64 a la vez.
Calcular un mosaico a la vez significa pasar por encima de los mosaicos, lo que parecería llevar más tiempo. Sin embargo, dos cosas funcionan a su favor cuando se realiza el cálculo de los mosaicos. En primer lugar, las teselas se pueden evaluar en varios subprocesos al mismo tiempo. Segundo, el uso de la memoria transitoria es mucho, mucho más bajo que el cálculo del modo inmediato.
Todo lo cual es una explicación larga de por qué desea utilizar JAI para este tipo de procesamiento de imágenes.
Un par de notas y advertencias:
- Usted puede derrotar representación basada baldosas sin darse cuenta. En cualquier lugar en el que tenga una Imagen Buffered en el flujo de trabajo, no puede actuar como fuente o receptor de mosaicos.
- Si renderiza en el disco utilizando los operadores JAI o JAI Image I/O para JPEG, entonces está en buena forma. Si intenta utilizar las clases de imágenes integradas del JDK, necesitará toda la memoria. (Básicamente, evite mezclar los dos tipos de manipulación de imágenes. El modo inmediato y el modo diferido no se combinan bien).
- Todas las cosas elegantes con ROI, mosaicos y modo diferido son transparentes para el programa. Solo haces una llamada API en la clase JAI. Solo maneja la maquinaria si necesita más control sobre cosas como el tamaño de los mosaicos, el almacenamiento en caché y la simultaneidad.