Java 将数据 URL 转换为 BufferedImage

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18569591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 09:05:40  来源:igfitidea点击:

Convert Data-URL to BufferedImage

javabufferedimagejavax.imageiodata-url

提问by Daniel

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.

我有一个来自图像文件的数据 URL,必须将它传递给另一个函数。沿着从 Data-URL 到 BufferedImage 的这条路径,它需要是一个 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.

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

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

我使用 ImageIO.getReaderFormatNames() 来获取支持的文件名并得到以下列表:

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,...

我尝试传递的 dataURLs 是这样的:data:image/png;base64,...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?

在这种情况下,还有什么可能导致 inputImage 为空?更有趣的是,我该如何解决?

采纳答案by ChristophT

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.

正如评论已经说过的,图像数据是 Base64 编码的。要检索二进制数据,您必须去除类型/编码标头,然后将 Base64 内容解码为二进制数据。

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

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

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

回答by Roman Nikitchenko

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

唯一的一个问题RFC2397字符串是它的一切规范的数据,但之前data:,可选:

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

So pure Java 8 solution accounting this would be:

所以纯 Java 8 解决方案会计这将是:

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.

当然应该检查 dataStartIndex 。

回答by nyuwec

I think, a simple regex replace would be better and more conform to the RFC2397:

我认为,一个简单的正则表达式替换会更好,更符合RFC2397

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

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

The RFC states that the data:and the ,are the required prefixes for a data url, therefore it is wise to match for them.

RFC 声明 thedata:和 the,是数据 url 所需的前缀,因此匹配它们是明智的。