Skip to main content

[JAI-IMAGEIO] Writing a generic image converter

2 replies [Last post]
Anonymous

I am wondering if I am being too optimistic in what the image writers
and metadata converters can do for me. So say in the case of tiff->png
I'll need to scale the image based on the metadata's resolution, and for
tiff->jpg I'll have to alter the metadata to match the destination bands
(I get this sometimes javax.imageio.IIOException: Metadata components !=
number of destination bands).

I'm just trying to make my image conversion code as generic as possible,
and maybe I am missing something here or I really do need to handle
conversion specifics myself for each case.

public ArrayList readWrite(InputStream in, String
formatName) throws IOException {
ArrayList images = new ArrayList();

ImageInputStream inStream = ImageIO.createImageInputStream(in);
ImageReader reader = ImageIO.getImageReaders(inStream).next();
reader.setInput(inStream);

int numImages = reader.getNumImages(true);
IIOMetadata streamMetadata = reader.getStreamMetadata();

for (int imageIndex = 0; imageIndex < numImages; imageIndex++) {
RenderedImage image = reader.read(imageIndex);

IIOMetadata imageMetadata =
reader.getImageMetadata(imageIndex);

ByteArrayOutputStream bout = new ByteArrayOutputStream();
ImageOutputStream outStream = new
MemoryCacheImageOutputStream(bout);

Iterator itr = (Iterator)
ImageIO.getImageWritersByFormatName(formatName);
ImageWriter writer = itr.next();

ImageWriteParam wparam = writer.getDefaultWriteParam();

imageMetadata =
writer.convertImageMetadata(imageMetadata, new
ImageTypeSpecifier(image), wparam);

writer.setOutput(outStream);

if (wparam.canWriteCompressed() &&
!formatName.equalsIgnoreCase("JPEG")) {

wparam.setCompressionMode(ImageWriteParam.MODE_COPY_FROM_METADATA);
}
if (wparam.canWriteTiles()) {

wparam.setTilingMode(ImageWriteParam.MODE_COPY_FROM_METADATA);
}

writer.write(imageMetadata, new IIOImage(image, null,
imageMetadata), wparam);

outStream.flush();

images.add(bout.toByteArray());

outStream.close();
bout.close();

return images;
}

--
Aaron Bruegl

---------------------------------------------------------------------
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.
robert engels

You cannot use the source image's metadata, since the destination
image format may not support images with that pixel depth - so yes,
you will need to do some special case processing if you want to use
the ideal compression/format for a particular image.

On Jul 11, 2006, at 11:28 AM, Aaron Bruegl wrote:

> I am wondering if I am being too optimistic in what the image
> writers and metadata converters can do for me. So say in the case
> of tiff->png I'll need to scale the image based on the metadata's
> resolution, and for tiff->jpg I'll have to alter the metadata to
> match the destination bands (I get this sometimes
> javax.imageio.IIOException: Metadata components != number of
> destination bands).
>
> I'm just trying to make my image conversion code as generic as
> possible, and maybe I am missing something here or I really do need
> to handle conversion specifics myself for each case.
>
> public ArrayList readWrite(InputStream in, String
> formatName) throws IOException {
> ArrayList images = new ArrayList();
> ImageInputStream inStream =
> ImageIO.createImageInputStream(in);
> ImageReader reader = ImageIO.getImageReaders(inStream).next();
> reader.setInput(inStream);
> int numImages = reader.getNumImages(true);
> IIOMetadata streamMetadata = reader.getStreamMetadata();
> for (int imageIndex = 0; imageIndex < numImages;
> imageIndex++) {
> RenderedImage image = reader.read(imageIndex);
>
> IIOMetadata imageMetadata = reader.getImageMetadata
> (imageIndex);
>
> ByteArrayOutputStream bout = new
> ByteArrayOutputStream();
> ImageOutputStream outStream = new
> MemoryCacheImageOutputStream(bout);
>
> Iterator itr = (Iterator)
> ImageIO.getImageWritersByFormatName(formatName);
> ImageWriter writer = itr.next();
>
> ImageWriteParam wparam = writer.getDefaultWriteParam();
>
> imageMetadata = writer.convertImageMetadata
> (imageMetadata, new ImageTypeSpecifier(image), wparam);
>
> writer.setOutput(outStream);
>
> if (wparam.canWriteCompressed() && !
> formatName.equalsIgnoreCase("JPEG")) {
> wparam.setCompressionMode
> (ImageWriteParam.MODE_COPY_FROM_METADATA);
> }
> if (wparam.canWriteTiles()) {
> wparam.setTilingMode
> (ImageWriteParam.MODE_COPY_FROM_METADATA);
> }
>
> writer.write(imageMetadata, new IIOImage(image,
> null, imageMetadata), wparam);
>
> outStream.flush();
>
> images.add(bout.toByteArray());
>
> outStream.close();
> bout.close();
> return images;
> }
>
> --
> Aaron Bruegl
>
> ---------------------------------------------------------------------
> 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

You should be able to determine from the ImageWriter's originating provider
whether it can encode a given image image type:

http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/spi/ImageWriterSpi.html#canEncodeImage(javax.imageio.ImageTypeSpecifier)

Assuming that the writer can encode your image then you have to know whether
the destination and source metadata have any format(s) in common. This can
also be determined using the provider. In general the only common metadata
format is the plug-in neutral format "javax_imageio_1.0"

http://java.sun.com/j2se/1.5.0/docs/api/javax/imageio/metadata/doc-files...

so that there will be some loss of information during transcoding.

Brian

On Tue, 11 Jul 2006, robert engels wrote:

> You cannot use the source image's metadata, since the destination image
> format may not support images with that pixel depth - so yes, you will need
> to do some special case processing if you want to use the ideal
> compression/format for a particular image.
>
>
> On Jul 11, 2006, at 11:28 AM, Aaron Bruegl wrote:
>
>> I am wondering if I am being too optimistic in what the image writers and
>> metadata converters can do for me. So say in the case of tiff->png I'll
>> need to scale the image based on the metadata's resolution, and for
>> tiff->jpg I'll have to alter the metadata to match the destination bands (I
>> get this sometimes javax.imageio.IIOException: Metadata components !=
>> number of destination bands).
>>
>> I'm just trying to make my image conversion code as generic as possible,
>> and maybe I am missing something here or I really do need to handle
>> conversion specifics myself for each case.
>>
>> public ArrayList readWrite(InputStream in, String formatName)
>> throws IOException {
>> ArrayList images = new ArrayList();
>> ImageInputStream inStream = ImageIO.createImageInputStream(in);
>> ImageReader reader = ImageIO.getImageReaders(inStream).next();
>> reader.setInput(inStream);
>> int numImages = reader.getNumImages(true);
>> IIOMetadata streamMetadata = reader.getStreamMetadata();
>> for (int imageIndex = 0; imageIndex < numImages; imageIndex++)
>> {
>> RenderedImage image = reader.read(imageIndex);
>>
>> IIOMetadata imageMetadata =
>> reader.getImageMetadata(imageIndex);
>>
>> ByteArrayOutputStream bout = new ByteArrayOutputStream();
>> ImageOutputStream outStream = new
>> MemoryCacheImageOutputStream(bout);
>>
>> Iterator itr = (Iterator)
>> ImageIO.getImageWritersByFormatName(formatName);
>> ImageWriter writer = itr.next();
>>
>> ImageWriteParam wparam = writer.getDefaultWriteParam();
>>
>> imageMetadata = writer.convertImageMetadata(imageMetadata,
>> new ImageTypeSpecifier(image), wparam);
>>
>> writer.setOutput(outStream);
>>
>> if (wparam.canWriteCompressed() &&
>> !formatName.equalsIgnoreCase("JPEG")) {
>> wparam.setCompressionMode(ImageWriteParam.MODE_COPY_FROM_METADATA);
>> }
>> if (wparam.canWriteTiles()) {
>> wparam.setTilingMode(ImageWriteParam.MODE_COPY_FROM_METADATA);
>> }
>>
>> writer.write(imageMetadata, new IIOImage(image, null,
>> imageMetadata), wparam);
>>
>> outStream.flush();
>>
>> images.add(bout.toByteArray());
>>
>> outStream.close();
>> bout.close();
>> return images;
>> }
>>
>> --
>> Aaron Bruegl
>>
>> ---------------------------------------------------------------------
>> 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