Skip to main content

[JAI-IMAGEIO] Handling TIFF reading errors [long]

6 replies [Last post]
Anonymous

If you have a few minutes please read this entire message.

Summary: If the TIFF reader attempts to read a given region of an image
perhaps comprising several strips or tiles and it encounters an error
which prevents some or all of the pixels being read, then should it

A) always throw an IOException, even if some pixels were read;
B) emit a warning if some pixels were read but throw an IOException if no
pixels were read;
C) always emit a warning, even if no pixels were read.

Brian

--- BEGIN Rambling ---

There has been a lot of discussion about handling the errors encountered when
reading TIFF images, especially monochrome images compressed using the T.4 and
T.6 (fax group 3 and 4, respectively) bi-level encodings. A number of you are
interested in getting this resolved soon so we thought it best to return to
the problem now.

At the formal specification level there is a single method at issue:

http://java.sun.com/j2se/1.4.2/docs/api/javax/imageio/ImageReader.html#read(int,%20javax.imageio.ImageReadParam)

All the exceptions that this method is specified possibly to throw occur
essentially due to bad parameters except IOException. It is how the
IOExceptions are handled that is at issue.

In the TIFF ImageReader, the destination region is populated by reading the
data of each strip or tile which overlaps the source region. The contents of
these data segments are each read by invoking an implementation method
decodeTile() which in turn invokes TIFFDecompressor.decode():

http://download.java.net/media/jai-imageio/javadoc/1.1-beta/com/sun/media/imageio/plugins/tiff/TIFFDecompressor.html#decode()

So we have essentially this situation:

public BufferedImage read(int imageIndex, ImageReadParam param)
throws IOException {

// code omitted

for (int tj = minTileY; tj <= maxTileY; tj++) {
for (int ti = minTileX; ti <= maxTileX; ti++) {
decodeTile(ti, tj, -1);
}
}

// code omitted

return theImage;
}

private void decodeTile(int ti, int tj, int band) throws IOException {
// code omitted
decompressor.decode();
// code omitted
}

Part of the solution proposed by Andrey would modify decodeTile by bracketing
the decode() call in decodeTile() like this

private void decodeTile(int ti, int tj, int band) throws IOException {
// code omitted
try {
decompressor.decode();
}
//catch errors but don't break decoding
//and continue with next tile/strip
catch(Throwable t) {
processWarningOccurred(t.getMessage());
}
// code omitted
}

so as to emit a warning instead of throwing a Throwable. This is essentially
option C outlined about.

At the other extreme, I wanted to be able to identify each type of error
encountered in decoding the compressed data sets and issue an appropriate
warning. This however would require a lot more analysis.

Robert suggested this week that an intermediate course would be to do
something simple now which would address the immediate problems and defer a
more complicated solution until for example version 1.2 of JAI Image I/O. I
think this is a good idea and would like to propose a compromise solution.

The compromise is to have read() throw an IIOException if and only if no
(zero) pixels in the requested region are read successfully. This means
that decompressor.decode() should throw an IIOException when it encounters a
condition from which it cannot recover only if has not decoded a single pixel
in the requested tile; otherwise it will emit a warning. If decode() throws an
IIOException then decodeTile() will propagate it. Therefore read() should
count the number of successful calls to decodeTile and throw an IIOException
if and only if this number is zero.

Here is a code sample indicating the proposed change

public BufferedImage read(int imageIndex, ImageReadParam param)
throws IOException {

// code omitted

int numTilesDecoded = 0;
for (int tj = minTileY; tj <= maxTileY; tj++) {
for (int ti = minTileX; ti <= maxTileX; ti++) {

try {
decodeTile(ti, tj, -1);
numTilesDecoded++;
} catch(IIOException iioe) {
processWarningOccurred("Failed to read tile ["+
ti+","+tj+"]: "+
iioe.getMessage());
}
}
}

if(numTilesDecoded == 0) {
throw new IIOException("Could not decode any data!");
}

// code omitted

return theImage;
}

To be complerely effective this will require changes to the various
decompressor.decode() methods such that they emit a warning if they
encounter an unrecoverable error and have decoded one or more pixels or an
IIOException otherwise. This will initially be done for the bi-level encodings
RLE, T.4, and T.6 and later for the other compresion types. The exact nature
of the source or all warnings would not necessarily e identified.

