Java ImageIO-ext TIFF文件在读取时损坏

时间:2012-05-16 21:08:46

标签: java tiff javax.imageio jai

我正在尝试使用最少量的其他库在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(右侧下载链接)

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

但是,原始代码很小。我实际上并没有使用imageio-ext导入,但程序将在没有它们的情况下失败。我之前也没有使用imageio-ext

请帮忙!我需要能够在Java中使用.tif图像,而无需安装软件。

3 个答案:

答案 0 :(得分:2)

如果你已经使用了所有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的更好方法,请赐教:)

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

我最终选择了Apache-Commons Imaging(原名为Sanselan)的最新版本。 Imaging提供了对TIFF文件的开箱即用支持(起初我有点麻烦,但是从旧的Sanselan切换到较新的Commons Imaging可以解决这个问题)。

我必须对自己进行逆向工程(在保持宽高比的同时以指定的宽度加载单个子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;
}