我可以告诉BufferedImage最初的文件类型是什么吗?

时间:2014-01-11 01:00:36

标签: java image bufferedimage javax.imageio

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

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

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

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

我知道我可以在加载图片时简单地解析文件路径以找到扩展名并将其保存以供日后使用,但理想情况下我喜欢直接从BufferedImage执行此操作

3 个答案:

答案 0 :(得分:8)

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

答案 1 :(得分:7)

BufferedImage没有“格式”

一旦将字节翻译成BufferedImage源文件的格式完全丢失,内容就不再代表像素信息的原始字节数组。

解决方案

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

答案 2 :(得分:0)

可以在类实例中封装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);