RE: [JAI-IMAGEIO] Getting filename to codec?
This seems to be a fairly common problem, I guess I'll chime in here
with my experiences. I call it the "associated files" problem, because
it deals with the need to find other files that are associated with a
given input file. I just completed a design that accommodates this
situation last week, so it's fresh in my mind.
We originally used a specialized ImageReadParam to pass the File
(or the filename) into the reader. But it seems that for certain
cases, the ImageReadParam isn't available early enough in the
decoding process, or perhaps not at the right times.
Our second implementation was to create our own custom implementation
of ImageInputStream that contained the file (much like the solution
talked about below). This works fine, although we didn't use the
ImageInputStreamSpi but rather just created the custom stream
Then we encountered problems when we wanted our readers to be able
to read from, say, an HTTP stream or some other non-file stream.
The issue of locating "associated resources" (the other file or
files, with different extensions or whatever) becomes more tricky
in these cases. We needed to abstract this so we could open
images and other resources from any source.
We considered using a custom ImageInputStreamSpi, but these are
keyed off the java class of the input object (from which you are
trying to generate an ImageInputStream). In our case, for example,
we might want a different implementation depending on whether
we're creating an http URL or some other kind of URL. So there is
no way, using the ImageInputStreamSpi, to differentiate between
one kind of URL and another (since the Spi mechanism uses the java
class to choose a Spi).
What I came up with relies a little bit on our architecture that
was already in place, but its principle could be adapted to any
application. Essentially, we have an abstraction of the
ImageReader called an ImageSource, which allows you to get
image attributes and metadata, as well as RenderedImages. Then
there is an ImageSourceFactory that constructs these based on
an identifier -- in most cases a filename, but possibly also
a URL or other token.
The ImageSourceFactory creates a stream and uses it to perform
a lookup from ImageIO.getImageReaders(). The stream itself is
created using a special interface called a StreamFactory (surprise).
StreamFactory implementations are plugin objects that use a SPI
mechanism (much like the ImageReaderSpis). A resource name
(filename, URL string etc) is passed to a lookup object that
identifies the appropriate StreamFactory for the resource.
The resource name and the StreamFactory are bundled up in a
wrapper object we call a SourceID (which is actually built in
a different place).
The StreamFactory is used by the ImageSourceFactory to produce
an ImageInputStream for the ImageReader lookup. Once an
ImageReader is located, we check to see if it is "one of ours",
i.e. an ImageReader implemented in-house that requires this
ability to locate associated files. If so, we have a custom
API (just a one-method interface) that allows passing the
custom object to the reader BEFORE it is used in the app.
In pseudocode it's something like this:
public ImageSource createImageSource(String resource)
// use custom SPI mechanism to find a StreamFactory
StreamFactory factory = lookupStreamFactory(resource);
SourceID sid = new SourceID(resource, factory);
ImageInputStream stream = factory.createImageInputStream(resource);
ImageReader reader = getImageReaderFromImageIO(stream);
if(reader instanceof SourceIDImageReader)
// this gives our custom readers access to the filename and stream
return new ImageIoImageSource(reader);
The only thing that is NOT handled by this code is the case where
your ImageReaderSpi needs to know about associated files BEFORE it can
decide whether a given image is supported by your ImageReader. As you
can see, we're not embedding the filename/resource name directly IN
the ImageInputStream. In our case, the SourceID encapsulates that. But
you certainly could do something much like the above, where the
StreamFactory puts the resource name directly in the ImageInputStream
that it creates. Then you could get access to it on the canDecodeInput()
calls to your ImageReaderSpi.
I hope this description helps somebody or provides food for thought.
> -----Original Message-----
> From: Fabrizio Giudici [mailto:Fabrizio.Giudici@tidalwave.it]
> Sent: Thursday, June 01, 2006 3:26 AM
> To: firstname.lastname@example.org
> Subject: Re: [JAI-IMAGEIO] Getting filename to codec?
> On Jun 1, 2006, at 6:28 AM, email@example.com wrote:
> > I'm implementing an ImageIO codec which is based on
> > an image library that, unfortunately, requires a file
> > name in order to open the image as opposed to supporting
> using already
> > opened files or streams.
> > I see that in writing the codec I can specify different
> > sorts of input objects (ImageInputStream, for example)
> > so it seems the codec can support opening the image
> > based on a string filename. What I don't see is how
> > to get JAI to send a filename across.
> > When I do a JAI.create( "ImageRead", filename ) it
> > seems that the ImageRead operation has already opened
> > the file and turned it into an ImageInputStream by the
> > time it gets to my codec. Is there a trick to getting
> > the data across? Or do I need to write my own JAI
> > operation?
> I had a similar problem with a codec I wrote for the Canon
> .CRW format, where unfortunately a single image is split into
> two files with two
> extensions, and matching should be done by file name.
> I registered a custom ImageInputStreamSpi, which is a factory that
> can control the
> way an ImageInputStream are created. In this way I instantiate a
> custom ImageInputStream
> which "remembers" the original file:
> public class FileImageInputStream2 extends FileImageInputStream
> private File file;
> public FileImageInputStream2 (File file) throws
> FileNotFoundException, IOException
> this.file = file;
> public File getFile ()
> return file;
> In this way, an instance of FileImageInputStream2 is passed to your
> codec and you can invoke
> the getFile() method. There's something to improve, but it's
> The complete code is available for download at jrawio.dev.java.net,
> look at the package
> Fabrizio Giudici, Ph.D. - Java Architect, Project Manager
> Tidalwave s.a.s. - "We make Java work. Everywhere."
> http://www.tidalwave.it/blog - Fabrizio.Giudici@tidalwave.it
> mobile: +39 348.150.6941 - fax: +39 027.005.105.36
> To unsubscribe, e-mail: firstname.lastname@example.org
> For additional commands, e-mail:
To unsubscribe, e-mail: email@example.com
For additional commands, e-mail: firstname.lastname@example.org