とにかく書く

日々の雑感や知り得たことを、とにかく書いています

マルチページTIFFを開く

Java でマルチページ Tiff ファイルを開く方法を調べたのでメモする。
以下の「マルチページ tiff を分割する」を参考にしました。
JavaSE ImageIO で tiff 画像を扱う - @//メモ


Tiff は、JavaFX の Image クラスではサポートされていないようで、Image クラスのコンストラクタに tiff 画像のパスを指定しても読み込めない。
代わりに ImageIO クラス (javax.imageio.ImageIO) の read メソッドで BufferedImaeg クラスのインスタンスに読み込んで(Java 9から可能?)SwingFXUtils.toFXImage メソッドで WritableImage クラスのインスタンスに変換する必要がある。
ただ、これでもマルチページの Tiff 画像の場合、最初のページしか表示されない。

マルチページの Tiff ファイルから任意のページを取り出すには、ImageReader クラスを実現した Tiff 復号エンジンを使って、reader メソッドで読み出す必要がある。
この日本語よりコードの方がわかりやすいかも。

package application;
	
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;

import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.stage.Stage;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;

public class Main extends Application {
	@Override
	public void start(Stage primaryStage) {
		try {
			Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName("tiff");
			ImageReader reader = readers.next();
			ImageInputStream imageInputStream = ImageIO.createImageInputStream(new File("test.tiff"));
			reader.setInput(imageInputStream, false);
			// ページ数を表示 (たとえば10ページ)
			System.out.println(reader.getNumImages(true)); 
			// 指定ページを表示 (0オリジンのため 0 - 9 が指定可能。)
			BufferedImage bufferedImage = reader.read(2);
			
			// あとは描画しているだけ。テスト用の画像が大きかったので ScrollPane を使っている。
			WritableImage writableImage = SwingFXUtils.toFXImage(bufferedImage, null);
			ImageView imageView = new ImageView();
			imageView.setImage(writableImage);
			Group root = new Group(imageView);
			ScrollPane scrollPane = new ScrollPane(root);
			Scene scene = new Scene(scrollPane,400,400);
			scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
			primaryStage.setScene(scene);
			primaryStage.show();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		launch(args);
	}
}