Amy Pearson Amy is a Java developer and member of the support team. Her main technical interests are JavaFX and Cloud. Out of hours she enjoys gaming and Virtual reality.

How to create your own Java ImageIO Plugin

2 min read

women working on the computer coding java imageio

women working on the computer coding java imageio

What is ImageIO?

ImageIO is an API included in the JDK that allows you to read and write images in Java. It also allows you to access image metadata. ImageIO can also be extended with third-party plugins which can extend or replace standard ImageIO functionality (for example support for new image formats or switching to another JPEG2000 decoder). This is done through a plugin API where ImageIO will look for certain files which tell it about the changes.

How does an ImageIO plugin work?

When you call ImageIO.read(imageStream) it compiles a list of service provider instances that meet the function you require(reading in this case) and the format of the image. This is done by using the canDecodeInput method which you will see later on.

Using a plugin can be helpful because you don’t have to change all your code to fit another Image library, the plugin does all the work for you. Also if you are looking to create your own plugin this can help your image library to be more accessible to customers.

How to create your own ImageIO plugin

First, let’s talk about what you need in order to communicate with ImageIO. I briefly mentioned earlier Service Provider Instances(spis). A spi is used to let the Service Registry know what image formats are available to read or write and provide information on what format is being handled. For example, you have a BMPImageReaderSpi and then a BMPImageWriterSpi.

A basic ReaderSpi would comprise of:

public class BMPImageReaderSpi extends ImageReaderSpi {
    private static final String vendorName = "IDRSolutions";
    private static final String version = "1.0";
    private static final String readerClassName = JDeliImageReader.class.getName();
    private static final String[] writerSpiNames = {"com.idrsolutions.JDeliImageWriterSpi"};
 
    // Metadata formats, more information below
    private static final boolean supportsStandardStreamMetadataFormat = false;
    private static final String nativeStreamMetadataFormatName = null;
    private static final String nativeStreamMetadataFormatClassName = null;
    private static final String[] extraStreamMetadataFormatNames = null;
    private static final String[] extraStreamMetadataFormatClassNames = null;
    private static final boolean supportsStandardImageMetadataFormat = false;
    private static final String nativeImageMetadataFormatName = "com.idrsolutions.JDeliMetadata_1.0";
    private static final String nativeImageMetadataFormatClassName = "com.idrsolutions.JDeliMetadata";
    private static final String[] extraImageMetadataFormatNames = null;
    private static final String[] extraImageMetadataFormatClassNames = null;    
    private static final String[] names = {"BMP"};
    private static final String[] suffixes = {"bmp"};
    private static final String[] MIMETypes = {"image/bmp"};
 
    public BMPImageReaderSpi() {
 
        super(vendorName, version,
        names, suffixes, MIMETypes,
        readerClassName,
        new Class[]{ImageInputStream.class}, // Accept ImageInputStreams
        writerSpiNames,
        supportsStandardStreamMetadataFormat,
        nativeStreamMetadataFormatName,
        nativeStreamMetadataFormatClassName,
        extraStreamMetadataFormatNames,
        extraStreamMetadataFormatClassNames,
        supportsStandardImageMetadataFormat,
        nativeImageMetadataFormatName,
        nativeImageMetadataFormatClassName,
        extraImageMetadataFormatNames,
        extraImageMetadataFormatClassNames);
    }
 
    @Override
    public String getDescription(final Locale locale) {
        return "BMP JDeli Image Reader";
    }
 
    @Override
    public boolean canDecodeInput(final Object source) throws IOException {
        //some code to check you can decode
        return canDecode;
 
    }
    @Override
    public String getDescription(final Locale locale) {
        return "bmp Image Reader";
    }  
    @Override
    public ImageReader createReaderInstance() throws IOException {
        return ImageReader(this);
    }
}

The ImageWriterSpi method is very similar just instead of canDecodeInput you have canEncodeInput:

@Override
public boolean canEncodeImage(final ImageTypeSpecifier imageType) {
   //code to check you can encode
    return canEncode;
}

The more formats that you support the more classes you will have to provide. As you can imagine this can begin to get quite lengthy. If you have an imageReaderspi and a reader for each format and then the same with writing and then any extra param classes.

This is the approach we used when we wrote our JDeli ImageIO plugin (a free plugin for uses of the commercial JDeli image library). We thought it best to have one imageReader and one imageWriter that all the different spis point to. This obviously works for us because we have all the image handling in JDeli and not in the readers and writers themselves. This approach may also work for you and reduce the number of classes you will need to make which is always good!

You should ensure that your spis are picked up by ImageIO by having a META-INF/services folder inside the resources folder. The services folder should contain two files: one lists your ImageWriterSpis, and the other lists your ImageReaderSpis as seen below:

 

Now you should have an ImageIO plugin of your own! If you would like to find out more about our JDeli ImageIO Plugin, you can find it on Github with all the source code for the plugin (so it also provides a nice example for you).



Tired of bad quality image libraries?

Write and Read Images in Java Find out why our customers trust JDeli with reading/writing images in Java

Amy Pearson Amy is a Java developer and member of the support team. Her main technical interests are JavaFX and Cloud. Out of hours she enjoys gaming and Virtual reality.

Leave a Reply

Your email address will not be published. Required fields are marked *

IDRsolutions Ltd 2021. All rights reserved.