
import java.net.*;
import java.io.*;
import java.awt.*;
import java.awt.image.*;


import java.awt.event.*;
import javax.swing.*;

import java.awt.geom.AffineTransform;
import java.awt.font.TextLayout;

import java.awt.image.*;
import com.sun.image.codec.jpeg.*;

import java.util.*;
import java.io.*;

import java.awt.image.BufferedImage;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Collections;
import java.util.Random;



public class segmentation extends JInternalFrame { 
    int histogram[];   
    private Image    image = null;
    public BufferedImage bImage=null;
    public BufferedImage bi[];
    Histogram hist ; 
 
 public  segmentation(){}

 public   segmentation (Image img,boolean bool) {
          bi = new BufferedImage[4];
 } 
 
 public BufferedImage get_horz_Hist (Image img) 
 {
     // 1. Create array of images
          for ( int i = 0; i < bi.length; i++ ) 
          {
            int iw = img.getWidth(this);
            int ih = img.getHeight(this);
            bi[i] = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB);
            Graphics2D big = bi[i].createGraphics();
            big.drawImage(img,0,0,this);
         }
      //   Prepare the image 
             bImage=bi[1];
             bi[0]=new BufferedImage(bi[1].getWidth(),bi[1].getHeight(),BufferedImage.TYPE_BYTE_GRAY);  // Horizontal histogram
             bi[3]=Histogram(bi[1],bi[0]);    
             saveImageToFile( bi[0],"Hhist.jpg");
                   
        // Read histogram image in image of type  Image 
             Image Histimage =  Toolkit.getDefaultToolkit().createImage(bi[0].getSource());
                  
       // then get the array in histogram [] []
       // First get the Width and Hieght of origenal histogram
              int ImgW = Histimage.getWidth(this);
              int ImgH = Histimage.getHeight(this);
              histogram  = new int[ImgW*ImgH];
                    
       // Store pixels in histogram array  
              PixelGrabber pg = new PixelGrabber(Histimage, 0, 0, ImgW, ImgH,histogram, 0, ImgW);
         	   try {
			pg.grabPixels();
		      }
		   catch(InterruptedException e) {
			System.err.println("Grabbing Interrupted");
			e.printStackTrace();
		  }  
         // Now Convert the one-Dim histogram array
         // into two-Dim  array to process first column
                  
               int[][] twoDim = new int[ImgH][ImgW];
        // List listHistogram = new ArrayList();
                  
               for (int saNum = 0; saNum < ImgH; ++saNum)
               { for (int elNum = 0; elNum < ImgW; ++elNum)
                 { twoDim[saNum][elNum] = histogram[ImgH * saNum + elNum];
                 }
               }
                  
  List tallestList = new ArrayList();
  int numColoredRows = 0;
  int tempTallestIndex = -1;
  int tempTallestNum = 0;
  
  List listA = new ArrayList();
  List listB = new ArrayList();
  listA.add(new Integer (0));
  
  for(int rowIndex = 0; rowIndex < twoDim.length; rowIndex++) {
 
    // The current row to examine.
    int[] row = twoDim[rowIndex];
    
    // Count the number of (concatenated) colored pixels
    // from the current row.
    int numColoredPixels = numColoredPixelsInRow(row);
 
    if(numColoredPixels >0) numColoredRows++;
 
    if(numColoredPixels > tempTallestNum) 
    {
      tempTallestNum = numColoredPixels;
      tempTallestIndex = rowIndex;
    }
    
    if(numColoredRows > 1 && (rowIndex == twoDim.length-1 || 
                              numColoredPixels == 0)) 
    {
        tallestList.add(new Integer(tempTallestIndex));
    }
    
    if(numColoredPixels == 0) 
    {
      numColoredRows = 0;
      tempTallestIndex = -1;
      tempTallestNum = 0;
    }
  }
                        
  System.out.println("List tallestList   : " + tallestList);
  
 //get the Width and Hieght of origenal histogram
   int OImgW = bi[2].getWidth(this);
   int OImgH = bi[2].getHeight(this);
  
