/*
 * Copyright (C) 2005-2006 Kouji Sugisawa. All rights reserved.
 */

package jp.sourceforge.livez.images;

import java.awt.Image;
import java.awt.Toolkit;
import java.awt.image.AreaAveragingScaleFilter;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.IndexColorModel;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import org.apache.commons.io.FilenameUtils;

/**
 * 簡易な画像変換用ユーティリティクラスです。
 * 
 * @author 杉澤 浩二
 */
public final class ImageConverter {

	/**
	 * インスタンス化出来ない事を強制します。
	 */
	private ImageConverter() {}

	public static void converte(final String src, final ImageType type)
		throws IllegalArgumentException, IOException {

		String dist = getDistFilename(src, type);

		converte(new File(src), new File(dist), type);
	}

	public static void converte(final String src, final ImageType type, final double scale)
		throws IllegalArgumentException, IOException {

		String dist = getDistFilename(src, type);

		converte(new File(src), new File(dist), type, scale, scale);
	}

	public static void converte(final String src, final ImageType type, final double sx, final double sy)
		throws IllegalArgumentException, IOException {

		String dist = getDistFilename(src, type);

		converte(new File(src), new File(dist), type, sx, sy);
	}

	public static void converte(final String src, final ImageType type, final int width, final int height)
		throws IllegalArgumentException, IOException {

		String dist = getDistFilename(src, type);

		converte(new File(src), new File(dist), type, width, height);
	}

	/**
	 * 指定された入力ファイル名と出力ファイル形式から既定の出力ファイル名を返します。
	 * 
	 * @param src 入力ファイル名
	 * @param type 出力ファイル形式
	 * @return 既定の出力ファイル名
	 * @throws IllegalArgumentException パラメータが不正な場合
	 */
	private static String getDistFilename(final String src, final ImageType type) throws IllegalArgumentException {
		if (src == null || src.length() <= 0)
			throw new IllegalArgumentException("src is null or blank.");
		if (type == null)
			throw new IllegalArgumentException("type is null.");
		
		return FilenameUtils.getFullPath(src) + FilenameUtils.getBaseName(src) + '.' + type.getSuffix();
	}


	public static void converte(
		final String src,
		final String dist,
		final ImageType type)
		throws IllegalArgumentException, IOException {

		converte(new File(src), new File(dist), type);
	}

	public static void converte(
		final String src,
		final String dist,
		final ImageType type,
		final double scale)
		throws IllegalArgumentException, IOException {

		converte(new File(src), new File(dist), type, scale, scale);
	}

	public static void converte(
		final String src,
		final String dist,
		final ImageType type,
		final double sx,
		final double sy)
		throws IllegalArgumentException, IOException {

		converte(new File(src), new File(dist), type, sx, sy);
	}

	public static void converte(
		final String src,
		final String dist,
		final ImageType type,
		final int width,
		final int height)
		throws IllegalArgumentException, IOException {

		converte(new File(src), new File(dist), type, width, height);
	}


	public static void converte(
		final File src,
		final File dist,
		final ImageType type)
		throws IllegalArgumentException, IOException {

		converte(src, dist, type, -1, -1);
	}

	public static void converte(
		final File src,
		final File dist,
		final ImageType type,
		final double scale)
		throws IllegalArgumentException, IOException {
	
		converte(src, dist, type, scale, scale);
	}

	public static void converte(
		final File src,
		final File dist,
		final ImageType type,
		final double sx,
		final double sy)
		throws IllegalArgumentException, IOException {
	
		BufferedImage in = ImageIO.read(src);
		BufferedImage out = converteBufferedImage(in, type, sx, sy);
		ImageIO.write(out, type.getFormatName(), dist);
	}

	public static void converte(
		final File src,
		final File dist,
		final ImageType type,
		final int width,
		final int height)
		throws IllegalArgumentException, IOException {

		BufferedImage in = ImageIO.read(src);
		BufferedImage out = converteBufferedImage(in, type,
			width > 0 ? width : in.getWidth(),
			height > 0 ? height : in.getHeight()
		);
		ImageIO.write(out, type.getFormatName(), dist);
	}

/*
	private static BufferedImage readJpegFile(final InputStream in) throws ImageFormatException, IOException {
		JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in); 
		return decoder.decodeAsBufferedImage(); 
	}
*/

	/**
	 * 指定された画像を指定された変換方法によって変換した画像のコピーを返します。
	 * 
	 * @param source 画像
	 * @param type 画像形式
	 * @return 変換された画像
	 * @throws IllegalArgumentException
	 */
	public static BufferedImage converteBufferedImage(
		final BufferedImage source,
		final ImageType type)
		throws IllegalArgumentException {

		return converteBufferedImage(source, type, source.getWidth(), source.getHeight());
	}

	/**
	 * 指定された画像を指定された変換方法によって変換した画像のコピーを返します。
	 * 
	 * @param source 画像
	 * @param scale 倍率
	 * @param type 画像形式
	 * @return 変換された画像
	 * @throws IllegalArgumentException
	 */
	public static BufferedImage converteBufferedImage(
		final BufferedImage source,
		final ImageType type,
		final double scale)
		throws IllegalArgumentException {

		return converteBufferedImage(source, type, (int)(source.getWidth() * scale), (int)(source.getHeight() * scale));
	}

	/**
	 * 指定された画像を指定された変換方法によって変換した画像のコピーを返します。
	 * 
	 * @param source 画像
	 * @param sx 横倍率
	 * @param sy 縦倍率
	 * @param type 画像形式
	 * @return 変換された画像
	 * @throws IllegalArgumentException
	 */
	public static BufferedImage converteBufferedImage(
		final BufferedImage source,
		final ImageType type,
		final double sx,
		final double sy)
		throws IllegalArgumentException {

		return converteBufferedImage(source, type, (int)(source.getWidth() * sx), (int)(source.getHeight() * sy));
	}

	/**
	 * 指定された画像を指定された変換方法によって変換した画像のコピーを返します。
	 * 
	 * @param source 画像
	 * @param width 幅(ピクセル)
	 * @param height 高さ(ビクセル)
	 * @param type 画像形式
	 * @return 変換された画像
	 * @throws IllegalArgumentException
	 */
	public static BufferedImage converteBufferedImage(
		final BufferedImage source,
		final ImageType type,
		final int width,
		final int height)
		throws IllegalArgumentException {

		if (type == null)
			throw new IllegalArgumentException();

		ImageFilter filter = new AreaAveragingScaleFilter(width, height);
		Image image = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(source.getSource(), filter));

		int t = type.getBufferedImageType() == -1 ? source.getType() : type.getBufferedImageType();

		BufferedImage result;

		IndexColorModel indexColorModel = type.getIndexColorModel();
		if (indexColorModel == null)
			result = new BufferedImage(width, height, t);
		else {
			result = new BufferedImage(width, height, t, indexColorModel);
		}

		result.createGraphics().drawImage(image, 0, 0, null);

		return result;
	}

}
