Skip to main content

[JAI] PlanarImage vs. BufferedImage

11 replies [Last post]
Anonymous

Hello all,

In some of the examples that I've seen, it looks when an image is displayed
it's first loaded as a PlanarImage (using JAI.create), but then for display
purposes the PlanarImage.getAsBufferedImage() method is used to display it
as a BufferedImage. Doesn't a BufferedImage always hold all of the pixel
data in memory? How does this work for displaying very large images? I
thought that memory usage was much more efficient as a PlanarImage (due to
JAI's ability to do tiling, etc). What happens when it's converted to a
BufferedImage? When using JAI, should images only be manipulated using the
JAI PlanarImage API's but then always displayed as a BufferedImage?

Thanks,

Ryan

[att1.html]

Reply viewing options

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

You should be able to draw the PlanarImage, which is a RenderedImage, using

http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Graphics2D.html#drawRenderedImage(java.awt.image.RenderedImage,%20java.awt.geom.AffineTransform)

Only the tiles which overlap the drawing area will be requested from the
image thereby reducing your memory requirement.

Brian

On Mon, 24 Oct 2005, Nidel, Mike wrote:

> The simple answer is to stick with PlanarImage for operations etc., then
> when you are ready to display pixels, only then do you use a
> BufferedImage.
>
> The key is that your input image should be tiled. If it is a large
> untiled image,
> you probably won't be able to avoid reading the whole contents into
> memory.
> If you have tiled imagery, then you can call PlanarImage.getTile() only
> for the
> tiles you need to draw.
>
> Mike
>
> -----Original Message-----
> From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
> Sent: Monday, October 24, 2005 9:39 AM
> To: interest@jai.dev.java.net
> Subject: [JAI] PlanarImage vs. BufferedImage
>
>
>
> Hello all,
>
>
>
> In some of the examples that I've seen, it looks when an image
> is displayed it's first loaded as a PlanarImage (using JAI.create), but
> then for display purposes the PlanarImage.getAsBufferedImage() method is
> used to display it as a BufferedImage. Doesn't a BufferedImage always
> hold all of the pixel data in memory? How does this work for displaying
> very large images? I thought that memory usage was much more efficient
> as a PlanarImage (due to JAI's ability to do tiling, etc). What happens
> when it's converted to a BufferedImage? When using JAI, should images
> only be manipulated using the JAI PlanarImage API's but then always
> displayed as a BufferedImage?
>
>
>
> Thanks,
>
> Ryan
>
>
>
>

----------------
Brian Burkhalter
Java Multimedia, Imaging, and Graphics
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: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

Kustaa Nyholm

Hi Ryan,

don't no if this helps any, but you can turn byte[] 's to a BufferedImage more efficiently with along the lines of the following code:

DataBuffer db = new DataBufferByte(bts[0], 0);
WritableRaster wr = Raster.createInterleavedRaster(db, w, h, w, 1,
new int[] { 0 }, new Point(0, 0));
Hashtable ht = new Hashtable();
ht.put("owner", "kusti");
ColorModel ccm = new ComponentColorModel(ColorSpace
.getInstance(ColorSpace.CS_GRAY), new int[] { 8 }, false,
false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
BufferedImage bi = new BufferedImage(ccm, wr, true, ht);

This particular example is for byte[] -> gray scale, but it works for RGB as well with the approriate changes (don't have my reference here).
This can be faster than setRGB(). Of course it works the otherway round too. getting bytes out of a BufferedImage. In my experience this can be faster than getRGB() although eventually they both call the underlying functions (is suspect).

Of storing image data to database.

We've done that as blob's and it works and has some advantages, but we are moving away from that solution. The main problem (for us) is that backing up large databases is a pain, and very wastefull (in our application the image data never changes once it is stored). So we are implementing a solution in which we store image data in a file system and only keep references to it in the database. To keep image data safe and private we have a server process that accesses the file system (only that process has read/write access to that file system) and only retrieve images through that server process.

Just my 2 snt worth.

cheers Kusti

Kustaa Nyholm
Research Manager, Software
Research and Technology Division
PLANMECA OY
Asentajankatu 6
00880 HELSINKI
FINLAND

Please note our new telephone and fax numbers!
Tel: +358 20 7795 572 (direct)
Fax: +358 20 7795 676
GSM: +358 40 580 5193
e-mail: kustaa.nyholm@planmeca.com

This e-mail may contain confidential or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden. We will not be liable for direct, indirect, special or consequential damages arising from alteration of the contents of this message by a third party or as a result of any virus being passed for viruses.

>>> ryan.lecompte@pangonetworks.com 24.10.2005 20:15 >>>
Thanks for the information, Mike. I also had another question related to
actually storing large images in databases. We are storing our images into
the database as raw bytes. Basically we start out with a BufferedImage and
create a ByteArrayOutputStream that is wrapped with a GZIPOutputStream. This
is then wrapped in a DataOutputStream where we store the image type, width,
height and raw pixels by calling BufferedImage.getRGB(). We then just
persisted the raw byte[] array to the database as a blob. When we retrieve
the image, we basically do the opposite operation and retrieve the raw
bytes, create a BufferedImage, and then set each pixel using
BufferedImage.setRGB. Is there a more efficient way to do this? It's
problematic for us since we are now dealing with very large images, and it
takes a lot of memory and time to unpack all of this data into a
reconstituted BufferedImage object.

Thanks!

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 10:47 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

The simple answer is to stick with PlanarImage for operations etc., then

when you are ready to display pixels, only then do you use a BufferedImage.

The key is that your input image should be tiled. If it is a large untiled
image,

you probably won't be able to avoid reading the whole contents into memory.

If you have tiled imagery, then you can call PlanarImage.getTile() only for
the

tiles you need to draw.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 9:39 AM
To: interest@jai.dev.java.net
Subject: [JAI] PlanarImage vs. BufferedImage

Hello all,

In some of the examples that I've seen, it looks when an image is displayed
it's first loaded as a PlanarImage (using JAI.create), but then for display
purposes the PlanarImage.getAsBufferedImage() method is used to display it
as a BufferedImage. Doesn't a BufferedImage always hold all of the pixel
data in memory? How does this work for displaying very large images? I
thought that memory usage was much more efficient as a PlanarImage (due to
JAI's ability to do tiling, etc). What happens when it's converted to a
BufferedImage? When using JAI, should images only be manipulated using the
JAI PlanarImage API's but then always displayed as a BufferedImage?

Thanks,

Ryan

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

Nidel, Mike

Yes, if the image were based on disk, you wouldn't have to load the
whole thing into memory if you use a PlanarImage.

An alternate method would be to partition your images into tiles and
write each tile into the database as a separate BLOB.
Treat each tile as an independent image (using whatever format you want,
compressed or uncompressed). Then, when you
reconstitute the image for display, you just iterate over the tiles you
need, getting each from the database. In this case,
your tiling is external to the format rather than internal.

Just a thought. It really depends what you're doing with the image.

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Tuesday, October 25, 2005 1:22 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

Mike,

You are absolutely correct in that we actually have the whole
image in memory as a byte[] array. Could you recommend a more efficient
way of retrieving the image from the database? What if the image were
stored on the file system (not as a BLOB in the database). If I used
JAI.create("fileload", ...), the entire image wouldn't be loaded in
memory if it were tiled, correct? I guess my only other option would be
to somehow (as you mentioned earlier I believe) write my own ImageIO
plugin reader/writer such that it reads only pieces of the image from
the database and not the entire thing? It seems like this kind of thing
must have been solved before?

Thanks,

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Tuesday, October 25, 2005 11:17 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

But you already have all the data in memory (in the byte[])...
so why the concern of using a BufferedImage?

Admittedly, if you read the byte[] and create a BufferedImage
from it, you'll have two copies of the data in memory. If your memory is
not large enough to do this, you'll have to find another way. If it is,
you could just dispose of the byte[] after reading the BufferedImage.

But getting the data out of the DB the way you are, you can't
avoid having at least one copy of the image fully in memory.

I think of PlanarImage as a wrapper for the tiles of the data.
If the data is untiled, then as soon as you need any of the data, you
have to get it all. If the data is tiled in some way, then only the
needed tiles are computed. But if all the data for your tiles is already
in memory, then you can't really get around anything just by putting a
PlanarImage in front of it.

JPEG doesn't support tiling but JPEG2000 does. It also has
visually-lossless and numerically-lossless compression methods. There is
a reader/writer in the JAI ImageIO tools package. I haven't ever used
the writer, though, so I can't vouch for its performance/capabilities.
Actually, there are two readers, at least on Windows. One is native
accelerated and the other is not.

Sounds like getting rid of GZIP is a good start towards
improving your performance.

Mike

-----Original Message-----
From: Ryan LeCompte
[mailto:ryan.lecompte@pangonetworks.com]
Sent: Tuesday, October 25, 2005 10:12 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

Hello Mike,

The current implementation uses GZIP, but I don't think
that disk space is an issue here. We can definitely stop using GZIP. I
did a little bit of performance testing, and it turns out that using
DataInputStream.readInt() on a ByteArrayInputStream is much faster than
using a ByteArrayInputStream that's wrapped in a GZIPInputStream. I
think that the time it takes to actually read the raw bytes from the
BLOB in the database will be much faster if we remove the GZIP layer.

After we read all of the data for the image, we
basically are left with a byte[] array. What's the most memory-efficient
way to represent the image in Java? I know that using a BufferedImage
isn't that efficient since it stores all pixels in memory. Is the most
efficient representation a PlanarImage that you get from reading the
image using JAI.create? Note that the image format doesn't matter. You
suggested writing the images as JPEG2000 images. Wouldn't this defeat
the benefit of using a PlanarImage since JPEG doesn't support tiling?
Also, our application is the only one that would be accessing/reading
these images. Thanks for responding and I look forward to any advice
that you can provide.

Thanks,

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 1:48 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

A couple questions to further specify the problem:

1. I'm curious how large is "large"?

2. Is your application the only client to the image
database? E.g. are the images stored or retrieved by any other apps than
yours?

3. Does the image format matter?

4. How much does your DB usage matter?

At first glance (the 5-minute answer), you could write
your own ImageReader (it's not that incredibly hard really) and your own
RenderedImage (may want to subclass PlanarImage, but it may not be
possible). Your RenderedImage could manage the DB access.

A couple of possible approaches, depending on your
answers above:

1. skip the GZIP, write JPEG2000 images straight to the
DB

2. write a tiled image to the DB, potentially even
writing each tile into its own separate BLOB.

If you aren't too concerned about space in the DB (which
is probably not true since you're doing a GZIP) then you could just
write uncompressed images right to the database. In any case, if you get
into a complicated specialized solution you'll probably need to write
your own ImageIO plugin.

Mike

-----Original Message-----
From: Ryan LeCompte
[mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 1:15 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

Thanks for the information, Mike. I also had
another question related to actually storing large images in databases.
We are storing our images into the database as raw bytes. Basically we
start out with a BufferedImage and create a ByteArrayOutputStream that
is wrapped with a GZIPOutputStream. This is then wrapped in a
DataOutputStream where we store the image type, width, height and raw
pixels by calling BufferedImage.getRGB(). We then just persisted the raw
byte[] array to the database as a blob. When we retrieve the image, we
basically do the opposite operation and retrieve the raw bytes, create a
BufferedImage, and then set each pixel using BufferedImage.setRGB. Is
there a more efficient way to do this? It's problematic for us since we
are now dealing with very large images, and it takes a lot of memory and
time to unpack all of this data into a reconstituted BufferedImage
object.

Thanks!

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 10:47 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

The simple answer is to stick with PlanarImage
for operations etc., then

when you are ready to display pixels, only then
do you use a BufferedImage.

The key is that your input image should be
tiled. If it is a large untiled image,

you probably won't be able to avoid reading the
whole contents into memory.

If you have tiled imagery, then you can call
PlanarImage.getTile() only for the

tiles you need to draw.

Mike

-----Original Message-----
From: Ryan LeCompte
[mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 9:39 AM
To: interest@jai.dev.java.net
Subject: [JAI] PlanarImage vs.
BufferedImage

Hello all,

In some of the examples that I've seen,
it looks when an image is displayed it's first loaded as a PlanarImage
(using JAI.create), but then for display purposes the
PlanarImage.getAsBufferedImage() method is used to display it as a
BufferedImage. Doesn't a BufferedImage always hold all of the pixel data
in memory? How does this work for displaying very large images? I
thought that memory usage was much more efficient as a PlanarImage (due
to JAI's ability to do tiling, etc). What happens when it's converted to
a BufferedImage? When using JAI, should images only be manipulated using
the JAI PlanarImage API's but then always displayed as a BufferedImage?

Thanks,

Ryan

[att1.html]

Nidel, Mike

But you already have all the data in memory (in the byte[])... so why
the concern of using a BufferedImage?

Admittedly, if you read the byte[] and create a BufferedImage from it,
you'll have two copies of the data in memory. If your memory is not
large enough to do this, you'll have to find another way. If it is, you
could just dispose of the byte[] after reading the BufferedImage.

But getting the data out of the DB the way you are, you can't avoid
having at least one copy of the image fully in memory.

I think of PlanarImage as a wrapper for the tiles of the data. If the
data is untiled, then as soon as you need any of the data, you have to
get it all. If the data is tiled in some way, then only the needed tiles
are computed. But if all the data for your tiles is already in memory,
then you can't really get around anything just by putting a PlanarImage
in front of it.

JPEG doesn't support tiling but JPEG2000 does. It also has
visually-lossless and numerically-lossless compression methods. There is
a reader/writer in the JAI ImageIO tools package. I haven't ever used
the writer, though, so I can't vouch for its performance/capabilities.
Actually, there are two readers, at least on Windows. One is native
accelerated and the other is not.

Sounds like getting rid of GZIP is a good start towards improving your
performance.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Tuesday, October 25, 2005 10:12 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

Hello Mike,

The current implementation uses GZIP, but I don't think that
disk space is an issue here. We can definitely stop using GZIP. I did a
little bit of performance testing, and it turns out that using
DataInputStream.readInt() on a ByteArrayInputStream is much faster than
using a ByteArrayInputStream that's wrapped in a GZIPInputStream. I
think that the time it takes to actually read the raw bytes from the
BLOB in the database will be much faster if we remove the GZIP layer.

After we read all of the data for the image, we basically are
left with a byte[] array. What's the most memory-efficient way to
represent the image in Java? I know that using a BufferedImage isn't
that efficient since it stores all pixels in memory. Is the most
efficient representation a PlanarImage that you get from reading the
image using JAI.create? Note that the image format doesn't matter. You
suggested writing the images as JPEG2000 images. Wouldn't this defeat
the benefit of using a PlanarImage since JPEG doesn't support tiling?
Also, our application is the only one that would be accessing/reading
these images. Thanks for responding and I look forward to any advice
that you can provide.

Thanks,

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 1:48 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

A couple questions to further specify the problem:

1. I'm curious how large is "large"?

2. Is your application the only client to the image database?
E.g. are the images stored or retrieved by any other apps than yours?

3. Does the image format matter?

4. How much does your DB usage matter?

At first glance (the 5-minute answer), you could write your own
ImageReader (it's not that incredibly hard really) and your own
RenderedImage (may want to subclass PlanarImage, but it may not be
possible). Your RenderedImage could manage the DB access.

A couple of possible approaches, depending on your answers
above:

1. skip the GZIP, write JPEG2000 images straight to the DB

2. write a tiled image to the DB, potentially even writing each
tile into its own separate BLOB.

If you aren't too concerned about space in the DB (which is
probably not true since you're doing a GZIP) then you could just write
uncompressed images right to the database. In any case, if you get into
a complicated specialized solution you'll probably need to write your
own ImageIO plugin.

Mike

-----Original Message-----
From: Ryan LeCompte
[mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 1:15 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

Thanks for the information, Mike. I also had another
question related to actually storing large images in databases. We are
storing our images into the database as raw bytes. Basically we start
out with a BufferedImage and create a ByteArrayOutputStream that is
wrapped with a GZIPOutputStream. This is then wrapped in a
DataOutputStream where we store the image type, width, height and raw
pixels by calling BufferedImage.getRGB(). We then just persisted the raw
byte[] array to the database as a blob. When we retrieve the image, we
basically do the opposite operation and retrieve the raw bytes, create a
BufferedImage, and then set each pixel using BufferedImage.setRGB. Is
there a more efficient way to do this? It's problematic for us since we
are now dealing with very large images, and it takes a lot of memory and
time to unpack all of this data into a reconstituted BufferedImage
object.

Thanks!

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 10:47 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

The simple answer is to stick with PlanarImage for
operations etc., then

when you are ready to display pixels, only then do you
use a BufferedImage.

The key is that your input image should be tiled. If it
is a large untiled image,

you probably won't be able to avoid reading the whole
contents into memory.

If you have tiled imagery, then you can call
PlanarImage.getTile() only for the

tiles you need to draw.

Mike

-----Original Message-----
From: Ryan LeCompte
[mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 9:39 AM
To: interest@jai.dev.java.net
Subject: [JAI] PlanarImage vs. BufferedImage

Hello all,

In some of the examples that I've seen, it looks
when an image is displayed it's first loaded as a PlanarImage (using
JAI.create), but then for display purposes the
PlanarImage.getAsBufferedImage() method is used to display it as a
BufferedImage. Doesn't a BufferedImage always hold all of the pixel data
in memory? How does this work for displaying very large images? I
thought that memory usage was much more efficient as a PlanarImage (due
to JAI's ability to do tiling, etc). What happens when it's converted to
a BufferedImage? When using JAI, should images only be manipulated using
the JAI PlanarImage API's but then always displayed as a BufferedImage?

Thanks,

Ryan

[att1.html]

Ryan LeCompte

Mike,

You are absolutely correct in that we actually have the whole image in
memory as a byte[] array. Could you recommend a more efficient way of
retrieving the image from the database? What if the image were stored on the
file system (not as a BLOB in the database). If I used
JAI.create("fileload", .), the entire image wouldn't be loaded in memory if
it were tiled, correct? I guess my only other option would be to somehow (as
you mentioned earlier I believe) write my own ImageIO plugin reader/writer
such that it reads only pieces of the image from the database and not the
entire thing? It seems like this kind of thing must have been solved before?

Thanks,

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Tuesday, October 25, 2005 11:17 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

But you already have all the data in memory (in the byte[])... so why the
concern of using a BufferedImage?

Admittedly, if you read the byte[] and create a BufferedImage from it,
you'll have two copies of the data in memory. If your memory is not large
enough to do this, you'll have to find another way. If it is, you could just
dispose of the byte[] after reading the BufferedImage.

But getting the data out of the DB the way you are, you can't avoid having
at least one copy of the image fully in memory.

I think of PlanarImage as a wrapper for the tiles of the data. If the data
is untiled, then as soon as you need any of the data, you have to get it
all. If the data is tiled in some way, then only the needed tiles are
computed. But if all the data for your tiles is already in memory, then you
can't really get around anything just by putting a PlanarImage in front of
it.

JPEG doesn't support tiling but JPEG2000 does. It also has visually-lossless
and numerically-lossless compression methods. There is a reader/writer in
the JAI ImageIO tools package. I haven't ever used the writer, though, so I
can't vouch for its performance/capabilities. Actually, there are two
readers, at least on Windows. One is native accelerated and the other is
not.

Sounds like getting rid of GZIP is a good start towards improving your
performance.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Tuesday, October 25, 2005 10:12 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

Hello Mike,

The current implementation uses GZIP, but I don't think that disk space is
an issue here. We can definitely stop using GZIP. I did a little bit of
performance testing, and it turns out that using DataInputStream.readInt()
on a ByteArrayInputStream is much faster than using a ByteArrayInputStream
that's wrapped in a GZIPInputStream. I think that the time it takes to
actually read the raw bytes from the BLOB in the database will be much
faster if we remove the GZIP layer.

After we read all of the data for the image, we basically are left with a
byte[] array. What's the most memory-efficient way to represent the image in
Java? I know that using a BufferedImage isn't that efficient since it stores
all pixels in memory. Is the most efficient representation a PlanarImage
that you get from reading the image using JAI.create? Note that the image
format doesn't matter. You suggested writing the images as JPEG2000 images.
Wouldn't this defeat the benefit of using a PlanarImage since JPEG doesn't
support tiling? Also, our application is the only one that would be
accessing/reading these images. Thanks for responding and I look forward to
any advice that you can provide.

Thanks,

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 1:48 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

A couple questions to further specify the problem:

1. I'm curious how large is "large"?

2. Is your application the only client to the image database? E.g. are the
images stored or retrieved by any other apps than yours?

3. Does the image format matter?

4. How much does your DB usage matter?

At first glance (the 5-minute answer), you could write your own ImageReader
(it's not that incredibly hard really) and your own RenderedImage (may want
to subclass PlanarImage, but it may not be possible). Your RenderedImage
could manage the DB access.

A couple of possible approaches, depending on your answers above:

1. skip the GZIP, write JPEG2000 images straight to the DB

2. write a tiled image to the DB, potentially even writing each tile into
its own separate BLOB.

If you aren't too concerned about space in the DB (which is probably not
true since you're doing a GZIP) then you could just write uncompressed
images right to the database. In any case, if you get into a complicated
specialized solution you'll probably need to write your own ImageIO plugin.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 1:15 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

Thanks for the information, Mike. I also had another question related to
actually storing large images in databases. We are storing our images into
the database as raw bytes. Basically we start out with a BufferedImage and
create a ByteArrayOutputStream that is wrapped with a GZIPOutputStream. This
is then wrapped in a DataOutputStream where we store the image type, width,
height and raw pixels by calling BufferedImage.getRGB(). We then just
persisted the raw byte[] array to the database as a blob. When we retrieve
the image, we basically do the opposite operation and retrieve the raw
bytes, create a BufferedImage, and then set each pixel using
BufferedImage.setRGB. Is there a more efficient way to do this? It's
problematic for us since we are now dealing with very large images, and it
takes a lot of memory and time to unpack all of this data into a
reconstituted BufferedImage object.

Thanks!

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 10:47 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

The simple answer is to stick with PlanarImage for operations etc., then

when you are ready to display pixels, only then do you use a BufferedImage.

The key is that your input image should be tiled. If it is a large untiled
image,

you probably won't be able to avoid reading the whole contents into memory.

If you have tiled imagery, then you can call PlanarImage.getTile() only for
the

tiles you need to draw.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 9:39 AM
To: interest@jai.dev.java.net
Subject: [JAI] PlanarImage vs. BufferedImage

Hello all,

In some of the examples that I've seen, it looks when an image is displayed
it's first loaded as a PlanarImage (using JAI.create), but then for display
purposes the PlanarImage.getAsBufferedImage() method is used to display it
as a BufferedImage. Doesn't a BufferedImage always hold all of the pixel
data in memory? How does this work for displaying very large images? I
thought that memory usage was much more efficient as a PlanarImage (due to
JAI's ability to do tiling, etc). What happens when it's converted to a
BufferedImage? When using JAI, should images only be manipulated using the
JAI PlanarImage API's but then always displayed as a BufferedImage?

Thanks,

Ryan

[att1.html]

Brian Burkhalter

Did you say before that the image in the database is compressed, i.e.,
gzipped? In that case I think you would have to load all the bytes in the
image. The only way around that would be to store the data as randomly
accessible uncompressed data, as compressed or uncompressed tiled data, or use
something like JPEG 2000 which lets you extract a random piece of the image.

Brian

On Tue, 25 Oct 2005, Ryan LeCompte wrote:

> I guess my only other option would be to somehow (as
> you mentioned earlier I believe) write my own ImageIO plugin reader/writer
> such that it reads only pieces of the image from the database and not the
> entire thing? It seems like this kind of thing must have been solved before?

----------------
Brian Burkhalter
Java Multimedia, Imaging, and Graphics
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: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

Bob Deen

> In some of the examples that I’ve seen, it looks when an image is
> displayed it’s first loaded as a PlanarImage (using JAI.create), but
> then for display purposes the PlanarImage.getAsBufferedImage() method is
> used to display it as a BufferedImage. Doesn’t a BufferedImage always
> hold all of the pixel data in memory? How does this work for displaying
> very large images? I thought that memory usage was much more efficient
> as a PlanarImage (due to JAI’s ability to do tiling, etc). What happens
> when it’s converted to a BufferedImage? When using JAI, should images
> only be manipulated using the JAI PlanarImage API’s but then always
> displayed as a BufferedImage?

Yes, that would be a very inefficient, although simple, way to do it.

Any use of PlanarImage.GetAsBufferedImage will not only cause the entire
image to be held in memory, but loaded/computed as well. That would be
deadly for a really big image.

If that's what your display widget is doing then I'd recommend getting a
more sophisticated one.

BTW, it's a quirk of Java2D that you do have to get a BufferedImage
ultimately before drawing to the screen, but that can be done on a tile
basis (without copying, usually) rather than for the entire image so it
really doesn't hurt anything.

-Bob Deen @ NASA-JPL Multimission Image Processing Lab
Bob.Deen@jpl.nasa.gov

---------------------------------------------------------------------
To unsubscribe, e-mail: interest-unsubscribe@jai.dev.java.net
For additional commands, e-mail: interest-help@jai.dev.java.net

Nidel, Mike

A couple questions to further specify the problem:

1. I'm curious how large is "large"?
2. Is your application the only client to the image database? E.g. are
the images stored or retrieved by any other apps than yours?
3. Does the image format matter?
4. How much does your DB usage matter?

At first glance (the 5-minute answer), you could write your own
ImageReader (it's not that incredibly hard really) and your own
RenderedImage (may want to subclass PlanarImage, but it may not be
possible). Your RenderedImage could manage the DB access.

A couple of possible approaches, depending on your answers above:

1. skip the GZIP, write JPEG2000 images straight to the DB
2. write a tiled image to the DB, potentially even writing each tile
into its own separate BLOB.

If you aren't too concerned about space in the DB (which is probably not
true since you're doing a GZIP) then you could just write uncompressed
images right to the database. In any case, if you get into a complicated
specialized solution you'll probably need to write your own ImageIO
plugin.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 1:15 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

Thanks for the information, Mike. I also had another question
related to actually storing large images in databases. We are storing
our images into the database as raw bytes. Basically we start out with a
BufferedImage and create a ByteArrayOutputStream that is wrapped with a
GZIPOutputStream. This is then wrapped in a DataOutputStream where we
store the image type, width, height and raw pixels by calling
BufferedImage.getRGB(). We then just persisted the raw byte[] array to
the database as a blob. When we retrieve the image, we basically do the
opposite operation and retrieve the raw bytes, create a BufferedImage,
and then set each pixel using BufferedImage.setRGB. Is there a more
efficient way to do this? It's problematic for us since we are now
dealing with very large images, and it takes a lot of memory and time to
unpack all of this data into a reconstituted BufferedImage object.

Thanks!

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 10:47 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

The simple answer is to stick with PlanarImage for operations
etc., then

when you are ready to display pixels, only then do you use a
BufferedImage.

The key is that your input image should be tiled. If it is a
large untiled image,

you probably won't be able to avoid reading the whole contents
into memory.

If you have tiled imagery, then you can call
PlanarImage.getTile() only for the

tiles you need to draw.

Mike

-----Original Message-----
From: Ryan LeCompte
[mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 9:39 AM
To: interest@jai.dev.java.net
Subject: [JAI] PlanarImage vs. BufferedImage

Hello all,

In some of the examples that I've seen, it looks when an
image is displayed it's first loaded as a PlanarImage (using
JAI.create), but then for display purposes the
PlanarImage.getAsBufferedImage() method is used to display it as a
BufferedImage. Doesn't a BufferedImage always hold all of the pixel data
in memory? How does this work for displaying very large images? I
thought that memory usage was much more efficient as a PlanarImage (due
to JAI's ability to do tiling, etc). What happens when it's converted to
a BufferedImage? When using JAI, should images only be manipulated using
the JAI PlanarImage API's but then always displayed as a BufferedImage?

Thanks,

Ryan

[att1.html]

Ryan LeCompte

Hello Mike,

The current implementation uses GZIP, but I don't think that disk space is
an issue here. We can definitely stop using GZIP. I did a little bit of
performance testing, and it turns out that using DataInputStream.readInt()
on a ByteArrayInputStream is much faster than using a ByteArrayInputStream
that's wrapped in a GZIPInputStream. I think that the time it takes to
actually read the raw bytes from the BLOB in the database will be much
faster if we remove the GZIP layer.

After we read all of the data for the image, we basically are left with a
byte[] array. What's the most memory-efficient way to represent the image in
Java? I know that using a BufferedImage isn't that efficient since it stores
all pixels in memory. Is the most efficient representation a PlanarImage
that you get from reading the image using JAI.create? Note that the image
format doesn't matter. You suggested writing the images as JPEG2000 images.
Wouldn't this defeat the benefit of using a PlanarImage since JPEG doesn't
support tiling? Also, our application is the only one that would be
accessing/reading these images. Thanks for responding and I look forward to
any advice that you can provide.

Thanks,

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 1:48 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

A couple questions to further specify the problem:

1. I'm curious how large is "large"?

2. Is your application the only client to the image database? E.g. are the
images stored or retrieved by any other apps than yours?

3. Does the image format matter?

4. How much does your DB usage matter?

At first glance (the 5-minute answer), you could write your own ImageReader
(it's not that incredibly hard really) and your own RenderedImage (may want
to subclass PlanarImage, but it may not be possible). Your RenderedImage
could manage the DB access.

A couple of possible approaches, depending on your answers above:

1. skip the GZIP, write JPEG2000 images straight to the DB

2. write a tiled image to the DB, potentially even writing each tile into
its own separate BLOB.

If you aren't too concerned about space in the DB (which is probably not
true since you're doing a GZIP) then you could just write uncompressed
images right to the database. In any case, if you get into a complicated
specialized solution you'll probably need to write your own ImageIO plugin.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 1:15 PM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

Thanks for the information, Mike. I also had another question related to
actually storing large images in databases. We are storing our images into
the database as raw bytes. Basically we start out with a BufferedImage and
create a ByteArrayOutputStream that is wrapped with a GZIPOutputStream. This
is then wrapped in a DataOutputStream where we store the image type, width,
height and raw pixels by calling BufferedImage.getRGB(). We then just
persisted the raw byte[] array to the database as a blob. When we retrieve
the image, we basically do the opposite operation and retrieve the raw
bytes, create a BufferedImage, and then set each pixel using
BufferedImage.setRGB. Is there a more efficient way to do this? It's
problematic for us since we are now dealing with very large images, and it
takes a lot of memory and time to unpack all of this data into a
reconstituted BufferedImage object.

Thanks!

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 10:47 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

The simple answer is to stick with PlanarImage for operations etc., then

when you are ready to display pixels, only then do you use a BufferedImage.

The key is that your input image should be tiled. If it is a large untiled
image,

you probably won't be able to avoid reading the whole contents into memory.

If you have tiled imagery, then you can call PlanarImage.getTile() only for
the

tiles you need to draw.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 9:39 AM
To: interest@jai.dev.java.net
Subject: [JAI] PlanarImage vs. BufferedImage

Hello all,

In some of the examples that I've seen, it looks when an image is displayed
it's first loaded as a PlanarImage (using JAI.create), but then for display
purposes the PlanarImage.getAsBufferedImage() method is used to display it
as a BufferedImage. Doesn't a BufferedImage always hold all of the pixel
data in memory? How does this work for displaying very large images? I
thought that memory usage was much more efficient as a PlanarImage (due to
JAI's ability to do tiling, etc). What happens when it's converted to a
BufferedImage? When using JAI, should images only be manipulated using the
JAI PlanarImage API's but then always displayed as a BufferedImage?

Thanks,

Ryan

[att1.html]

Nidel, Mike

The simple answer is to stick with PlanarImage for operations etc., then
when you are ready to display pixels, only then do you use a
BufferedImage.

The key is that your input image should be tiled. If it is a large
untiled image,
you probably won't be able to avoid reading the whole contents into
memory.
If you have tiled imagery, then you can call PlanarImage.getTile() only
for the
tiles you need to draw.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 9:39 AM
To: interest@jai.dev.java.net
Subject: [JAI] PlanarImage vs. BufferedImage

Hello all,

In some of the examples that I've seen, it looks when an image
is displayed it's first loaded as a PlanarImage (using JAI.create), but
then for display purposes the PlanarImage.getAsBufferedImage() method is
used to display it as a BufferedImage. Doesn't a BufferedImage always
hold all of the pixel data in memory? How does this work for displaying
very large images? I thought that memory usage was much more efficient
as a PlanarImage (due to JAI's ability to do tiling, etc). What happens
when it's converted to a BufferedImage? When using JAI, should images
only be manipulated using the JAI PlanarImage API's but then always
displayed as a BufferedImage?

Thanks,

Ryan

[att1.html]

Ryan LeCompte

Thanks for the information, Mike. I also had another question related to
actually storing large images in databases. We are storing our images into
the database as raw bytes. Basically we start out with a BufferedImage and
create a ByteArrayOutputStream that is wrapped with a GZIPOutputStream. This
is then wrapped in a DataOutputStream where we store the image type, width,
height and raw pixels by calling BufferedImage.getRGB(). We then just
persisted the raw byte[] array to the database as a blob. When we retrieve
the image, we basically do the opposite operation and retrieve the raw
bytes, create a BufferedImage, and then set each pixel using
BufferedImage.setRGB. Is there a more efficient way to do this? It's
problematic for us since we are now dealing with very large images, and it
takes a lot of memory and time to unpack all of this data into a
reconstituted BufferedImage object.

Thanks!

Ryan

_____

From: Nidel, Mike [mailto:mike.nidel@lmco.com]
Sent: Monday, October 24, 2005 10:47 AM
To: interest@jai.dev.java.net
Subject: RE: [JAI] PlanarImage vs. BufferedImage

The simple answer is to stick with PlanarImage for operations etc., then

when you are ready to display pixels, only then do you use a BufferedImage.

The key is that your input image should be tiled. If it is a large untiled
image,

you probably won't be able to avoid reading the whole contents into memory.

If you have tiled imagery, then you can call PlanarImage.getTile() only for
the

tiles you need to draw.

Mike

-----Original Message-----
From: Ryan LeCompte [mailto:ryan.lecompte@pangonetworks.com]
Sent: Monday, October 24, 2005 9:39 AM
To: interest@jai.dev.java.net
Subject: [JAI] PlanarImage vs. BufferedImage

Hello all,

In some of the examples that I've seen, it looks when an image is displayed
it's first loaded as a PlanarImage (using JAI.create), but then for display
purposes the PlanarImage.getAsBufferedImage() method is used to display it
as a BufferedImage. Doesn't a BufferedImage always hold all of the pixel
data in memory? How does this work for displaying very large images? I
thought that memory usage was much more efficient as a PlanarImage (due to
JAI's ability to do tiling, etc). What happens when it's converted to a
BufferedImage? When using JAI, should images only be manipulated using the
JAI PlanarImage API's but then always displayed as a BufferedImage?

Thanks,

Ryan

[att1.html]