Tuesday 9 February 2016

search over list using jquery

This is search over list using jquery
In this tutorial we can search over a list,can select that list and add to new list.
 

<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
    $("#hide").click(function(){
        $("p").hide();
    });
    $("#show").click(function(){
        $("p").show();
    });

           count = $('#right-side ul li').size();
            document.getElementById("count").innerHTML = count;

            if($('#right-side ul li').size()<1){
                $("#update_btn").hide()
            }else{
                $("#update_btn").show()
            }

            $("#txtSearchPage").keyup(function () {

                var search = $(this).val();

                $("#append-left-list>li").show();
                if (search)
                    $("#append-left-list>li").not(":containsNoCase(" + search + ")").hide();
            });


            $.expr[":"].containsNoCase = function (el, i, m) {
                var search = m[3];
                if (!search) return false;
                return new RegExp(search, "i").test($(el).text());
            };

            $('.masterTooltip').hover(function () {
                        // Hover over code
                        var title = $(this).attr('title');
                        $(this).data('tipText', title).removeAttr(
                                'title');
                        $('<p class="tooltip"></p>').text(title)
                                .appendTo('body').fadeIn('slow');
                    },
                    function () {
                        // Hover out code
                        $(this).attr('title',
                                $(this).data('tipText'));
                        $('.tooltip').remove();
                    }).mousemove(function (e) {
                        var mousex = e.pageX + 20; //Get X coordinates
                        var mousey = e.pageY + 10; //Get Y coordinates
                        $('.tooltip').css({
                            top: mousey,
                            left: mousex
                        })
                    });
            var size = 1;
            $('#left-side li').click(function () {
                $(this).toggleClass('active');
            });

            $('#right-side li').click(function () {
                $(this).toggleClass('active');
            });


            $('#addrightElement').click(function () {
                var $items = $('#right-side li.active');
                if ($('#right-side li.active').length != 0) {
                    size = size - 1;
                    $items.removeClass('active');
                    $('#left-side ul').append($items);
                    count = $('#right-side ul li').size();

                    document.getElementById("count").innerHTML = count;
                }
                if($('#right-side ul li').size()<1){
                    $("#update_btn").hide()
                }else{
                    $("#update_btn").show()
                }
            });



            $("#update_btn").click(function(){

                var listItems = $("#append-right-list  li");
                listItems.each(function(li) {
                    console.log($(this).attr('value'));

                    var newhidden = $("<input type='hidden' name='ids' value='"+$(this).attr('value')+"' />");

                    $('#formID').prepend(newhidden)
                });

                return true

            });


            $('#addleftElement').click(function () {
                size = $('#right-side ul li').length;

                var len = $('#left-side li.active').length;
                size = size + 1;
                var $items = $('#left-side li.active');
                if ($('#left-side li.active').length != 0) {
                    $items.removeClass('active');
                    $('#right-side ul').append($items);
                    count = $('#right-side ul li').size();
                    $('#right-side ul li').show();
                    document.getElementById("count").innerHTML = count;
                }
                if($('#right-side ul li').size()<1){
                    $("#update_btn").hide()
                }else{
                    $("#update_btn").show()
                }
            });

        });




    </script>



</head>
<body>

<p>If you click on the "Hide" button, I will disappear.</p>

<button id="hide">Hide</button>
<button id="show">Show</button>



<div style="padding: 20px">

    <table style="padding :30px" >
        <tr>
            <td><b>All List</b> &nbsp;&nbsp;&nbsp;<input placeholder="Search"
                                                                        id="txtSearchPage"></td>
            <td></td>
            <td><b>Selected List</b></td>
        </tr>

        <tr>
            <td valign="top">
                <Section id="left-side">

                    <ul id="append-left-list">
                  
                   <li  class="masterTooltip" title="Branch Office suraj" value="1">suraj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="1">sura</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="12">surj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="12">suaj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="111">sraj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="132">uraj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="112">asuraj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="121">ssuraj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="41">suuraj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="51">surraj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="231">suradj</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="16">surajd</li>
                   <li  class="masterTooltip" title="Branch Office suraj" value="124">surajd</li>

                </ul>

                </Section>
            </td>
            <td style='vertical-align: middle !important; padding: 0px 30px 0px 30px;'>
                <input id="addleftElement" type="button" value="&#187;" class="button1"/><br/>
                <input id="addrightElement" type="button" value="&#171;" class="button1"/><br/>
            </td>
            <td valign="top">
                <Section id="right-side">
                    <ul id="append-right-list">
                       
                    </ul>
                </Section>
            </td>

        </tr>
        <tr>
            <td style='padding: 0px 30px 0px 30px;'>

                <form ID="formID" action="nextAction">
                  
                    <input id="update_btn" type="submit" value="Update"
                         /><br/>
                </form>

            </td>
            <td></td>
              <td><p><b>No. Of Selected  :</b> <span id="count">0</span></p></td>
        </tr>
    </table>


</div>


</body>
</html>

Friday 30 January 2015

IMAGE INPAINTING

ImageSelection package

Entry.java

package imageselection;

import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;

/**
 * Class to enable selection of region to be inpainted
 */
public class Entry extends JPanel {

  protected Image entryImage;                       // Image to be displayed
  protected Graphics entryGraphics;                 // graphics object to the entry image
  protected int lastX = -1;                         // X co-ordinate of last pressed co-ordinate
  protected int lastY = -1;                         // Y co-ordinate of last pressed co-ordinate
  protected int polySides = 0;                      // number of sides of the polygon to be inpainted
  private Vector PolygonCoordinatesX;               // vector to store X co-ordinate of all vertices of a polygon
  private Vector PolygonCoordinatesY;               // vector to store Y co-ordinate of all vertices of a polygon
  private Image img;                                // instance of Image class
  public Stack SavedImages;                         // stack used to implement undo option
  public Stack RedoImages;                          // stack used to implement redo option
  private int firstX = -1;                          // variable to store first X co-ordinate of a polygon
  private int firstY = -1;                          // variable to store first Y co-ordinate of a polygon
  private int currX = -1;                           // variable to store current X co-ordinate of a polygon
  private int currY = -1;                           // variable to store current Y co-ordinate of a polygon
  public Boolean isDisabled = false;                // flag to determine status of the inpainting module
  public int maxX = -1;                             // stores maximum of all X co-ordinates of all polygon
  public int maxY = -1;                             // stores maximum of all Y co-ordinates of all polygon
  public int minX = -1;                             // stores minimum of all X co-ordinates of all polygon
  public int minY = -1;                             // stores minimum of all Y co-ordinates of all polygon

  Boolean pressed;                                  // Defines whether the polygon is started or not

