/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.cemte.jacek.mpo;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
/**
 *
 * @author jwr
 */
public class LuminanceColorDemo extends JFrame{
    ImageOps ops=null;
    JFileChooser jfc_chooser=null;
    JButton jb_openFile=null;
    JComboBox jcb_colorSystems=null;
    JComboBox jcb_scaleFactorC1=null;
    JComboBox jcb_scaleFactorC2=null;
    JComboBox jcb_scaleFactorC3=null;
    
    JButton jb_transform=null;
    JButton jb_exit=null;
    JButton jb_clear=null;
    
    File pathToImage=null;
    String colorSystems[]={"YUV", "YCrCb"};
    String scaleFactors[]={"1","2","4","8","16","64"};

    Image outImage=null;
    int [] outData=null;

    int chosenCS=-1;
    int cF1=1,cF2=1,cF3=1;
    int chosenFactor[]=new int[3];

    public LuminanceColorDemo(String txt){
        super(txt);
        this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        ops=new ImageOps();
        initGUI();
    }

    public void initGUI(){
        jfc_chooser = new JFileChooser();
        //JFrame jf = new JFrame("Demonstracja różnicy w odbiorze luminancji i koloru");

        setLayout(new GridLayout(4,1));
        jb_openFile=new JButton("Otwórz plik z obrazem kolorowym!");
        jb_openFile.setFont(new Font("Dialog", Font.BOLD, 24));
        
        jb_openFile.setForeground(Color.blue);
        jb_openFile.addActionListener(new ActionListener(){
           public void actionPerformed(ActionEvent ae){
                int result = jfc_chooser.showOpenDialog(new JFrame());
                if (result == JFileChooser.APPROVE_OPTION) {
                    pathToImage = jfc_chooser.getSelectedFile();
                    System.out.println(pathToImage.getAbsolutePath());
                }
           }
        });
        add(jb_openFile);
        jcb_colorSystems=new JComboBox(colorSystems);
        jcb_colorSystems.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                chosenCS= jcb_colorSystems.getSelectedIndex();
            }
        });
        add(jcb_colorSystems);

        JPanel jp=new JPanel();
        jcb_scaleFactorC1=new JComboBox(scaleFactors);
        jcb_scaleFactorC1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                cF1= jcb_scaleFactorC1.getSelectedIndex();
            }
        });
        jcb_scaleFactorC2=new JComboBox(scaleFactors);
        jcb_scaleFactorC2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                cF2= jcb_scaleFactorC2.getSelectedIndex();
            }
        });
        jcb_scaleFactorC3=new JComboBox(scaleFactors);
        jcb_scaleFactorC3.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                cF3= jcb_scaleFactorC3.getSelectedIndex();
            }
        });
        jp.add(new JLabel("Współczynniki skali dla komponentów (Y U V):"));
        //JPanel pJC=new JPanel
        jp.add(jcb_scaleFactorC1);
        jp.add(jcb_scaleFactorC2);
        jp.add(jcb_scaleFactorC3);

        add(jp);

        JPanel controlPanel = new JPanel();

        jb_exit=new JButton("KONIEC");
        
        jb_exit.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent ae){
                System.exit(0);
            }
        });
        jb_clear=new JButton("ORYGINAŁ");
        jb_clear.addActionListener(new ActionListener(){
           public void actionPerformed(ActionEvent ae){
               if (pathToImage==null) return;
               int mode=0;
               int scalingFactor=1;
               
               outImage=ops.readBImage(pathToImage.getAbsolutePath());
               ImageViewPanel ivp=new ImageViewPanel(0,0,ops.width,ops.height,outImage,"Obraz oryginalny");
           } 
        });
        
        jb_transform=new JButton("KONWERTUJ");
        jb_transform.addActionListener(new ActionListener(){
           public void actionPerformed(ActionEvent ae){
               if (pathToImage==null) return;
               int mode=0;
               int scalingFactor=1;
               if(cF1==1&&cF2==1&&cF3==1){
                   
                   
               }else
               if(cF1>0){
                   if(cF2>1||cF3>1){
                       mode=7;
                   }else{
                       mode=4;
                   }
                   scalingFactor=Integer.parseInt(scaleFactors[cF1]);
               }else{
                   if(cF2>1&&cF3>1){
                       mode=3;
                       scalingFactor=Integer.parseInt(scaleFactors[cF2]);
                   }else{
                       if(cF2>1){
                           mode=2;
                           scalingFactor=Integer.parseInt(scaleFactors[cF2]);
                       }else{
                           mode=1;
                           scalingFactor=Integer.parseInt(scaleFactors[cF3]);
                       }
                   }
                   
               }
               System.out.println("TEST: "+mode+", "+scalingFactor);
               outData=convertImageForward(pathToImage);
               outData=convertImageReverse(chromaSubSample(outData,mode,scalingFactor));
               outImage=ImageFactory.create3CImage(ops.width, ops.height, outData);
               ImageViewPanel ivp=new ImageViewPanel(0,0,ops.width,ops.height,outImage,"Obraz po transformacji");
           } 
        });

        controlPanel.add(jb_exit);
        controlPanel.add(jb_clear);
        controlPanel.add(jb_transform);
        add(controlPanel);

    }//initGUI()

    public int[] convertImageForward(File pathToImage){
        int dTmp;
        int[] yuv=new int[3];
        int [] result=null;
        int offset=0;
        if(pathToImage.isFile()){
            BufferedImage bi=ops.readBImage(pathToImage.getAbsolutePath());
            result=new int[ops.width*ops.height];
            for(int i=0;i<ops.height;i++){
                offset=i*ops.width;
                for(int j=0;j<ops.width;j++){
                    dTmp=bi.getRGB(j, i);
                    yuv=ColorSpaceTransform.rgb2yuv2((dTmp>>16)&255, (dTmp>>8)&255, dTmp&255);
                    result[offset+j]=(255<<24)+((yuv[0]&255)<<16)+((yuv[1]&255)<<8)+(yuv[2]&255);
                    /*
                    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)

    public int[] convertImageReverse(int []data){
        int result[]=null;
        int[] rgb=new int[3];
        int offset=0*ops.width+0;

        result=new int[data.length];
        for(int i=0;i<result.length;i++){
            rgb=ColorSpaceTransform.yuv2rgb2((data[i]>>16)&255, (data[i]>>8)&255, data[i]&255);
            result[i]=(255<<24)+((rgb[0]&255)<<16)+((rgb[1]&255)<<8)+(rgb[2]&255);
            if(i==offset){
                   System.out.println("Y="+((data[i]>>16)&255)+"U="+ ((data[i]>>8)&255)+"V="+( data[i]&255));
                   System.out.println("RGB="+Arrays.toString(rgb));
                   System.out.println("Result="+result[i]);
            }
            //result[i]=255;
        }//for i
        return result;
    }

    public int [] subsample(int [] data, int ch, int factor){
        int [] result=new int[data.length];
        int c1=0,c2=0,c3=0;

        for(int i=0;i<data.length;i++){
            c1=(data[i]>>16)&255;
            c2=(data[i]>>8)&255;
            c3=(data[i])&255;
            switch (ch){
                case 4:
                        c1=(int)c1/factor;
                        c1=factor*c1;
                        break;
                case 2:
                        c2=(int)c2/factor;
                        c2=factor*c2;
                        break;
                case 1:
                        c3=(int)c3/factor;
                        c3=factor*c3;
                        break;
                case 3:
                        c2=(int)c2/factor;
                        c2=factor*c2;
                        c3=(int)c3/factor;
                        c3=factor*c3;
                        break;
                case 7:
                        c1=(int)c1/factor;
                        c1=factor*c1;
                        c2=(int)c2/factor;
                        c2=factor*c2;
                        c3=(int)c3/factor;
                        c3=factor*c3;
                        break;
                default: break;
            };
            result[i]=(255<<24)+(c1<<16)+(c2<<8)+c3;
        }
        return result;
    }//subsample()

    public int [] chromaSubSample(int [] data, int ch, int factor){
        int [] result=new int[data.length];
        int c1=0,c2=0,c3=0;
        
        int prevC1=0,prevC2=0,prevC3=0;
        //factor=16;
        int j=factor;
        for(int i=0;i<data.length;i++){
            c1=(data[i]>>16)&255;
            c2=(data[i]>>8)&255;
            c3=(data[i])&255;
            if((j%factor)!=0){
                /*
                switch(ch){
                    case 2: c2=prevC2;
                            c3=prevC3;
                            break;
                    case 3: c1=prevC1;
                            break;
                    default: break;
                };
                 
                 */
                switch(ch){
                case 4:
                        c1=prevC1;
                        break;
                case 2:
                        c2=prevC2;
                        break;
                case 1:
                        c3=prevC3;
                        break;
                case 3:
                        c2=prevC2;
                        c3=prevC3;
                        break;
                case 7:
                        c1=prevC1;
                        c2=prevC2;
                        c3=prevC3;
                        break;
                default: break;
                }
            }else {
                prevC1=c1;
                prevC2=c2;
                prevC3=c3;
            }
            if(j>1)
                j--;
            else
              j=factor;
            if(i%ops.width==0)
                j=factor;
            result[i]=(255<<24)+(c1<<16)+(c2<<8)+c3;
        }
        return result;
    }


    public static void main(String a[]){
        LuminanceColorDemo lcd=new LuminanceColorDemo("Demonstracja różnicy w odbiorze luminancji i koloru - Jacek Rumiński");
        int v[]=ColorSpaceTransform.rgb2yuv2(154,231,119);
        System.out.println(Arrays.toString(v));
        int w[]=ColorSpaceTransform.yuv2rgb2(v[0],v[1],v[2]);
        System.out.println(Arrays.toString(w));
        System.out.println("wartosc=" +(1%2));
        lcd.setSize(700,500);
        lcd.setVisible(true);
    }//main()

}//class
