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
ImageIO.write(image, "jpg", outStream);
What I want:
ImageIO.write(image, ImageTypes.JPEG, outStream);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With