Apurv
Apurv

Reputation: 4525

Changing the Functionality of a Java ImageIO class

I was working with

javax.imageio.ImageIO class

The one provided by sun doesn't provide support for reading .tif files. So if I try to read a .tif file, it just returns a null. Then I downloaded this api from oracle's website and included it in the classpath. This api uses jni as was evident from a .so file in that folder. After that I didn't have to change anything in my code and it worked. How could this happen? Wouldn't the class names have clashed?

There were 3 things in the api that i had downloaded:

  1. clibwrapper_jiio.jar
  2. jai_imageio.jar
  3. libclib_jiio.so

I didn't have to do any additional import. In fact, the functionality provided by the ImageIO class was enchanced

I am really curious about how this works.

Here is the class in javax.imageio package. The class has been declared as final. And it does some weird complex stuff that I can't understand. Could someone explain how to achieve this effect with a simpler example.

http://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html

Upvotes: 2

Views: 446

Answers (2)

Andrew Thompson
Andrew Thompson

Reputation: 168825

Java's Image IO works using the Service Provider Interface (see links below for more details).

JavaSound works the same way. To add support for (e.g.) MP3 to JavaSound, it is only necessary to add the mp3plugin.jar of the JMF to the run-time class-path, then JavaSound can decode MP3 files as easily as it can a WAV (using the exact same classes - very funky).

I expect the installation of JAI did a similar thing, by adding a bunch of service providers for different image types to the lib directory of the JRE.

  1. ImageWriterSpi
  2. Creating Extensible Applications With the Java Platform.

Upvotes: 2

Edwin Buck
Edwin Buck

Reputation: 70909

ImageIO has a scanForPlugins(...) method. I'd imagine that on class load time it takes a peek around the CLASSPATH and looks for anything that could extend its functionality.

The javadoc which hints to this is here.

You could do something similar by putting a static block in one of your classes

public class MyClass {

  public static scanForExtensions() {
    ... code looking for extensions goes here ...
    ... for each found extension, register them in the "ExtensionRegistry"
    ExtensionRegistry.register(extension);
  }

  static  {
    scanForExtensions();
  }

  public void doSomething(String input) {
    for (Extension extension : ExtensionRegistry.getExtensions()) {
      if (extension.canHandle(input)) {
        extension.handle(input);
        return;
      }
    }
    throw UnhandledInputException("No extension to handle " + input);
  }

}

Upvotes: 4

Related Questions