
/* @(#) ImageEnhancer.java 1.0 99/10/4
 * Copyright (c) 1999 Larry Rodrigues
 */
package app;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.color.*;
import vis.beans.plotter.*;
import java.awt.geom.*;
import com.vistech.imagedata.*;
import com.vistech.imageviewer.*;
import com.sun.image.codec.jpeg.*;
import com.vistech.imageviewer.DisplayMode;
import java.beans.*;
 /** A sample application that allows users to apply some image processiong operations such as
   * window/level, convolution, etc.
   * @version 1.0  10 April 1999
   * @author Lawrence Rodrigues
   */
public class ImageEnhancer extends JPanel {
   protected ImageCanvas2D srcImageCanvas, destImageCanvas;
   protected int imageWidth, imageHeight;
   protected int viewerWidth, viewerHeight;
   protected  WindowLevelGUI wlpan;

   public static BufferedImage readAsBufferedImage(String filename) {
      try {
         FileInputStream fis = new FileInputStream(filename);
         JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(fis);
         BufferedImage bi = decoder.decodeAsBufferedImage();
         return bi;
      } catch(Exception e) {
         System.out.println(e);
         return null;
      }
   }

   public void loadAndDisplay(String filename){
      BufferedImage img = readAsBufferedImage(filename);
      displayImage(img);
   }

   public void displayImage(BufferedImage img) {
      int width = img.getWidth();
      int height = img.getHeight();
      displayImage(img, width, height);
   }


   private Dimension getViewerSize(double imageAspectRatio){
      Dimension d= Toolkit.getDefaultToolkit().getScreenSize();
      int maxWidth = (int)(d.width *4/5.0);
      int maxHeight = (int)(d.height*4/5.0);
      double screenAspectRatio = maxWidth/(double)maxHeight;
      int viewerWidth,viewerHeight;
      if(imageAspectRatio  > screenAspectRatio){
          viewerWidth =   maxWidth;
          viewerHeight = (int)( maxHeight* screenAspectRatio/imageAspectRatio);
      }else{
          viewerHeight =   maxHeight;
          viewerWidth = (int)(maxWidth* imageAspectRatio/screenAspectRatio);
      }
      return new Dimension(viewerWidth, viewerHeight);
   }

   public void displayImage(BufferedImage img, int width, int height) {
      JFrame fr = new JFrame();
      fr.addWindowListener(
         new WindowAdapter() {
            public void windowClosing(WindowEvent e){
               System.exit(0);
            }
         } );
      fr.setTitle("Image Enhancer");
      imageWidth = img.getWidth();
      imageHeight = img.getHeight();
      double aspectRatio = imageWidth/(double)imageHeight;
      Dimension d = getViewerSize(aspectRatio);
      viewerWidth = d.width;
      viewerHeight = d.height;
      width = d.width/2;
      height = d.width/2;
      //srcImageCanvas= new ImagePanel(img, imageWidth, imageHeight);
      //srcImageCanvas= new CompositeCanvas2D();
      srcImageCanvas= new ImageCanvas2D();
      srcImageCanvas.setBufferedImage(img);

      srcImageCanvas.setPreferredSize(new Dimension(imageWidth, imageHeight));
      JScrollPane srcjsp = new JScrollPane(srcImageCanvas);
      srcImageCanvas.setDisplayMode(DisplayMode.ORIG_SIZE);

      //destImageCanvas = new ImagePanel(img, imageWidth, imageHeight);
      //destImageCanvas= new CompositeCanvas2D();
      destImageCanvas= new ImageCanvas2D();
      destImageCanvas.setBufferedImage(img);
      destImageCanvas.setPreferredSize(new Dimension(imageWidth, imageHeight));
      JScrollPane destjsp = new JScrollPane(destImageCanvas);
      destImageCanvas.setDisplayMode(DisplayMode.ORIG_SIZE);
      JPanel viewerpan = new JPanel();
      viewerpan.setSize(2*width, height);
      viewerpan.setLayout(new GridLayout(1,2));
      viewerpan.add(srcjsp);
      viewerpan.add(destjsp);
      Container cp = fr.getContentPane();
      fr.getContentPane().setLayout(new BorderLayout());
      cp.add(viewerpan);
      JTabbedPane jtp = new JTabbedPane();
      EnhancePanel enhancepan = new EnhancePanel();
      jtp.add("Enhance", enhancepan);
      EdgeDetectPanel  edgedetectpan = new EdgeDetectPanel();
      jtp.add("Edge Detect", edgedetectpan);
      ColorConvertPanel colorconvertpan = new ColorConvertPanel();
      jtp.add("Color Convert", colorconvertpan);
      BandCombinePanel  bandcombinepan = new BandCombinePanel();
      jtp.add("Band Combine", bandcombinepan);

      WindowLevel windowLevel = new WindowLevel(destImageCanvas);
      wlpan = new WindowLevelGUI(windowLevel);
      setWLSliderValues();
      jtp.add("Window Level", wlpan);

      cp.add(BorderLayout.SOUTH, jtp);
      fr.pack();

      fr.setSize(new Dimension(2*imageWidth+20, imageHeight+110));
      fr.show();
      srcImageCanvas.repaint();
      destImageCanvas.repaint();
   }

