将Data-URL转换为BufferedImage

18

我有一张图片文件的 Data-URL,并需要将其传递到另一个函数。在从 Data-URL 转换为 BufferedImage 的过程中,需要将其转换为 byteArray。

我的做法如下:

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();
}

问题是它总是抛出UnknownImageFormatException异常,这意味着inputImage为空,也就是说,ImageIO.read无法识别图像类型。

我已经使用了ImageIO.getReaderFormatNames()获取支持的文件名列表,得到以下列表:

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

我尝试传递的dataURLs格式如下:data:image/png;base64,... 或者 data:image/jpg;base64,...

据我了解,这些是受支持的文件格式,应该可以识别。

除此之外,还有什么原因会导致输入图像(inputImage)为空呢?更有趣的是,我该如何解决它?


3
您需要将Base64编码的字符串解码为二进制格式,以便ImageIO可以读取,或者,如果您有一个URL对象,可以直接将其传递给ImageIO。请注意,翻译内容仅限于对原文的翻译,不包括额外的解释和其他内容。 - MadProgrammer
2
根据@MadProgrammer的建议,您可以使用DatatypeConverter将base 64字符串转换回byte[] - Andrew Thompson
3个回答

25

正如评论中所说,图像数据已经以Base64编码。要检索二进制数据,您需要剥离类型/编码标头,然后将Base64内容解码为二进制数据。

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

我使用来自Apache common-codec的org.apache.commons.codec.binary.Base64,其他Base64解码器也应该可以工作。


8
自Java 8起,在核心JDK中有一个Base64编码器/解码器:http://download.java.net/jdk8/docs/api/java/util/Base64.html - Jules

12
RFC2397字符串唯一的问题是其规范中仅将"data:"和","之前的所有内容视为可选项。
data:[<mediatype>][;base64],<data>

因此,解决此问题的纯Java 8解决方案如下:

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

当然需要检查dataStartIndex。


2
我认为,一个简单的正则表达式替换会更好,并且更符合RFC2397的规范:

java.util.Base64.getDecoder().decode(b64DataString.replaceFirst("data:.+,", ""))

RFC规定data:,是数据url所必需的前缀,因此最好匹配它们。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接