jiichan.com

PROGRAMMING

Java
javascript
CSS
PHP

イメージを回転する

Exifの関係で、孫の写真をサーバに送った後にその写真が回転していることに気づくということが多々ありました。
そのたびに画像処理ソフトで元に戻してからあらためてサーバーに送るということをしていました。
重い画像処理ソフトをいちいち立ち上げるのも面倒なので、回転ツールを作ることにしあちらこちら調べながらようやく出来上がりました。
現在は、ExifのOrientationタグを見て自動で回転するようにして使っています。

イメージ回転の全コード

いざ、作ろうと調べたらjavaで画像を回転する方法はさまざまあるようです。
その中でも、回転の軸を画像の中心にする方法がネットでは多かったようです。
ただ、自分的には原点を軸に回転する方法がしっくりというか簡単に考えられたのでその方法で作ることにしました。
次がその全コードです。

public class ImgRotate {
	/*
	inputPath 元画像パス
	outputPath 出力画像パス
	angle 回転角度
	*/
	
	public ImgRotate(String inputPath, String outputPath, int angle){
		int width;
		int height;

		BufferedImage sourceImage;
		BufferedImage outputImage;
		try {
			File inputFile = new File(inputPath);
			// 元画像ファイル読み込み(戻り値はBufferdImageオブジェクト)
			sourceImage = ImageIO.read(inputFile);
			width = sourceImage.getWidth();
			height = sourceImage.getHeight();
			
			// 回転後のイメージ描画領域確保
			switch (angle) {
				case 90:
				case 270:
					// 回転のため縦横のサイズを逆にして確保
					outputImage = 
						new BufferedImage(height, width, BufferedImage.TYPE_INT_RGB);	
					break;
				case 180:
					outputImage = 
						new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
					break;
				default:
					outputImage = null;
			}

			// outputImage(BufferedImage)に描画するためのGraphics2Dを作成
			Graphics2D g2 = outputImage.createGraphics();
			// 回転変換用
			AffineTransform afRotate = new AffineTransform();
			// 平行移動用
			AffineTransform afTrans = new AffineTransform();
			
			// 原点を中心にangle度回転
			afRotate.rotate(Math.toRadians(angle), 0.0, 0.0);
			// BufferdImageと画像が合うように移動
			switch (angle) {
				case 90:
					afTrans.translate(height, 0.0);
					break;
				case 180:
					afTrans.translate(width, height);
					break;
				case 270:
					afTrans.translate(0.0, width);
					break;
			}
			// 回転と移動を連結させる(回転後に移動となる)
			// 数式だと移動の行列と回転の行列をかけあわせることになるが、
			// AffineTransformではconcatenateメソッドで連結することで一連の変化になる。
			// 必ず後の変換(移動:afTrans)に、前の変換(回転:afRotate)を付け足す。
			afTrans.concatenate(afRotate);

			// g2(Graphics2D)で、sourceImageに変換(afTrans)を適用して
			// outputImage(BufferedImage)に描画
		   g2.drawImage(sourceImage, afTrans, null);
			
			// ファイルに書き出し
		   boolean bool = ImageIO.write(outputImage, "jpg", new File(outputPath));	
		} catch (IOException e) {
			System.out.println(e);
		}
	}
}

AffineTransformのconcatenateメソッドで変換を連結することができると知りました。
オラクルのページ では「concatenate(AffineTransform Tx): Txによって元のユーザー空間にマップされた新しいユーザー空間を提供するためにもっとも一般的に使用される方法で、 AffineTransform TxをこのAffineTransform Cxに連結します。」と解説されていましたが全く意味が分かりませんでした。