Skip to main content

RE: [JAI] Improving speed of scaling (was Re: GIF image corrupt and Re: why is my performance...)

2 replies [Last post]

> Hi Mike,
> Thanks a bunch for this good explanation of what is
> happening. But if I
> have this large, untiled* TIFF image
> on a server and I get numerous requests to "see" parts of it in a
> browser, what is the best way to serve these
> sub-images - maybe I'm doing it wrong by using the crop and scale
> operations (and trying to keep original
> image in memory)?

it sounds like you're doing the right thing in principle. keep in
mind that each operator can have a tile cache associated with it,
and this is generally the mechanism for keeping things "in memory".
you may need to tweak the tile cache to manage exactly what you do
and don't want kept in memory.

> You mentioned re-tiling the image. Are you
> suggesting that retiling the untiled image and
> saving that retiled image in memory (or writing it to disk and let
> subsequent requests read the retiled image)
> might speed things up?

Yes on both counts. if you have enough memory to keep the entire
image in the heap, then go ahead and do it. or, if you have enough
memory to bring the image into the heap but can't KEEP it around,
then write it to a temp file and reread that for the actual viewing.

> -------------------------------TIFF image info for one of my images
> -----------------
> * Below is the output of a tiff viewer (sorry, I couldn't get
> tiffinfo
> to work on my XP box), but it seems
> to indicate a non-tiled image.)

yes, it looks untiled to me. oh well.


To unsubscribe, e-mail:
For additional commands, e-mail:

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Thomas Wolf

Mike, thanks again! One last question (hopefully):

Nidel, Mike wrote:
> it sounds like you're doing the right thing in principle. keep in
> mind that each operator can have a tile cache associated with it,
> and this is generally the mechanism for keeping things "in memory".
> you may need to tweak the tile cache to manage exactly what you do
> and don't want kept in memory.

So if I
PlanarImage loadImage = JAI.create("stream", ...);
and then adjust the tile cache for loadImage to be sufficient to store
the single-tile 200mb TIFF, and do a getTiles() operation, then
"loadImage" can be used for subsequent operations (and subsequent user
requests for sub-images), knowing that the single tile that makes up the
image is already in memory, right? So subsequent operations don't need
to have their tile cache tweaked - 'cause they'll just work on the single
tile handed to them by the "loadImage" operation/image....right?

I will try the tweaking and see what results I see.

Thanks a bunch for all your help.

To unsubscribe, e-mail:
For additional commands, e-mail:

Brian Burkhalter

Here are a few comments on this subject thread from last week.

* "Stream" operation versus "ImageRead" operation

JAI includes the "Stream", "FileLoad" and "URL" operations for reading images
from a stream, file, or URL respectively. These operations use the
ImageDecoder implementations supplied via the
package. The "ImageRead" operation is part of JAI-Image I/O Tools. It uses
whatever ImageReader plug-ins are available via the Java Image I/O Framework
javax.imageio. JAI Image I/O Tools also includes the "ImageWrite" operation
which also uses javax.imageio and subsumes the capabilities of the "Encode"
and "FileStore" operations in JAI.

In general we encourage the use of Image I/O and the ImageRead/ImageWrite
operations as opposed to the older codecs and codec-based operations. The
latter are being maintained for the time being but are not part of any true
specification and are unlikely to be enhanced.

One thing that ImageRead allows is what was suggested by Mike Nidel which is
generating an image with tile dimensions specified by an ImageLayout in a
RenderingHints passed to the operation. (This is NOT supported by Stream.)
This however will tend to be efficient at least for large images only if it
is possible to randomly access arbitrary regions of the image being read.
Such is the case for uncompressed TIFF images such as that described in this
thread. Generally random access will not be efficient if compression is used
unless the data were already tiled so that a limited number of tiles would
need to be read to satisfy a request.

* Determining whether an image is tiled

The method javax.imageio.ImageReader.isImageTiled() may be used to determine
whether an image is tiled. If the ImageRead operation is used, a handle to the
ImageReader is available as a property on the source image. Alternately, the
metadata may be examined to determine the state of tiling. For this the native
format metadata structure must be used as the generic metadata
javax_imageio_1.0 does not include tiling information. The metadata are also
available as a property.

* PlanarImage.getAsBufferedImage()

Given that a PlanarImage is semantically read-only while a BufferedImage is
read-write, this method will always allocate a single raster which will
contain all the data in the PlanarImage. It is therefore not very memory
efficient for large data sets.

* Operation chains, execution, and caching

As Mike indicated, when a RenderedOp is created a node is simply added to the
operation graph but data are not immediately computed (unless the operation is
marked as "immediate" such as for image writing operations). When data are
requested, the computed tiles are stored in the TileCache associated with the
operation. Tiles are subject to being flushed from the cache if it runs out of
memory so that it is possible that an operation will have to compute its
tiles more than once. By default a single TileCache instance with a memory
capacity of 16Mb is shared by all operations. The memory capacity of this
cache may be modified by the application which may also set separate caches on
individual operations. Setting a zero-capacity cache will disable caching on
an operation.

* The scenario in question

In the specific scenario referred to in the thread, a server was making
available to the client the output of an operation chain applied only to a
specific subregion of the source image. Given that the source image is an
uncompressed TIFF image, it should be possible to handle this situation
efficiently without reading the entire image into memory. There are a couple
of ways to handle this. In both cases JAI-Image I/O Tools is used in
preference to the JAI codecs.

1. Re-tile the image

As mentioned, you could re-tile the source image to a given tile size using an
ImageLayout in the RenderingHints. In this case only the tiles needed to
satisfy the client request will be read. You should be able to keep your
TileCache capacity smaller in this case and can probably determine an
approximate reasonable size based on the tile dimensions, the typical size of
the client-requested region, and the number of ops in the chain.

2. In this case you would have the same operation chain in effect but instead
of specifing the tile size you would pass in an ImageReadParam to ImageRead
and include the source region. Subsequent client requests would then edit the
chain by supplying a new ImageReadParam. You would then trap the generated
RenderingChangeEvent to determine what to re-do at the sink of the op chain.
The drawback with this approach is that you have to determine the source
region to request which is not the case in approach 1.


Brian Burkhalter
Advanced Development/Media & Entertainment
Market Development Engineering
Sun Microsystems, Inc.

This email message is for the sole use of the intended recipient(s)
and may contain confidential and privileged information. Any
unauthorized review, use, disclosure or distribution is prohibited.
If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.

To unsubscribe, e-mail:
For additional commands, e-mail: