てけとーぶろぐ。

ソフトウェアの開発と、お絵かきと、雑記と。

画像ファイルの内容から適切な拡張子を得る(Java版)

前にRubyでつくったのだけどAndroid版ImageSpiderの為にJava版も必要になり作成。
変なところあったらご指摘ください。

package jp.ne.sakura.kurima.imagespider.util;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;

public class ImageFileExtentionGetter {

	/**
	 * 指定の画像ファイルの内容から適切な拡張子の文字列を推測して返す
	 * 不明な場合や例外発生時は空文字列を返す
	 * ".bmp" ".gif" ".jpg" ".png" ".psd" ".tif" に対応
	 * WBMP, JPEG 2000, PICT 等はヘッダでの判定が複雑そうなのと一般的ではないことから割愛
	 *
	 * @param filePath 画像ファイルのファイルパス
	 * @return {@code ".bmp"} 等ファイルの内容から推測した拡張子の文字列
	 */	
	public static String getImageFileExtention(String filePath) {

		FileInputStream fis = null;
		InputStream is = null;
		byte[] buf = new byte[8];
		int len = 0;
		try {
			fis = new FileInputStream(filePath);
			is = new BufferedInputStream(fis);
			len = is.read(buf);
			if (len == -1) {
				return "";
			}
		} catch (Exception e) {
			return "";
		} finally {
			try {
				if (is != null) {
					is.close();
				}
			} catch (Exception e) {
			}
			try {
				if (fis != null) {
					fis.close();
				}
			} catch (Exception e) {
			}
		}

		final byte[] BMP_SIG = new byte[] { 0x42, 0x4D };
		final byte[] GIF_SIG_1 = new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 };
		final byte[] GIF_SIG_2 = new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 };
		final byte[] JPG_SIG = new byte[] { (byte)0xFF, (byte)0xD8, (byte)0xFF };
		final byte[] PNG_SIG = new byte[] { (byte)0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A };
		final byte[] PSD_SIG = new byte[] { 0x38, 0x42, 0x50, 0x53 };
		final byte[] TIF_SIG_1 = new byte[] { 0x49, 0x49, 0x2A, 0x00 };
		final byte[] TIF_SIG_2 = new byte[] { 0x4D, 0x4D, 0x00, 0x2A };

		if (len >= BMP_SIG.length && compareByteArray(buf, BMP_SIG, BMP_SIG.length) == 0) {
			return ".bmp";
		} else if (len >= GIF_SIG_1.length && compareByteArray(buf, GIF_SIG_1, GIF_SIG_1.length) == 0) {
			return ".gif";
		} else if (len >= GIF_SIG_2.length && compareByteArray(buf, GIF_SIG_2, GIF_SIG_2.length) == 0) {
			return ".gif";
		} else if (len >= JPG_SIG.length && compareByteArray(buf, JPG_SIG, JPG_SIG.length) == 0) {
			return ".jpg";
		} else if (len >= PNG_SIG.length && compareByteArray(buf, PNG_SIG, PNG_SIG.length) == 0) {
			return ".png";
		} else if (len >= PSD_SIG.length && compareByteArray(buf, PSD_SIG, PSD_SIG.length) == 0) {
			return ".psd";
		} else if (len >= TIF_SIG_1.length && compareByteArray(buf, TIF_SIG_1, TIF_SIG_1.length) == 0) {
			return ".tif";
		} else if (len >= TIF_SIG_2.length && compareByteArray(buf, TIF_SIG_2, TIF_SIG_2.length) == 0) {
			return ".tif";
		}

		return "";
	}

	/**
	 * byte配列を指定長さ分比較して結果を返す
	 *
	 * @param a1 比較対象の配列(1つ目)
	 * @param a2 比較対象の配列(2つ目)
	 * @param compareLength 比較する長さ
	 * @return 指定長さの内容が等しければ{@code 0}を等しくなければ{@code -1}
	 * いずれかの配列の長さが比較用の指定長さに満たない場合は{@code -1}
	 */	
	private static int compareByteArray(byte[] a1, byte[] a2, int compareLength) {
		if (a1.length < compareLength || a2.length < compareLength) {
			return -1;
		}
		for (int i = 0; i < compareLength; i++) {
			if (a1[i] != a2[i]) {
				return -1;
			}
		}
		return 0;
	}
}