/*
 * Created on Oct 22, 2005
 * $Id: ImageCutter.html,v 1.1 2005/11/12 15:13:09 mogo Exp $
 * $Source: /usr/local/cvsroot/bluemarble/ImageCutter.html,v $
 */
package be.mogo.businesslogic.location;

import java.awt.image.BufferedImage;
import java.io.File;
import java.math.BigDecimal;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.ImageOutputStream;


/**
 * @author mogo
 *
 */
public class ImageCutter {
    
    private static final String DIR_500M = "/mnt/raid/bluemarble/bmng/world_500m";
    private static final String[] mapNames = { "A1" ,"B1", "C1", "D1", "A2", "B2", "C2", "D2" };
    private static final String BASENAME = "world.200401.3x21600x21600";
    
    private static final int MAIN_TILE_WIDTH = 21600;
    private static final int TILE_WIDTH = 150;
    
    private static final String IMAGETYPE_EXTENSION = "png";
    private static final String IMAGETYPE_WRITE_EXTENSION = "jpg";
    private static final float COMPRESSION_QUALITY = 0.5F;
    
    private static final String DIRECTORY_PROCESSED = "/home/mogo/projects/bluemarble";
    
    private static final int[] scales = { 144, 36, 18, 12, 6, 4, 2, 0 };

 
    public static void main(String[] args) {
        ImageCutter cutter = new ImageCutter();
        try {
            for (int i = 0; i < scales.length; i++) {
                cutter.makeTiles( scales[i] );
            }
        } 
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    
    public void makeTiles( int scale ) throws Exception {
        
        int modifier = 0;
        
        if ( scale != 0 ){
            if ( (MAIN_TILE_WIDTH / scale) % TILE_WIDTH != 0 ){
                throw new Exception("scale can not be used to process tiles of " + TILE_WIDTH + " width");
            }
            modifier = (MAIN_TILE_WIDTH / scale) / TILE_WIDTH;
        }
        else {
            modifier = MAIN_TILE_WIDTH / TILE_WIDTH;
        }
        
        System.out.println("----> modifier =" + modifier );
        
        Iterator iter = ImageIO.getImageWritersBySuffix(IMAGETYPE_WRITE_EXTENSION);
        ImageWriter writer = (ImageWriter)iter.next();
     
        int mainX = -180;
        int mainY = -90;
        
        for (int i = 0; i < mapNames.length; i++) {

            //read the main tile
            String fileName = BASENAME + "." + mapNames[i] + "." + IMAGETYPE_EXTENSION;
            System.out.println("starting file :" + DIR_500M + "     " + fileName );
            File mainTile = new File(DIR_500M,  fileName);
            ImageInputStream iis = ImageIO.createImageInputStream( mainTile );
            ImageReader reader = (ImageReader)ImageIO.getImageReadersBySuffix(IMAGETYPE_EXTENSION).next();
            reader.setInput( iis, true );
            ImageReadParam param = reader.getDefaultReadParam();
            if ( scale != 0 ) {
                //scale if necessary
                param.setSourceSubsampling( scale, scale, 0, 0 );
            }
            BufferedImage bimage = reader.read( 0, param );
            reader.dispose();
            iis.close();

            //create the processdirectory if it does not exist
            File directoryToProcess = new File( DIRECTORY_PROCESSED, "" + scale);
            if ( !directoryToProcess.exists() || !directoryToProcess.isDirectory() ){
                directoryToProcess.mkdirs();
            }
            
            //compose the subtiles
            BigDecimal x = new BigDecimal(mainX);
            x = x.setScale( 3,BigDecimal.ROUND_HALF_EVEN);
            for ( int j=0; j < modifier; j++ ){
                BigDecimal y = new BigDecimal(mainY);
                y = y.setScale( 3,BigDecimal.ROUND_HALF_EVEN);
                for ( int k = 0; k < modifier; k++ ){
                    BufferedImage sub = bimage.getSubimage( j * TILE_WIDTH, k * TILE_WIDTH, TILE_WIDTH, TILE_WIDTH);
                    File alteredFile = new File( directoryToProcess, x + "x" + y +"." + IMAGETYPE_WRITE_EXTENSION );
                    ImageOutputStream ios = ImageIO.createImageOutputStream( alteredFile );
                    writer.setOutput( ios );
                    writer.write( null, new IIOImage(sub, null, null), getImageWriteParam( writer) );
                    writer.reset();
                    System.out.println( "done writing: " + alteredFile );
                    ios.close();
                    y = increase( y, modifier );
                }
                x = increase( x, modifier );
            }
            
            if ( i == 3 ){
                mainX = -180; mainY = 0;
            }
            else {
                mainX = mainX + 90;
            }
            
        }   
    }
    
    
    private ImageWriteParam getImageWriteParam( ImageWriter writer ){
        ImageWriteParam imgWriteParam = writer.getDefaultWriteParam();
        imgWriteParam.setCompressionMode( ImageWriteParam.MODE_EXPLICIT );
        imgWriteParam.setCompressionQuality( COMPRESSION_QUALITY );
        imgWriteParam.setProgressiveMode( ImageWriteParam.MODE_DEFAULT);
        return imgWriteParam;
    }
    
    
    
    private BigDecimal increase( BigDecimal xORy, int modifier ){
        BigDecimal bd = new BigDecimal(90);
        bd = bd.setScale( 3,BigDecimal.ROUND_HALF_EVEN);
        bd = bd.divide( new BigDecimal(modifier), BigDecimal.ROUND_HALF_EVEN);
        xORy = xORy.add( bd );
        return xORy;
    }
    
  
    
    
}