【问题标题】:Java ImageIO-ext TIF File Corrupt when ReadJava ImageIO-ext TIF 文件在读取时损坏
【发布时间】:2012-05-16 21:08:46
【问题描述】:

我正在尝试使用最少数量的附加库在 Java 中显示 .tif

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

import javax.media.jai.widget.*;
import it.geosolutions.imageio.utilities.*;
import it.geosolutions.imageioimpl.plugins.tiff.*;
import com.sun.media.imageioimpl.common.*;

public static void main(String[] args) {
    try {
        File f = new File("image.tif");  
        BufferedImage tif = ImageIO.read(f);  
        ImageIcon ic = new ImageIcon(tif);  
        JFrame frame = new JFrame();  
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);  
        JLabel label = new JLabel(ic);  
        frame.add(label);  
        frame.setVisible(true);  
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我正在使用的库是:

 jai-core-1.1.3.jar
 jai-imageio-1.1.jar
 imageio-ext-tiff.1.1.3.jar
 imageio-ext-utilities.1.1.3.jar

从这里:http://java.net/projects/imageio-ext(右侧的下载链接)

但是,显示的图像是: 这绝对是不是原始图像。我所知道的也没有抛出任何错误。此外,原始图像很好,不会改变。

但是,原始代码很小。我实际上并没有使用 imageio-ext 导入,但是如果没有它们,程序将会失败。我也没有用过imageio-ext

请帮忙!我需要能够在不安装软件的情况下在 Java 中使用.tif 图像。

【问题讨论】:

  • 错误是什么?你能把堆栈跟踪吗?

标签: java tiff javax.imageio jai


【解决方案1】:

如果您已经使用了所有 JAI/ImageIO 库,您可能想尝试以下方法(对我来说效果很好):

import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.ImageCodec;
import com.sun.media.jai.codec.ImageDecoder;

// This function is minimal, you should add exceptions and error handling
public RenderedImage read(String filename)
    FileSeekableStream fss = new FileSeekableStream(filename);
    ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", fss, null);
    RenderedImage image = decoder.decodeAsRenderedImage()
    fss.close();
    return image;
}

如果您需要BufferedImage 而不是RenderedImage,我找到的唯一解决方案是使用此函数:

public static BufferedImage Rendered2Buffered(RenderedImage image) {
    BufferedImage bi = new BufferedImage(image.getWidth(), image.getHeight(), image.getSampleModel().getDataType());
    bi.setData(image.getData());
    return bi;
}

但请注意,image.getSampleModel().getDataType() 通常会返回BufferedImage.TYPE_CUSTOM,这使得BufferedImage 无法创建!就我而言,我必须根据image.getSampleModel().getSampleSize(0) 返回的样本大小“猜测”类型(因为我知道我正在使用的图像格式)。 如果您知道将RenderedImage 转换为BufferedImage 的更好方法,请赐教:)

【讨论】:

    【解决方案2】:

    您认为需要 JAI 库来解码和使用 TIFF 文件是正确的,但即使您已导入它们,您实际上并没有使用它们!

    Here is a short tutorial 展示了如何创建一个 TIFFDecodeParam 对象(来自 JAI 库),然后使用它来解码(和显示)一个 TIFF 图像。

    您可能还会发现JAI API Library 也很有用。

    【讨论】:

    • 您链接到的教程使用不同的库而不是ImageIO-ext 这些库在哪里?我不得不承认在找到 ImageIO-ext 库之前搜索了一段时间的 JAI 库。
    • 另外,这是一个有趣的分析,因为在上面的程序中不包含导入的时候会抛出异常,但是当它们存在时不会抛出异常......
    • 您需要的库是javax.media.jai.*com.sun.media.jai.codec.*。据我所知,这两个都包含在(Sun)JDK 的安装中。老实说,我没有注意到您还链接到 imageio-ext 库。我以前从未遇到过这些,这就是为什么我认为您没有使用 JAI 库。
    • 看来ImageIO-ext 库“增强”了内置 ImageIO 的功能。如果您不包含这些库,那么默认的 ImageIO(在您的代码中使用)不支持 TIFF,并且会引发无效的文件格式异常(我相信是 IOException)。
    • 有趣...我有 javax.media.jai.*; 包和 com.sun.media.jai.*; 包,但我没有 com.sun.media.jai.codec.*; 包...这可能是以后添加到 JDK 中的吗(我忘了说我必须使用 1.5)?
    【解决方案3】:

    我最终选择了最新版本的 Apache-Commons Imaging(以前称为 Sanselan)。 Imaging 为 TIFF 文件提供开箱即用的支持(起初我遇到了一点麻烦,但通过从旧的 Sanselan 切换到新的 Commons Imaging 解决了这个问题)。

    我必须自己对一些功能进行逆向工程(以指定宽度加载单个 sub-TIFF,同时保持纵横比):

    /**
     * Load a scaled sub-TIFF image.  Loads nth sub-image and scales to given width; preserves aspect ratio.
     * 
     * @param fileName String filename
     * @param index Index of sub-TIFF; will throw ArrayIndexOutOfBoundsException if sub-image doesn't exist
     * @param w Desired width of image; height will scale
     * @return Image (BufferedImage)
     * @throws IOException
     * @throws ImageReadException
     */
    public static Image loadScaledSubTIFF(String fileName, int index, int w) throws IOException, ImageReadException {
        File imageFile = new File(fileName);
        ByteSourceFile bsf = new ByteSourceFile(imageFile);
        FormatCompliance formatCompliance = FormatCompliance.getDefault();
        TiffReader tiffReader = new TiffReader(true);
        TiffContents contents = tiffReader.readDirectories(bsf, true, formatCompliance);
        TiffDirectory td = contents.directories.get(index);
        Image bi = td.getTiffImage(tiffReader.getByteOrder(), null);
        Object width = td.getFieldValue(new TagInfo("", 256, TiffFieldTypeConstants.FIELD_TYPE_SHORT) {/**/});
        Object height = td.getFieldValue(new TagInfo("", 257, TiffFieldTypeConstants.FIELD_TYPE_SHORT) {/**/});
        int newWidth = w;
        int newHeight = (int) ((newWidth * ((Number)height).doubleValue()) / (((Number)width).doubleValue()));
    
        bi = bi.getScaledInstance(w, newHeight, java.awt.Image.SCALE_FAST);
        height = null;
        width = null;
        td = null;
        contents = null;
        tiffReader = null;
        formatCompliance = null;
        bsf = null;
        return bi;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-21
      • 1970-01-01
      相关资源
      最近更新 更多