javajavax.imageio

javax.imageio.ImageIO file format constants


In javax.imageio.ImageIO there is a method #write(RenderedImage im, String formatName, OutputStream output) that accepts a "stringly-typed" format developer wants image to be written to.

There is an inner class called CanEncodeImageAndFormatFilter deep inside that file that checks if there is an SPI (whatever it is) that supports the aforementioned format. For example, BMPImageWriterSpi declares

    private static String[] formatNames = {"bmp", "BMP"};

But in all these SPI-classes these format names are declared either private or package-default, so I cannot access them in my application. But I'd like to expose that format parameter in API I'm working on right now, but I don't want to reinvent the wheel.

➥ Is there an enum or something I can safely use as a format name parameter for the #write method?

Yes, this is more like an opinion based question with coding-style tag. :D


UPD: What I have:

ImageIO.write(image, "jpg", outStream);

What I want:

ImageIO.write(image, ImageTypes.JPEG, outStream);

Solution

  • There is no such Enum you are looking for in the default Java API.

    The reason is that the Java Image I/O API uses the Service provider interface (SPI). Which allows to create extensible applications. In the scope of your question additional image reader/writer classes (which implements the respective interface) can be added to the classpath and will be discovered automatically during runtime. The application can use them without even knowing at compile time they exist. Hence such Enum not exist.

    You can discover all currently known ImageWriter implementations with following snippet.

    import javax.imageio.spi.IIORegistry;
    import javax.imageio.spi.ImageWriterSpi;
    import java.util.Arrays;
    import java.util.Iterator;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
            IIORegistry registry = IIORegistry.getDefaultInstance();
            Iterator<ImageWriterSpi> serviceProviders = registry.getServiceProviders(ImageWriterSpi.class, false);
            while(serviceProviders.hasNext()) {
                ImageWriterSpi next = serviceProviders.next();
                System.out.printf("description: %-27s   format names: %s%n",
                        next.getDescription(Locale.ENGLISH),
                        Arrays.toString(next.getFormatNames())
                );
            }
        }
    }
    

    output for Java 13

    description: Standard BMP Image Writer     format names: [bmp, BMP]
    description: Standard JPEG Image Writer    format names: [JPEG, jpeg, JPG, jpg]
    description: Standard WBMP Image Writer    format names: [wbmp, WBMP]
    description: Standard PNG image writer     format names: [png, PNG]
    description: Standard GIF image writer     format names: [gif, GIF]
    description: Standard TIFF image writer    format names: [tif, TIF, tiff, TIFF]
    

    Below is a simplified example how the SPI could be used.

    assume following files in the current directory

    Main.class                  - the one from above source
    ExampleImageWriterSpi.java  - an example implementation of the ImageWriterSpi
    

    ExampleImageWriterSpi.java

    package sub.optimal;
    
    import javax.imageio.ImageTypeSpecifier;
    import javax.imageio.ImageWriter;
    import javax.imageio.spi.ImageWriterSpi;
    import java.io.IOException;
    import java.util.Locale;
    
    public class ExampleImageWriterSpi extends ImageWriterSpi {
    
        private static final String[] formatNames = { "xyz", "XYZ"};
    
        public String getDescription(Locale locale) {
            return "Example XYZ image writer";
        }
    
        @Override
        public String[] getFormatNames() {
            return formatNames;
        }
    
        // following is without implementation in this example
        public boolean canEncodeImage(ImageTypeSpecifier type) {
            return false;
        }
    
        public ImageWriter createWriterInstance(Object extension) throws IOException {
            return null;
        }
    }
    

    compile the class

    javac ExampleImageWriterSpi.java
    

    create the provider configuration file
    (the filename specifies the implemented interface, the line specifies the implementing class)

    mkdir -p META-INF/services/
    echo sub.optimal.ExampleImageWriterSpi > META-INF/services/javax.imageio.spi.ImageWriterSpi
    

    create an archive for the service provider

    jar cf example-image-writer.jar META-INF/ sub/
    

    run the plain example code

    java Main
    

    output (all service providers which are part of the Java runtime)

    description: Standard BMP Image Writer     format names: [bmp, BMP]
    description: Standard JPEG Image Writer    format names: [JPEG, jpeg, JPG, jpg]
    description: Standard WBMP Image Writer    format names: [wbmp, WBMP]
    description: Standard PNG image writer     format names: [png, PNG]
    description: Standard GIF image writer     format names: [gif, GIF]
    description: Standard TIFF image writer    format names: [tif, TIF, tiff, TIFF]
    

    run the example with the additional service provider

    java -cp example-image-writer.jar:. Main
    

    output

    description: Example XYZ image writer      format names: [xyz, XYZ]
    description: Standard JPEG Image Writer    format names: [JPEG, jpeg, JPG, jpg]
    description: Standard WBMP Image Writer    format names: [wbmp, WBMP]
    description: Standard PNG image writer     format names: [png, PNG]
    description: Standard GIF image writer     format names: [gif, GIF]
    description: Standard BMP Image Writer     format names: [bmp, BMP]
    description: Standard TIFF image writer    format names: [tif, TIF, tiff, TIFF]
    

    You might create the enum yourself. But you should check at runtime if there is a provider available for this image type. e.g. TIFF was not available in the Java runtime before Java 9.