   for(int i = 0; i < (tallestList.size()-1); i++) {
      Integer intWrapper1 = (Integer)tallestList.get(i);
      Integer intWrapper2 = (Integer)tallestList.get(i+1);
      int firstValue = intWrapper1.intValue() ;
      int secondValue = intWrapper2.intValue() ;
      int newValue = (firstValue + secondValue) /2 ;
      listB.add(new Integer(newValue));
      listA.add(new Integer(newValue));
    }
   listB.add(new Integer(OImgH));
                  
  for(int i = 0; i < (listA.size()); i++)  
  {
    Integer intWrapper = (Integer)listA.get(i);
    int intPrimitive = intWrapper.intValue() ;
    Integer intWrapper1 = (Integer)listB.get(i);
    int savePrimitive = intWrapper1.intValue() ;
    int h = (savePrimitive - intPrimitive);
    saveImageToFile(bi[2].getSubimage(0,intPrimitive, OImgW,h),"Line"+i+".jpg");
  }  
  return bi[0];                  
 }

  public BufferedImage get_Ver_Hist  (Image img) 
 {
     
     /// Prepare images
        for ( int i = 0; i < bi.length; i++ ) 
          {

            int iw = img.getWidth(this);
            int ih = img.getHeight(this);

            bi[i] = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_RGB);
            Graphics2D big = bi[i].createGraphics();
            big.drawImage(img,0,0,this);
         }
       bImage=bi[1];
       bi[0]=new BufferedImage(bi[1].getWidth(),bi[1].getHeight(),BufferedImage.TYPE_BYTE_GRAY);  // Horizontal histogram
       bi[3]=Histogram(bi[1],bi[0]);    
       saveImageToFile( bi[3],"Vhist.jpg");

      // This is the part of segmentation into words            
                                   
      // Read histogram image in image of type  Image 
        Image Histimage =  Toolkit.getDefaultToolkit().createImage(bi[3].getSource());

      // then get the array in histogram [] []
       // First get the Width and Hieght of origenal histogram
       int ImgW = Histimage.getWidth(this);
       int ImgH = Histimage.getHeight(this);
       histogram  = new int[ImgW*ImgH];

       // Store pixels in histogram array  
       PixelGrabber pg = new PixelGrabber(Histimage, 0, 0, ImgW, ImgH,histogram, 0, ImgW);
       try {
            pg.grabPixels();
          }
       catch(InterruptedException e) {
            System.err.println("Grabbing Interrupted");
            e.printStackTrace();
      }  

                  
     // Now Convert the one-Dim histogram array
     // into two-Dim  array to process first column

      int[][] twoDim = new int[ImgH][ImgW];

      for (int saNum = 0; saNum < ImgH; ++saNum)
      {for (int elNum = 0; elNum < ImgW; ++elNum)
        { twoDim[saNum][elNum] = histogram[ImgH * saNum + elNum];
        }
      }
                             
    // Initiliaze an array list to store points where image should be splitted
                  
      List listA = new ArrayList();
      List listB = new ArrayList();
      List listC = new ArrayList();

      int [] row = twoDim[ImgH-1];
      int averageSpace = findAverage(row,ImgW,ImgH);

       listA.add(new Integer(0));

      // Copmute the values where image has to split and store them
      // in Arraylist.
      // read first column of the histogram array
      // and checks for blank areas by mark first zero then next one 
      // the area btwn these two marks should be blank, choose to split 
      // the image in the avergae value of these marks.

      int lo= -3; // no zeros scanned yet
      int hi; // the second index
      int c= 0; // number of zero sequence scanned
      int processedCol = twoDim.length-1; 

      for (hi= 0; hi < 256 ; hi++)
           if ( (twoDim[processedCol][hi] == -1)) { // we're scanning zeros 
              if (lo < 0) // this is the first zero we've scanned
                 lo= hi;
           }
           else if (lo>= 0) { // we're not scanning zeros anymore
              c =  process(listA, listB,c, lo, hi,averageSpace); 
              lo= -3; // register the fact
           }

      // after the loop (all zeros at the end of the array?):
      if (lo >= 0)
              c =  process(listA, listB,c, lo, hi,averageSpace); 

                               
       //get the Width and Hieght of origenal histogram
       int OImgW = bi[2].getWidth(this);
       int OImgH = bi[2].getHeight(this);
       listB.add(new Integer(OImgW));
       for(int i = 0; i < (listA.size()); i++)  

         {
          Integer intWrapper = (Integer)listA.get(i);
          int intPrimitive = intWrapper.intValue() ;
         Integer intWrapper1 = (Integer)listB.get(i);
          int savePrimitive = intWrapper1.intValue() ;
          int h = savePrimitive - intPrimitive;

          saveImageToFile(bi[2].getSubimage(intPrimitive,0,h,OImgH),"Word"+i+".jpg"); 
         }  
      return bi[3];
                   
}

