我正在尝试使用最少量的其他库在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
图像,而无需安装软件。
答案 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;
}