   public int[] getPixels(BufferedImage img, int wid, int ht){
      int pix[] = new int[wid*ht];
      for(int i=0;i<ht;i++){
          for(int j=0;j<wid;j++){
              pix[i*wid+j] = img.getRGB(j,i);
          }
      }
      return pix;
   }

   public int[] computeMinMax(int inp[]) {
       int max = Integer.MIN_VALUE;
       int min = Integer.MAX_VALUE;
       ColorModel cm = ColorModel.getRGBdefault();
       int sum =0;
       for(int i=0; i<inp.length;i++){
           int pix1 = cm.getRed(inp[i]);
           int pix2 = cm.getGreen(inp[i]);
           int pix3 = cm.getBlue(inp[i]);
           if(pix1 > max) max = pix1;
           if(pix2 > max) max = pix2;
           if(pix3 > max) max = pix3;

           if(pix1 < min ) min = pix1;
           if(pix2 < min ) min = pix2;
           if(pix3 < min ) min = pix3;
       }
       int[] minmax = new int[2];
       minmax[0] = min;
       minmax[1] = max;
       return minmax;
   }
    public void setWLSliderValues(){
      BufferedImage bi = destImageCanvas.getBufferedImage();
      if(bi == null) return;
      int wid = bi.getWidth();
      int ht = bi.getHeight();
      int[] pix = getPixels(bi, wid,ht);
      int minmax[] = computeMinMax(pix);
      //System.out.println("first = "+ minmax.length);
      //System.out.println("second = "+ minmax[0].length);
      wlpan.initSliders(minmax);
   }

   public void reset(){
      if(srcImageCanvas!= null) srcImageCanvas.reset();
      if(destImageCanvas != null) destImageCanvas.reset();
   }

   protected void displayOrig() {
      BufferedImage srcImage = srcImageCanvas.getBufferedImage();
      destImageCanvas.setBufferedImage(srcImage);
      destImageCanvas.repaint();
   }

   protected void sharpen() {
      ConvolveOp sharpOp = ConvolveOpFactory.getSharpOp();
      displayDestImage(sharpOp);
   }
   protected void blur() {
      ConvolveOp blurOp = ConvolveOpFactory.getBlurOp();
      displayDestImage(blurOp);
   }
   protected void sobelVert() {
      ConvolveOp sobelOp = ConvolveOpFactory.getSobelVertOp();
      displayDestImage(sobelOp);
   }

   protected void sobelHoriz() {
      ConvolveOp sobelOp = ConvolveOpFactory.getSobelHorizOp();
      displayDestImage(sobelOp);
   }


   protected void displayDestImage(BufferedImageOp op){
      BufferedImage srcImage = srcImageCanvas.getBufferedImage();
      BufferedImage destImage = op.createCompatibleDestImage(srcImage,
                                                  srcImage.getColorModel());
      destImage = op.filter(srcImage, destImage);
      destImageCanvas.setBufferedImage(destImage);
  }

