package ij.plugin.filter;
import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;

/**Binary Fill (Process/Binary/Fill) by Gabriel Landini, G.Landini at bham.ac.uk. */
public class BinaryFiller implements PlugInFilter {
    protected boolean backgroundIsZero;

    public int setup(String arg, ImagePlus imp) {
        if (imp==null)
            {IJ.noImage(); return DONE;}
        ImageStatistics stats=imp.getStatistics();
        if (stats.histogram[0]+stats.histogram[255]!=stats.pixelCount){
            IJ.error("8-bit binary image (0 and 255) required.");
            return DONE;
        }
        backgroundIsZero = Prefs.blackBackground;
        if (imp.isInvertedLut()) 
            backgroundIsZero = !backgroundIsZero;           
        return IJ.setupDialog(imp, DOES_8G);
    }

    public void run(ImageProcessor ip) {
        int xe = ip.getWidth();
        int ye = ip.getHeight();
        int x, y;
        boolean b;
        int [][] pixel = new int [xe][ye];

        //original converted to white particles
        if (!backgroundIsZero)
            ip.invert();
            
        //get original
        for(y=0;y<ye;y++) {
            for(x=0;x<xe;x++)
                pixel[x][y]=ip.getPixel(x,y);
        }

        //label background borders
        for (y=0; y<ye; y++){
            if(ip.getPixel(0,y)==0)
                ip.putPixel(0,y,127);
            if(ip.getPixel(xe-1,y)==0)
                ip.putPixel(xe-1,y,127);
        }

        for (x=0; x<xe; x++){
            if(ip.getPixel(x,0)==0)
                ip.putPixel(x,0,127);
            if(ip.getPixel(x,ye-1)==0)
                ip.putPixel(x,ye-1,127);
        }

        //flood background from borders
        //the background of 8-connected particles is 4-connected
        b=true;
        while(b){
            b=false;
            for(y=1;y<ye-1;y++) {
                for(x=1;x<xe-1;x++) {
                    if (ip.getPixel(x,y)==0){
                        if(ip.getPixel(x,y-1)==127 || ip.getPixel(x-1,y)==127) {
                            ip.putPixel(x,y,127);
                            b=true;
                        }
                    }
                }
            }
            for(y=ye-2;y>=1;y--) {
                for(x=xe-2;x>=1;x--) {
                    if (ip.getPixel(x,y)==0){
                        if(ip.getPixel(x+1,y)==127 || ip.getPixel(x,y+1)==127) {
                            ip.putPixel(x,y,127);
                            b=true;
                        }
                    }
                }
            }
        }//idempotent

        for(y=0;y<ye;y++) {
            for(x=0;x<xe;x++){
                if(ip.getPixel(x,y)==0)
                    ip.putPixel(x,y,255);
                else
                    ip.putPixel(x,y,pixel[x][y]);
            }
        }

        //return to original state
        if (!backgroundIsZero)
            ip.invert();
    }

}