  /**
   * constructor of Entry class
   * @param img default image to display
   */
  Entry(Image img)
  {
    entryImage = img;
    enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK|
                 AWTEvent.MOUSE_EVENT_MASK|
                 AWTEvent.COMPONENT_EVENT_MASK);
    pressed = false;
    SavedImages = new Stack();
    RedoImages = new Stack();
    PolygonCoordinatesX = new Vector();
    PolygonCoordinatesY = new Vector();
  }
  /**
   * method to show updated image
   * @param img image to display
   */
  public void showImage(Image img)
  {
      entryImage = img;
      entryGraphics = entryImage.getGraphics();
      repaint();       
  }

  /**
   * method to get entryimage
   * @return entryimage
   */
  public Image getImage()
  {
      return entryImage;
  }
 
    @SuppressWarnings("unchecked")
  protected void initImage()
  {
        img = entryImage;
        entryGraphics = entryImage.getGraphics();
        Image tmg = createImage(entryImage.getWidth(this),entryImage.getHeight(this));
        Graphics tg = tmg.getGraphics();
    tg.drawImage(entryImage,0,0,null);
        SavedImages.push(tmg);
        repaint();
  }
  
    @Override
  public void paint(Graphics g)
  {
    if ( entryImage==null )
      initImage();
    g.drawImage(entryImage,0,0,this);

    /**
     * Draw red rectangle on first selected co-ordinate of a polygon
     */
    if (firstX != -1) {
        g.setColor(Color.red);
        g.drawRect(firstX-5, firstY-5, 10, 10);
        g.drawRect(firstX-4, firstY-4, 8, 8);
    }

    g.setColor(Color.black);
    g.drawRect(0,0,getWidth(),getHeight());
    g.setColor(Color.green);
   
    if (PolygonCoordinatesX == null || PolygonCoordinatesY == null) {
        return;
    }

    /**
     * Draw black rectangle on every other co-ordinate of a polygon except the first co-ordinate
     */
    g.setColor(Color.black);
    for (int i = 1; i < PolygonCoordinatesX.size(); ++i) {
        g.drawRect((Integer)PolygonCoordinatesX.get(i)-5, (Integer)PolygonCoordinatesY.get(i)-5, 10, 10);
        g.drawRect((Integer)PolygonCoordinatesX.get(i)-4, (Integer)PolygonCoordinatesY.get(i)-4, 8, 8);
    }
    g.setColor(Color.green);

    if (lastX != -1) {
        g.drawLine(lastX, lastY, currX, currY);             // draw line between successive co-ordinates
    }
  }

  @Override
    @SuppressWarnings("unchecked")
  protected void processMouseEvent(MouseEvent e)
  {
      if (!isDisabled) {
        if ( e.getID()==MouseEvent.MOUSE_PRESSED && !pressed) {
            lastX = e.getX();
            lastY = e.getY();
            firstX = lastX;
            firstY = lastY;
            pressed = true;
            PolygonCoordinatesX.add(lastX);
            PolygonCoordinatesY.add(lastY);
            repaint();
        } else if (e.getID() == MouseEvent.MOUSE_PRESSED && pressed) {
            entryGraphics.setColor(Color.green);
            entryGraphics.drawLine(lastX,lastY,e.getX(),e.getY());
            getGraphics().drawImage(entryImage,0,0,this);
            repaint();
            lastX = e.getX();
            lastY = e.getY();
            maxX = maxY = -1;
            minX = lastX;
            minY = lastY;
            PolygonCoordinatesX.add(lastX);
            PolygonCoordinatesY.add(lastY);
            if (Math.abs(lastX - (Integer)PolygonCoordinatesX.get(0)) < 10 && Math.abs(lastY - (Integer)PolygonCoordinatesY.get(0)) < 10) {
                int[] PolyX = new int[PolygonCoordinatesX.size()];
                int[] PolyY = new int[PolygonCoordinatesY.size()];
                for (int i = 0; i < PolygonCoordinatesX.size(); ++i) {
                    PolyX[i] = (Integer)PolygonCoordinatesX.get(i);
                    PolyY[i] = (Integer)PolygonCoordinatesY.get(i);

                    if (minX > PolyX[i]) {
                        minX = PolyX[i];
                    }
                    if (minY > PolyY[i]) {
                        minY = PolyY[i];
                    }
                    if (maxX < PolyX[i]) {
                        maxX = PolyX[i];
                    }
                    if (maxY < PolyY[i]) {
                        maxY = PolyY[i];
                    }
                    System.out.println(PolygonCoordinatesX.get(i) + ", " + PolygonCoordinatesY.get(i));
                }
                polySides = PolygonCoordinatesX.size();
                entryGraphics.fillPolygon(PolyX, PolyY, polySides);
                PolygonCoordinatesX.clear();
                PolygonCoordinatesY.clear();
                currX = currY = -1;
                lastX = lastY = -1;
                firstX = firstY = -1;
                pressed = false;
                Image tmg = createImage(entryImage.getWidth(this),entryImage.getHeight(this));
                Graphics tg = tmg.getGraphics();
                tg.drawImage(entryImage,0,0,null);
                //UndoImages.add(tmg);
                SavedImages.push(tmg);
                RedoImages.clear();
                repaint();
            }
        } else {
            return;
        }
      }
  }
 
    @Override
  protected void processMouseMotionEvent(MouseEvent e)
  {
        if (!isDisabled) {
            if ( e.getID()!=MouseEvent.MOUSE_MOVED )
              return;

            currX = e.getX();
            currY = e.getY();
            repaint();
        }
  }

    void setDisabled()
    {
        isDisabled = true;
    }

    void setEnabled()
    {
        isDisabled = false;
    }

    public Boolean getPressed() {
        return pressed;
    }

    void entryReset() {
        PolygonCoordinatesX.clear();
        PolygonCoordinatesY.clear();
        currX = currY = -1;
        lastX = lastY = -1;
        firstX = firstY = -1;
        pressed = false;
    }
   
    Object entryImage() {
        throw new UnsupportedOperationException("Not yet implemented");
    }
   
}



GradientCalculator.java

package imageselection;

import java.util.*;

/**
 *
 */
public class GradientCalculator {

    public double[][] gradientX;        // Variable to communicate the gradient in X direction with calling class
    public double[][] gradientY;        // Variable to communicate the gradient in X direction with calling class
    int r, g, b;                        // temporary variables to store the r, g and b values of the pixels.

    /**
     * Function that calculates the gradient from the image given in argument using the central difference method.
     * @param pixelmap  Pixelmap of the image
     * @param ih    Height of the image
     * @param iw    Width of the image
     */
    public void calculateGradientFromImage (int pixelmap[][], int ih, int iw)
    {
        gradientX = new double[ih][iw];
        gradientY = new double[ih][iw];

        int[] row = new int[ih];
        int[] column = new int[iw];

        for (int i = 0; i < ih; ++i) {
            row[i] = i+1;
        }

        for (int i = 0; i < iw; ++i) {
            column[i] = i+1;
        }

        double t1, t2, t3;
        if (ih > 1) {
            /**
             * Calculate gradient for boundary pixels.
             */
            for (int j = 0; j < iw; ++j) {
                extractRGB(pixelmap, 1, j);
                int r2 = r; int g2 = g; int b2 = b;

                extractRGB(pixelmap, 0, j);
                int r1 = r; int g1 = g; int b1 = b;

                t1 = (double)(r2-r1)/(row[1]-row[0]);
                t2 = (double)(g2-g1)/(row[1]-row[0]);
                t3 = (double)(b2-b1)/(row[1]-row[0]);
                gradientX[0][j] = -((double)t1+t2+t3)/(3.0*255.0);

                extractRGB(pixelmap, ih-1, j);
                int rn = r; int gn = g; int bn = b;

                extractRGB(pixelmap, ih-2, j);
                int rn1 = r; int gn1 = g; int bn1 = b;

                t1 = (double)(rn-rn1)/(row[ih-1]-row[ih-2]);
                t2 = (double)(gn-gn1)/(row[ih-1]-row[ih-2]);
                t3 = (double)(bn-bn1)/(row[ih-1]-row[ih-2]);
                gradientX[ih-1][j] = -((double)t1+t2+t3)/(3.0*255.0);
            }
        }

        if (ih > 2) {
            /**
             * Calculate the gradient for central pixels.
             */
            for (int i = 1; i < ih-1; ++i) {
                for (int j = 0; j < iw; ++j) {
                    extractRGB(pixelmap, i+1, j);
                    int r2 = r; int g2 = g; int b2 = b;

                    extractRGB(pixelmap, i-1, j);
                    int r1 = r; int g1 = g; int b1 = b;

                    t1 = (double)(r2-r1)/(row[i+1]-row[i-1]);
                    t2 = (double)(g2-g1)/(row[i+1]-row[i-1]);
                    t3 = (double)(b2-b1)/(row[i+1]-row[i-1]);
                    gradientX[i][j] = -((double)t1+t2+t3)/(3.0*255.0);
                }
            }
        }

        if (iw > 1) {
            /**
             * Calculate gradient for boundary pixels.
             */
            for (int j = 0; j < ih; ++j) {
                extractRGB(pixelmap, j, 1);
                int r2 = r; int g2 = g; int b2 = b;

                extractRGB(pixelmap, j, 0);
                int r1 = r; int g1 = g; int b1 = b;

                t1 = (double)(r2-r1)/(column[1]-column[0]);
                t2 = (double)(g2-g1)/(column[1]-column[0]);
                t3 = (double)(b2-b1)/(column[1]-column[0]);
                gradientY[j][0] = (double)(t1+t2+t3)/(3.0*255.0);

                extractRGB(pixelmap, j, iw-1);
                int rn = r; int gn = g; int bn = b;

                extractRGB(pixelmap, j, iw-2);
                int rn1 = r; int gn1 = g; int bn1 = b;
               
                t1 = (double)(rn-rn1)/(column[iw-1]-column[iw-2]);
                t2 = (double)(gn-gn1)/(column[iw-1]-column[iw-2]);
                t3 = (double)(bn-bn1)/(column[iw-1]-column[iw-2]);
                gradientY[j][iw-1] = (double)(t1+t2+t3)/(3.0*255.0);
            }
        }

        if (iw > 2) {
            /**
             * Calculate gradient for central pixels.
             */
            for (int i = 0; i < ih; ++i) {
                for (int j = 1; j < iw-1; ++j) {

                    extractRGB(pixelmap, i, j+1);
                    int r2 = r; int g2 = g; int b2 = b;

                    extractRGB(pixelmap, i, j-1);
                    int r1 = r; int g1 = g; int b1 = b;

                    t1 = (double)(r2-r1)/(column[j+1]-column[j-1]);//g(2:n-1,:) = (f(3:n,:)-f(1:n-2,:))./h(:,ones(p,1));
                    t2 = (double)(g2-g1)/(column[j+1]-column[j-1]);
                    t3 = (double)(b2-b1)/(column[j+1]-column[j-1]);
                    gradientY[i][j] = (double)(t1+t2+t3)/(3.0*255.0);
                }
            }
        }
    }

