/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package csa.tiletools.graphics;

import csa.config.Configuration;
import csa.gui.Windowable;
import csa.gui.components.CSAView;
import csa.gui.dialogs.InternalFrameFileChoser;
import csa.gui.image.OctTreeQuantizer;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.util.*;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 *
 * @author salchr
// does keep Alpha! But reduces colors only in respect to RGB not to A
 */
public class ColorReduceJPanel extends javax.swing.JPanel implements Windowable{
    int inSetting;

    private CSAView mParent = null;
    private javax.swing.JMenuItem mParentMenuItem = null;
    private BufferedImage orgImage = null;


    @Override
    public void closing(){}
    @Override
    public void setParentWindow(CSAView jpv)
    {
        mParent = jpv;
    }
    @Override
    public void setMenuItem(javax.swing.JMenuItem item)
    {
        mParentMenuItem = item;
        mParentMenuItem.setText("Color Reducer");
    }
    @Override
    public javax.swing.JMenuItem getMenuItem()
    {
        return mParentMenuItem;
    }
    @Override
    public javax.swing.JPanel getPanel()
    {
        return this;
    }



    /**
     * Creates new form ColorReduceJPanel
     */
    public ColorReduceJPanel() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        singleImagePanel1 = new csa.tiletools.graphics.SingleImagePanel();
        jSliderSourceScale = new javax.swing.JSlider();
        jTextFieldImageSource = new javax.swing.JTextField();
        jButtonFileSelect = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        jTextField1 = new javax.swing.JTextField();
        jButton1 = new javax.swing.JButton();
        jTextField2 = new javax.swing.JTextField();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();

        singleImagePanel1.setPreferredSize(new java.awt.Dimension(100, 100));