Andrey suggested another change to decodeTile() which is to emit a warning and
not attempt to decode the tile if either the strip offset or strip byte count
is zero. This is a good idea but in the scope of the aforementioned solution
an IIOException would be thrown (and caught in read) as described. Therefore
in decodeTile() instead of this

long offset = getTileOrStripOffset(tileIndex);
long byteCount = getTileOrStripByteCount(tileIndex);

//some images report wrong strip/tile count
if(offset == 0 || byteCount == 0) {
processWarningOccurred("Empty tile skipped:" + tileIndex);
return;
}

I would suggest this

long offset = getTileOrStripOffset(tileIndex);
if(offset <= 0L) {
throw new IIOException("Tile or strip offset is zero!");
}
long byteCount = getTileOrStripByteCount(tileIndex);
if(byteCount <= 0L) {
throw new IIOException("Tile or strip byte count is zero!");
}

Please comment at your convenience.

----------------
Brian Burkhalter
Java Media, 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-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Reply viewing options

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

Hi Brian,

I need to unsubscribe the email account of an ex-employee here from the JAI
and ImageIO mailing lists. The account has been removed internally but there
still is an alias active to forward emails to the old address to my account.
This means I can't send an unsubscribe request from that account. Since I am
also personally subscribed to the same lists, I'm getting all emails in
double and can't filter one out.

Could you please unsubscribe bill@digicharm.com from the mailing lists? As
you can see, the domain name is the same as mine.

I'm sorry to be sending this to you, but I can't think of another way.

Thanks a lot!

Marc Boscher
Communications Digicharm Inc.
(514) 448-4475

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

Marc Boscher

Sorry everyone, that last email was not meant for the whole list.

Marc Boscher

-----Original Message-----
From: Marc Boscher [mailto:marcb@digicharm.com]
Sent: June 27, 2006 8:54 AM
To: interest@jai-imageio.dev.java.net
Subject: [JAI-IMAGEIO] unsubscribing an old account

Hi Brian,

I need to unsubscribe the email account of an ex-employee here from the JAI
and ImageIO mailing lists. The account has been removed internally but there
still is an alias active to forward emails to the old address to my account.
This means I can't send an unsubscribe request from that account. Since I am
also personally subscribed to the same lists, I'm getting all emails in
double and can't filter one out.

Could you please unsubscribe bill@digicharm.com from the mailing lists? As
you can see, the domain name is the same as mine.

I'm sorry to be sending this to you, but I can't think of another way.

Thanks a lot!

Marc Boscher
Communications Digicharm Inc.
(514) 448-4475

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

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

Robert Engels

I like option B, since in "most" cases I would assume that current code is
trying to display/print an image, so for the common case, the some image
would still display.

Maybe an ImageIO system property, ImageIO.setThrowExceptionOnAnyError(), so
that existing applications can get the original behavior?

-----Original Message-----
From: Brian.Burkhalter@Sun.COM [mailto:Brian.Burkhalter@Sun.COM]
Sent: Friday, June 23, 2006 5:07 PM
To: JAI-Image I/O discussion list
Subject: [JAI-IMAGEIO] Handling TIFF reading errors [long]

If you have a few minutes please read this entire message.

Summary: If the TIFF reader attempts to read a given region of an image
perhaps comprising several strips or tiles and it encounters an error which
prevents some or all of the pixels being read, then should it

A) always throw an IOException, even if some pixels were read;
B) emit a warning if some pixels were read but throw an IOException if no
pixels were read;
C) always emit a warning, even if no pixels were read.

Brian

--- BEGIN Rambling ---

There has been a lot of discussion about handling the errors encountered
when reading TIFF images, especially monochrome images compressed using the
T.4 and
T.6 (fax group 3 and 4, respectively) bi-level encodings. A number of you
are interested in getting this resolved soon so we thought it best to return
to the problem now.

At the formal specification level there is a single method at issue:

http://java.sun.com/j2se/1.4.2/docs/api/javax/imageio/ImageReader.html#read(
int,%20javax.imageio.ImageReadParam)

All the exceptions that this method is specified possibly to throw occur
essentially due to bad parameters except IOException. It is how the
IOExceptions are handled that is at issue.

