Convert Data-URL to BufferedImage

2019-02-06 10:21发布

问题:

I have a Data-URL from an image file and have to pass it through to another function. Along this path from Data-URL to the BufferedImage it needs to be a byteArray.

my approach was the following:

String dataUrl;
byte[] imageData = dataUrl.getBytes();

// pass the byteArray along the path

// create BufferedImage from byteArray
BufferedImage inputImage = ImageIO.read(new ByteArrayInputStream(imageData));

// If the picture is null, then throw an unsupported image exception.
if (inputImage == null) {
    throw new UnknownImageFormatException();
}

The problem is, it always throws the UnknownImageFormatException Exception, which means inputImage is null, which means, the ImageIO.read did not recognize the imagetype.

I've used ImageIO.getReaderFormatNames() to get the supported Filenames and got the following list:

Supported Formats: 
jpg, BMP, bmp, JPG, jpeg, wbmp, png, JPEG, PNG, WBMP, GIF, gif

The dataURLs I try to pass are like: data:image/png;base64,... or data:image/jpg;base64,...

As far as I understand, those are in the supported filelist and therefor should be recognized.

What else could cause the inputImage to be null in this case? And more interesting, how do I solve it?

回答1:

As the comments already said the image data is Base64 encoded. To retrieve the binary data you have to strip the type/encoding headers, then decode the Base64 content to binary data.

String encodingPrefix = "base64,";
int contentStartIndex = dataUrl.indexOf(encodingPrefix) + encodingPrefix.length();
byte[] imageData = Base64.decodeBase64(dataUrl.substring(contentStartIndex));

I use org.apache.commons.codec.binary.Base64 from apaches common-codec, other Base64 decoders should work as well.



回答2:

The only one problem with RFC2397 string is its specification with everything before data but data: and , optional:

data:[<mediatype>][;base64],<data>

So pure Java 8 solution accounting this would be:

final int dataStartIndex = dataUrl.indexOf(",") + 1;
final String data = dataUrl.substring(dataStartIndex);
byte[] decoded = java.util.Base64.getDecoder().decode(data);

Of course dataStartIndex should be checked.