  protected void grayColorConvert() {
      ColorSpace graySpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
      ColorConvertOp ccOp = new ColorConvertOp(graySpace, null);
      displayDestImage(ccOp);
  }

   protected void grayBandCombine() {
      BandCombineOp gbcOp = BandCombineOpFactory.getGrayBandCombineOp();
      displayDestImage(gbcOp);
   }
   
   protected void displayDestImage(BandCombineOp op){
      BufferedImage srcImage = srcImageCanvas.getBufferedImage();
      WritableRaster srcRaster =   srcImage.getRaster();
      BufferedImage destImage = new BufferedImage(srcImage.getWidth(), srcImage.getHeight(),
                    BufferedImage.TYPE_BYTE_GRAY);

      WritableRaster destRaster = destImage.getRaster(); // = op.createCompatibleDestRaster(srcRaster);
      destRaster = op.filter(srcRaster, destRaster);
      destImageCanvas.setBufferedImage(destImage);
   }

   
   class ColorConvertPanel extends JPanel{
      public ColorConvertPanel(){
         createUI();
      }
      protected void createUI() {
         ButtonGroup bg = new ButtonGroup();
         JRadioButton orig = new JRadioButton("Original");
         orig.setSelected(true);
         orig.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                 displayOrig();
              }
            }
         );
         JRadioButton graybc= new JRadioButton("Gray scale");
         graybc.setSelected(true);
         graybc.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                 grayColorConvert();
              }
            }
         );
         bg.add(orig);
         bg.add(graybc);
         add(orig);
         add(graybc);
      }
   }

   class BandCombinePanel extends JPanel{
      public BandCombinePanel(){
         createUI();
      }
      protected void createUI() {
         ButtonGroup bg = new ButtonGroup();
         JRadioButton orig = new JRadioButton("Original");
         orig.setSelected(true);
         orig.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                displayOrig();
              }
            }
         );
         JRadioButton graybc= new JRadioButton("Gray scale");
         graybc.setSelected(false);
         graybc.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                 grayBandCombine();
              }
            }
         );
         bg.add(orig);
         bg.add(graybc);
         add(orig);
         add(graybc);
      }
   }

   class EdgeDetectPanel extends JPanel{
      public EdgeDetectPanel(){
         createUI();
      }
      protected void createUI() {
         JRadioButton orig = new JRadioButton("Original");
         orig.setSelected(true);
         orig.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                 displayOrig();
              }
            }
         );
         ButtonGroup bg = new ButtonGroup();
         JRadioButton sobelv = new JRadioButton("Sobel Vert");
         sobelv.setSelected(false);
         sobelv.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                 sobelVert();
              }
            }
         );
         JRadioButton sobelh = new JRadioButton("Sobel Horiz");
         sobelh.setSelected(false);
         sobelh.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                 sobelHoriz();
              }
            }
        );
        bg.add(orig);
        bg.add(sobelv);
        bg.add(sobelh);
        add(orig);
        add(sobelv);
        add(sobelh);
      }
   }

   class EnhancePanel extends JPanel{
      public EnhancePanel(){
         createUI();
      }
      protected void createUI() {
         ButtonGroup bg = new ButtonGroup();
         JRadioButton orig = new JRadioButton("Original");
         orig.setSelected(true);
         orig.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                 displayOrig();
              }
            }
         );
         JRadioButton sharp = new JRadioButton("Sharpen");
         sharp.setSelected(false);
         sharp.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                 sharpen();
              }
            }
         );

         JRadioButton blur = new JRadioButton("Blur");
         blur.setSelected(false);
         blur.addChangeListener(
            new ChangeListener() {
              public void stateChanged(ChangeEvent e) {
                 blur();
              }
            }
         );
         bg.add(orig);
         bg.add(sharp);
         bg.add(blur);
         add(orig);
         add(sharp);
         add(blur);
      }
   }

   public static void  main(String[] args){
      ImageEnhancer ip = new ImageEnhancer();
      if(args.length <1) {
         System.out.println("Enter a valid JPEG file name");
         System.exit(0);
      }
      ip.loadAndDisplay(args[0]);
   }
 }