    /**
     * Function to calculate gradient for other matrices
     * @param a The matrix for which gradient is to be calculated
     * @param ih    Height of the matrix
     * @param iw    Width of the matrix
     */
    public void calculateGradient (int a[][], int ih, int iw)
    {
        gradientX = new double[ih][iw];
        gradientY = new double[ih][iw];
        Vector h = new Vector();
        int[] row = new int[ih];
        int[] column = new int[iw];

        for (int i = 0; i < ih; ++i) {
            row[i] = i+1;
        }

        for (int i = 0; i < iw; ++i) {
            column[i] = i+1;
        }

        if (ih > 1) {
            for (int j = 0; j < iw; ++j) {
                gradientY[0][j] = (double)(a[1][j] - a[0][j])/(row[1]-row[0]);
                gradientY[ih-1][j] = (double)(a[ih-1][j] - a[ih-2][j])/(row[ih-1]-row[ih-2]);
            }
        }

        if (ih > 2) {
            for (int i = 1; i < ih-1; ++i) {
                for (int j = 0; j < iw; ++j) {
                    gradientY[i][j] = (double)(a[i+1][j] - a[i-1][j])/(row[i+1]-row[i-1]);
                }
            }
        }

         if (iw > 1) {
            for (int j = 0; j < ih; ++j) {
                gradientX[j][0] = (double)(a[j][1] - a[j][0])/(column[1]-column[0]);
                gradientX[j][iw-1] = (double)(a[j][iw-1] - a[j][iw-2])/(column[iw-1]-column[iw-2]);
            }
        }

        if (iw > 2) {
            for (int i = 0; i < ih; ++i) {
                for (int j = 1; j < iw-1; ++j) {
                    gradientX[i][j] = (double)(a[i][j+1] - a[i][j-1])/(column[j+1]-column[j-1]);
                }
            }
        }
    }

    /**
     * Function to calculate RGB values of the pixel
     * @param img
     * @param i
     * @param j
     */
    void extractRGB(int img[][], int i, int j)
    {
        r = 0xff & (img[i][j] >> 16);
        g = 0xff & (img[i][j] >> 8);
        b = 0xff & (img[i][j]);
    }
}


Main.java

package imageselection;

import com.permission.Display;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.UIManager;
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import inpaint.*;

/**
 * Class to make UI and communicate the ImageInpainting module
 * @author Pulkit & Sapan
 */
public class Main extends JFrame implements Runnable{
   
    public Entry entry;                             // Defines the object of Entry class
    protected Image entryImage;                     // variable of type Image
    JScrollPane pictureScrollPane;                  // Scrollpane for scrolling Images(whenever required)
    File outputFile;                                // file used while saving the image
    String fileExtension;                           // string to store the extension of a image
    ImageInpaint Inpainter;                         // Defines the object of ImageInpaint class
    Thread inpaintThread = null;                    // thread for the inpaint process
    private Boolean fastInpaint = false;            // flag to determine fastInpaint
    //Button playbtn;

    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JButton jButton4;
    private javax.swing.JButton jButton6;
    private javax.swing.JButton jButton7;
    private javax.swing.JFrame jFrame5;
    private javax.swing.JFrame jFrame6;
    private javax.swing.JFrame jFrame7;
    private javax.swing.JToolBar jToolBar1;
   
    @SuppressWarnings("deprecation")
    Main()
    {
        Inpainter = new ImageInpaint(this);         // Creates an instance of the ImageInpaint class

        /**
         * sets look and feel for the UI
         */
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }

        /**
         * Action to be performed on clicking the close button
         */
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        initComponents();

        /**
         * Reads the image to be inpainted.
         */
        try {
            entryImage = ImageIO.read(getClass().getResource("/imageselection/Images/defaultImage.png"));
        } catch (IOException ex) {
            Logger.getLogger(Entry.class.getName()).log(Level.SEVERE, null, ex);
        }
       
        setTitle("Image Inpainting");                         // Set the title of the Window
        getContentPane().setLayout(null);
        setSize(500,500);                                     //Set Window Width and Height
      
        entry = new Entry(entryImage);                        // creates an instance of the entry class
       
        entry.setPreferredSize(new Dimension(entryImage.getWidth(this),entryImage.getHeight(this)));
       
        getContentPane().add(entry);
        entry.initImage(); 
        pictureScrollPane = new JScrollPane();                // creates an instance of the JScrollPane class
        getContentPane().add(pictureScrollPane);
        int w = Math.min(entryImage.getWidth(this)+3,getContentPane().getWidth());
        int h = Math.min(entryImage.getHeight(this)+3,getContentPane().getHeight()-50);
        if (h == entryImage.getHeight(this)+3) {
            pictureScrollPane.setBounds((getContentPane().getWidth()-w)/2,(getContentPane().getHeight()-h)/2, w, h);
        } else {
            pictureScrollPane.setBounds((getContentPane().getWidth()-w)/2,(getContentPane().getHeight()-h)/2, w, h+25);
        }
       
        pictureScrollPane.setAlignmentY(CENTER_ALIGNMENT);
        pictureScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        pictureScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        pictureScrollPane.setViewportView(entry);
       