In the TIFF ImageReader, the destination region is populated by reading the
data of each strip or tile which overlaps the source region. The contents of
these data segments are each read by invoking an implementation method
decodeTile() which in turn invokes TIFFDecompressor.decode():

http://download.java.net/media/jai-imageio/javadoc/1.1-beta/com/sun/medi...
ageio/plugins/tiff/TIFFDecompressor.html#decode()

So we have essentially this situation:

public BufferedImage read(int imageIndex, ImageReadParam param)
throws IOException {

// code omitted

for (int tj = minTileY; tj <= maxTileY; tj++) {
for (int ti = minTileX; ti <= maxTileX; ti++) {
decodeTile(ti, tj, -1);
}
}

// code omitted

return theImage;
}

private void decodeTile(int ti, int tj, int band) throws IOException {
// code omitted
decompressor.decode();
// code omitted
}

Part of the solution proposed by Andrey would modify decodeTile by
bracketing the decode() call in decodeTile() like this

private void decodeTile(int ti, int tj, int band) throws IOException {
// code omitted
try {
decompressor.decode();
}
//catch errors but don't break decoding
//and continue with next tile/strip
catch(Throwable t) {
processWarningOccurred(t.getMessage());
}
// code omitted
}

so as to emit a warning instead of throwing a Throwable. This is essentially
option C outlined about.

At the other extreme, I wanted to be able to identify each type of error
encountered in decoding the compressed data sets and issue an appropriate
warning. This however would require a lot more analysis.

Robert suggested this week that an intermediate course would be to do
something simple now which would address the immediate problems and defer a
more complicated solution until for example version 1.2 of JAI Image I/O. I
think this is a good idea and would like to propose a compromise solution.

The compromise is to have read() throw an IIOException if and only if no
(zero) pixels in the requested region are read successfully. This means that
decompressor.decode() should throw an IIOException when it encounters a
condition from which it cannot recover only if has not decoded a single
pixel in the requested tile; otherwise it will emit a warning. If decode()
throws an IIOException then decodeTile() will propagate it. Therefore read()
should count the number of successful calls to decodeTile and throw an
IIOException if and only if this number is zero.

Here is a code sample indicating the proposed change

public BufferedImage read(int imageIndex, ImageReadParam param)
throws IOException {

// code omitted

int numTilesDecoded = 0;
for (int tj = minTileY; tj <= maxTileY; tj++) {
for (int ti = minTileX; ti <= maxTileX; ti++) {

try {
decodeTile(ti, tj, -1);
numTilesDecoded++;
} catch(IIOException iioe) {
processWarningOccurred("Failed to read tile ["+
ti+","+tj+"]: "+
iioe.getMessage());
}
}
}

if(numTilesDecoded == 0) {
throw new IIOException("Could not decode any data!");
}

// code omitted

return theImage;
}

To be complerely effective this will require changes to the various
decompressor.decode() methods such that they emit a warning if they
encounter an unrecoverable error and have decoded one or more pixels or an
IIOException otherwise. This will initially be done for the bi-level
encodings RLE, T.4, and T.6 and later for the other compresion types. The
exact nature of the source or all warnings would not necessarily e
identified.

Andrey suggested another change to decodeTile() which is to emit a warning
and not attempt to decode the tile if either the strip offset or strip byte
count is zero. This is a good idea but in the scope of the aforementioned
solution an IIOException would be thrown (and caught in read) as described.
Therefore in decodeTile() instead of this

long offset = getTileOrStripOffset(tileIndex);
long byteCount = getTileOrStripByteCount(tileIndex);

//some images report wrong strip/tile count
if(offset == 0 || byteCount == 0) {
processWarningOccurred("Empty tile skipped:" + tileIndex);
return;
}

I would suggest this

long offset = getTileOrStripOffset(tileIndex);
if(offset <= 0L) {
throw new IIOException("Tile or strip offset is zero!");
}
long byteCount = getTileOrStripByteCount(tileIndex);
if(byteCount <= 0L) {
throw new IIOException("Tile or strip byte count is zero!");
}

Please comment at your convenience.

----------------
Brian Burkhalter
Java Media, 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-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

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

Brian Burkhalter

On Mon, 26 Jun 2006, Robert Engels wrote:

> I like option B,