public void saveImageToFile(BufferedImage bi,String strFileName){
      if(bi == null) return;

        try{

            File file = new File("./", strFileName);
            FileOutputStream out = new FileOutputStream(file);
            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
            JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);
            param.setQuality(1.0f, false);
            encoder.setJPEGEncodeParam(param);
            encoder.encode(bi);

           }catch(Exception e){ return;}

    }//end of saveImageToFile()

public BufferedImage Histogram(BufferedImage src,BufferedImage hist_out){

        BufferedImage dest = new BufferedImage(src.getWidth(),src.getHeight(),BufferedImage.TYPE_BYTE_GRAY);
        hist = new Histogram();
        int isize=src.getWidth();
        int jsize=src.getHeight();

        int[] src_1d=new int[isize*jsize];
        int[] out_1d=new int[isize*jsize];

        Raster rt=src.getData();
        rt.getSamples(0,0,isize,jsize,0,src_1d);

        int[] dest_1d=hist.histogram(src_1d,isize,jsize,out_1d);

        dest.getRaster().setSamples(0,0,isize,jsize,0,dest_1d);
        hist_out.getRaster().setSamples(0,0,isize,jsize,0,out_1d);

        return dest;
       
}//end  

public  static int findAverage(int[] row, int w, int h) {
               
    // Initiliaze an array list to store points where image should be splitted
       List listC = new ArrayList();
  // Copmute the values where image has to split and store them
  // in Arraylist.
  // read first column of the histogram array
  // and checks for blank areas by mark first zero then next one 
  // the area btwn these two marks should be blank, choose to split 
  // the image in the avergae value of these marks.

      int lo= -3; // no zeros scanned yet
      int hi; // the second index
      int c= 0; // number of zero sequence scanned
  
      for (hi= 0; hi < h; hi++){

           if ( (row[hi] == -1)) { // we're scanning zeros 
              if (lo < 0) // this is the first zero we've scanned
                 lo= hi;
           }
           else if (lo>= 0) { // we're not scanning zeros anymore
              c =  processspace(c,lo, hi,listC); 
              lo= -3; // register the fact
           }
      }
      // after the loop (all zeros at the end of the array?):
      if (lo >= 0)
              c =  processspace(c,lo, hi,listC); 
       // Instead of getting average, get median !!
        int sum =0;
        for(int i = 0; i < (listC.size()); i++) {

             Integer intWrapper = (Integer)listC.get(i);
             int intPrimitive = intWrapper.intValue() ;
             sum = (sum + intPrimitive);
        }

        int getAverage = (sum / listC.size());
        return getAverage;

}

static int processspace(int c,int lo, int hi, List listC) {
   listC.add(new Integer (hi - lo));
   return c;
}  

static int process(List listA, List listB,int c, int lo, int hi, int averageSpace) { 
 //   if ( (hi-lo)>= averageSpace){
   listA.add(new Integer ((lo+hi)/2));
   listB.add(new Integer ((lo+hi)/2)); //}
    return c;
} 

 /**
 * @param   the row as an array of int's.
 * @return  the number of non-zero pixels
 */
public  static int numColoredPixelsInRow(int[] row) {
  int count = 0;  int startPoint =0;//row.length/4);
  for(int i = startPoint; i < row.length; i++) {
    if(row[i] != -1) count++;
  }
  return count;

}  

}