        this.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                int w = Math.min(entryImage.getWidth(entry)+3,getContentPane().getWidth());
                int h = Math.min(entryImage.getHeight(entry)+3,getContentPane().getHeight()-50);
                if (h == entryImage.getHeight(entry)+3) {
                    pictureScrollPane.setBounds((getContentPane().getWidth()-w)/2,(getContentPane().getHeight()-h)/2, w, h);
                } else {
                    pictureScrollPane.setBounds((getContentPane().getWidth()-w)/2,(getContentPane().getHeight()-h)/2, w, h+25);
                }
         //       pictureScrollPane.setBounds((getContentPane().getWidth()-w)/2,(getContentPane().getHeight()-h)/2, w, h);
                pictureScrollPane.setViewportView(entry);
            }
        });
    }

    /**
     * main function execution starts from here
     * @param args command line argument
     */
    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
        (new Main()).show();
    }
   
     private void initComponents() {
        JFrame jFrame1 = new javax.swing.JFrame();
        JFrame jFrame2 = new javax.swing.JFrame();
        JFrame jFrame3 = new javax.swing.JFrame();
        JFrame jFrame4 = new javax.swing.JFrame();



        JMenuBar jMenuBar1 = new javax.swing.JMenuBar();
       
        JMenu jMenu1 = new javax.swing.JMenu();
        JMenu jMenu2 = new javax.swing.JMenu();
        JMenu jMenu3 = new javax.swing.JMenu();
        JMenu jMenu4 = new javax.swing.JMenu();
       
        JMenuItem jMenuItem1 = new javax.swing.JMenuItem();
        JMenuItem jMenuItem2 = new javax.swing.JMenuItem();
        JMenuItem jMenuItem3 = new javax.swing.JMenuItem();       
        JMenuItem jMenuItem4 = new javax.swing.JMenuItem();
        JMenuItem jMenuItem5 = new javax.swing.JMenuItem();       
        JMenuItem jMenuItem6 = new javax.swing.JMenuItem();
        JMenuItem jMenuItem7 = new javax.swing.JMenuItem();
        JMenuItem jMenuItem8 = new javax.swing.JMenuItem();
        JMenuItem jMenuItem9 = new javax.swing.JMenuItem();

        javax.swing.GroupLayout jFrame1Layout = new javax.swing.GroupLayout(jFrame1.getContentPane());
        jFrame1.getContentPane().setLayout(jFrame1Layout);
        jFrame1Layout.setHorizontalGroup(
            jFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jFrame1Layout.setVerticalGroup(
            jFrame1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jFrame2Layout = new javax.swing.GroupLayout(jFrame2.getContentPane());
        jFrame2.getContentPane().setLayout(jFrame2Layout);
        jFrame2Layout.setHorizontalGroup(
            jFrame2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jFrame2Layout.setVerticalGroup(
            jFrame2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jFrame3Layout = new javax.swing.GroupLayout(jFrame3.getContentPane());
        jFrame3.getContentPane().setLayout(jFrame3Layout);
        jFrame3Layout.setHorizontalGroup(
            jFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jFrame3Layout.setVerticalGroup(
            jFrame3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jFrame4Layout = new javax.swing.GroupLayout(jFrame3.getContentPane());
        jFrame4.getContentPane().setLayout(jFrame4Layout);
        jFrame4Layout.setHorizontalGroup(
            jFrame4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jFrame4Layout.setVerticalGroup(
            jFrame4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jMenu1.setText("File");

        jMenuItem1.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/open.png")));
        jMenuItem1.setText("Open Image");
        jMenu1.add(jMenuItem1);
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });

        jMenuItem2.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/save.png")));
        jMenuItem2.setText("Save");
        jMenu1.add(jMenuItem2);
        jMenuItem2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem2ActionPerformed(evt);
            }
        });

        jMenuItem7.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.ALT_MASK | java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem7.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/saveAs.png")));
        jMenuItem7.setText("Save As");
        jMenu1.add(jMenuItem7);
        jMenuItem7.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem7ActionPerformed(evt);
            }
        });
       
        jMenuItem3.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F4, java.awt.event.InputEvent.ALT_MASK));
        jMenuItem3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/exit.png")));
        jMenuItem3.setText("Exit");
        jMenu1.add(jMenuItem3);
        jMenuItem3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem3ActionPerformed(evt);
            }
        });

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Edit");

        jMenuItem4.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Z, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/undo.png")));
        jMenuItem4.setText("Undo");
        jMenu2.add(jMenuItem4);
        jMenuItem4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem4ActionPerformed(evt);
            }
        });

        jMenuItem5.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Y, java.awt.event.InputEvent.CTRL_MASK));
        jMenuItem5.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/redo.png")));
        jMenuItem5.setText("Redo");
        jMenu2.add(jMenuItem5);
        jMenuItem5.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem5ActionPerformed(evt);
            }
        });

        jMenuBar1.add(jMenu2);


        jMenu3.setText("Inpaint");

        jMenuItem8.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, java.awt.event.InputEvent.CTRL_MASK));
        //jMenuItem8.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/open.png")));
        jMenuItem8.setText("Run");
        jMenu3.add(jMenuItem8);
        jMenuItem8.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem8ActionPerformed(evt);
            }
        });

        jMenu4.setText("Help");

     
       
       
        jMenuBar1.add(jMenu3);

        jMenuBar1.add(jMenu4);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 279, Short.MAX_VALUE)
        );

        jFrame5 = new javax.swing.JFrame();
        jFrame6 = new javax.swing.JFrame();
        jFrame7 = new javax.swing.JFrame();
        jToolBar1 = new javax.swing.JToolBar();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jButton4 = new javax.swing.JButton();
        jButton6 = new javax.swing.JButton();
        jButton7 = new javax.swing.JButton();

        javax.swing.GroupLayout jFrame5Layout = new javax.swing.GroupLayout(jFrame5.getContentPane());
        jFrame5.getContentPane().setLayout(jFrame5Layout);
        jFrame5Layout.setHorizontalGroup(
            jFrame5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jFrame5Layout.setVerticalGroup(
            jFrame5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jFrame6Layout = new javax.swing.GroupLayout(jFrame6.getContentPane());
        jFrame6.getContentPane().setLayout(jFrame6Layout);
        jFrame6Layout.setHorizontalGroup(
            jFrame6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jFrame6Layout.setVerticalGroup(
            jFrame6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout jFrame7Layout = new javax.swing.GroupLayout(jFrame7.getContentPane());
        jFrame7.getContentPane().setLayout(jFrame7Layout);
        jFrame7Layout.setHorizontalGroup(
            jFrame7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        jFrame7Layout.setVerticalGroup(
            jFrame7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        jToolBar1.setRollover(true);

        jButton1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/open.png"))); // NOI18N
        jButton1.setFocusable(false);
        jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton1.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(jButton1);
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });

        jButton2.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/save.png"))); // NOI18N
        jButton2.setFocusable(false);
        jButton2.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton2.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(jButton2);
        jButton2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem2ActionPerformed(evt);
            }
        });

        jButton3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/undo.png"))); // NOI18N
        jButton3.setFocusable(false);
        jButton3.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton3.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(jButton3);
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem4ActionPerformed(evt);
            }
        });

        jButton4.setIcon(new javax.swing.ImageIcon(getClass().getResource("/imageselection/Images/redo.png"))); // NOI18N
        jButton4.setFocusable(false);
        jButton4.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER);
        jButton4.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
        jToolBar1.add(jButton4);
        jButton4.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem5ActionPerformed(evt);
            }
        });


        javax.swing.GroupLayout layout1 = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout1);
        layout1.setHorizontalGroup(
            layout1.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jToolBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
        );
        layout1.setVerticalGroup(
            layout1.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout1.createSequentialGroup()
                .addComponent(jToolBar1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(275, Short.MAX_VALUE))
        );

        pack();
    }

     /**
      * action performed for opening file
      * @param evt
      */
     private void jMenuItem1ActionPerformed(ActionEvent evt) {

         if (!entry.isDisabled) {

             BufferedImage selectedImage;

             JFileChooser _fileChooser = new JFileChooser();
             int retval = _fileChooser.showOpenDialog(Main.this);

             /**
              * extensions of images user is allowed to choose
              */
             final String[] okFileExtensions = new String[] {"jpg", "png", "gif", "bmp", "jpeg"};
             File file;

             if (retval == JFileChooser.APPROVE_OPTION) {
                try {
                    file = _fileChooser.getSelectedFile();
                    Boolean flag = false;
                    for (String extension : okFileExtensions) {
                        if (file.getName().toLowerCase().endsWith(extension)) {
                            outputFile = file;
                            fileExtension = extension;
                            flag = true;
                        }
                    }
                    if (!flag) {
                        JOptionPane.showMessageDialog(this, "Please choose a jpg, jpeg, png, bmp or gif file only.","Error",JOptionPane.ERROR_MESSAGE);
                        return;
                    }

                    entry.SavedImages.clear();
                    entry.RedoImages.clear();
                    selectedImage = ImageIO.read(file);
                    Image tmg = createImage(((Image)selectedImage).getWidth(this),((Image)selectedImage).getHeight(this));
                    Graphics tg = tmg.getGraphics();
                    tg.drawImage((Image)selectedImage,0,0,null);
                    entry.SavedImages.push(selectedImage);
                    entryImage = tmg;
                    entry.showImage(entryImage);
                    entry.setPreferredSize(new Dimension(entryImage.getWidth(this),entryImage.getHeight(this)));
                    int w = Math.min(entryImage.getWidth(this)+3,getContentPane().getWidth());
                    int h = Math.min(entryImage.getHeight(this)+3,getContentPane().getHeight());
                    pictureScrollPane.setBounds((getContentPane().getWidth()-w)/2,(getContentPane().getHeight()-h)/2, w, h);
                    pictureScrollPane.setViewportView(entry);
                } catch (IOException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
          }
         }
     }

     /**
      * action performed for undo event
      * @param evt
      */
    @SuppressWarnings("unchecked")
      private void jMenuItem4ActionPerformed(ActionEvent evt)
      {
        Boolean flag = false;

         if ((!entry.isDisabled) && (entry.SavedImages.size()>1)) {
            if (entry.getPressed()) {
                entry.entryReset();
                flag = true;
            }
            entry.RedoImages.push(entry.SavedImages.pop());
            Image tmg = createImage(((Image)entry.SavedImages.peek()).getWidth(this),((Image)entry.SavedImages.peek()).getHeight(this));
            Graphics tg = tmg.getGraphics();
            tg.drawImage((Image)entry.SavedImages.peek(),0,0,null);
            entry.showImage(tmg);
           
            entry.setPreferredSize(new Dimension(entryImage.getWidth(this),entryImage.getHeight(this)));
            int w = Math.min(entryImage.getWidth(this)+3,getContentPane().getWidth());
            int h = Math.min(entryImage.getHeight(this)+3,getContentPane().getHeight());
            pictureScrollPane.setBounds((getContentPane().getWidth()-w)/2,(getContentPane().getHeight()-h)/2, w, h);
            pictureScrollPane.setViewportView(entry);

            if (flag) {
                jMenuItem5ActionPerformed(evt);
            }
         }
      }

    /**
      * action performed for redo event
      * @param evt
      */
    @SuppressWarnings("unchecked")
     private void jMenuItem5ActionPerformed(ActionEvent evt)
     {
         if ((!entry.isDisabled) && (entry.RedoImages.size()>0)) {
           
            Image tmg = createImage(((Image)entry.RedoImages.peek()).getWidth(this),((Image)entry.RedoImages.peek()).getHeight(this));
            Graphics tg = tmg.getGraphics();
            tg.drawImage((Image)entry.RedoImages.peek(),0,0,null);
            entry.showImage(tmg);
            entry.SavedImages.push(entry.RedoImages.pop());

            entry.setPreferredSize(new Dimension(entryImage.getWidth(this),entryImage.getHeight(this)));
            int w = Math.min(entryImage.getWidth(this)+3,getContentPane().getWidth());
            int h = Math.min(entryImage.getHeight(this)+3,getContentPane().getHeight());
            pictureScrollPane.setBounds((getContentPane().getWidth()-w)/2,(getContentPane().getHeight()-h)/2, w, h);
            pictureScrollPane.setViewportView(entry);
         }
      }
  

    /**
      * action performed for saving image
      * @param evt
      */
     private void jMenuItem2ActionPerformed(ActionEvent evt)
     {        
         if (outputFile == null) {
             System.err.println("Error!! No file to save");
             return;
         }
        
         try {
             BufferedImage bi = (BufferedImage)entry.getImage();
             ImageIO.write(bi, fileExtension, outputFile);
         } catch (IOException e) {
             System.err.println("Error!! File not saved");
         }
     }

     /**
      * action performed when user wants to save image with different name
      * @param evt
      */
     @SuppressWarnings("unchecked")
      private void jMenuItem7ActionPerformed(ActionEvent evt)
      {        
         JFileChooser _fileChooser = new JFileChooser();
         int retval = _fileChooser.showSaveDialog(Main.this);

         final String[] okFileExtensions = new String[] {"jpg", "png", "gif", "bmp", "jpeg"};
         File file;

         if (retval == JFileChooser.APPROVE_OPTION) {            
            file = _fileChooser.getSelectedFile();
            Boolean flag = false;
            for (String extension : okFileExtensions) {
                if (file.getName().toLowerCase().endsWith(extension)) {
                    if (outputFile == null) {                           
                        System.err.println("Error!! No file to save");
                        return;
                    }
                    try {
                        outputFile = file;
                        fileExtension = extension;
                        BufferedImage bi = (BufferedImage)entry.getImage();
                        ImageIO.write(bi, fileExtension, outputFile);
                        System.out.println("Saved");
                    } catch (IOException e) {
                        System.err.println("Error!! File not saved");
                    }


                    flag = true;
                }
            }
            if (!flag) {
                JOptionPane.showMessageDialog(this, "Please choose a jpg, jpeg, png, bmp or gif file only.","Error",JOptionPane.ERROR_MESSAGE);
                return;
            }
        }
      
      }

     /**
      * action performed for inpaint
      * @param evt
      */
     private void jMenuItem8ActionPerformed(ActionEvent evt) {
        if(Display.diplaay()==true){
         Inpainter.halt = false;
         Inpainter.completed = false;
          if ( inpaintThread==null ) {
              entry.setDisabled();
              inpaintThread = new Thread(this);
              inpaintThread.start();
          }
        }else{
            JOptionPane.showMessageDialog(this, "Can't Run");
        }
     }

     /**
      * action performed for exit
      * @param evt
      */
     private void jMenuItem3ActionPerformed(ActionEvent evt)
     {
               System.exit(0);
     }
    
     class SymAction implements java.awt.event.ActionListener {
         public void actionPerformed(java.awt.event.ActionEvent event)
         {
             Object object = event.getSource();            
         }
     }

     /**
      * calls the method to start inpainting
      */
    public void run()
    {
        Inpainter.init((BufferedImage)entry.getImage(), (BufferedImage)entry.getImage(),fastInpaint);
    }

    /**
     * Method to communicate with the Inpainting module
     * @param toShow updated image
     */
    public void updateStats(BufferedImage toShow)
    {
        UpdateStats stats = new UpdateStats();
        stats.toShow = toShow;
        try {
            SwingUtilities.invokeAndWait(stats);
        } catch ( Exception e ) {
            JOptionPane.showMessageDialog(this,"Error: " + e,"Training",
            JOptionPane.ERROR_MESSAGE);
        }


        if (Inpainter.completed) {                               // Inpainting completes
           
            JOptionPane.showMessageDialog(this,
                                    "                      Inpainting is completed.","Inpainting",
                                    JOptionPane.PLAIN_MESSAGE);
        }
        if (Inpainter.completed || Inpainter.halt) {
            System.out.println ("Inpainting completed or halted");
            inpaintThread = null;
            Image tmg = createImage(((Image)toShow).getWidth(this),((Image)toShow).getHeight(this));
            Graphics tg = tmg.getGraphics();
            tg.drawImage((Image)toShow,0,0,null);
            entry.SavedImages.push(tmg);
            entry.setEnabled();
            entry.RedoImages.clear();
            fastInpaint = false;
        }
    }

    public class UpdateStats implements Runnable {

        BufferedImage toShow;

        public void run()
        {
            entry.showImage(toShow);
        }
    }
}

