Mobile based Isolated Handwritten Character recognition Software - MbHWRAnuj

This software is developed to recognize handwritten isolated characters in English, Devanagiri and Gurmukhi scripts. The Java mobile version has been used to run application on mobiles with Symbian operating systems. The image and video clip of software in recognition is presented here.

The source code including main components of handwriting recognition as preprocessing, feature extraction and elastic matching based recognition are presented below. Please ask for details of codes.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
import javax.microedition.io.file.FileConnection;
import java.lang.*;
import java.lang.Math.*;
import java.util.*;
/**
 * @author Anuj Sharma
 */
public class HelloMIDlet extends MIDlet implements CommandListener {
  private boolean midletPaused = false;
  private Display display;
  protected boolean started;
  private MbHWRAnujCanvas canvas;
  //<editor-fold defaultstate="collapsed" desc=" Generated Fields ">//GEN-BEGIN:|fields|0|
  private Command exitCommand;
  private Form form;
  private StringItem stringItem;
  //</editor-fold>//GEN-END:|fields|0|
    /**
     * The HelloMIDlet constructor.
     */
    public HelloMIDlet() {
       
       
    }
    //<editor-fold defaultstate="collapsed" desc=" Generated Methods ">//GEN-BEGIN:|methods|0|
    //</editor-fold>//GEN-END:|methods|0|
    //<editor-fold defaultstate="collapsed" desc=" Generated Method: initialize ">//GEN-BEGIN:|0-initialize|0|0-preInitialize
    /**
     * Initilizes the application.
     * It is called only once when the MIDlet is started. The method is called before the <code>startMIDlet</code> method.
     */
    private void initialize() {//GEN-END:|0-initialize|0|0-preInitialize
        // write pre-initialize user code here
//GEN-LINE:|0-initialize|1|0-postInitialize
        // write post-initialize user code here
    }//GEN-BEGIN:|0-initialize|2|
    //</editor-fold>//GEN-END:|0-initialize|2|
    //<editor-fold defaultstate="collapsed" desc=" Generated Method: startMIDlet ">//GEN-BEGIN:|3-startMIDlet|0|3-preAction
    /**
     * Performs an action assigned to the Mobile Device - MIDlet Started point.
     */
    public void startMIDlet() {//GEN-END:|3-startMIDlet|0|3-preAction
        // write pre-action user code here
        switchDisplayable(null, getForm());//GEN-LINE:|3-startMIDlet|1|3-postAction
        // write post-action user code here
        display = Display.getDisplay(this);
        canvas  = new MbHWRAnujCanvas(this);
    }//GEN-BEGIN:|3-startMIDlet|2|
    //</editor-fold>//GEN-END:|3-startMIDlet|2|
    //<editor-fold defaultstate="collapsed" desc=" Generated Method: resumeMIDlet ">//GEN-BEGIN:|4-resumeMIDlet|0|4-preAction
    /**
     * Performs an action assigned to the Mobile Device - MIDlet Resumed point.
     */
    public void resumeMIDlet() {//GEN-END:|4-resumeMIDlet|0|4-preAction
        // write pre-action user code here
//GEN-LINE:|4-resumeMIDlet|1|4-postAction
        // write post-action user code here
    }//GEN-BEGIN:|4-resumeMIDlet|2|
    //</editor-fold>//GEN-END:|4-resumeMIDlet|2|
    //<editor-fold defaultstate="collapsed" desc=" Generated Method: switchDisplayable ">//GEN-BEGIN:|5-switchDisplayable|0|5-preSwitch
    /**
     * Switches a current displayable in a display. The <code>display</code> instance is taken from <code>getDisplay</code> method. This method is used by all actions in the design for switching displayable.
     * @param alert the Alert which is temporarily set to the display; if <code>null</code>, then <code>nextDisplayable</code> is set immediately
     * @param nextDisplayable the Displayable to be set
     */
    public void switchDisplayable(Alert alert, Displayable nextDisplayable) {//GEN-END:|5-switchDisplayable|0|5-preSwitch
        // write pre-switch user code here
        Display display = getDisplay();//GEN-BEGIN:|5-switchDisplayable|1|5-postSwitch
        if (alert == null) {
            display.setCurrent(nextDisplayable);
        } else {
            display.setCurrent(alert, nextDisplayable);
        }//GEN-END:|5-switchDisplayable|1|5-postSwitch
        // write post-switch user code here
    }//GEN-BEGIN:|5-switchDisplayable|2|
    //</editor-fold>//GEN-END:|5-switchDisplayable|2|
    //<editor-fold defaultstate="collapsed" desc=" Generated Method: commandAction for Displayables ">//GEN-BEGIN:|7-commandAction|0|7-preCommandAction
    /**
     * Called by a system to indicated that a command has been invoked on a particular displayable.
     * @param command the Command that was invoked
     * @param displayable the Displayable where the command was invoked
     */
    public void commandAction(Command command, Displayable displayable) {//GEN-END:|7-commandAction|0|7-preCommandAction
        // write pre-action user code here
        if (displayable == form) {//GEN-BEGIN:|7-commandAction|1|19-preAction
            if (command == exitCommand) {//GEN-END:|7-commandAction|1|19-preAction
                // write pre-action user code here
                exitMIDlet();//GEN-LINE:|7-commandAction|2|19-postAction
                // write post-action user code here
            }//GEN-BEGIN:|7-commandAction|3|7-postCommandAction
        }//GEN-END:|7-commandAction|3|7-postCommandAction
        // write post-action user code here
    }//GEN-BEGIN:|7-commandAction|4|
    //</editor-fold>//GEN-END:|7-commandAction|4|
    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: exitCommand ">//GEN-BEGIN:|18-getter|0|18-preInit
    /**
     * Returns an initiliazed instance of exitCommand component.
     * @return the initialized component instance
     */
    public Command getExitCommand() {
        if (exitCommand == null) {//GEN-END:|18-getter|0|18-preInit
            // write pre-init user code here
            exitCommand = new Command("Exit", Command.EXIT, 0);//GEN-LINE:|18-getter|1|18-postInit
            // write post-init user code here
        }//GEN-BEGIN:|18-getter|2|
        return exitCommand;
    }
    //</editor-fold>//GEN-END:|18-getter|2|
    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: form ">//GEN-BEGIN:|14-getter|0|14-preInit
    /**
     * Returns an initiliazed instance of form component.
     * @return the initialized component instance
     */
    public Form getForm() {
        if (form == null) {//GEN-END:|14-getter|0|14-preInit
            // write pre-init user code here
            form = new Form("Welcome", new Item[] { getStringItem() });//GEN-BEGIN:|14-getter|1|14-postInit
            form.addCommand(getExitCommand());
            form.setCommandListener(this);//GEN-END:|14-getter|1|14-postInit
            // write post-init user code here
        }//GEN-BEGIN:|14-getter|2|
        return form;
    }
    //</editor-fold>//GEN-END:|14-getter|2|
    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: stringItem ">//GEN-BEGIN:|16-getter|0|16-preInit
    /**
     * Returns an initiliazed instance of stringItem component.
     * @return the initialized component instance
     */
    public StringItem getStringItem() {
        if (stringItem == null) {//GEN-END:|16-getter|0|16-preInit
            // write pre-init user code here
            stringItem = new StringItem("Hello", "Hello, World!");//GEN-LINE:|16-getter|1|16-postInit
            // write post-init user code here
        }//GEN-BEGIN:|16-getter|2|
        return stringItem;
    }
    //</editor-fold>//GEN-END:|16-getter|2|
    /**
     * Returns a display instance.
     * @return the display instance.
     */
    public Display getDisplay () {
        return Display.getDisplay(this);
    }
    /**
     * Exits MIDlet.
     */
    public void exitMIDlet() {
        switchDisplayable (null, null);
        destroyApp(true);
        notifyDestroyed();
    }
    /**
     * Called when MIDlet is started.
     * Checks whether the MIDlet have been already started and initialize/starts or resumes the MIDlet.
     */
    public void startApp() {
        if (midletPaused) {
            resumeMIDlet ();
        } else {
            initialize ();
            startMIDlet ();
        }
        midletPaused = false;
        display.setCurrent( canvas );
    }
    /**
     * Called when MIDlet is paused.
     */
    public void pauseApp() {
        midletPaused = true;
    }
    /**
     * Called to signal the MIDlet to terminate.
     * @param unconditional if true, then the MIDlet has to be unconditionally terminated and all resources has to be released.
     */
    public void destroyApp(boolean unconditional) {
    }
}
class MbHWRAnujCanvas extends Canvas implements CommandListener, Runnable
{
  private Display display;
  private Command cmExit;          // Exit midlet
  private Command cmClear;         // Clear display
  private Command cmSave;          // Save to file
  private Command cmNext;           // to move to next character
  private Command cmPP;             // calling preprocessing methods
 