Good: so do I.

> since in "most" cases I would assume that current code is
> trying to display/print an image, so for the common case, the some image
> would still display.

The consensus seems to be that if *some* data can be read then this is a
non-fatal condition and the plug-in should therefore populate the image
insofar as possible and emit a warning rather than bailing our altogether.

> Maybe an ImageIO system property, ImageIO.setThrowExceptionOnAnyError(), so
> that existing applications can get the original behavior?

We can't change that javax.imageio spec here. I think all we can do is to
define better what is fatal and what it not.

Brian

> -----Original Message-----
> From: Brian.Burkhalter@Sun.COM [mailto:Brian.Burkhalter@Sun.COM]
> Sent: Friday, June 23, 2006 5:07 PM
> To: JAI-Image I/O discussion list
> Subject: [JAI-IMAGEIO] Handling TIFF reading errors [long]
>
> If you have a few minutes please read this entire message.
>
> Summary: If the TIFF reader attempts to read a given region of an image
> perhaps comprising several strips or tiles and it encounters an error which
> prevents some or all of the pixels being read, then should it
>
> A) always throw an IOException, even if some pixels were read;
> B) emit a warning if some pixels were read but throw an IOException if no
> pixels were read;
> C) always emit a warning, even if no pixels were read.
>
> Brian
>
> --- BEGIN Rambling ---
>
> There has been a lot of discussion about handling the errors encountered
> when reading TIFF images, especially monochrome images compressed using the
> T.4 and
> T.6 (fax group 3 and 4, respectively) bi-level encodings. A number of you
> are interested in getting this resolved soon so we thought it best to return
> to the problem now.
>
> At the formal specification level there is a single method at issue:
>
> http://java.sun.com/j2se/1.4.2/docs/api/javax/imageio/ImageReader.html#read(
> int,%20javax.imageio.ImageReadParam)
>
> All the exceptions that this method is specified possibly to throw occur
> essentially due to bad parameters except IOException. It is how the
> IOExceptions are handled that is at issue.
>
> In the TIFF ImageReader, the destination region is populated by reading the
> data of each strip or tile which overlaps the source region. The contents of
> these data segments are each read by invoking an implementation method
> decodeTile() which in turn invokes TIFFDecompressor.decode():
>
> http://download.java.net/media/jai-imageio/javadoc/1.1-beta/com/sun/medi...
> ageio/plugins/tiff/TIFFDecompressor.html#decode()
>
> So we have essentially this situation:
>
> public BufferedImage read(int imageIndex, ImageReadParam param)
> throws IOException {
>
> // code omitted
>
> for (int tj = minTileY; tj <= maxTileY; tj++) {
> for (int ti = minTileX; ti <= maxTileX; ti++) {
> decodeTile(ti, tj, -1);
> }
> }
>
> // code omitted
>
> return theImage;
> }
>
> private void decodeTile(int ti, int tj, int band) throws IOException {
> // code omitted
> decompressor.decode();
> // code omitted
> }
>
> Part of the solution proposed by Andrey would modify decodeTile by
> bracketing the decode() call in decodeTile() like this
>
> private void decodeTile(int ti, int tj, int band) throws IOException {
> // code omitted
> try {
> decompressor.decode();
> }
> //catch errors but don't break decoding
> //and continue with next tile/strip
> catch(Throwable t) {
> processWarningOccurred(t.getMessage());
> }
> // code omitted
> }
>
> so as to emit a warning instead of throwing a Throwable. This is essentially
> option C outlined about.
>
> At the other extreme, I wanted to be able to identify each type of error
> encountered in decoding the compressed data sets and issue an appropriate
> warning. This however would require a lot more analysis.
>
> Robert suggested this week that an intermediate course would be to do
> something simple now which would address the immediate problems and defer a
> more complicated solution until for example version 1.2 of JAI Image I/O. I
> think this is a good idea and would like to propose a compromise solution.
>
> The compromise is to have read() throw an IIOException if and only if no
> (zero) pixels in the requested region are read successfully. This means that
> decompressor.decode() should throw an IIOException when it encounters a
> condition from which it cannot recover only if has not decoded a single
> pixel in the requested tile; otherwise it will emit a warning. If decode()
> throws an IIOException then decodeTile() will propagate it. Therefore read()
> should count the number of successful calls to decodeTile and throw an
> IIOException if and only if this number is zero.
>
> Here is a code sample indicating the proposed change
>
> public BufferedImage read(int imageIndex, ImageReadParam param)
> throws IOException {
>
> // code omitted
>
> int numTilesDecoded = 0;
> for (int tj = minTileY; tj <= maxTileY; tj++) {
> for (int ti = minTileX; ti <= maxTileX; ti++) {
>
> try {
> decodeTile(ti, tj, -1);
> numTilesDecoded++;
> } catch(IIOException iioe) {
> processWarningOccurred("Failed to read tile ["+
> ti+","+tj+"]: "+
> iioe.getMessage());
> }
> }
> }
>
> if(numTilesDecoded == 0) {
> throw new IIOException("Could not decode any data!");
> }
>
> // code omitted
>
> return theImage;
> }
>
> To be complerely effective this will require changes to the various
> decompressor.decode() methods such that they emit a warning if they
> encounter an unrecoverable error and have decoded one or more pixels or an
> IIOException otherwise. This will initially be done for the bi-level
> encodings RLE, T.4, and T.6 and later for the other compresion types. The
> exact nature of the source or all warnings would not necessarily e
> identified.
>
> Andrey suggested another change to decodeTile() which is to emit a warning
> and not attempt to decode the tile if either the strip offset or strip byte
> count is zero. This is a good idea but in the scope of the aforementioned
> solution an IIOException would be thrown (and caught in read) as described.
> Therefore in decodeTile() instead of this
>
> long offset = getTileOrStripOffset(tileIndex);
> long byteCount = getTileOrStripByteCount(tileIndex);
>
> //some images report wrong strip/tile count
> if(offset == 0 || byteCount == 0) {
> processWarningOccurred("Empty tile skipped:" + tileIndex);
> return;
> }
>
> I would suggest this
>
> long offset = getTileOrStripOffset(tileIndex);
> if(offset <= 0L) {
> throw new IIOException("Tile or strip offset is zero!");
> }
> long byteCount = getTileOrStripByteCount(tileIndex);
> if(byteCount <= 0L) {
> throw new IIOException("Tile or strip byte count is zero!");
> }
>
> Please comment at your convenience.
>
> ----------------
> Brian Burkhalter
> Java Media, 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-imageio.dev.java.net
> For additional commands, e-mail: interest-help@jai-imageio.dev.java.net
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: interest-unsubscribe@jai-imageio.dev.java.net
> For additional commands, e-mail: interest-help@jai-imageio.dev.java.net
>
>