PACKAGE 

INPAINT

IMAGEINPAINT.JAVA

package inpaint;

import imageselection.GradientCalculator;
import java.util.*;                     // Packages for basic Java utilities, e.g. Vector etc.
import java.awt.*;                      // Packages for Java Images
import java.awt.image.*;                // Packages for Image processing in Java
import java.awt.image.PixelGrabber;     // Package for grabbing Pixels from the Image
import imageselection.Main;             // Application's Main class


/**
 * Class to Inpaint the given Image.
 * Call Function init with original image, fillImage and quickPaint as arguments
 * @author Sapan & Pulkit
 */


public class ImageInpaint {
    BufferedImage origImg;              // BufferedImage Object to represent updated image at every step
    Image fillImg;                      // Image Object to represent Image with target region marked
    BufferedImage img;                  // BufferedImage Object to represent original Image
    WritableRaster raster;              // Raster to write to the image
    int iw, ih;                         // iw: Width of Image, ih: Height of Image
    int pixels[];                       // Temporary array that will initially store the grabbed pixels
    int pixelmap[][];                   // Matrix to store the pixels of original image
    int fillPixelmap[][];               // Matrix to store the pixels of image marked with target region
    int sourceRegion[][];               // Matrix to store Boolean values for Source Region (is updated after each iteration)
    int initialSourceRegion[][];        // Matrix to store Boolean values for Initial Source Region
    double fillRegion[][];              // Matrix to store Boolean values for Target Region
    double gradientX[][];               // Matrix to represent the perpendicular Gradient at each point in X direction
    double gradientY[][];               // Matrix to represent the perpendicular Gradient at each point in Y direction
    double confidence[][];              // Matrix that stores the Confidence values for each pixel
    double data[][];                    // Matrix to store the data terms for each pixel
    GradientCalculator gc;              // Object of GradientCalculator class used to calculate gradient
    double omega = 0.7;                 // Represents the omega used in confidence term
    double Alpha = 0.2;                 // Represents the multiplier for confidence term in calculating priority
    double Beta = 0.8;                  // Represents the multiplier for data term in calculating priority
    int maxX;                           // The maximum X coordinate of the target region
    int maxY;                           // The maximum Y coordinate of the target region
    int minX;                           // The minimum X coordinate of the target region
    int minY;                           // The minimum Y coordinate of the target region
    int continuousCol = 0;              // The maximum number of continuous green pixels in one column
    int continuousRow = 0;              // The maximum number of continuous green pixels in one row
    protected Main owner;               // Object to the Main Class. Used in passing updates after every iteration
    public Boolean halt = false;        // Used to stop inpainting.
    public Boolean completed = false;        // Used to report when the inpainting is complete.
    final int diamX = 50;               // Diameter (in X direction) of the Region to be searched for
    final int diamY = 30;               // Diameter (in Y direction) of the Region to be searched for
    private int pixelPosX;              // The X-coordinate of current pixel being processed
    private int pixelPosY;              // The Y-coordinate of current pixel being processed
    int w = 3;                          // Patch size is 2*w + 1
    double con[][] = new double[][] {{1, 1, 1}, {1, -8, 1}, {1, 1, 1}}; //Laplacian filter used in founding boundary of target region

