package org.cemte.jacek.mpo;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.Panel;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.awt.image.MemoryImageSource;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JWindow;

public class ImageOps {
	
	private BufferedImage bi;
	private Image img;
	
	private int imageData[];
	public int width=0;
	public int height=0;
	
	public BufferedImage readBImage(String path){
		try{ 
			bi= ImageIO.read(new File(path)); 
			setParams();
			convertBIType();
		}catch(IOException e) {
			System.out.println("Image read problem: "+e);
			bi=null;
		}
		return bi;
	}//readBImage()
	
	public boolean writeBImage(String path, String type){
		boolean state=false;
		try{ 
			ImageIO.write(bi, type, new File(path));
			state=true;
		}catch(IOException e) {
			System.out.println("Image write problem: "+e);
		}
		return state;
	}//writeBImage()
	
	public boolean setImage(Image i){
		if(i!=null){
			img=i;
			width=i.getWidth(null);
			height=i.getHeight(null);
			return true;
		}else
			return false;
	}//setImage()
	
	public boolean setBImage(BufferedImage bImg){
		if(bImg!=null){
			bi=bImg;
			width=bi.getWidth();
			height=bi.getHeight();
			return true;
		}else
			return false;
	}//setBImage()
	
	public void setParams(){
		if(bi!=null){
			width=bi.getWidth();
			height=bi.getHeight();
		}
	}//
	
	public Image getImage(){
		return img;
	}//getImage()
	
	public BufferedImage getBImage(){
                System.out.println("TEST: "+bi);
		return bi;
	}//getBImage()
	
	public void img2bi(){
		bi=getBI(width,height);
	}//img2bi
	
	public BufferedImage getBI(int w, int h){
		bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); 
		
		Graphics2D g2 = bi.createGraphics(); 
		g2.drawImage(img, 0, 0, null);
		return bi;
	}//getBI
	
	public BufferedImage convertBIType(){
		BufferedImage bnew;
		bnew = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
		
		Graphics2D g2 = bnew.createGraphics(); 
		g2.drawImage(bi, 0, 0, null);
		bi=bnew;
		return bi;
	}//getBI
        
        public BufferedImage scale(double scaleFactor){
            width=(int)(scaleFactor*bi.getWidth());
            height=(int)(scaleFactor*bi.getHeight());
         
            img = bi.getScaledInstance(width,height,Image.SCALE_AREA_AVERAGING);
            img2bi();
            convertBIType();
            return bi;
        }
	
	
	public void filter(float[] lp) {
	
            Kernel kernel = new Kernel(3,3,lp); 
            ConvolveOp cop = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null); 
            bi = cop.filter(bi,null); 

	}//filter() 
	
	public void geomTransform(){
                    AffineTransform transform = new AffineTransform();
                    transform.setToScale(0.5, 0.5);
		    AffineTransformOp op = new AffineTransformOp(transform, null);
		    bi=op.filter(bi, null);
		    transform.setToRotation(15.0*Math.PI/180.0);
		    op = new AffineTransformOp(transform, null);
		    bi=op.filter(bi, null);
		    width=bi.getWidth();
		    height=bi.getHeight();
	}//geomTransform()
	
	public BufferedImage reflect() {
		
            int height = bi.getHeight();

            BufferedImage result = new BufferedImage(bi.getWidth(), height * 2,
                    BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2 = result.createGraphics();

             // Paints original image
            g2.drawImage(bi, 0, 0, null);

            // Paints mirrored image
            g2.scale(1.0, -1.0);
            g2.drawImage(bi, 0, -height - height, null);
            g2.scale(1.0, -1.0);

            // Move to the origin of the clone
            g2.translate(0, height);

            // Creates the alpha mask
            GradientPaint mask;
            mask = new GradientPaint(0, 0, new Color(1.0f, 1.0f, 1.0f, 0.5f),
                    0, height / 2, new Color(1.0f, 1.0f, 1.0f, 0.0f));
            Paint oldPaint = g2.getPaint();
            g2.setPaint(mask);

            // Sets the alpha composite
            g2.setComposite(AlphaComposite.DstIn);

            // Paints the mask
            g2.fillRect(0, 0, bi.getWidth(), height);
            bi=result;
            g2.dispose();
            return bi;
    }//
        
    public int[] convertCS(int cs, int ch){
        int dTmp;
        int[] newCS=new int[3];
        double[] csD=new double[3];
        float[] csF=new float[3];
        int [] result=null;
        int offset=0;
        if(bi!=null){
            if(width==0 || height==0){
                setParams();
            }
            result=new int[width*height];
            for(int i=0;i<height;i++){
                offset=i*width;
                for(int j=0;j<width;j++){
                    dTmp=bi.getRGB(j, i);
                    switch(cs){
                        case 1:
                                newCS=ColorSpaceTransform.rgb2YIQ((dTmp>>16)&255, (dTmp>>8)&255, dTmp&255);
                                result[offset+j]=(255<<24)+((newCS[ch]&255)<<16)+((newCS[ch]&255)<<8)+(newCS[ch]&255);
                                break;
                        case 2:
                                newCS=ColorSpaceTransform.rgb2YIQ((dTmp>>16)&255, (dTmp>>8)&255, dTmp&255);
                                result[offset+j]=(255<<24)+(((newCS[0]-newCS[2])&255)<<16)+(((newCS[0]-newCS[2])&255)<<8)+((newCS[0]-newCS[2])&255);
                                break;   
                        case 3:
                                csD=ColorSpaceTransform.rgb2YIQ_Double(((dTmp>>16)&255)/255.0, ((dTmp>>8)&255)/255.0, (dTmp&255)/255.0);
                                result[offset+j]=(255<<24)+(((int)(csD[ch]*255.0)&255)<<16)+(((int)(csD[ch]*255.0)&255)<<8)+((int)(csD[ch]*255.0)&255);
                                break;  
                        case 4:
                                csF=ColorSpaceTransform.rgb2HSB_FLOAT(((dTmp>>16)&255), ((dTmp>>8)&255), (dTmp&255));
                                result[offset+j]=(255<<24)+(((int)(csF[ch]*255.0)&255)<<16)+(((int)(csF[ch]*255.0)&255)<<8)+((int)(csF[ch]*255.0)&255);
                                break;    
                        default:
                                break;
                    }
                    /*
                    if(i==0&&j==0){
                        System.out.println("YUV="+Arrays.toString(yuv));
                        System.out.println("R="+((dTmp>>16)&255)+"G="+ ((dTmp>>8)&255)+"B="+( dTmp&255));
                        System.out.println("Yt="+(yuv[0]<<16)+"Ut="+ (yuv[1]<<8)+"Vt="+(yuv[2]));
                        System.out.println("Result="+result[offset+j]);
                    }
                     */
                    //result[offset+j]=(255<<24)+20;//ColorSpaceTransform.scale(yuv[2]);
                }//for j
            }//for i
        }//if
        //System.out.println(Arrays.toString(result));
        return result;
    }//convertImageForward(File pathToImage)
            

	

}//class ImageOps

