package com.twelvemonkeys.imageio.stream; import com.twelvemonkeys.io.StringInputStream; import com.twelvemonkeys.io.enc.Base64Decoder; import com.twelvemonkeys.io.enc.DecoderStream; import javax.imageio.spi.ImageInputStreamSpi; import javax.imageio.stream.FileCacheImageInputStream; import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.Locale; /** * Base64DataURLImageInputStreamSpi * * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a> * @author last modified by $Author: haraldk$ * @version $Id: Base64DataURLImageInputStreamSpi.java,v 1.0 03.09.13 09:35 haraldk Exp$ */ public class Base64DataURLImageInputStreamSpi extends ImageInputStreamSpi { // This is generally a bad idea, because: // - It is bound to String.class, and not all strings are base64 encoded data URLs. // - It's better to just create a decoder stream from the base64 stream, and use what's already in ImageIO.... public Base64DataURLImageInputStreamSpi() { super("TwelveMonkeys", "0.1-BETA", String.class); } @Override public ImageInputStream createInputStreamInstance(final Object input, final boolean useCache, final File cacheDir) throws IOException { String string = (String) input; InputStream stream = createStreamFromBase64(string); return useCache && cacheDir != null ? new FileCacheImageInputStream(stream, cacheDir) : new MemoryCacheImageInputStream(stream); } private InputStream createStreamFromBase64(String string) { if (!string.startsWith("data:")) { throw new IllegalArgumentException(String.format("Not a data URL: %s", string)); } int index = string.indexOf(';'); if (index < 0 || !string.regionMatches(index + 1, "base64,", 0, "base64,".length())) { throw new IllegalArgumentException(String.format("Not base64 encoded: %s", string)); } int offset = index + "base64,".length() + 1; return new DecoderStream(new StringInputStream(string.substring(offset), Charset.forName("UTF-8")), new Base64Decoder()); } @Override public boolean canUseCacheFile() { return true; } @Override public String getDescription(Locale locale) { return "Service provider that instantiates a FileCacheImageInputStream or MemoryCacheImageInputStream from a Base64 encoded data string"; } }