    /**
     * Constructor for the ImageInpaint Class
     * @param owner Object to the Main class representing the owner of ImageInpaint object.
     */
    public ImageInpaint(Main owner) {
        this.owner = owner;
    }

    /**
     * Function to inpaint the given image.
     * @param a_origImg Original Image (without the target region marked)
     * @param a_fillImg Image with the target region marked in green color
     * @param quickInpaint  Flag to specify whether quick painting is enabled or not
     */
    @SuppressWarnings("unchecked")
    public void init(BufferedImage a_origImg, BufferedImage a_fillImg, Boolean quickInpaint)
    {
        halt = false;
        int i, j;
        try {
            origImg = a_origImg;
            img = a_origImg;
            fillImg = a_fillImg;
            raster = origImg.getRaster();

            iw = img.getWidth(null);
            ih = img.getHeight(null);

            /**
             * Grab the pixels of Original Image.
             */
            pixels = new int[iw*ih];
            PixelGrabber pg = new PixelGrabber(img, 0, 0, iw, ih, pixels, 0, iw);
            pg.grabPixels();
            pixelmap = new int[ih][iw];

            for (i = 0; i < ih; i ++) {
                for (j = 0; j < iw; j ++) {
                    pixelmap[i][j] = pixels [i*iw+j];
                }
            }

             /**
             * Grab the pixels of Fill Image.
             */
           
           
            PixelGrabber fillPg = new PixelGrabber(fillImg, 0, 0, iw, ih, pixels, 0, iw);
            fillPg.grabPixels();
            fillPixelmap = new int[ih][iw];

            for (i = 0; i < ih; i ++) {
                for (j = 0; j < iw; j ++) {
                    fillPixelmap[i][j] = pixels [i*iw+j];
                }
            }

        } catch (InterruptedException e1) {
            javax.swing.JOptionPane.showMessageDialog(owner, "Error " + e1,"Error!!",
                                    javax.swing.JOptionPane.ERROR_MESSAGE);
            System.out.println("Error " + e1);
        }

        /**
         * Create instance of GradientCalculator to calculate gradients.
         */
       
       
        gc = new GradientCalculator();
        gc.calculateGradientFromImage(pixelmap, ih, iw);        // Calculate Perpendicular Gradient for original image.
        gradientX = gc.gradientX;
        gradientY = gc.gradientY;
       
        initialize_confidence_term();                           // Initialize the confidence term
        initialize_data_term();                                 // Initialize the data term

        fillRegion = new double[ih][iw];                        // Allocate Space for fillRegion
        sourceRegion = new int[ih][iw];                         // Allocate Space for SourceRegion
        initialSourceRegion = new int[ih][iw];                  // Allocate Space for initialSourceRegion

        /**
         * Initialize minX, minY, maxX and maxY to find these coordinates
         */
        minX = iw;
        minY = ih;
        maxX = maxY = 0;

        int pixel, r, g, b, countrow, countcol;
        continuousRow = continuousCol = 0;
        for (i = 0; i < ih; i ++) {
            countrow = 0;
            for (j = 0; j < iw; j ++) {
                pixel = fillPixelmap[i][j];
                r = 0xff & (pixel >> 16);                       // Obtain the red Component
                g = 0xff & (pixel >> 8);                        // Obtain the green Component
                b = 0xff & (pixel);                             // Obtain the blue Component
                /**
                 * If the color is green, mark it as fillRegion
                 * Otherwise mark it as SourceRegion.
                 */
                if (r == 0 && g == 255 && b == 0) {
                    countrow ++;                                // Increase the number of continuous green pixels
                    fillRegion[i][j] = 1;
                    sourceRegion[i][j] = 0;
                    initialSourceRegion[i][j] = 0;
                    if (j < minX) {
                        minX = j;
                    }
                    if (i < minY) {
                        minY = i;
                    }
                    if (j > maxX) {
                        maxX = j;
                    }
                    if (i > maxY) {
                        maxY = i;
                    }
                } else {
                    if (countrow > continuousRow) {
                        continuousRow = countrow;
                    }
                    countrow = 0;
                    fillRegion[i][j] = 0;
                    sourceRegion[i][j] = 1;
                    initialSourceRegion[i][j] = 1;
                }
            }
        }

        for (i = 0; i < iw; ++i) {
            countcol = 0;
            for (j = 0; j < ih; ++j) {
                pixel = fillPixelmap[j][i];
                r = 0xff & (pixel >> 16);                       // Obtain the red Component
                g = 0xff & (pixel >> 8);                        // Obtain the green Component
                b = 0xff & (pixel);                             // Obtain the blue Component
                /**
                 * If pixel is green, increase the countcol by 1.
                 */
                if (r == 0 && g == 255 && b == 0) {
                    countcol ++;                                // Increase the number of continuous green pixels
                } else {
                    if (countcol > continuousCol) {
                        continuousCol = countcol;
                    }
                    countcol = 0;
                }
            }
        }

        //System.out.println("Col = " + continuousCol);
        //System.out.println("Col = " + continuousRow);

        Boolean flag = true;                        // Flag to represent the completion of the inpainting process

        double[][] temp = new double[ih][iw];
        double[][] sourceGradX = new double[ih][iw];
        double[][] sourceGradY = new double[ih][iw];

        Vector dR = new Vector();                   // Vector to store pixels of the boundary
        Vector Nx = new Vector();                   // Vector to store corresponding gradient in X direction
        Vector Ny = new Vector();                   // Vector to store corresponding gradient in Y direction

        double count;                               // Temporary variable used in calculating confidence terms for patches
        double Rcp;                                 // Temporary variable used in calculating confidence terms for patches
        double tempPriority;                         // Temporary variable used in calculating maximum priority

        while (flag) {

            /**
             * Filter the fillRegion with Laplacian Filter. Done to find the pixels on the boundary.
             */
            temp = conv2 (fillRegion, con);

            /**
             * Find the gradient of Source Region.
             */
            gc.calculateGradient(sourceRegion, ih, iw);
            sourceGradX = gc.gradientX;
            sourceGradY = gc.gradientY;

            dR.clear();
            Nx.clear();
            Ny.clear();

            /**
             * Add the coordinates of boundary pixels to dR and their gradients to Nx and Ny.
             */
            for (i = 0; i < temp[0].length; i ++) {
                for (j = 0; j < temp.length; j ++) {
                    if (temp[j][i] > 0) {
                            dR.add(i*temp.length + j);
                            Nx.add(sourceGradX[j][i]);
                            Ny.add(sourceGradY[j][i]);
                    }
                }
            }

            double[][] N = normr(Nx, Ny);       // Normalize Nx and Ny and store in N

            Vector q = new Vector();
            count = 0.0;

            /**
             * Now calculate Confidence Terms for all the pixels in the boundary of target region.
             */
            for (i = 0; i < dR.size(); i ++) {
                int[][] Hp = getpatch(pixelmap, (Integer)dR.get(i));
                System.out.println();
                for (j = 0; j < Hp.length; j ++) {
                    for (int k = 0; k < Hp[0].length; k ++) {
                        int col = (int)Hp[j][k]/ih;
                        int row = (int)Hp[j][k]%ih;
                        System.out.println(col+"   "+row);
                        if (fillRegion[row][col] == 0) {
                           
                            count += confidence[row][col];
                            q.add(Hp[j][k]);
                        }
                    }
                }
               
                int col = (Integer)dR.get(i)/ih;
                int row = (Integer)dR.get(i)%ih;
                confidence[row][col] = count/(double)(Hp.length*Hp[0].length);
                count = 0;
            }

            double maxPriority = 0.0;
            int maxPriorityIndex = -1;
            /**
             * After calculating confidence terms, now calculate data term and then find the patch with maximum priority.
             * This is done using the additive priority term.
             */
            for (i = 0; i < dR.size(); i ++) {
                int col = (Integer)dR.get(i)/ih;
                int row = (Integer)dR.get(i)%ih;

                /**
                 * Calculate Data term. +0.001 to prevent it from getting value Zero.
                 */
                data[row][col] = Math.abs(gradientX[row][col]*N[i][0] + gradientY[row][col]*N[i][1]) + 0.001;
   
                /**
                 * Elevated Confidence term. This prevents it from reaching Zero to soon.
                 */
                Rcp = (1-omega)*confidence[row][col]+omega;

                tempPriority = Alpha*Rcp + Beta*data[row][col];     // Calculate Priority using additive function

                /**
                 * find the patch with maximum priority
                 */
                if (tempPriority >= maxPriority) {
                    maxPriority = tempPriority;
                    maxPriorityIndex = i;
                }
            }

            if (maxPriorityIndex == -1) break;          // If no patch is found, then inpainting is complete.

            /**
             * Obtain the patch with maximum priority.
             * @Hp: Coordinates of patch with maximum priority
             * @toFill: Represents which pixels (from the patch) are to be filled
             * @toFillTrans: Transpose of ToFill matrix
             */
            int[][] Hp = getpatch (pixelmap, (Integer)dR.get(maxPriorityIndex));
            double[][] toFill = new double[Hp.length][Hp[0].length];
            double[][] toFillTrans = new double[Hp[0].length][Hp.length];

            /**
             * Calculate ToFill and ToFillTrans
             */
            for (i = 0; i < Hp.length; i ++) {
                for (j = 0; j < Hp[0].length; j ++) {
                    int col = (int)Hp[i][j]/ih;
                    int row = (int)Hp[i][j]%ih;
                    toFill[i][j] = fillRegion[row][col];
                    toFillTrans[j][i] = fillRegion[row][col];
                }
            }

            pixelPosX = (Integer)dR.get(maxPriorityIndex)/ih;
            pixelPosY = (Integer)dR.get(maxPriorityIndex)%ih;
            /**
             * Find the Best Exemplar. if quickInpaint is set, then only a small region of complete image is scanned.
             * We now get the starting and ending X and Y coordinates of the best Patch.
             */
            int[] best = bestExemplar(Hp, toFillTrans, initialSourceRegion, quickInpaint);

            int nRows = best[3] - best[2] + 1;
            int nCols = best[1] - best[0] + 1;

            /**
             * Find the patch represented by best.
             */
            int[][] X = new int[nRows][nCols];
            int[][] Y = new int[nRows][nCols];
            int[][] Hq = new int[nRows][nCols];
            for (i = 0; i < nRows; i ++) {
                for (j = 0; j < nCols; j ++) {
                    X[i][j] = best[0] + j;
                    Y[i][j] = best[2] + i;
                    Hq[i][j] = X[i][j] + Y[i][j]*ih;
                }
            }

            int p = (Integer)dR.get(maxPriorityIndex);

            /**
             * Update the image, data values and confidence values.
             */
            for (i = 0; i < toFill.length; i ++) {
                for (j = 0; j < toFill[0].length; j ++) {
                    if (toFill[i][j] != 0) {
                        toFill[i][j] = 1;
                        int col = (int)Hp[i][j]/ih;
                        int row = (int)Hp[i][j]%ih;

                        int col1 = Hq[i][j]/ih;
                        int row1 = Hq[i][j]%ih;
                       
                        fillRegion[row][col] = 0;       // Since the region is reconstructed, remove from fillRegion
                        sourceRegion[row][col] = 1;     // Since the region is reconstructed, add to SourceRegion

                        /** Propagate Confidence and Isophote Values */
                        confidence[row][col] = confidence[p%ih][p/ih];
                        gradientX[row][col] = gradientX[row1][col1];
                        gradientY[row][col] = gradientY[row1][col1];
                        pixelmap[row][col] = pixelmap[row1][col1];

                        /**
                         * Update the image pixels
                         */
                        int[] color = new int[3];
                        color[0] = 0xff & (pixelmap[row1][col1] >> 16);
                        color[1] = 0xff & (pixelmap[row1][col1] >> 8);
                        color[2] = 0xff & (pixelmap[row1][col1]);
                        raster.setPixel(col, row, color);
                    }
                }
            }

            if (halt) break;
            owner.updateStats(origImg);         // Inform the owner about the updated image.
            Thread.yield();

            /**
             * Find whether any other pixels are remaining to be inpainted.
             */
            flag = false;
            for (i = 0; i < fillRegion.length; ++i) {
                for (j = 0; j < fillRegion[0].length; ++j) {
                    if (fillRegion[i][j] == 1) {
                        flag = true;
                        break;
                    }
                }
                if (flag) break;        // If none of the pixels are in target region, break
            }

            if (halt) break;     // Stop Inpainting if owner halts the process.
        }
        /**
         * No need of gradient calculator now.
         * Mark it as null to drop a hint to garbageCollector that it can now be removed.
         */
        gc = null;
        if (!halt) {
            completed = true;
        } else {
            completed = false;
        }
        owner.updateStats(origImg);     // Inform the owner about the updates.
        Thread.yield();
    }

