Java 我能说出 BufferedImage 最初的文件类型吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21057191/
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
Can I tell what the file type of a BufferedImage originally was?
提问by Thunderforge
In my code, I have a BufferedImagethat was loaded with the ImageIOclass like so:
在我的代码中,我有一个加载了ImageIO类的BufferedImage,如下所示:
BufferedImage image = ImageIO.read(new File (filePath);
Later on, I want to save it to a byte array, but the ImageIO.write
method requires me to pick either a GIF, PNG, or JPG format to write my image as (as described in the tutorial here).
后来,我想将它保存为一个字节数组,但ImageIO.write
方法需要我来接的GIF,PNG,或JPG格式来写我的图像(如本教程中介绍这里)。
I want to pick the same file type as the original image. If the image was originally a GIF, I don't want the extra overhead of saving it as a PNG. But if the image was originally a PNG, I don't want to lose translucency and such by saving it as a JPG or GIF. Is there a way that I can determine from the BufferedImage what the original file format was?
我想选择与原始图像相同的文件类型。如果图像最初是 GIF,我不希望将其保存为 PNG 的额外开销。但是,如果图像最初是 PNG,我不想通过将其保存为 JPG 或 GIF 来失去半透明性。有没有办法可以从 BufferedImage 确定原始文件格式是什么?
I'm aware that I could simply parse the file path when I load the image to find the extension and just save it for later, but I'd ideally like a way to do it straight from the BufferedImage.
我知道我可以在加载图像时简单地解析文件路径以找到扩展名,然后将其保存以备后用,但理想情况下,我想要一种直接从 BufferedImage 执行此操作的方法。
采纳答案by haraldK
As @JarrodRoberson says, the BufferedImage
has no "format" (i.e. no file format, it does have one of several pixel formats, or pixel "layouts"). I don't know Apache Tika, but I guess his solution would also work.
正如@JarrodRoberson 所说,BufferedImage
它没有“格式”(即没有文件格式,它确实有几种像素格式之一,或像素“布局”)。我不知道 Apache Tika,但我想他的解决方案也适用。
However, if you prefer using only ImageIO
and not adding new dependencies to your project, you could write something like:
但是,如果您更喜欢只使用ImageIO
而不是向项目添加新的依赖项,您可以编写如下内容:
ImageInputStream input = ImageIO.createImageInputStream(new File(filePath));
try {
Iterator<ImageReader> readers = ImageIO.getImageReaders(input);
if (readers.hasNext()) {
ImageReader reader = readers.next();
try {
reader.setInput(input);
BufferedImage image = reader.read(0); // Read the same image as ImageIO.read
// Do stuff with image...
// When done, either (1):
String format = reader.getFormatName(); // Get the format name for use later
if (!ImageIO.write(image, format, outputFileOrStream)) {
// ...handle not written
}
// (case 1 done)
// ...or (2):
ImageWriter writer = ImageIO.getImageWriter(reader); // Get best suitable writer
try {
ImageOutputStream output = ImageIO.createImageOutputStream(outputFileOrStream);
try {
writer.setOutput(output);
writer.write(image);
}
finally {
output.close();
}
}
finally {
writer.dispose();
}
// (case 2 done)
}
finally {
reader.dispose();
}
}
}
finally {
input.close();
}
回答by Thunderforge
BufferedImage does not have a "format"
BufferedImage 没有“格式”
Once the bytes have been translated into a BufferedImage
the formatof the source file is completely lost, the contents represent a raw byte array of the pixel information nothing more.
一旦字节被转换成源文件BufferedImage
的格式就完全丢失了,内容仅代表像素信息的原始字节数组。
Solution
解决方案
You should use the Tika
library to determine the format from the original byte stream before the BufferedImage
is created and not rely on file extensions which can be inaccurate.
您应该Tika
在BufferedImage
创建之前使用该库来确定原始字节流的格式,而不是依赖于可能不准确的文件扩展名。
回答by Ted van Gaalen
One could encapsulate the BufferedImage and related data in class instance(s) like so:
可以将 BufferedImage 和相关数据封装在类实例中,如下所示:
final public class TGImage
{
public String naam;
public String filename;
public String extension;
public int layerIndex;
public Double scaleX;
public Double scaleY;
public Double rotation;
public String status;
public boolean excluded;
public BufferedImage image;
public ArrayList<String> history = new ArrayList<>(5);
public TGImage()
{
naam = "noname";
filename = "";
extension ="";
image = null;
scaleX = 0.0;
scaleY = 0.0;
rotation = 0.0;
status = "OK";
excluded = false;
layerIndex = 0;
addHistory("Created");
}
final public void addHistory(String str)
{
history.add(TGUtil.getCurrentTimeStampAsString() + " " + str);
}
}
and then use it like this:
然后像这样使用它:
public TGImage loadImage()
{
TGImage imgdat = new TGImage();
final JFileChooser fc = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("Image Files", "jpg", "png", "gif", "tif");
fc.setFileFilter(filter);
fc.setCurrentDirectory(new File(System.getProperty("user.home")));
int result = fc.showOpenDialog(this); // show file chooser
if (result == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
System.out.println("Selected file extension is " + TGUtil.getFileExtension(file));
if (TGUtil.isAnImageFile(file))
{
//System.out.println("This is an Image File.");
try
{
imgdat.image = ImageIO.read(file);
imgdat.filename = file.getName();
imgdat.extension = TGUtil.getFileExtension(file);
info("image has been loaded from file:" + imgdat.filename);
} catch (IOException ex)
{
Logger.getLogger(TGImgPanel.class.getName()).log(Level.SEVERE, null, ex);
imgdat.image = null;
info("File not loaded IOexception: img is null");
}
} else
{
imgdat = null;
info("File not loaded: The requested file is not an image File.");
}
}
return imgdat;
}
Then you have everything relevant together in TGImage instance(s). and perhaps use it in an imagelist like so:
然后你在 TGImage 实例中将所有相关的东西放在一起。也许在图像列表中使用它,如下所示:
ArrayList<TGImage> images = new ArrayList<>(5);