【问题标题】:Can I tell what the file type of a BufferedImage originally was?我可以告诉 BufferedImage 最初的文件类型是什么吗?
【发布时间】:2014-01-11 01:00:35
【问题描述】:

在我的代码中,我有一个 BufferedImage,它加载了 ImageIO 类,如下所示:

BufferedImage image = ImageIO.read(new File (filePath);

稍后,我想将其保存到字节数组中,但ImageIO.write 方法要求我选择 GIF、PNG 或 JPG 格式来写入我的图像(如教程 here 中所述) .

我想选择与原始图像相同的文件类型。如果图像最初是 GIF,我不希望将其保存为 PNG 的额外开销。但是,如果图像最初是 PNG,我不想通过将其保存为 JPG 或 GIF 来失去半透明度等。有没有办法可以从 BufferedImage 确定原始文件格式是什么?

我知道我可以在加载图像时简单地解析文件路径以查找扩展名并将其保存以备后用,但理想情况下,我希望有一种直接从 BufferedImage 执行此操作的方法。

【问题讨论】:

标签: java image bufferedimage javax.imageio


【解决方案1】:

正如@JarrodRoberson 所说,BufferedImage 没有“格式”(即没有文件格式,它确实有几种像素格式或像素“布局”之一)。我不知道 Apache Tika,但我想他的解决方案也可以。

但是,如果您更喜欢只使用 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();
}

【讨论】:

  • 选择这个作为 asnwer 是因为,虽然 Tika 可能更可靠,但我不关心添加 25 MB 的依赖项,所以这对我来说最终是一个更好的解决方案,我可以接受“足够可靠”。谢谢!
【解决方案2】:

BufferedImage 没有“格式”

一旦字节被转换为BufferedImage,源文件的格式就完全丢失了,内容仅代表像素信息的原始字节数组。

解决方案

您应该在创建BufferedImage 之前使用Tika 库从原始字节流中确定格式,而不是依赖可能不准确的文件扩展名。

【讨论】:

    【解决方案3】:

    可以像这样将 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);
      }
    }
    

    然后像这样使用它:

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

    然后,您将所有相关的内容都放在 TGImage 实例中。 或许可以像这样在图像列表中使用它:

    ArrayList<TGImage> images = new ArrayList<>(5);
    

    【讨论】:

      猜你喜欢
      • 2017-07-27
      • 1970-01-01
      • 2020-12-31
      • 2014-11-25
      • 2021-11-16
      • 1970-01-01
      • 1970-01-01
      • 2011-01-08
      • 2010-09-18
      相关资源
      最近更新 更多