    /**
     * Initializes the confidence term to zero for pixels in target region and 1 for pixels in source region.
     */
    void initialize_confidence_term()
    {
        confidence = new double[ih][iw];
        for(int i = 0; i < ih; i ++) {
            for (int j = 0; j < iw; j ++) {
                int p = pixelmap[i][j];
                int r = 0xff & (p >> 16);
                int g = 0xff & (p >> 8);
                int b = 0xff & (p);
                if (r == 0 && g == 255 && b == 0) {
                    confidence[i][j] = 0;
                } else {
                    confidence[i][j] = 1;
                }
            }
        }
    }

    /**
     * Initialize the data term.
     */
    void initialize_data_term()
    {
        data = new double[ih][iw];
        for (int i = 0; i < ih; i ++) {
            for (int j = 0; j < iw; j ++) {
                data[i][j] = -0.1;
            }
        }
    }

    /**
     * Function to convolve the given matrix with another matrix
     * @param a Matrix to be convolved
     * @param b Matrix to be convolved with
     * @return The result after convolution.
     */
    double[][] conv2 (double a[][], double b[][])
    {
        int ra = a.length;
        int ca = a[0].length;
        int rb = b.length;
        int cb = b[0].length;

        // do full convolution
        double c[][] = new double[ra+rb-1][ca+cb-1];
        for (int i = 0; i < rb; i ++) {
            for (int j = 0; j < cb; j ++) {
                int r1 = i;
                int r2 = r1 + ra - 1;
                int c1 = j;
                int c2 = c1 + ca - 1;
                for (int k = r1; k < r2; k ++) {
                    for (int l = c1; l < c2; l ++) {
                        c[k][l] = c[k][l] + b[i][j]*a[k-r1+1][l-c1+1];
                    }
                }
            }
        }

        double out[][] = new double[ra][ca];
        //extract region of size(a) from c
        int r1 = rb/2;
        int r2 = r1 + ra - 1;
        int c1 = cb/2;
        int c2 = c1 + ca - 1;
        for (int i = r1; i < r2; i ++) {
            for (int j = c1; j < c2; j ++) {
                out[i-r1+1][j-c1+1] = c[i][j];
            }
        }      
        return out;
    }

    /**
     * Function to normalize the given vectors and return them concatenated in one single matrix
     * @param X Vector 1
     * @param Y Vector 2
     * @return  The result after normalizing and then concatenating the two vectors.
     */
    @SuppressWarnings("unchecked")
    double[][] normr (Vector X, Vector Y )
    {
        double normalized[][] = new double[X.size()][2];
        for (int i = 0; i < X.size(); i ++) {
            double temp1 = (Double)X.get(i);
            double temp2 = (Double)Y.get(i);
           
            temp1 *= temp1;
            temp2 *= temp2;
           
            double temp3;
           
            if(temp1 + temp2 == 0) {
                temp3 = 0;
            } else {
                temp3 = (double)1/(temp1 + temp2);
                temp3 = Math.sqrt(temp3);
            }
           
            normalized[i][0] = temp3*(Double)X.get(i);
            normalized[i][1] = temp3*(Double)Y.get(i);
        }
    
        return normalized;
    }