----------------
Brian Burkhalter
Java Media, 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-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net

Bob Deen

>> Maybe an ImageIO system property,
>> ImageIO.setThrowExceptionOnAnyError(), so
>> that existing applications can get the original behavior?
>
> We can't change that javax.imageio spec here. I think all we can do is
> to define better what is fatal and what it not.

Maybe not. But we could/should, as a community, propose appropriate
changes for the next IIO spec revision. A "JAI-IIO" community solution
should I hope carry more weight than any individual customer suggesting
the same thing. Especially since this community contains likely the biggest
(and certainly most sophisticated) users of IIO.

(it goes beyond this topic, to whatever OTHER holes we see in the IIO
interface too...)

-Bob

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

Brian Burkhalter

On Mon, 26 Jun 2006, Bob Deen wrote:

>>> Maybe an ImageIO system property, ImageIO.setThrowExceptionOnAnyError(),
>>> so
>>> that existing applications can get the original behavior?
>>
>> We can't change that javax.imageio spec here. I think all we can do is to
>> define better what is fatal and what it not.
>
> Maybe not. But we could/should, as a community, propose appropriate
> changes for the next IIO spec revision. A "JAI-IIO" community solution
> should I hope carry more weight than any individual customer suggesting
> the same thing. Especially since this community contains likely the biggest
> (and certainly most sophisticated) users of IIO.
>
> (it goes beyond this topic, to whatever OTHER holes we see in the IIO
> interface too...)

I concur. It's "just" a matter of organizing the information.

Brian

----------------
Brian Burkhalter
Java Media, 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-imageio.dev.java.net
For additional commands, e-mail: interest-help@jai-imageio.dev.java.net