        javax.swing.GroupLayout singleImagePanel1Layout = new javax.swing.GroupLayout(singleImagePanel1);
        singleImagePanel1.setLayout(singleImagePanel1Layout);
        singleImagePanel1Layout.setHorizontalGroup(
            singleImagePanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 590, Short.MAX_VALUE)
        );
        singleImagePanel1Layout.setVerticalGroup(
            singleImagePanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 377, Short.MAX_VALUE)
        );

        jSliderSourceScale.setMajorTickSpacing(1);
        jSliderSourceScale.setMaximum(11);
        jSliderSourceScale.setMinimum(1);
        jSliderSourceScale.setMinorTickSpacing(1);
        jSliderSourceScale.setOrientation(javax.swing.JSlider.VERTICAL);
        jSliderSourceScale.setPaintTicks(true);
        jSliderSourceScale.setSnapToTicks(true);
        jSliderSourceScale.setValue(6);
        jSliderSourceScale.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSliderSourceScaleStateChanged(evt);
            }
        });

        jTextFieldImageSource.setToolTipText("Image path Info");
        jTextFieldImageSource.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                jTextFieldImageSourceFocusLost(evt);
            }
        });

        jButtonFileSelect.setText("...");
        jButtonFileSelect.setToolTipText("If multiple files are selected, an \"Add Series\" is done automatically for all images.");
        jButtonFileSelect.setMargin(new java.awt.Insets(0, 1, 0, -1));
        jButtonFileSelect.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButtonFileSelectActionPerformed(evt);
            }
        });

        jLabel2.setText("Image source");

        jTextField1.setText("16");

        jButton1.setText("Reduce by Octree");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        jLabel3.setText("Color Count");

        jLabel4.setText("Reduce To");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(singleImagePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 590, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel2)
                            .addComponent(jLabel3)
                            .addComponent(jLabel4))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(jTextFieldImageSource, javax.swing.GroupLayout.PREFERRED_SIZE, 388, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(jButtonFileSelect))
                            .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, 48, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jButton1))))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 67, Short.MAX_VALUE)
                .addComponent(jSliderSourceScale, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(singleImagePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 377, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                            .addComponent(jTextFieldImageSource, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel2)
                            .addComponent(jButtonFileSelect)))
                    .addComponent(jSliderSourceScale, javax.swing.GroupLayout.PREFERRED_SIZE, 384, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel3))
                .addGap(0, 55, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void jSliderSourceScaleStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSliderSourceScaleStateChanged
        if (inSetting>0) return;
        int value = jSliderSourceScale.getValue();
        double scale = value - 5;
        if (value <6)
        {
            int invScale = 7-value;
            scale = 1.0/invScale;
        }
//        currentScale = scale;
//        jLabel14.setText("Scale * "+scale);
//        singleImagePanel1.setScale(scale);
        // jScrollPane2.getViewport().setView(singleImagePanel1);
    }//GEN-LAST:event_jSliderSourceScaleStateChanged

    private void jTextFieldImageSourceFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jTextFieldImageSourceFocusLost
        setImage();
    }//GEN-LAST:event_jTextFieldImageSourceFocusLost

    private void jButtonFileSelectActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButtonFileSelectActionPerformed

        InternalFrameFileChoser fc = new csa.gui.dialogs.InternalFrameFileChoser();
        fc.setMultiSelectionEnabled(false);
        fc.setCurrentDirectory(new java.io.File("."));
        fc.setCurrentDirectory(new java.io.File("images"));
        FileNameExtensionFilter  filter = new  FileNameExtensionFilter("Images", "jpg", "jpeg", "png", "bmp", "gif");
        fc.setFileFilter(filter);
        int r = fc.showOpenDialog(Configuration.getConfiguration().getMainFrame());
        if (r != InternalFrameFileChoser.APPROVE_OPTION) return;
        String fullPath = fc.getSelectedFile().getAbsolutePath();
        jTextFieldImageSource.setText(csa.util.Utility.makeRelative(fullPath));
        setImage();
        inSetting++;
        jSliderSourceScale.setValue(6);
        singleImagePanel1.setScale(1);
        inSetting--;
    }//GEN-LAST:event_jButtonFileSelectActionPerformed

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed

        if (orgImage==null) return;
        OctTreeQuantizer quant = new OctTreeQuantizer(csa.util.UtilityString.IntX(jTextField1.getText(), 2));
        int[] pixels = convertTo2DUsingGetRGB(orgImage);
        quant.addPixels(pixels, 0, pixels.length);
	int[] ctable = quant.buildColorTable();

        int width = orgImage.getWidth();
        int height = orgImage.getHeight();
        int[] newPixels = new int[height*width];
        int c = 0;
        for (int row = 0; row < height; row++) {
           for (int col = 0; col < width; col++)
           {
                int rgba =orgImage.getRGB(col, row);
                int orgAlpha = (rgba >> 24) & 0xFF;
                int color = ctable[quant.getIndexForColor(pixels[c])];
                // delete old Alpha
                color = (color &0xffffff);

                color = color + ((orgAlpha& 0xFF) << 24);

               newPixels[c] = color;
              c++;
           }
        }

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        WritableRaster wr = image.getRaster();
        wr.setDataElements(0, 0, width, height, newPixels);
        singleImagePanel1.setImage(image);
        showColorCount(image);
        invalidate();
        validate();
        repaint();
    }//GEN-LAST:event_jButton1ActionPerformed

    int showColorCount(BufferedImage image)
    {
        int width = image.getWidth();
        int height = image.getHeight();
        HashMap<Integer, Integer> colors = new HashMap<Integer, Integer>();
        int[] pixels = convertTo2DUsingGetRGB(image);
        int c = 0;
        for (int row = 0; row < height; row++) {
           for (int col = 0; col < width; col++)
           {
              colors.put(pixels[c], pixels[c]);
              c++;
           }
        }
        jTextField2.setText(""+colors.size());
        return colors.size();
    }

    private static int[] convertTo2DUsingGetRGB(BufferedImage image)
    {
      int width = image.getWidth();
      int height = image.getHeight();
      int[] result = new int[height*width];

      int c = 0;
      for (int row = 0; row < height; row++) {
         for (int col = 0; col < width; col++) {
            result[c++] = image.getRGB(col, row);
         }
      }
      return result;
    }


    void setImage()
    {
        singleImagePanel1.setImage(jTextFieldImageSource.getText());
        orgImage = singleImagePanel1.getImage();
        showColorCount(orgImage);
        invalidate();
        validate();
        repaint();
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButtonFileSelect;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JSlider jSliderSourceScale;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextFieldImageSource;
    private csa.tiletools.graphics.SingleImagePanel singleImagePanel1;
    // End of variables declaration//GEN-END:variables
}