    /**
     * Function that returns the patch around the given pixel.
     * @param pixelmap  Matrix representing the pixelmap of the image.
     * @param p Position of the pixel around which patch is to be calculated
     * @return  a matrix that contains the coordinates of the pixels that form the patch.
     */
    @SuppressWarnings("unchecked")
    int[][] getpatch (int[][] pixelmap, int p)
    {
       
        int y;
        int x;

        p = p-1;
        y = (p/ih);//+ 1;
        p = p % ih;
        x = p+1;
       
        int temp1 = Math.max(x-w, 0);           // Starting X coordinate
        int temp2 = Math.min(x+w,ih-1);         // Ending X coordinate
        int temp3 = Math.max(y-w,0);            // Starting Y Coordinate
        int temp4 = Math.min(y+w,iw-1);         // Ending Y Coordinate
           
        //int[][] X = new int[temp4-temp3+1][temp2-temp1+1];
        //int[][] Y = new int[temp4-temp3+1][temp2-temp1+1];
        int [][] N = new int[temp4-temp3+1][temp2-temp1+1];
       
        for (int i = 0; i < temp4-temp3+1; i ++) {
            for (int j = 0; j < temp2-temp1+1; j ++) {
                //X[i][j] = temp1 + j;
                //Y[i][j] = temp3 + i;
               
                System.out.println(i+"Patching pixel value :- "+N[i][j]);
                N[i][j] = temp1+j + (temp3+i)*ih;
            }
        }
        return N;
    }

    /**
     * Function that finds the best exemplar from the image that matches the patch given to the fucntion.
     * By default, it finds the complete image to look for the best exemplar.
     * But if quickInpaint is set, it only looks for the patch inside a region defined by minX, maxX, minY, maxY, diamX and diamY
     * @param Hp    Patch for which the best exemplar is to be found
     * @param toFill    Pixels that are to be filled from the patch.
     * @param sourceRegion  the source region from where to look for the best exemplar
     * @param quickInpaint  Flag that represents whether or not to perform quick Inpainting.
     * @return  Returns an integer array with four elements representing starting x coordinate, ending x coordinate, starting y coordinate and ending y coordinate respectively.
     */
 int[] bestExemplar (int [][] Hp, double[][] toFill, int[][] sourceRegion, Boolean quickInpaint)
    {
        int [][] Ip = new int[toFill.length][toFill[0].length];
        for (int i = 0; i < toFill[0].length; i ++) {
            for (int j = 0; j < toFill.length; j ++) {
                int col = (int)Hp[i][j]/ih;
                int row = (int)Hp[i][j]%ih;
                Ip[j][i] = pixelmap[row][col];              // transpose
            }
        }

        int[][] rIp = new int[Ip.length][Ip[0].length];
        int[][] gIp = new int[Ip.length][Ip[0].length];
        int[][] bIp = new int[Ip.length][Ip[0].length];

        for (int i = 0; i < Ip.length; ++i) {
            for (int j = 0; j < Ip[0].length; ++j) {
                /**
                 * Extract the RGB components of the image.
                 */
                rIp[i][j] = 0xff & (Ip[i][j] >> 16);
                gIp[i][j] = 0xff & (Ip[i][j] >> 8);
                bIp[i][j] = 0xff & (Ip[i][j]);
            }
        }

        int mm, nn;
        int startX;
        int startY;
        int endX;
        int endY;
        int m = Ip.length;
        int n = Ip[0].length;
        if (quickInpaint) {

            startX = Math.max(0, pixelPosX - n/2 - continuousRow - diamX/2);      // Set the start X coordinate above the pixel's X-coordinate by some amount
            startY = Math.max(0, pixelPosY - m/2 - continuousCol -diamY/2);       // Set the start Y coordinate above the pixel's Y-coordinate by some amount
            endX = Math.min(pixelmap[0].length-1, pixelPosX + n/2 + continuousRow + diamX/2);
            endY = Math.min(pixelmap.length-1, pixelPosY + m/2 + continuousCol + diamY/2);
            mm = endY - startY + 1;
            nn = endX - startX + 1;
        } else {
            mm = pixelmap.length;
            nn = pixelmap[0].length;
            startX = 0;
            startY = 0;
            endX = endY = 0;
        }
        int i,j,ii,jj,ii2,jj2,M,N,I,J;
        double patchErr=0.0,err=0.0,bestErr = 99999999999999999999.0, bestPatchErr1 = 99999999999999999999.0;
        int[] best = {0, 0, 0, 0};
        Boolean skipPatchFlag = false;
       
        /** for each patch */
        N= startX + nn-n+1;  M= startY + mm-m+1;
        for (j = startX; j < N; j++) {
            J = j+n-1;
            for (i = startY; i < M; i++) {
                I = i+m-1;
               
                skipPatchFlag = false;
               
                double meanR = 0.0;
                double meanG = 0.0;
                double meanB = 0.0;
               
               
                /**
                 * Calculate patch error
                 */
                for (jj = j, jj2 = 0; jj <= J; jj++,jj2++) {
                    for (ii = i,ii2 = 0; ii <= I; ii++,ii2++) {

                        /**
                         * If any pixels does not belong to the source region, then skip the patch.
                         */
                        if (sourceRegion[ii][jj]!=1) {
                            skipPatchFlag = true;
                            break;
                        }
                        if (toFill[ii2][jj2]==0) {
                            int rImage = 0xff & (pixelmap[ii][jj] >> 16);
                            int gImage = 0xff & (pixelmap[ii][jj] >> 8);
                            int bImage = 0xff & (pixelmap[ii][jj]);

                            /**
                             * Calculate the mean square error for the patch.
                             */
                            err = rImage - rIp[ii2][jj2]; patchErr += err*err;
                            err = gImage - gIp[ii2][jj2]; patchErr += err*err;
                            err = bImage - bIp[ii2][jj2]; patchErr += err*err;
                            /**
                             * Calculate the mean of the color values. Used when we get two patches with same best error.
                             */
                            meanR += rImage;
                            meanG += gImage;
                            meanB += bImage;
                        }
                    }
                    if (skipPatchFlag) {
                        break;
                    }
                }
               
                /**
                 * Update
                 */
                if (!skipPatchFlag && patchErr < bestErr ) {
                    bestErr = patchErr;
                    best[0] = i; best[1] = I;
                    best[2] = j; best[3] = J;

                    /**
                     * Calculate the variance of the patch.
                     */
                    double patchErr1 = 0.0;
                    for (jj = j, jj2 = 0; jj <= J; jj++,jj2++) {
                        for (ii = i,ii2 = 0; ii <= I; ii++,ii2++) {
                            if (toFill[ii2][jj2]==1) {
                                int rImage = 0xff & (pixelmap[ii][jj] >> 16);
                                int gImage = 0xff & (pixelmap[ii][jj] >> 8);
                                int bImage = 0xff & (pixelmap[ii][jj]);

                                err = rImage - meanR; patchErr1 += err*err;
                                err = gImage - meanG; patchErr1 += err*err;
                                err = bImage - meanB; patchErr1 += err*err;
                            }
                        }
                    }
                    bestPatchErr1 = patchErr1;      // Update the variance of the best patch found so far.
                } else if (!skipPatchFlag && patchErr == bestErr) {
                    /**
                     * If the current patch has same error as the previous best patch
                     * we find the variance of this patch.
                     * The patch with minimum variance is now selected as the best patch.
                     */
                    double patchErr1 = 0.0;
                    for (jj = j, jj2 = 0; jj <= J; jj++,jj2++) {
                        for (ii = i,ii2 = 0; ii <= I; ii++,ii2++) {
                            if (toFill[ii2][jj2]==1) {
                                int rImage = 0xff & (pixelmap[ii][jj] >> 16);
                                int gImage = 0xff & (pixelmap[ii][jj] >> 8);
                                int bImage = 0xff & (pixelmap[ii][jj]);

                                err = rImage - meanR; patchErr1 += err*err;
                                err = gImage - meanG; patchErr1 += err*err;
                                err = bImage - meanB; patchErr1 += err*err;
                            }
                        }
                    }
                    /**
                     * Select the new patch if it has lower variance.
                     * Otherwise discard.
                     */
                    if (bestPatchErr1 > patchErr1) {
                        best[0] = i; best[1] = I;
                        best[2] = j; best[3] = J;
                        bestPatchErr1 = patchErr1;
                    }
                }
               
                patchErr = 0.0;
            }
        }

        if (best[0] == 0 && best[1] == 0 && best[2] == 0 && best[3] == 0) {
            return (bestExemplar (Hp, toFill, sourceRegion, false));
        }
        return best;
    }
}