package org.maachang.util.image;

import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * イメージコンバート.
 * <BR><BR>
 * イメージをコンバートするオブジェクト.
 *
 * @version 2007/11/29
 * @author  masahito suzuki
 * @since   MaachangBase 1.05
 */
public class ImageConvertor {
    
    /**
     * デフォルトレート.
     */
    private static final int DEFAULT_RATE = 75 ;
    
    /**
     * 最小レート.
     */
    private static final int MIN_RATE = 35 ;
    
    /**
     * 最大レート.
     */
    private static final int MAX_RATE = 100 ;
    
    /**
     * デフォルトファイルタイプ.
     */
    private static final String DEFAULT_TYPE = "JPEG" ;
    
    /**
     * ファイルタイプ : JPEG.
     */
    public static final String JPEG_TYPE = "JPEG" ;
    
    /**
     * ファイルタイプ : GIF.
     */
    public static final String GIF_TYPE = "GIF" ;
    
    /**
     * ファイルタイプ : PNG.
     */
    public static final String PNG_TYPE = "PNG" ;
    
    
    
    /**
     * コンストラクタ.
     */
    private ImageConvertor() {
    }
    
    /**
     * 指定イメージ情報をロード.
     * <BR><BR>
     * 指定イメージ情報をロードします.
     * <BR>
     * @param name 対象のイメージファイル名を設定します.
     * @return ImageInfo イメージ情報が格納された情報が返されます.
     * @exception IOException I/O例外.
     */
    public static final ImageInfo loadImage( String name )
        throws IOException {
        
        if( name == null || ( name = name.trim() ).length() <= 0 ) {
            throw new IOException( "指定ファイル名は不正です" ) ;
        }
        
        BufferedInputStream stream = new BufferedInputStream(
            new FileInputStream( name ) ) ;
        
        try {
            ImageInfo ret = ImageConvertor.loadImage( stream ) ;
            stream.close() ;
            stream = null ;
            return ret ;
        } catch( IOException io ) {
            throw io ;
        } finally {
            if( stream != null ) {
                try {
                    stream.close() ;
                } catch( Exception e ) {
                }
            }
        }
    }
    
    /**
     * 指定イメージ情報をロード.
     * <BR><BR>
     * 指定イメージ情報をロードします.
     * <BR>
     * @param stream 対象のイメージストリームを設定します.
     * @return ImageInfo イメージ情報が格納された情報が返されます.
     * @exception IOException I/O例外.
     */
    public static final ImageInfo loadImage( InputStream stream )
        throws IOException {
        
        if( stream == null ) {
            throw new IOException( "指定ストリーム条件は不正です" ) ;
        }
        
        BufferedImage image = BaseImageConvertor.readImage( stream ) ;
        if( image != null ) {
            return new ImageInfo( image ) ;
        }
        
        throw new IOException( "イメージのロードに失敗しました" ) ;
    }
    
    /**
     * 指定イメージ情報をセーブ.
     * <BR><BR>
     * 指定されたイメージ情報をセーブします.
     * <BR>
     * @param info 対象のイメージ情報を設定します.
     * @param name 保存先のイメージファイル名を指定します.
     * @param type 保存タイプを設定します.<BR>
     *             たとえば、JPEGで保存したい場合は、JPEG_TYPEを設定します.
     * @param rate 保存タイプがJPEGの場合に有効となるレート情報を設定します.
     * @exception IOException I/O例外.
     */
    public static final void saveImage( ImageInfo info,String name,String type,int rate )
        throws IOException {
        
        if( info == null || info.isUse() == false ) {
            throw new IOException( "セーブ対象のイメージ情報は存在しません" ) ;
        }
        if( name == null || ( name = name.trim() ).length() <= 0 ) {
            throw new IOException( "指定ファイル名は不正です" ) ;
        }
        
        BufferedOutputStream stream = new BufferedOutputStream(
            new FileOutputStream( name ) ) ;
        
        try {
            ImageConvertor.saveImage( info,stream,type,rate ) ;
            stream.close() ;
            stream = null ;
        } catch( IOException io ) {
            throw io ;
        } finally {
            if( stream != null ) {
                try {
                    stream.close() ;
                } catch( Exception e ) {
                }
            }
        }
    }
    
    /**
     * 指定イメージ情報をセーブ.
     * <BR><BR>
     * 指定されたイメージ情報をセーブします.
     * <BR>
     * @param info 対象のイメージ情報を設定します.
     * @param stream 保存先のイメージストリームを指定します.
     * @param type 保存タイプを設定します.<BR>
     *             たとえば、JPEGで保存したい場合は、JPEG_TYPEを設定します.
     * @param rate 保存タイプがJPEGの場合に有効となるレート情報を設定します.
     * @exception IOException I/O例外.
     */
    public static final void saveImage( ImageInfo info,OutputStream stream,String type,int rate )
        throws IOException {
        
        if( info == null || info.isUse() == false ) {
            throw new IOException( "セーブ対象のイメージ情報は存在しません" ) ;
        }
        if( stream == null ) {
            throw new IOException( "指定ストリームは不正です" ) ;
        }
        if( type == null || ( type = type.trim() ).length() <= 0 ) {
            type = DEFAULT_TYPE ;
        }
        if( rate == -1 ) {
            rate = DEFAULT_RATE ;
        }
        else if( rate <= MIN_RATE ) {
            rate = MIN_RATE ;
        }
        else if( rate >= MAX_RATE ) {
            rate = MAX_RATE ;
        }
        
        try {
            BufferedImage image = info.getImage() ;
            if( image == null ) {
                throw new IOException( "セーブ対象のイメージ情報は存在しません" ) ;
            }
            double rateDouble = ( double )rate / 100.0f ;
            BaseImageConvertor.writeImage( stream,image,type,rateDouble ) ;
            stream.flush() ;
        } catch( IOException io ) {
            throw io ;
        }
        
    }
    
    /**
     * イメージを指定サイズに変換.
     * <BR><BR>
     * イメージを指定サイズに変換します.
     * <BR>
     * @param info 対象のイメージ情報を設定します.
     * @param width 対象の指定サイズWidthを設定します.
     * @param height 対象の指定サイズHeightを設定します.
     * @param color 対象の減食カラー値を設定します.
     * @exception IOException I/O例外.
     */
    public static final void convert( ImageInfo info,int width,int height,int color )
        throws IOException {
        
        if( info == null || info.isUse() == false ) {
            throw new IOException( "セーブ対象のイメージ情報は存在しません" ) ;
        }
        
        try {
            
            BufferedImage image = info.getImage() ;
            if( image == null ) {
                throw new IOException( "対象のイメージ情報は存在しません" ) ;
            }
            
            // 解像度変換.
            if( image.getWidth() != width || image.getHeight() != height ){
                image = BaseImageConvertor.convertImage( image,width,height ) ;
            }
            
            // 減色処理.
            if( color > 0 ){
                image = BaseImageConvertor.decColorImage( image,color ) ;
            }
            
            // 処理結果の内容を再設定.
            info.setImage( image ) ;
            
        } catch( IOException io ) {
            throw io ;
        }
        
    }
}

