无法使用Java ImageIO标准库读写TIFF图像文件

28

我不知道如何处理TIFF图像,但是使用纯Java标准的ImageIO库无法读取或写入其中任何一种。有什么想法吗?

谢谢。


2
你正在使用Java SE吗?Java高级图像API支持TIFF格式。详见此处 - MPG
3
要处理TIFF文件,您需要使用JAI包。这是一个显示TIFF文件的简单示例:显示TIF - RealHowTo
2
遇到了同样的问题,将JAI的jar添加到我的类路径中解决了它。无需更改代码,也无需在编译时添加JAI。只需在运行时添加它,ImageIO.getImageReaders 将能够自动找到它,因为它会扫描类路径以查找读取器。 - SomethingSomething
5个回答

23
如果由于任何原因您不喜欢或无法使用JAI,我已经为ImageIO编写了一个TIFF ImageReader插件,并在GitHub上提供。它是纯Java编写的,不需要安装任何本地程序,并且附带非常友好的开源许可证(BSD)。
该插件支持所有基线TIFF选项以及许多标准扩展。从3.1版本开始,TIFF插件还具有写入支持。
只需将适当的JAR文件添加到类路径中,使用起来就像这样简单:
BufferedImage image = ImageIO.read(inputTIFF);
// ...modify image (compose, resize, sharpen, etc)...
ImageIO.write(image, "TIFF", outputTIFF);

你好,haraldK,你怎么使用这个?我一点也不喜欢JAI,我找不到任何将tiff文件转换为jpg的示例。我尝试了以下代码:BufferedImage image = ImageIO.read(new File(inFile));!ImageIO.write(image, "jpg", new File(outFile))) - delkant
@delkant 这段代码应该是可行的,如果你已经将所有东西正确安装。请查看安装说明以获取更多详细信息,或者如果您无法使其工作,请提交一个问题(包含所有详细信息)。 - Harald K

13
根据JEP 262:TIFF Image I/O,原先作为JAI一部分的TIFF插件将作为Java SE的一部分提供,从Java 9开始可用。
这意味着,使用Java 9或更高版本,以下代码将可以直接运行,无需任何额外的导入或依赖:
BufferedImage image = ImageIO.read(inputTIFF);
// ...modify image (compose, resize, sharpen, etc)...
ImageIO.write(image, "TIFF", outputTIFF);

我还没有能够验证此插件对非基线TIFF格式的支持,但是我认为至少基线TIFF应该得到完全支持。


5

我尝试了JAI,但它对我没用。

你卡在哪里了?下面的内容是否适用于您?

import java.io.File;
import java.io.FileOutputStream;
import java.awt.image.RenderedImage;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import javax.media.jai.NullOpImage;
import javax.media.jai.OpImage;
import com.sun.media.jai.codec.SeekableStream;
import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.TIFFDecodeParam;
import com.sun.media.jai.codec.ImageDecoder;
import com.sun.media.jai.codec.ImageCodec;

public class Main {
    public static void main(String args[]) {
        File file = new File("input.tif");
        try {
            SeekableStream s = new FileSeekableStream(file);
            TIFFDecodeParam param = null;
            ImageDecoder dec = ImageCodec.createImageDecoder("tiff", s, param);
            RenderedImage op = new NullOpImage(dec.decodeAsRenderedImage(0),
                                               null,
                                               OpImage.OP_IO_BOUND,
                                               null);
            FileOutputStream fos = new FileOutputStream("output.jpg");
            JPEGImageEncoder jpeg = JPEGCodec.createJPEGEncoder(fos);
            jpeg.encode(op.getData());
            fos.close();
        }
        catch (java.io.IOException ioe) {
            System.out.println(ioe);
        } 
    }
}

4
如果您在类路径中有jai_imageio.jar,那么您应该可以像平常一样使用ImageIO API。 - MadProgrammer
这个jar包是哪个版本的,它存储在哪个仓库中?我在Maven中找不到它。 - SoftwareSavant

2

Java 9版本开始支持TIFF格式。如果您尝试在旧的Java版本中使用ImageIO处理TIFF,它会抛出异常。

如果您想在早期版本中使用TIFF,可以通过添加Twelve Monkey的依赖项来与Java一起使用。

Twelve Monkey的Maven依赖项:

<dependency>
   <groupId>com.twelvemonkeys.imageio</groupId>
   <artifactId>imageio-tiff</artifactId>
   <version>3.5</version>
</dependency>*

我还会提供一个示例,使用Twelve Monkey将多个图像合并为具有页面的单个TIFF。
BufferedImage b1 = null;
BufferedImage b2 = null;

TIFFImageReaderSpi SPI = new TIFFImageReaderSpi();

ImageReader imageReader1 = SPI.createReaderInstance();
ImageInputStream iis1 = ImageIO.createImageInputStream(new File("1.tif"));
imageReader1.setInput(iis1);
b1 = imageReader1.read(0); 

ImageReader imageReader2 = SPI.createReaderInstance();
ImageInputStream iis2 = ImageIO.createImageInputStream(new File("2.tif"));
imageReader2.setInput(iis2);
b2 = imageReader2.read(0);

ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();

writer.setOutput(ImageIO.createImageOutputStream(new File("3.tif")));

ImageWriteParam writeParam = writer.getDefaultWriteParam();
//writeParam.setTilingMode(ImageWriteParam.MODE_EXPLICIT);
//writeParam.setCompressionType("Deflate");

writer.prepareWriteSequence(null);

IIOImage i1 = new IIOImage(b1, null, null);
IIOImage i2 = new IIOImage(b2, null, null);

writer.writeToSequence(i1, writeParam);
writer.writeToSequence(i2, writeParam);

writer.endWriteSequence();
writer.dispose();

上述代码适用于Java8,旨在打开两个TIFF图像并将其合并为单个图像。您也可以根据需要使用压缩。只需使用注释行添加压缩即可。

-4
添加 Maven 依赖项:

<dependency>
  <groupId>org.geotoolkit</groupId>
  <artifactId>geotk-coverageio</artifactId>
  <version>3.17</version>
</dependency>

代码示例:

import org.geotoolkit.image.io.plugin.RawTiffImageReader;

IIORegistry registry = IIORegistry.getDefaultInstance();   
registry.registerServiceProvider(new RawTiffImageReader.Spi());            

String[] a = ImageIO.getReaderFileSuffixes();    
for (int i=0; i<a.length; i++) {
 System.out.println(a[i]);
}   

BufferedImage image = ImageIO.read(new File("C:\\mypic.tiff"));

ImageIO.write(image, "jpg",new File("C:\\out.jpg"));
ImageIO.write(image, "gif",new File("C:\\out.gif"));
ImageIO.write(image, "png",new File("C:\\out.png"));
ImageIO.write(image, "tif",new File("C:\\out.tiff"));

我担心这种依赖关系已经不再可用了。下面是适用于我的方法:<dependency> <groupId>com.github.jai-imageio</groupId> <artifactId>jai-imageio-core</artifactId> <version>1.3.1</version> </dependency> (我没有尝试过使用你的整个代码)。 - Purrrple

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接