  private int startx = 0, starty = 0, currentx = 0, currenty = 0, strokeNumber=1;
  private HelloMIDlet midlet;
  private boolean clearDisplay = false;
  public boolean forMobile = false, forPP = false, forGurmukhi = true;
  public boolean forRec = false, toReadFile = true;
  public String pointList; public String currentList, strCharacterResultKey;
  public String[] imageNames; public String imagePath;
  public String charKey, recognizedGurmukhiImage;
  public int index = 0; public char ch;
  Image image = null;
  Image imageLeft = null; Image imageRight = null; Image imageCancel = null;
  Image recImage = null;
  public Vector vecList; public Point currentPoint;
  public Vector vecOrgList; String name; String charName;
  Preprocessing objPP; Recognition ObjR; FileHandling objFH;
  /*--------------------------------------------------
  * Constructor
  *-------------------------------------------------*/
  public MbHWRAnujCanvas(HelloMIDlet midlet)
  {
    this.midlet = midlet;
    // Create exit command & listen for events
    cmExit = new Command("Exit", Command.EXIT, 1);
    cmClear = new Command("Clear", Command.SCREEN, 1);
    cmSave = new Command("Save", Command.SCREEN, 1);
    cmNext = new Command("Next", Command.SCREEN, 1);
    cmPP = new Command("Recognition", Command.SCREEN, 1);
    addCommand(cmExit);
    addCommand(cmClear);
    addCommand(cmSave);
    addCommand(cmNext);
    addCommand(cmPP);
    setCommandListener(this);
    if(forGurmukhi){
        imageNames = new String[42];
        loadImageNames();
        charKey = charKeyName(imageNames[index]);
    }
    vecList = new Vector();
    strCharacterResultKey = new String();
    recognizedGurmukhiImage = new String();
    objPP = new Preprocessing(); ObjR = new Recognition();
  }
  public void loadImageNames(){
      int i=0;
      if(forGurmukhi){
          imageNames[i++]="urha"; imageNames[i++]="erha"; imageNames[i++]="eerhi";imageNames[i++]="sussa"; imageNames[i++]="haha"; imageNames[i++]="kukka";
          imageNames[i++]="khukha"; imageNames[i++]="gugga"; imageNames[i++]="ghugga"; imageNames[i++]="ungga"; imageNames[i++]="chucha";
          imageNames[i++]="chhuchha"; imageNames[i++]="jujja"; imageNames[i++]="jhujja";
          imageNames[i++]="yanza"; imageNames[i++]="tainka"; imageNames[i++]="thutha"; imageNames[i++]="dudda";
          imageNames[i++]="dhudda"; imageNames[i++]="nahnha"; imageNames[i++]="tutta"; imageNames[i++]="thuttha"; imageNames[i++]="duda"; imageNames[i++]="dhuda";
          imageNames[i++]="nunna"; imageNames[i++]="puppa"; imageNames[i++]="phupha"; imageNames[i++]="bubba"; imageNames[i++]="bhubba";
          imageNames[i++]="mumma"; imageNames[i++]="yaiyya"; imageNames[i++]="rara"; imageNames[i++]="lulla"; imageNames[i++]="vava";
          imageNames[i++]="rahrha"; imageNames[i++]="fuffa"; imageNames[i++]="shusha"; imageNames[i++]="khukha"; imageNames[i++]="guggabindi";
          imageNames[i++]="zuzza"; imageNames[i]="lhulla";
      }
      else{
          imageNames[i++]="1"; imageNames[i++]="2"; imageNames[i++]="3"; imageNames[i++]="4"; imageNames[i++]="5";
          imageNames[i++]="6"; imageNames[i++]="7"; imageNames[i++]="8"; imageNames[i++]="9"; imageNames[i++]="10";
          imageNames[i++]="11"; imageNames[i++]="12"; imageNames[i++]="13"; imageNames[i++]="14"; imageNames[i++]="15";
          imageNames[i++]="16"; imageNames[i++]="17"; imageNames[i++]="18"; imageNames[i++]="19"; imageNames[i++]="20";
          imageNames[i++]="21"; imageNames[i++]="22"; imageNames[i++]="23"; imageNames[i++]="24"; imageNames[i++]="25";
          imageNames[i++]="26"; imageNames[i++]="27"; imageNames[i++]="28"; imageNames[i++]="29"; imageNames[i++]="30";
          imageNames[i++]="31"; imageNames[i++]="32"; imageNames[i++]="33"; imageNames[i++]="34"; imageNames[i++]="35";
          imageNames[i++]="36"; imageNames[i++]="37"; imageNames[i++]="38"; imageNames[i++]="39"; imageNames[i++]="40";
          imageNames[i++]="41"; imageNames[i]="42";
      }
  }
  public void inputImage()
  {
    if(forMobile)   imagePath = "file:///e:/chars/";  //for mobile
    else    imagePath = "file:///root1/gchars/";  //for emulator
    imagePath+=imageNames[index];
    imagePath+=".PNG";
    FileConnection fconn;
    try {
      fconn = (FileConnection) Connector.open(imagePath);
     InputStream in = fconn.openInputStream();
      this.image = Image.createImage(in);
      in.close();
      fconn.close();
      }
      catch (IOException e1) {
      e1.printStackTrace();
      }
      catch (java.lang.SecurityException e3) {
      e3.printStackTrace();
      }
  }
  protected void paint(Graphics g)
  {
    if(forGurmukhi){
    if(forPP){
        g.setColor(255, 255, 255);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(0, 0, 0);
        int i, sn;
        for(i=0; i<vecList.size()-2; i++){
            currentPoint = (Point)vecList.elementAt(i);
            sn = currentPoint.strokeNumber;
            startx = (int)currentPoint.x+10;  starty = (int)currentPoint.y;
            currentPoint = (Point)vecList.elementAt(i+1);
            if(sn!=currentPoint.strokeNumber)   continue;
            currentx = (int)currentPoint.x+10;  currenty = (int)currentPoint.y;
            starty *= -1; currenty *= -1;
            g.drawRect(startx, starty, 1, 1);
            //g.drawLine(startx, starty, currentx, currenty);
            displayGurmukhiImage();
            if(recImage != null){
                g.drawImage(recImage, getWidth() / 2, 30, Graphics.HCENTER | Graphics.VCENTER);
            }
            else {
                g.drawString("No image available", getWidth() / 2, getHeight() / 2,
                Graphics.HCENTER | Graphics.BASELINE);
            }
        }
       
    }
    else{
        if(clearDisplay)
        {
              g.setColor(255, 255, 255);
              g.fillRect(0, 0, getWidth(), getHeight());
             
              if(image != null){
                  g.drawImage(image, getWidth() / 2, 30, Graphics.HCENTER
                  | Graphics.VCENTER);
              } else {
                  g.drawString("No image available", getWidth() / 2, getHeight() / 2,
                  Graphics.HCENTER | Graphics.BASELINE);
              }
              inputImageLeftArrow();
              if(imageLeft != null){
                  g.drawImage(imageLeft, 30, 30, Graphics.HCENTER
                  | Graphics.VCENTER);
              } else {
                  g.drawString("No image available", getWidth() / 2, getHeight() / 2,
                  Graphics.HCENTER | Graphics.BASELINE);
              }
                inputImageRightArrow();
                if(imageRight != null){
                      g.drawImage(imageRight, getWidth()-30, 30, Graphics.HCENTER
                      | Graphics.VCENTER);
                } else {
                      g.drawString("No image available", getWidth() / 2, getHeight() / 2,
                      Graphics.HCENTER | Graphics.BASELINE);
                }
                          
                inputImageCancel();
                if(imageCancel != null){
                      g.drawImage(imageCancel, getWidth()-15, getHeight()-15, Graphics.HCENTER
                      | Graphics.VCENTER);
                } else {
                      g.drawString("No image available", getWidth() / 2, getHeight() / 2,
                      Graphics.HCENTER | Graphics.BASELINE);
                }
                if(forRec){
                  
                    g.setColor(0, 0, 0);
                    int i, sn;
                    for(i=0; i<vecOrgList.size()-2; i++){
                        currentPoint = (Point)vecOrgList.elementAt(i);
                        sn = currentPoint.strokeNumber;
                        startx = (int)currentPoint.x;  starty = (int)currentPoint.y;
                        currentPoint = (Point)vecOrgList.elementAt(i+1);
                        if(sn!=currentPoint.strokeNumber)   continue;
                        currentx = (int)currentPoint.x;  currenty = (int)currentPoint.y;
                        starty *= -1; currenty *= -1;
                        g.drawRect(startx, starty, 1, 1);
                        //g.drawLine(startx, starty, currentx, currenty);
                        displayGurmukhiImage();
                        if(recImage != null){
                            g.drawImage(recImage, getWidth()-30, getHeight()/2, Graphics.HCENTER | Graphics.VCENTER);
                        }
                        else {
                            g.drawString("No image available", getWidth() / 2, getHeight() / 2,
                            Graphics.HCENTER | Graphics.BASELINE);
                        }
                    }
                }
            clearDisplay = false;
            startx = currentx = starty = currenty = 0;
            return;
        }  //nested if
        // Draw with black pen
        g.setColor(0, 0, 0);
        // Draw line
        g.drawLine(startx, starty, currentx, currenty);
        // New starting point is the current position
        startx = currentx;
        starty = currenty;
       
        inputImage();
        if(image != null){
              g.drawImage(image, getWidth() / 2, 30, Graphics.HCENTER
              | Graphics.VCENTER);
        } else {
              g.drawString("No image available", getWidth() / 2, getHeight() / 2,
              Graphics.HCENTER | Graphics.BASELINE);
        }
        inputImageLeftArrow();
        if(imageLeft != null){
              g.drawImage(imageLeft, 30, 30, Graphics.HCENTER
              | Graphics.VCENTER);
        } else {
              g.drawString("No image available", getWidth() / 2, getHeight() / 2,
              Graphics.HCENTER | Graphics.BASELINE);
        }
        inputImageRightArrow();
        if(imageRight != null){
              g.drawImage(imageRight, getWidth()-30, 30, Graphics.HCENTER
              | Graphics.VCENTER);
        } else {
              g.drawString("No image available", getWidth() / 2, getHeight() / 2,
              Graphics.HCENTER | Graphics.BASELINE);
        }
        inputImageCancel();
        if(imageCancel != null){
              g.drawImage(imageCancel, getWidth()-15, getHeight()-15, Graphics.HCENTER
              | Graphics.VCENTER);
        } else {
              g.drawString("No image available", getWidth() / 2, getHeight() / 2,
              Graphics.HCENTER | Graphics.BASELINE);
        }
        if(forRec){
         
            g.setColor(0, 0, 0);
            int i, sn;
            for(i=0; i<vecOrgList.size()-2; i++){
                currentPoint = (Point)vecOrgList.elementAt(i);
                sn = currentPoint.strokeNumber;
                startx = (int)currentPoint.x;  starty = (int)currentPoint.y;
                currentPoint = (Point)vecOrgList.elementAt(i+1);
                if(sn!=currentPoint.strokeNumber)   continue;
                currentx = (int)currentPoint.x;  currenty = (int)currentPoint.y;
                starty *= -1; currenty *= -1;
                //g.drawRect(startx, starty, 1, 1);
                g.drawLine(startx, starty, currentx, currenty);
                displayGurmukhiImage();
                if(recImage != null){
                    g.drawImage(recImage, getWidth()-30, getHeight()/2, Graphics.HCENTER | Graphics.VCENTER);
                }
                else {
                    g.drawString("No image available", getWidth() / 2, getHeight() / 2,
                    Graphics.HCENTER | Graphics.BASELINE);
                }
            }
        }
    }//else
    }//forGurmukhi
   
  }
  /*--------------------------------------------------
  * Command event handling
  *-------------------------------------------------*/
  public void commandAction(Command c, Displayable d)
  {
   if (c == cmExit)
      midlet.exitMIDlet();
   else if (c == cmClear)
    {
      forRec = false; forPP = false;
      vecOrgList.removeAllElements(); vecList.removeAllElements();//to come from preprocessing display
      clearDisplay = true;
      repaint();
      currentList = null;
      if(forGurmukhi){
          inputImage();
          inputImageLeftArrow(); inputImageRightArrow();
          charKey = charKeyName(imageNames[index]);
      }
    }
    else if (c == cmSave)
    {
        clearDisplay = true;
        repaint();
        if(currentList!=null){
             currentList+=";\n";
             if(pointList!=null) pointList += currentList;
             else pointList = currentList;
             currentList = null;
        }
        objFH = new FileHandling(pointList, forMobile, toReadFile);
        pointList = null;
      }
    else if(c == cmNext)
    {
        forRec = false; forPP = false;
        vecOrgList.removeAllElements(); vecList.removeAllElements();
        clearDisplay = true;
        repaint();
        if(currentList!=null){
             currentList+=";\n";
             if(pointList!=null) pointList += currentList;
             else pointList = currentList;
             currentList = null;
        }
        index++;
        if(forGurmukhi){
            inputImage();
            inputImageLeftArrow(); inputImageRightArrow();
            charKey = charKeyName(imageNames[index]);
        }
        vecList.removeAllElements(); strokeNumber=1;
    }
   else if(c == cmPP)
   {
       int count = 0; forRec = false; forGurmukhi = false; clearDisplay = true; repaint();
       Thread t = new Thread(this); t.start();
       while(t.isAlive()){
           count++;
           if(count>300) {
               try {
                   if(count==400){this.midlet.exitMIDlet();}
                   t.sleep(500); clearDisplay = true; repaint();
                  
                }
                catch( InterruptedException e ){
                 
                }
           }
       }
       if(currentList!=null){
            if(charKey.charAt(0)==ch) currentList += ",1";
            else currentList += ",0";
            currentList+=";\n";
            if(pointList!=null) pointList += currentList;
            else pointList = currentList;
            currentList = null;
      /*      toReadFile = false;  //to write results in file
            objFH = new FileHandling(pointList, forMobile, toReadFile);
            toReadFile = true;
        */  pointList = null;
        }
            //System.out.println("Stroke Number is: " + ch);
      // below commented lines to check preprocessing results
  /*
        ConvertVectorToList(vecList);
        FileHandling objFH = new FileHandling(pointList, forMobile);
      forPP = true;
        repaint();*/
 
    }//else if
  }//end of method
  public void run(){
    while(!forRec){
       
        if(vecList.size()>0){
            vecOrgList = vecList;
            vecList = objPP.startPreprocessing(vecList);
            //char ch = ObjR.RecognizingDevanagiriUsingEM(vecList, forMobile);
            ch = ObjR.RecognizingGurmukhiUsingSLS(vecList, forMobile);
            if(ch == '?'){
                recognizedGurmukhiImage = "notfound.PNG";
            }
            else{
                recognizedGurmukhiImage = showGurmukhiImage(ch);
                recognizedGurmukhiImage+=".PNG";
            }
            forGurmukhi = true;
            displayGurmukhiImage();
            forRec = true;
         }
    }
 
  }
  public void exit(){
      forRec = true;
  }
  /*--------------------------------------------------
  * Pointer pressed
  *-------------------------------------------------*/
  protected void pointerPressed(int x, int y)
  {
    if(x>=15 && x<=45 && y>=15 & y<=45){
        index--; if(index<0) index=0;
        clearDisplay = true;
        repaint();
        if(currentList!=null){
             currentList+=";\n";
             if(pointList!=null) pointList += currentList;
             else pointList = currentList;
             currentList = null;
        }
        if(forGurmukhi){
            inputImage(); inputImageLeftArrow(); inputImageRightArrow();
            charKey = charKeyName(imageNames[index]);
        }
        vecList.removeAllElements(); strokeNumber=1;
    }
    else if(x>=getWidth()-45 && x<=getWidth()-15 && y>=15 & y<=45){
        index++; if(index>41) index=41;
        clearDisplay = true;
        repaint();
        if(currentList!=null){
             currentList+=";\n";
             if(pointList!=null) pointList += currentList;
             else pointList = currentList;
             currentList = null;
        }
        if(forGurmukhi){
            inputImage(); inputImageLeftArrow(); inputImageRightArrow();
            charKey = charKeyName(imageNames[index]);
        }
        vecList.removeAllElements(); strokeNumber=1;
    }
    else if(x>=getWidth()-30 && x<=getWidth() && y>=getHeight()-30 & y<=getHeight()){
        forRec = false; forPP = false;
        if(vecList.size()>0){
            vecList.removeAllElements();//to come from preprocessing display
        }
     
        clearDisplay = true;
        repaint();
        currentList = null;
        if(forGurmukhi){
            inputImage(); inputImageLeftArrow(); inputImageRightArrow();
            charKey = charKeyName(imageNames[index]);
        }
        strokeNumber=1;
    }
    else{
        startx = x;
        starty = y;
        if(currentList == null){
            currentList = charKey; currentList += ","; strokeNumber=1;
        }
        currentList += "S";
        currentList += "X"; currentList += x; currentList += "Y-"; currentList += y;
        y*=-1; currentPoint=new Point(x,y,strokeNumber);
        vecList.addElement(currentPoint);
       
   }
  }
  /*--------------------------------------------------
  * Pointer moved
  *-------------------------------------------------*/
  protected void pointerDragged(int x, int y)
  {
    currentx = x;
    currenty = y;
    repaint();
    currentList += "X"; currentList += x; currentList += "Y-"; currentList += y;
    y*=-1; currentPoint=new Point(x,y,strokeNumber);
    vecList.addElement(currentPoint);
   
  }
  protected void pointerReleased(int x, int y)
  {
      strokeNumber++;
  }
  public String showGurmukhiImage(char ch){
      name = new String();
      switch(ch){
          case 'a': name = "urha"; break;
        case 'A': name = "erha"; break;
        case 'e': name = "eerhi"; break;
        case 's': name = "sussa"; break;
        case 'h': name = "haha"; break;
        case 'k': name = "kukka"; break;
        case 'K': name = "khukha"; break;
        case 'g': name = "gugga"; break;
        case 'G': name = "ghugga"; break;
        case '|': name = "ungga"; break;
        case 'c': name = "chucha"; break;
        case 'C': name = "chhuchha"; break;
        case 'j': name = "jujja"; break;
        case 'J': name = "jhujja"; break;
        case '\\': name = "yanza"; break;
        case 't': name = "tainka"; break;
        case 'T': name = "thutha"; break;
        case 'f': name = "dudda"; break;
        case 'd': name = "dhudda"; break;
        case 'x': name = "nahnha"; break;
        case 'q': name = "tutta"; break;
        case 'Q': name = "thuttha"; break;
        case 'F': name = "duda"; break;
        case 'D': name = "dhuda"; break;
        case 'n': name = "nunna"; break;
        case 'p': name = "puppa"; break;
        case 'P': name = "phupha"; break;
        case 'b': name = "bubba"; break;
        case 'B': name = "bhubba"; break;
        case 'm': name = "mumma"; break;
        case 'X': name = "yaiyya"; break;
        case 'r': name = "rara"; break;
        case 'l': name = "lulla"; break;
        case 'v': name = "vava"; break;
        case 'V': name = "rahrha"; break;
        case '&': name = "fuffa"; break;
        case 'S': name = "shusha"; break;
        case '^': name = "khukha"; break;
        case 'Z': name = "guggabindi"; break;
        case 'z': name = "zuzza"; break;
        case 'L': name = "lhulla"; break;
        case '?': name = "notfound"; break;
          default: name = "notfound"; break;
      }
      return name;
  }
  protected String charKeyName(String imageName){
      charName = new String();
      if(forGurmukhi){
        if(imageName == "urha") charName = "a";
        else if(imageName == "erha") charName = "A";
        else if(imageName == "eerhi") charName = "e";
        else if(imageName == "sussa") charName = "s";
        else if(imageName == "haha") charName = "h";
        else if(imageName == "kukka") charName = "k";
        else if(imageName == "khukha") charName = "K";
        else if(imageName == "gugga") charName = "g";
        else if(imageName == "ghugga") charName = "G";
        else if(imageName == "ungga") charName = "|";
        else if(imageName == "chucha") charName = "c";
        else if(imageName == "chhuchha") charName = "C";
        else if(imageName == "jujja") charName = "j";
        else if(imageName == "jhujja") charName = "J";
        else if(imageName == "yanza") charName = "\\";
        else if(imageName == "tainka") charName = "t";
        else if(imageName == "thutha") charName = "T";
        else if(imageName == "dudda") charName = "f";
        else if(imageName == "dhudda") charName = "d";
        else if(imageName == "nahnha") charName = "x";
        else if(imageName == "tutta") charName = "q";
        else if(imageName == "thuttha") charName = "Q";
        else if(imageName == "duda") charName = "F";
        else if(imageName == "dhuda") charName = "D";
        else if(imageName == "nunna") charName = "n";
        else if(imageName == "puppa") charName = "p";
        else if(imageName == "phupha") charName = "P";
        else if(imageName == "bubba") charName = "b";
        else if(imageName == "bhubba") charName = "B";
        else if(imageName == "mumma") charName = "m";
        else if(imageName == "yaiyya") charName = "X";
        else if(imageName == "rara") charName = "r";
        else if(imageName == "lulla") charName = "l";
        else if(imageName == "vava") charName = "v";
        else if(imageName == "rahrha") charName = "V";
        else if(imageName == "fuffa") charName = "&";
        else if(imageName == "shusha") charName = "S";
        else if(imageName == "khukha") charName = "^";
        else if(imageName == "guggabindi") charName = "Z";
        else if(imageName == "zuzza") charName = "z";
        else if(imageName == "lhulla") charName = "L";
       
      }
      else{
          int choice = Integer.parseInt(imageName);
          switch(choice){
            case 1: charName = "a"; break;
            case 2: charName = "A"; break;
            case 3: charName = "s"; break;
            case 4: charName = "S"; break;
            case 5: charName = "d"; break;
            case 6: charName = "D"; break;
            case 7: charName = "f"; break;
            case 8: charName = "F"; break;
            case 9: charName = "g"; break;
            case 10: charName = "G"; break;
            case 11: charName = "h"; break;
            case 12: charName = "j"; break;
            case 13: charName = "J"; break;
            case 14: charName = "k"; break;
            case 15: charName = "K"; break;
            case 16: charName = "l"; break;
            case 17: charName = "L"; break;
            case 18: charName = "z"; break;
            case 19: charName = "Z"; break;
            case 20: charName = "x"; break;
            case 21: charName = "X"; break;
            case 22: charName = "c"; break;
            case 23: charName = "C"; break;
            case 24: charName = "v"; break;
            case 25: charName = "V"; break;
            case 26: charName = "b"; break;
            case 27: charName = "B"; break;
            case 28: charName = "n"; break;
            case 29: charName = "m"; break;
            case 30: charName = ">"; break;
            case 31: charName = "q"; break;
            case 32: charName = "Q"; break;
            case 33: charName = "e"; break;
            case 34: charName = "E"; break;
            case 35: charName = "r"; break;
            case 36: charName = "t"; break;
            case 37: charName = "T"; break;
            case 38: charName = "p"; break;
            case 39: charName = "P"; break;
            case 40: charName = "{"; break;
            case 41: charName = "\\"; break;
            case 42: charName = "|"; break;
        }
    }
    return charName;
  }  //end of function
  public void ConvertVectorToList(Vector vecList){
      int i; pointList = charKey;
      for(i=0; i<vecList.size(); i++){
          currentPoint = (Point)vecList.elementAt(i);
          pointList+="X"; pointList+=currentPoint.x;
          pointList+="Y"; pointList+=currentPoint.y;
      }
      pointList+=";";
  }
  public void displayGurmukhiImage()
  {
    if(forMobile)   imagePath = "file:///e:/chars/";  //for mobile
    else    imagePath = "file:///root1/gchars/";  //for emulator
   
    imagePath+=recognizedGurmukhiImage;
   
    FileConnection fconn;
    try {
      fconn = (FileConnection) Connector.open(imagePath);
      InputStream in = fconn.openInputStream();
      this.recImage = Image.createImage(in);
      in.close();
      fconn.close();
      }
      catch (IOException e1) {
      e1.printStackTrace();
      }
      catch (java.lang.SecurityException e3) {
      e3.printStackTrace();
      }
  }
  public void inputImageLeftArrow()
  {
    if(forMobile)   imagePath = "file:///e:/chars/l_arrow.PNG";  //for mobile
    else    imagePath = "file:///root1/gchars/l_arrow.PNG";  //for emulator
    FileConnection fconn;
    try {
      fconn = (FileConnection) Connector.open(imagePath);
      InputStream in = fconn.openInputStream();
      this.imageLeft = Image.createImage(in);
      in.close();
      fconn.close();
      }
      catch (IOException e1) {
      e1.printStackTrace();
      }
      catch (java.lang.SecurityException e3) {
      e3.printStackTrace();
      }
  }
  public void inputImageRightArrow()
  {
    if(forMobile)   imagePath = "file:///e:/chars/r_arrow.PNG";  //for mobile
    else    imagePath = "file:///root1/gchars/r_arrow.PNG";  //for emulator
    FileConnection fconn;
    try {
      fconn = (FileConnection) Connector.open(imagePath);
      InputStream in = fconn.openInputStream();
      this.imageRight = Image.createImage(in);
      in.close();
      fconn.close();
      }
      catch (IOException e1) {
      e1.printStackTrace();
      }
      catch (java.lang.SecurityException e3) {
      e3.printStackTrace();
      }
  }
  public void inputImageCancel()
  {
    if(forMobile)   imagePath = "file:///e:/chars/cancel.PNG";  //for mobile
    else    imagePath = "file:///root1/gchars/cancel.PNG";  //for emulator
    FileConnection fconn;
    try {
      fconn = (FileConnection) Connector.open(imagePath);
     InputStream in = fconn.openInputStream();
      this.imageCancel = Image.createImage(in);
      in.close();
      fconn.close();
      }
      catch (IOException e1) {
      e1.printStackTrace();
      }
      catch (java.lang.SecurityException e3) {
      e3.printStackTrace();
      }
  }
}//end of class
class Point{
    public double x, y, angle;
    public int strokeNumber;
    public Point(){}
    public Point(int a, int b, int c){
        x=(double)a; y=(double)b; strokeNumber=c;
    }
    public Point(double a, double b, int c){
        x=a; y=b; strokeNumber=c;
    }
    public Point(Point P){
        this.x = P.x; this.y = P.y; this.strokeNumber = P.strokeNumber;
    }
    public Point(double a, double b, double c){
        x=a; y=b; angle=c;
    }
}
class FileHandling implements Runnable
{
    String pl; String path; boolean toRead;
    boolean forThread = true; int count=0; Thread tr = new Thread(this);
    public FileHandling(String path){
         toRead = true; this.path = path;
        
         tr.start();
    }
   public FileHandling(String pointList, boolean forMb, boolean toReadFile)
   {
      if(forMb) path =  "file:///e:/m.txt";
      else  path = "file:///root1/m.txt";
      pl = pointList; toRead = toReadFile;
     // Thread tr = new Thread(this);
      tr.start();
     // WriteFile();
   }
   public void run()
   {
       if(forThread){
       try
       {
           if(toRead)   readFile();
           else WriteFile();
       }
       catch(Exception e) {System.out.println(e);}
       finally{}
       }
   }
  public void WriteFile() throws IOException
  {
        /*String path = "root1/"; path += fileName; path += ".txt";
         String path = System.getProperty("fileconn.dir.photos");
        path += fileName; path += ".txt";*/
        byte[] bytePL = pl.getBytes();
        javax.microedition.io.Connection c = null;
        java.io.OutputStream os = null;
        try {
            c = javax.microedition.io.Connector.open(path, javax.microedition.io.Connector.READ_WRITE);
            javax.microedition.io.file.FileConnection fc =
                    (javax.microedition.io.file.FileConnection) c;
            if (!fc.exists())
                fc.create();
            //else
                //fc.fileSize();
                // fc.truncate(0);
            os = fc.openOutputStream(fc.fileSize());
            os.write(bytePL);
            os.flush();
        } catch (Exception e) {
            System.out.println("file not created by ANuj");
        } finally {
            try {
                if (os != null)
                    os.close();
                if (c != null)
                    c.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
   }
   public String readFile(){
        StringBuffer sb = new StringBuffer();
        javax.microedition.io.Connection c = null;
        java.io.InputStream is = null;
       
        try {
            c = javax.microedition.io.Connector.open(path, javax.microedition.io.Connector.READ);
            javax.microedition.io.file.FileConnection fc =
                    (javax.microedition.io.file.FileConnection) c;
            is = fc.openInputStream();
             try{
                  int chars, i = 0;
                  while ((chars = is.read()) != -1){
                    sb.append((char) chars);
                  }
              //    return sb.toString();
              }catch (Exception e){}
        } catch (Exception e) {
            System.out.println("file not created by ANuj");
        } finally {
            try {
                if (is != null)
                    is.close();
                if (c != null)
                    c.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        forThread = false;
        try {
           if(tr.isAlive()){
            tr.sleep(100);
           }
        }
        catch( InterruptedException e ){}
        return sb.toString();
    }
}
class Recognition {
    public  Vector trainList;
    public Recognition(){
       
    }
   
    public double Distance(Point PrevPoint, Point CurrPoint)
    {
            return(Math.sqrt((CurrPoint.x-PrevPoint.x)*(CurrPoint.x-PrevPoint.x) +
                    (CurrPoint.y-PrevPoint.y)*(CurrPoint.y-PrevPoint.y)));
    }
    private double Angle(Point P1, Point P2)
    {
            double radian, degree, k=(180/3.14);
            if(P1.x==P2.x)
            {
                    if(P1.y<=P2.y)
                            return 90;
                    else
                            return 270;
            }
            else
            {
                    degree=Math.tan((P2.y-P1.y)/(P2.x-P1.x));
                    degree = Math.abs(degree);
                    if(P2.x>P1.x && P1.y<=P2.y) return degree;
                    else if(P2.x>P1.x && P1.y>=P2.y) return (270+(90-degree));
                    else if(P2.x<P1.x && P1.y<=P2.y) return (90+(90-degree));
                    else if(P2.x<P1.x && P1.y>=P2.y) return (180+degree);
            }
            return degree;
    }
    private double mxatan(double arg)
    {
        double argsq, value;
        double p4  = .161536412982230228262e2;
        double p3  = .26842548195503973794141e3;
        double p2  = .11530293515404850115428136e4;
        double p1  = .178040631643319697105464587e4;
        double p0  = .89678597403663861959987488e3;
        double q4  = .5895697050844462222791e2;
        double q3  = .536265374031215315104235e3;
        double q2  = .16667838148816337184521798e4;
        double q1  = .207933497444540981287275926e4;
        double q0  = .89678597403663861962481162e3;
        argsq = arg*arg;
        value = ((((p4*argsq + p3)*argsq + p2)*argsq + p1)*argsq + p0);
        value = value/(((((argsq + q4)*argsq + q3)*argsq + q2)*argsq + q1)*argsq + q0);
        return value*arg;
    }
    private double msatan(double arg)
    {
        double sq2p1 = 2.414213562373095048802e0;
        double sq2m1  = .414213562373095048802e0;
        double PIO2 = 1.5707963267948966135E0;
        if(arg < sq2m1)
            return mxatan(arg);
        if(arg > sq2p1)
            return PIO2 - mxatan(1/arg);
            return PIO2/2 + mxatan((arg-1)/(arg+1));
    }
    // implementation of atan
    public double atan(double arg)
    {
        if(arg > 0)
            return msatan(arg);
        return -msatan(-arg);
    }
    public double Angle2(Point a, Point b) {
        double dx = b.x - a.x;
        double dy = b.y - a.y;
        double angle = 0.0d;
        if (dx == 0.0) {
            if(dy == 0.0)     angle = 0.0;
            else if(dy > 0.0) angle = Math.PI / 2.0;
            else              angle = (Math.PI * 3.0) / 2.0;
        }
        else if(dy == 0.0) {
            if(dx > 0.0)      angle = 0.0;
            else              angle = Math.PI;
        }
        else {
            if(dx < 0.0)      angle = atan(dy/dx) + Math.PI;
            else if(dy < 0.0) angle = atan(dy/dx) + (2*Math.PI);
            else              angle = atan(dy/dx);
        }
        return (angle * 180) / Math.PI;
    }
    private String[] splitString(String original) {
        Vector nodes = new Vector();
        String separator = "\n";
      //  System.out.println("split start...................");
        // Parse nodes into vector
        int index = original.indexOf(separator);
        while(index>=0) {
            nodes.addElement( original.substring(0, index) );
            original = original.substring(index+separator.length());
            index = original.indexOf(separator);
        }
        // Get the last node
        nodes.addElement( original );
        // Create splitted string array
        String[] result = new String[ nodes.size() ];
        if( nodes.size()>0 ) {
            for(int loop=0; loop<nodes.size(); loop++)
            {
                result[loop] = (String)nodes.elementAt(loop);
               // System.out.println(result[loop]);
            }
        }
        nodes.removeAllElements();
        return result;
    }
    private void ConvertStringToVector(String lineList){
        int i=0, l, indx=0; double AngleLine; String ps;
        trainList = new Vector();
        Point P1, P2, ObjT;
        P1=new Point(); P2=new Point(); ObjT = new Point();
        i=2;
        l=lineList.length();
        while(i<l)
        {
                if(lineList.charAt(i)==' ' || lineList.charAt(i)=='-' || lineList.charAt(i)=='S') {
                    i++; continue;
                }
                if(lineList.charAt(i)==';') break;
                if(lineList.charAt(i)=='X')
                {
                        i++; ps="";
                        while(lineList.charAt(i)!='Y')
                        {
                                ps+=lineList.charAt(i); i++;
                        }
                        P2.x = Double.parseDouble(ps);
                }
                if(lineList.charAt(i)=='Y')
                {
                        i++; ps="";
                        while(lineList.charAt(i)!='X')
                        {
                                if(lineList.charAt(i)=='S') { i++; break;}
                                if(lineList.charAt(i)==';') break;
                                ps+=lineList.charAt(i); i++;
                        }
                        P2.y = Double.parseDouble(ps);
                        ObjT.x = P2.x; ObjT.y = P2.y;
                        if(indx==0) { P1=P2; ObjT.angle=0; }
                        else ObjT.angle=Angle2(P1, P2);
                        trainList.addElement(ObjT);
                        P1=P2;
                }
        //    i++;
            }
    }
    public char RecognizingDevanagiriUsingEM(Vector vecList, boolean forMobile)
    {
        int i, iTest, iTrain, choice, nLine, recLine; //chk for check of train array
        char recognizedChar;
        double d, dMin, dTotal, dTotalMin;
        Point P, pTrain;
        String path, trainDataString; String trainLine[];
        //CStdioFile CharNameFile;
        choice=2; //1 for test, 2 for train
        dTotalMin=(double)100000000; recognizedChar = '0'; nLine=1; recLine=0;
        if(forMobile)   path = "file:///e:/chars/";  //for mobile
        else    path = "file:///root1/traindb/ppAnuj.dat";  //for emulator
        FileHandling ObjFH = new FileHandling(path);
        trainDataString = ObjFH.readFile();
        trainLine = splitString(trainDataString);
        for(i=0; i<trainLine.length; i++){
                ConvertStringToVector(trainLine[i]); dTotal=0;
                for(iTest=0; iTest<vecList.size(); iTest++)
                {
                    dMin=10000000; P = (Point)vecList.elementAt(iTest);
                    for(iTrain=0; iTrain<trainList.size(); iTrain++)
                    {
                        pTrain = (Point)trainList.elementAt(iTrain);
                        d=Math.abs(Distance(P, pTrain)) + Math.abs(P.angle-pTrain.angle);
                            if(d<dMin) dMin=d;
                    }
                    dTotal+=dMin;
                }
                if(dTotal<dTotalMin && dTotal!=0) {
                    dTotalMin=dTotal;
                    recognizedChar=trainLine[i].charAt(0); recLine=nLine;
                }
                trainList.removeAllElements();
        }
                      
        return recognizedChar;
    }
    private char GetDirection(double Angle)
    {
    if(Angle > 345 || Angle <= 15) return 'A';
    else if(Angle > 15 && Angle <= 45) return 'B';
    else if(Angle > 45 && Angle <= 75) return 'C';
    else if(Angle > 75 && Angle <= 105) return 'D';
    else if(Angle > 105 && Angle <= 135) return 'E';
    else if(Angle > 135 && Angle <= 165) return 'F';
    else if(Angle > 165 && Angle <= 195) return 'G';
    else if(Angle > 195 && Angle <= 225) return 'H';
    else if(Angle > 225 && Angle <= 255) return 'I';
    else if(Angle > 255 && Angle <= 285) return 'J';
    else if(Angle > 285 && Angle <= 315) return 'K';
    else if(Angle > 315 && Angle <= 345) return 'L';
    else return 'Z';
    }
    private String ConvertVectorToSLS(Vector vecList){
        int i, Size, gap, numOfSLS = 19; double angle;
        String slsForm = new String();
        Point P1, P2;
        Size = vecList.size(); gap = Size/(numOfSLS+1);
        for(i=0; i<(Size-gap); i+=gap){
            P1 = (Point)vecList.elementAt(i); P2 = (Point)vecList.elementAt(i+gap);
            angle = Angle2(P1, P2);
            slsForm += GetDirection(angle);
        }
        return slsForm;
    }
    private double methodSLS(String testLine, String trainCurrentLine){
        char ch1, ch2; int i=0, ChDiff, ChMin; double p=1;
        while(i<testLine.length())
        {
            if(i==trainCurrentLine.length()) break;
            ch1 = testLine.charAt(i); ch2 = trainCurrentLine.charAt(i);
            if(ch1 == ch2) p *= 1;
            else{
                ChDiff=Math.abs(ch1-ch2);
                if(ChDiff<7){
                    ChMin = ChDiff;
                }
                else{
                    ChMin=12-ChDiff;
                }
                if(ChMin!=-1){
                    p *= (double)1/(ChMin+1);
                }
                else p*=1;
            }
            i++;
        }
        return p;
    }
    public String sortCharKey(int[] recChar){
        int i, j, temp, l; l = recChar.length;
        String result = new String();
        for(i=0; i<l-1; i++){
            for(j=i+1; j<l; j++){
                if(recChar[i]>recChar[j]){
                    temp = recChar[i]; recChar[i] = recChar[j]; recChar[j] = temp;
                }
            }
        }
        for(i=0; i<l; i++){
            result += new Integer(recChar[i]).toString();
        }
        /*
        String temp; String result = new String();
        if(recChar.length>1){
            for(i=0; i<(recChar.length-1); i++){
                for(j=i+1; j<(recChar.length); j++){
                    if(recChar[i].compareTo(recChar[j])>0){
                        temp = recChar[i]; recChar[i]=recChar[j]; recChar[j]=temp;
                    }
                }
            }
        }
        for(i=0; i<recChar.length; i++)
        result += recChar[i];*/
        return result;
    }
    public String sortCharKey1(Vector recChar){
        int i, j; String s1, s2, temp; String result = new String();
        for(i=0; i<(recChar.size()-1); i++){
            for(j=i+1; j<(recChar.size()); j++){
                s1 = (String)recChar.elementAt(i); s2 = (String)recChar.elementAt(j);
                if(s1.compareTo(s2)>0){
                    temp = s1; s1=s2; s2=temp;
                    recChar.setElementAt(s1, i); recChar.setElementAt(s2, j);
                }
            }
        }
        for(i=0; i<recChar.size(); i++)
        result += (String)recChar.elementAt(i);
        return result;
    }
    public int findMatch(String line, String key){
        char result = '?'; int i=-1;
        for(i=0; i<key.length(); i++){
            if(key.charAt(i)==line.charAt(i)) continue;
            else{
                i = -1; break;
            }
        }
        if(i<line.length()){
            if(line.charAt(i)!=',') i = -1;
        }
        return i;
    }
    public int recStroke(Vector vecSubList, String path){
        int i; String testLine, trainCurrentLine, trainTotalLines, recStrokeNumber;
        String[] trainLine; double Prob, ProbMax;
        testLine = new String(); trainCurrentLine = new String();
        trainTotalLines = new String(); recStrokeNumber = new String();
        testLine = ConvertVectorToSLS(vecSubList);
        FileHandling ObjFH = new FileHandling(path);
        trainTotalLines = ObjFH.readFile();
        trainLine = splitString(trainTotalLines);
        ProbMax=-1;
        for(i=0; i<trainLine.length; i++){
            trainCurrentLine = trainLine[i];
            if(trainCurrentLine.length()<5) break;
            Prob = methodSLS(testLine, trainCurrentLine.substring(3, 22));
            if(Prob>ProbMax)
            {
                ProbMax = Prob; recStrokeNumber = trainCurrentLine.substring(0, 2);
            }
        }
        trainLine = new String[0]; trainTotalLines = null; trainCurrentLine = null;
        i = Integer.parseInt(recStrokeNumber);
        return i;
    }
    public char recCharacter(String recStrokeNumber, String path){
        int i, iChar; char resultChar = '?';
        String trainCurrentLine, trainTotalLines;
        String[] trainLine;
        FileHandling ObjFH = new FileHandling(path);
        trainTotalLines = ObjFH.readFile();
        trainLine = splitString(trainTotalLines);
        for(i=0; i<trainLine.length; i++){
            trainCurrentLine = trainLine[i];
            iChar = trainCurrentLine.length();
            if(trainCurrentLine.length()<3) break;
            trainCurrentLine = trainCurrentLine.substring(0, iChar-1);
            iChar = trainCurrentLine.length();
            if(trainCurrentLine.length()>recStrokeNumber.length()){
                if((recStrokeNumber.compareTo(trainCurrentLine.substring(0, iChar-3))==0)
                        && trainCurrentLine.charAt(iChar-3)==','){
                    resultChar = trainCurrentLine.charAt(iChar-2); break;
                }
            }
        }//for
        trainLine = new String[0]; trainTotalLines = null; trainCurrentLine = null;
       
        return resultChar;
    }
    public char RecognizingGurmukhiUsingSLS(Vector vecList, boolean forMobile){
        int i;
        int iChar; int[] recChar;
        int sn, snLength; Vector vecSubList; Point startP, nextP;
        char resultChar; //Vector recChar = new Vector();
        String path, recStrokeNumber;
        resultChar = '?'; iChar = 0;
        vecSubList = new Vector();
        //path for reading SLS strokes database
        path = new String();
        if(forMobile)   path = "file:///e:/traindb/MbSLS.dat";  //for mobile
        else    path = "file:///root1/traindb/MbSLS.dat";  //for emulator
       
        //get sub vector as each stroke
        nextP = (Point)vecList.elementAt(vecList.size()-1); snLength = nextP.strokeNumber;
        recChar = new int[snLength];
        for(i=0; i<vecList.size()-1; i++){
            startP = (Point)vecList.elementAt(i); nextP = (Point)vecList.elementAt(i+1);
            if(i==vecList.size()-2){
               
                vecSubList.addElement((Point)startP); vecSubList.addElement((Point)nextP);
                recChar[iChar] = recStroke(vecSubList, path);
               
                vecSubList.removeAllElements();
                break;
            }
            else if(startP.strokeNumber!=nextP.strokeNumber){
              
                recChar[iChar++] = recStroke(vecSubList, path);
              
                vecSubList.removeAllElements();
                continue;
            }
            else{
                vecSubList.addElement((Point)startP); continue;
            }
            //vecSubList.removeAllElements();
        }//for
                  
        recStrokeNumber = sortCharKey(recChar);
       
        if(forMobile)   path = "file:///e:/traindb/MbCharDB.dat";  //for mobile
        else    path = "file:///root1/traindb/MbCharDB.dat";  //for emulator
        resultChar = recCharacter(recStrokeNumber, path);
     
        return resultChar;
    } //end of method RecognizingGurmukhiUsingSLS
   
} //end of class Recognition
class Preprocessing{
    public int m_I; public Vector tempList, ppList;
    public int m_pointsAfterPP, m_pointsBeforePP;
    public void Preprocessing()
    {
        //ppList = new Vector(0); tempList = new Vector(0);
    }
    private double pow(double base, int power)
    {
        double result=1;
        for(int i=0; i<power ; i++)
        {
            result *= base;
        }
        return result;
    }
    public double Round(double number, int extra) {
        number = (double)(int)((number+0.005)*100.0)/100.0;
        return number;
    }
    private void RoundPoints(){
        int i, Size;
    Point P;
    Size=ppList.size();
    for(i=0; i<Size; i++)
    {
            P=(Point)ppList.elementAt(i);
            P.x=Round(P.x, 2); P.y=Round(P.y, 2);
            ppList.setElementAt(P, i);
    }
    }
    private double CalculateSlope(Point P1, Point P2)
    {
            if(P2.x!=P1.x)
                    return((P2.y-P1.y)/(P2.x-P1.x));
            else
                    return -9999;   ///-9999 is for appx. 90 degree
    }
    public double Distance(Point PrevPoint, Point CurrPoint)
    {
            return(Math.sqrt((CurrPoint.x-PrevPoint.x)*(CurrPoint.x-PrevPoint.x) +
                    (CurrPoint.y-PrevPoint.y)*(CurrPoint.y-PrevPoint.y)));
    }
    private void EqualDistance(int From, int To)
    {
            double l, d=1;
            Point P, P1, P2;
            P1=(Point)ppList.elementAt(From); P2=(Point)ppList.elementAt(To);
            l=Math.abs(Distance(P1, P2)); P=P1;
            while(l>d)
            {
                    P.strokeNumber=P1.strokeNumber;
                    P.x=(P1.x*(l-d)+P2.x*d)/l;
                    P.y=(P1.y*(l-d)+P2.y*d)/l;
                    tempList.addElement(P); m_I++;
                    P1=P; l=Math.abs(Distance(P1, P2));
            }
            tempList.addElement(P2); m_I++;
    }
    private void EquiDistancing()
    {
            int i, Size, Gap; Point P1, P2;
            m_I=0; tempList.removeAllElements();
            Size=ppList.size();
            if(Size>0)
            {
                tempList.addElement(ppList.elementAt(0)); m_I++;
                for(i=0;i<Size-1;i++)
                {
                    P1=(Point)ppList.elementAt(i);  P2=(Point)ppList.elementAt(i+1);
                    if(P1.strokeNumber==P2.strokeNumber)
                    {
                        EqualDistance(i, i+1);
                    }
                    else
                        tempList.addElement(ppList.elementAt(i+1)); m_I++;
                }
                tempList.addElement(ppList.elementAt(i)); m_I++;
            }
            ppList.removeAllElements(); m_I=0; Size=tempList.size();
            m_pointsAfterPP = tempList.size();
            if(m_pointsBeforePP>0)    Gap = (int)m_pointsAfterPP/m_pointsBeforePP;
            else    Gap = (int)m_pointsAfterPP;
            i=0;
            if(Size>0)
            {
                for(i=0;i<Size;i+=Gap)
                {
                     ppList.addElement(tempList.elementAt(i)); m_I++;
                }
            }
            tempList.removeAllElements();
    }
    private double ChainCodeMethod(int From, int To)
    {
            int i=0, Size, n0=0, n1=0, n2=0, n3=0;
            double m=1, theta;
            Point Pi, Pj;
            Size=ppList.size();
            if(Size>0)
            {
                    for(i=From;i<=To-3;i=i+3)
                    {
                            Pi=(Point)ppList.elementAt(i); Pj=(Point)ppList.elementAt(i+3);
                            m=CalculateSlope(Pi, Pj);
                            if(m>-0.41 && m<=0.41)
                                    n0++;
                            if(m>0.41 && m<=2.41)
                                    n1++;
                            if(m>-2.41 && m<=-0.41)
                                    n3++;
                            if(m>2.41)
                                    n2++;
                            if(m<=-2.41)
                                    n2++;
                    }
            }
            if((n1+n2+n3)==0)
                    return 0;
            theta=((double)(n1-n3)/(n1+n2+n3));
            theta=Round(theta, 2);
            return theta;
    }
    private void UpdateSlant(int From, int To, double theta)
    {
            int i;
            Point P;
            for(i=From;i<=To;i++)
            {
                    P=(Point)ppList.elementAt(i);
                    P.x=P.x-P.y*theta;
                    //P.x=Round(P.x, 2); P.y=Round(P.y, 2);
                    tempList.addElement(P); m_I++;
            }
    }
    private void SlantAdjustment(int From, int To)
    {
            int i; double AdjustX;
            Point P, P1, P2;
            P1=(Point)ppList.elementAt(From); P2=(Point)tempList.elementAt(From);
            AdjustX=P1.x-P2.x;
            for(i=From; i<=To; i++)
            {
                    P=(Point)tempList.elementAt(i);
                    P.x=P.x+AdjustX;
                    tempList.setElementAt(P,i);
            }
    }
    private void SlantCorrection()
    {
            int i=0, From=0, To, Size;
            double AdjustX, theta=0; Point P, P1, P2;
            m_I=0; Size=ppList.size();
            To=Size-1; P=(Point)ppList.elementAt(From); AdjustX=P.x;
            if(Size>0)
            {
                    for(i=0;i<ppList.size()-1; i++)
                    {
                        P1=(Point)ppList.elementAt(i); P2=(Point)ppList.elementAt(i+1);
                            if(P1.strokeNumber!=P2.strokeNumber || i==ppList.size()-2)
                            {
                                    To=i;
                                    theta=ChainCodeMethod(From, To);
                                    UpdateSlant(From, To, theta);
                                    SlantAdjustment(From, To);
                                    From=i+1;
                            }
                    }
                    UpdateArray();
            }
    }
    private void NeighbourMean(int i)
    {
            Point P, P1, P2;
            P=(Point)ppList.elementAt(i);
            P1=(Point)ppList.elementAt(i-1); P2=(Point)ppList.elementAt(i+1);
            P.x=(P1.x+P2.x)/4+P.x/2;
            P.y=(P1.y+P2.y)/4+P.y/2;
            ppList.setElementAt(P, i);
    }
    private void Smoothing()
    {
            int i, Size; Point P1, P2;
            m_I=0;
            Size=ppList.size();
            if(Size>0)
            {
                    for(i=1;i<Size-1;i++)
                    {
                            P1=(Point)ppList.elementAt(i); P2=(Point)ppList.elementAt(i+1);
                            if(P1.strokeNumber==P2.strokeNumber)
                            {
                                    NeighbourMean(i);
                            }
                            else
                                    i=i+1;
                    }
            }
            //RoundPoints();
       
    }
    private void BSplineFormula(Point P1, Point P2, Point P3, Point P4)
    {
            double mu, x, y; int sn;
            Point P;
            for(mu=0; mu<=1; mu+=0.4)
            {
                x = ((1-3*mu+3*mu*mu-mu*mu*mu)*P1.x + (3*mu*mu*mu-6*mu*mu+4)*P2.x +
                            (1+3*mu+3*mu*mu-3*mu*mu*mu)*P3.x + (mu*mu*mu)*P4.x)/6;
                y = ((1-3*mu+3*mu*mu-mu*mu*mu)*P1.y + (3*mu*mu*mu-6*mu*mu+4)*P2.y +
                            (1+3*mu+3*mu*mu-3*mu*mu*mu)*P3.y + (mu*mu*mu)*P4.y)/6;
                sn=P1.strokeNumber;
                P = new Point(x,y,sn);
                tempList.addElement(P); m_I++;
            }
    }
    private void UpdateArray()
    {
            int i, Size;
            Point P; ppList.removeAllElements();
            Size=tempList.size();
            for(i=0;i<Size;i++)
            {
                    P=(Point)tempList.elementAt(i);
                    ppList.addElement(P);
            }
            tempList.removeAllElements();
    }
    private void Interpolation()
    {
            int i, Size;
            Point P1, P2, P3, P4;
            i=0;m_I=0;
            Size=ppList.size();
            if(Size>4)
            {
                P1 = (Point)ppList.elementAt(i);
                tempList.addElement(P1); m_I++;
                for(i=0;i<(Size-3);i++)
                {
                    P1=(Point)ppList.elementAt(i); P2=(Point)ppList.elementAt(i+1);
                    P3=(Point)ppList.elementAt(i+2); P4=(Point)ppList.elementAt(i+3);
                    ///check for continous four points
                    if(P1.strokeNumber!=P2.strokeNumber)
                    {
                        tempList.addElement(P1); m_I++;
                        tempList.addElement(P2); m_I++;
                    }
                    else if(P1.strokeNumber!=P3.strokeNumber)
                    {
                        tempList.addElement(P1); m_I++;
                    }
                    else if(P1.strokeNumber!=P4.strokeNumber)
                    {
                        tempList.addElement(P1); m_I++;
                    }
                    else
                        BSplineFormula(P1, P2, P3, P4);
                }
            P1 = (Point)ppList.elementAt(Size-1);
            tempList.addElement(P1); m_I++;
            UpdateArray();
            }
   
    }
    private void SizeNormalization()
    {
            int i, Size;
            double m_FixedY, m_MaxX, m_MinX, m_MinY, m_MaxY, m_DiffX, m_DiffY;
            double m_Ky, m_Kx, m_K, m_NewXL;
            Point TempPoint; Size=ppList.size();
            m_MinX=2000; m_MaxX=0; m_MinY=0; m_MaxY=-2000; m_FixedY = 200;
            for(i=0; i<Size; i++)
            {
                TempPoint = (Point)ppList.elementAt(i);
                if(TempPoint.x<m_MinX) m_MinX=TempPoint.x;
                if(TempPoint.x>m_MaxX) m_MaxX=TempPoint.x;
                if(TempPoint.y<m_MinY) m_MinY=TempPoint.y;
                if(TempPoint.y>m_MaxY) m_MaxY=TempPoint.y;
            }
            m_DiffX = Math.abs(m_MaxX-m_MinX); m_DiffY=Math.abs(m_MinY-m_MaxY);
            m_Ky = Math.abs(m_FixedY/m_DiffY);
            m_K = Math.abs(m_DiffX/m_DiffY); m_NewXL = Math.abs(m_FixedY * m_K); m_Kx = m_NewXL/m_DiffX;
            for(i=0; i<Size; i++)
            {
                TempPoint = (Point)ppList.elementAt(i);
                TempPoint.y = (TempPoint.y-m_MaxY)*m_Ky;
                TempPoint.x = (TempPoint.x-m_MinX)*m_Kx;
                ppList.setElementAt(TempPoint, i);
            }
           
           
    }
    public void copyVector(Vector vecList){
        int i, Size; Point P;
        Size = vecList.size();
        for(i=0;i<Size;i++){
            P = (Point)vecList.elementAt(i);
            ppList.addElement((Point)P);
        }
    }
    public Vector startPreprocessing(Vector vecList)
    {
        ppList = new Vector(0); tempList = new Vector(0);
        copyVector(vecList);
        m_pointsBeforePP = ppList.size();
        SizeNormalization();
        Interpolation();
        Smoothing();
        SlantCorrection();
        EquiDistancing();
        RoundPoints();
        return ppList;
    }
}