// ----------------------------------------------------------------------------
// Project Sunflower - surfel based graphics system
// ----------------------------------------------------------------------------
// application: Diffuse demo
// author:      Pavel Tisnovsky
// file name:   Diffuse4.java
// directory:   java
// date:        22.06.2004
// description: Demonstracni aplikace pro vytvoreni a zobrazeni fraktalniho
//              objektu, ktery je zalozeny na simulaci difuze.
//              Podrobnejsi informace o tomto prikladu jsou popsany primo
//              v clanku.
// ----------------------------------------------------------------------------



// Nasledujici radky jsou urceny pro spusteni appletu v programu AppletViewer:
//
// <applet code="Diffuse4.class" width="640" height="400">
// </applet>
//
// pro kompatibilitu se starsi JVM firmy Microsofti se musi provest preklad
// pomoci prikazu:
// javac -target 1.1 Diffuse4.java



// ----------------------------------------------------------------------------
// seznam importovanych balicku
// ----------------------------------------------------------------------------
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.applet.Applet;



// ----------------------------------------------------------------------------
// Trida pro aplikaci filtru na zvolenou zdrojovou pixmapu. Vysledek se uklada
// do cilove pixmapy.
// ----------------------------------------------------------------------------
class Filter {
    private int imageWidth;                         // velikost zpracovavanych pixmap
    private int imageHeight;
    private int pixelSrc[];                         // zdrojova pixmapa
    private int pixelDest[];                        // cilova pixmapa



    // ------------------------------------------------------------------------
    // V konstruktoru se nastavi velikost filtru a zdrojova a cilova pixmapa.
    // ------------------------------------------------------------------------
    public Filter(int imageWidth, int imageHeight, int pixelSrc[], int pixelDest[]) {
        this.imageWidth=imageWidth;                 // nastavit velikost pixmapy
        this.imageHeight=imageHeight;
        this.pixelSrc=pixelSrc;                     // nastavit handle zdrojove
        this.pixelDest=pixelDest;                   // a cilove pixmapy
    }



    // ------------------------------------------------------------------------
    // Nastaveni nove sirky zpracovavane pixmapy.
    // ------------------------------------------------------------------------
    public void setImageWidth(int imageWidth) {
        this.imageWidth=imageWidth;
    }



    // ------------------------------------------------------------------------
    // Nastaveni nove vysky zpracovavane pixmapy.
    // ------------------------------------------------------------------------
    public void setImageHeight(int imageHeight) {
        this.imageHeight=imageHeight;
    }



    // ------------------------------------------------------------------------
    // Nastaveni zdrojove pixmapy.
    // ------------------------------------------------------------------------
    public void setSourceImage(int pixelSrc[]) {
        this.pixelSrc=pixelSrc;
    }



    // ------------------------------------------------------------------------
    // Nastaveni cilove pixmapy.
    // ------------------------------------------------------------------------
    public void setDestinationImage(int pixelDest[]) {
        this.pixelDest=pixelDest;
    }



    // ------------------------------------------------------------------------
    // Ziskani sirky zpracovavanych pixmap.
    // ------------------------------------------------------------------------
    public int getImageWidth() {
        return imageWidth;
    }



    // ------------------------------------------------------------------------
    // Ziskani vysky zpracovavanych pixmap.
    // ------------------------------------------------------------------------
    public int getImageHeight() {
        return imageHeight;
    }



    // ------------------------------------------------------------------------
    // Ziskani zdrojove pixmapy.
    // ------------------------------------------------------------------------
    public int[] getSourceImage() {
        return pixelSrc;
    }



    // ------------------------------------------------------------------------
    // Ziskani cilove pixmapy.
    // ------------------------------------------------------------------------
    public int[] getDestinationImage() {
        return pixelDest;
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // zadny filtr, pouze kopie zdrojove pixmapy do cilove pixmapy.
    // ------------------------------------------------------------------------
    public void filterNone() {
        int pos=0;
        for (int j=0; j<imageHeight; j++) {         // pro vsechny radky pixmapy
            for (int i=0; i<imageWidth; i++) {      // pro vsechny pixely na radku
                pixelDest[pos]=0xffffffff;          // provest vymazani pixelu
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // rozmazani v bloku 2x2 pixely s vyberem ve tvaru bloku.
    // ------------------------------------------------------------------------
    public void filter2x2smooth() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        for (int j=0; j<imageHeight-1; j++) {       // pro vsechny radky pixmapy
            for (int i=0; i<imageWidth-1; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+imageWidth];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=4; g/=4; b/=4;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // rozmazani v bloku 3x3 pixely s vyberem ve tvaru diamantu.
    // ------------------------------------------------------------------------
    public void filter3x3diamond() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=1+imageWidth;
        for (int j=1; j<imageHeight-1; j++) {       // pro vsechny radky pixmapy
            for (int i=1; i<imageWidth-1; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-imageWidth];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+imageWidth];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=4; g/=4; b/=4;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // rozmazani v bloku 3x3 pixely s vyberem ve tvaru osoveho krize.
    // ------------------------------------------------------------------------
    public void filter3x3cross() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=1+imageWidth;
        for (int j=1; j<imageHeight-1; j++) {       // pro vsechny radky pixmapy
            for (int i=1; i<imageWidth-1; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-imageWidth];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+imageWidth];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=5; g/=5; b/=5;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // rozmazani v bloku 3x3 pixelu s vyberem ve tvaru uhlopricneho krize.
    // ------------------------------------------------------------------------
    public void filter3x3Xcross() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=1+imageWidth;
        for (int j=1; j<imageHeight-1; j++) {       // pro vsechny radky pixmapy
            for (int i=1; i<imageWidth-1; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-imageWidth-1];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=5; g/=5; b/=5;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // rozmazani v bloku 3x3 pixelu s blokovym vyberem.
    // ------------------------------------------------------------------------
    public void filter3x3block() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=1+imageWidth;
        for (int j=1; j<imageHeight-1; j++) {       // pro vsechny radky pixmapy
            for (int i=1; i<imageWidth-1; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-imageWidth-1];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-imageWidth];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+imageWidth];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=9; g/=9; b/=9;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // rozmazani v bloku 5x5 pixelu s vyberem ve tvaru diamantu.
    // ------------------------------------------------------------------------
    public void filter5x5diamond() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=2+2*imageWidth;
        for (int j=2; j<imageHeight-2; j++) {       // pro vsechny radky pixmapy
            for (int i=2; i<imageWidth-2; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-2*imageWidth+0];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth+0];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=8; g/=8; b/=8;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // rozmazani v bloku 5x5 pixelu s vyberem ve tvaru osoveho krize.
    // ------------------------------------------------------------------------
    public void filter5x5cross() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=2+2*imageWidth;
        for (int j=2; j<imageHeight-2; j++) {       // pro vsechny radky pixmapy
            for (int i=2; i<imageWidth-2; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-2*imageWidth+0];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth+0];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth+0];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth+0];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=9; g/=9; b/=9;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // rozmazani v bloku 5x5 pixelu s vyberem ve tvaru uhlopricneho krize.
    // ------------------------------------------------------------------------
    public void filter5x5Xcross() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=2+2*imageWidth;
        for (int j=2; j<imageHeight-2; j++) {       // pro vsechny radky pixmapy
            for (int i=2; i<imageWidth-2; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-2*imageWidth-2];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-2*imageWidth+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth-2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=9; g/=9; b/=9;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // rozmazani v bloku 5x5 pixelu s vyberem ve tvaru bloku.
    // ------------------------------------------------------------------------
    public void filter5x5block() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=2+2*imageWidth;
        for (int j=2; j<imageHeight-2; j++) {       // pro vsechny radky pixmapy
            for (int i=2; i<imageWidth-2; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-2*imageWidth-2];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-2*imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-2*imageWidth+0];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-2*imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-2*imageWidth+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth-2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth+0];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth-2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth+0];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth-2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth+0];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=25; g/=25; b/=25;                // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // horizontalni filtr rozmazani tri pixelu.
    // ------------------------------------------------------------------------
    public void filter3pixelsH() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=1;
        for (int j=0; j<imageHeight; j++) {         // pro vsechny radky pixmapy
            for (int i=1; i<imageWidth-1; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-1];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=3; g/=3; b/=3;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // vertikalni filtr rozmazani tri pixelu.
    // ------------------------------------------------------------------------
    public void filter3pixelsV() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=imageWidth;
        for (int j=1; j<imageHeight-1; j++) {       // pro vsechny radky pixmapy
            for (int i=0; i<imageWidth; i++) {      // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-imageWidth];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+imageWidth];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=3; g/=3; b/=3;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // horizontalni filtr rozmazani peti pixelu.
    // ------------------------------------------------------------------------
    public void filter5pixelsH() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=2;
        for (int j=0; j<imageHeight; j++) {         // pro vsechny radky pixmapy
            for (int i=2; i<imageWidth-2; i++) {    // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-2];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+1];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=5; g/=5; b/=5;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede filtraci pixmapy s filtrem typu:
    // vertikalni filtr rozmazani peti pixelu.
    // ------------------------------------------------------------------------
    public void filter5pixelsV() {
        int pos=0;                                  // index do zdrojove a cilove pixmapy
        int color;                                  // RGBA barvove slozky zakodovane do typu int
        int r, g, b;                                // jednotlive rozkodovane barvove slozky
        filterNone();                               // nejprve pixmapy zkopirovat
        pos=2*imageWidth;
        for (int j=2; j<imageHeight-2; j++) {       // pro vsechny radky pixmapy
            for (int i=0; i<imageWidth; i++) {      // pro vsechny sloupce na radku pixmapy
                color=pixelSrc[pos-2*imageWidth];
                r =(color & 0x00ff0000)>>16;
                g =(color & 0x0000ff00)>>8;
                b =(color & 0x000000ff);
                color=pixelSrc[pos-  imageWidth];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+  imageWidth];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                color=pixelSrc[pos+2*imageWidth];
                r+=(color & 0x00ff0000)>>16;
                g+=(color & 0x0000ff00)>>8;
                b+=(color & 0x000000ff);
                r/=5; g/=5; b/=5;                   // provest filtraci
                pixelDest[pos]=(r<<16) | (g<<8) | b | (0xff<<24);
                pos++;
            }
        }
    }
}
// ----------------------------------------------------------------------------
// Konec tridy Filter.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// Trida s panelem, na kterem se zobrazuje pixmapa o predem danem rozmeru.
// ----------------------------------------------------------------------------
class ImagePanel extends Canvas {
    int               width;                        // rozmery pixmapy
    int               height;
    public int[]      pixels;                       // pixmapa - zdroj pixelu
    MemoryImageSource imageSource;                  // objekt zaobalujici zdroj pixelu
    Image             image;                        // pixmapa vytvorena nad zdrojem pixelu



    // ------------------------------------------------------------------------
    // V konstruktoru se nastavi velikost panelu a soucasne barva jeho pozadi.
    // ------------------------------------------------------------------------
    public ImagePanel(int width, int height) {
        pixels=new int[width*height];
        for (int j=0; j<height; j++)                // pro vsechny radky pixmapy
            for (int i=0; i<width; i++)             // pro vsechny sloupce pixmapy
                pixels[i+j*width]=0xffffffff;       // vyplnit pixmapu i s alfa kanalem
        imageSource=new MemoryImageSource(width, height, pixels, 0, height);
        image=createImage(imageSource);             // vytvoreni pixmapy
        this.width=width;                           // nastaveni velikosti pixmapy
        this.height=height;
        this.setBackground(Color.white);            // nastaveni vlastnosti panelu
        this.setSize(width, height);
    }



    // ------------------------------------------------------------------------
    // Pristup k jednotlivym pixelum pixmapy.
    // ------------------------------------------------------------------------
    public void putpixel(int x, int y, int r, int g, int b) {
        pixels[x+y*width]=r+(g<<8)+(b<<16)+(255<<24);
    }



    // ------------------------------------------------------------------------
    // Aplikaci dostupne prekresleni celeho panelu s volbou vymazu stare kresby.
    // ------------------------------------------------------------------------
    public void redraw(boolean clear) {
        Graphics g=this.getGraphics();
        if (clear)                                  // premazat starou kresbu
            g.clearRect(0, 0, width, height);
        image.flush();                              // prenest pixely do obrazu
        g.drawImage(image, 0, 0, this);             // a vykreslit obraz s pixmapou
    }



    // ------------------------------------------------------------------------
    // Prekresleni panelu s pixmapou.
    // ------------------------------------------------------------------------
    public void paint(Graphics g) {
        g.drawImage(image, 0, 0, this);             // vykreslit obraz s pixmapou
    }
}
// ----------------------------------------------------------------------------
// Konec tridy ImagePanel.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// Trida s kodem pro zobrazeni napovedy.
// ----------------------------------------------------------------------------
class WindowHelp extends Frame implements ActionListener {
    static boolean visible=false;                   // priznak indikujici zobrazeni napovedy



    // ------------------------------------------------------------------------
    // Konstrukce okna s napovedou.
    // ------------------------------------------------------------------------
    public WindowHelp() {
        TextArea text=new TextArea(
            "1. choose point shape\n"+
            "2. choose seed shape (set of starting points)\n"+
            "3. adjust number of generated points in a box\n"+
            "4. set filter type\n"+
            "5. set box width and height (in pixels)\n"+
            "6. then press the 'Recalc' button\n"+
            "7. apply filter with 'Redraw' button"
        );
        visible=true;
        Button buttonOK=new Button("ok");
        Label  label=new Label("How to work with this applet:");
        buttonOK.addActionListener(this);           // po stlaceni tlacitka se ma napoveda zavrit
        this.setSize(320, 240);                     // nastaveni velikosti a rozmeru okna
        this.setLocation(100, 100);
        this.setTitle("Diffuse 4 - Help");          // zobrazeni titulku
        this.add("Center", text);                   // a pridani vsech ovladacich prvku
        this.add("South", buttonOK);
        this.add("North", label);
        this.setVisible(true);
    }



    // ------------------------------------------------------------------------
    // Reakce na stlaceni tlacitka s textem OK.
    // ------------------------------------------------------------------------
    public void actionPerformed(ActionEvent e) {
        visible=false;
        this.dispose();
    }
}
// ----------------------------------------------------------------------------
// Konec tridy WindowHelp.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// Trida s kodem pro zobrazeni informaci o aplikaci.
// ----------------------------------------------------------------------------
class WindowAbout extends Frame implements ActionListener {
    static boolean visible=false;                   // priznak indikujici zobrazeni okna



    // ------------------------------------------------------------------------
    // Konstrukce okna s informaci o aplikaci.
    // ------------------------------------------------------------------------
    public WindowAbout() {
        TextArea text=new TextArea(
            "Diffuse 4 demo\n\n"+
            "version 1.0\n"+
            "Author: Pavel Tisnovsky\n"+
            "Date: 2004-06-22\n"+
            "http://www.fit.vutbr.cz/~tisnovpa\n"
        );
        visible=true;
        Button buttonOK=new Button("ok");
        Label  label=new Label("About Diffuse 4");
        buttonOK.addActionListener(this);           // po stlaceni tlacitka se ma okno zavrit
        this.setSize(320, 240);                     // nastaveni velikosti a rozmeru okna
        this.setLocation(100, 100);
        this.setTitle("Diffuse 4 - About");         // zobrazeni titulku
        this.add("Center", text);                   // a pridani vsech ovladacich prvku
        this.add("South", buttonOK);
        this.add("North", label);
        this.setVisible(true);
    }



    // ------------------------------------------------------------------------
    // Reakce na stlaceni tlacitka s textem OK.
    // ------------------------------------------------------------------------
    public void actionPerformed(ActionEvent e) {
        visible=false;
        this.dispose();
    }
}
// ----------------------------------------------------------------------------
// Konec tridy WindowAbout.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// Trida s kodem pro zobrazeni informaci o systemu.
// ----------------------------------------------------------------------------
class WindowInfo extends Frame implements ActionListener {
    static boolean visible=false;                   // priznak indikujici zobrazeni okna



    // ------------------------------------------------------------------------
    // Konstrukce okna s informacemi.
    // ------------------------------------------------------------------------
    public WindowInfo() {
        Runtime r=Runtime.getRuntime();             // ziskat objekt s informacemi o aplikaci
        TextArea text=new TextArea("");
        text.append("Total memory: "+r.totalMemory()+"\n");
        text.append("Free memory: "+r.freeMemory()+"\n");
        visible=true;
        Button buttonOK=new Button("ok");
        Label  label=new Label("System informations:");
        buttonOK.addActionListener(this);           // po stlaceni tlacitka se ma okno zavrit
        this.setSize(320, 240);                     // nastaveni velikosti a rozmeru okna
        this.setLocation(100, 100);
        this.setTitle("Diffuse 4 - Info");          // zobrazeni titulku
        this.add("Center", text);                   // a pridani vsech ovladacich prvku
        this.add("South", buttonOK);
        this.add("North", label);
        this.setVisible(true);
    }



    // ------------------------------------------------------------------------
    // Reakce na stlaceni tlacitka s textem OK.
    // ------------------------------------------------------------------------
    public void actionPerformed(ActionEvent e) {
        visible=false;
        this.dispose();
    }
}
// ----------------------------------------------------------------------------
// Konec tridy WindowInfo.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// Rozhrani s tvary seminek.
// ----------------------------------------------------------------------------
interface SeedShape {
    int OnePoint=         0,                        // seminko ve tvaru jednoho bodu
        TwoPoints=        1,                        // dva body na usecce
        ThreePoints=      2,                        // tri body ve vrcholech trojuhelnika
        FourPoints=       3,                        // ctyri body ve vrcholech ctverce
        ShortBottomLine=  4,                        // cast usecky
        BottomLine=       5,                        // usecka ve spodni casti obrazce
        Square=           6,                        // ctverec
        Border=           7,                        // ctverec az k okrajum bitmapy
        SmallCircle=      8,                        // mala kruznice
        NormalCircle=     9,                        // normalni kruznice
        BigCircle=       10;                        // vetsi kruznice
}
// ----------------------------------------------------------------------------
// Konec rozhrani SeedShape.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// Rozhrani s tvary bodu.
// ----------------------------------------------------------------------------
interface PointShape {
    int OnePixel=   0,                              // bod ma tvar jednoho pixelu
        Cross3x3=   1,                              // pet pixelu ve tvaru krize
        XCross3x3=  2,                              // pet pixelu ve tvaru uhlopricneho krize
        Diamond3x3= 3,                              // ctyri pixely ve tvaru diamantu
        Block3x3=   4,                              // blok deviti pixelu
        Cross5x5=   5,                              // dtto pro okoli 5x5
        XCross5x5=  6,
        Diamond5x5= 7,
        Block5x5=   8,
        Horizontal3=9,                              // tri pixely vedle sebe
        Horizontal5=10,                             // pet pixelu vedle sebe
        Vertical3=  11,                             // tri pixely pod sebou
        Vertical5=  12;                             // pet pixelu pod sebou
}
// ----------------------------------------------------------------------------
// Konec rozhrani PointShape.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// Rozhrani se jmeny filtru.
// ----------------------------------------------------------------------------
interface FilterType {
    int None=       0,                              // zadny filtr
        Smooth2x2=  1,                              // filtr typu 2x2 smooth
        Diamond3x3= 2,                              // filtr typu 3x3 diamond
        Cross3x3=   3,                              // filtr typu 3x3 cross
        XCross3x3=  4,                              // filtr typu 3x3 X cross
        Block3x3=   5,                              // filtr typu 3x3 block
        Diamond5x5= 6,                              // filtr typu 5x5 diamond
        Cross5x5=   7,                              // filtr typu 5x5 cross
        XCross5x5=  8,                              // filtr typu 5x5 X cross
        Block5x5=   9,                              // filtr typu 5x5 block
        Horizontal3=10,                             // filtr typu 3 pixels horizontal
        Horizontal5=11,                             // filtr typu 5 pixels horizontal
        Vertical3=  12,                             // filtr typu 3 pixels vertical
        Vertical5=  13;                             // filtr typu 5 pixels vertical
}
// ----------------------------------------------------------------------------
// Konec rozhrani FilterType.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// V pripade, ze by bylo nutne tento demonstrani program spustit jako Java ap-
// likaci, je mozne odkomentovat metodu "main". V tomto pripade se vsak vytvo-
// ri dalsi soubor .class s anonymni tridou Listener.
// ----------------------------------------------------------------------------
public class Diffuse4 extends Applet implements
        Runnable,
        ActionListener,
        ItemListener,
        AdjustmentListener,
        SeedShape,
        FilterType,
        PointShape
{
    static final int ImageWidth=256;                // sirka pixmapy s fraktalem
    static final int ImageHeight=256;               // vyska pixmapy s fraktalem
    static final int DrawingWidth=256;              // sirka kresby pouzivane pro konstrukci fraktalu

    int              points=10000;                  // pocet vsech iteraci
    int              boxWidth=50;                   // sirka boxu
    int              boxHeight=11;                  // vyska boxu
    int              boxes=30;                      // pocet boxu generovanych v jednom radku
    int              pointShape=PointShape.OnePixel;// typ vykreslovanych bodu
    int              seedShape=SeedShape.OnePoint;  // tvar seminka
    int              filterType=FilterType.Cross3x3;// typ pouziteho filtru
    boolean          neighboorType=false;           // typ okoli pixelu

    // vytvoreni vsech panelu pouzitych v appletu
    ImagePanel  panelLeft=           new ImagePanel(ImageWidth, ImageHeight);
    ImagePanel  panelCenter=         new ImagePanel(ImageWidth, ImageHeight);
    Panel       panelUp=             new Panel(new GridLayout(2, 4, 5, 5));// horni panel s list-boxy
    Panel       panelDown=           new Panel(new GridLayout(2, 4, 5, 5));// dolni panel s posuvniky
    Panel       panelRight=          new Panel(new GridLayout(8, 1));// pravy panel s tlacitky

    // filtr aplikovany na zdrojovou pixmapu, vysledek je v cilove pixmape
    Filter filter=new Filter(ImageWidth, ImageHeight, panelLeft.pixels, panelCenter.pixels);

    // objekt, ve kterem je implementovan algoritmus difuze
    Diffuser diffuser=null;

    // vytvoreni vsech textovych navesti pouzitych v appletu
    Label       labelPointShape=        new Label("Point shape");
    Label       labelSeedShape=         new Label("Seed shape");
    Label       labelNeighbourHoodType= new Label("Neighbourhood type");
    Label       labelFilterType=        new Label("Filter");
    Label       labelPointsInBox=       new Label("Points in box: "+String.valueOf(points));
    Label       labelBoxWidth=          new Label("Box width: "+String.valueOf(boxWidth)+" px");
    Label       labelBoxHeight=         new Label("Box height: "+String.valueOf(boxHeight)+" px");
    Label       labelBoxesInRow=        new Label("Boxes in row: "+String.valueOf(boxes));

    // vytvoreni vsech list-boxu pouzitych v appletu
    Choice      choicePointShape=       new Choice();  // list-box pro vyber tvaru bodu
    Choice      choiceSeedShape=        new Choice();  // list-box pro vyber tvaru seminka
    Choice      choiceNeigbourhoodType= new Choice();  // list-box pro vyber okoli pixelu
    Choice      choiceStopCondition=    new Choice();  // list-box pro vyber koncove podminky
    Choice      choiceFilter=           new Choice();  // list-box pro vyber aktivniho filtru

    // vytvoreni vsech tlacitek pouzitych v appletu
    Button      buttonRedraw=           new Button("Redraw");
    Button      buttonRecalc=           new Button("Recalc");
    Button      buttonAbout=            new Button("About");
    Button      buttonInfo=             new Button("Info");
    Button      buttonHelp=             new Button("Help");

    // vytvoreni vsech slideru pouzitych v appletu
    Scrollbar   scrollBarPoints=        new Scrollbar(Scrollbar.HORIZONTAL, points, 1000, 100, 20000+1000);
    Scrollbar   scrollBarBoxWidth=      new Scrollbar(Scrollbar.HORIZONTAL, boxWidth, 20, 50, 270);
    Scrollbar   scrollBarBoxHeight=     new Scrollbar(Scrollbar.HORIZONTAL, boxHeight, 2, 2, 22);
    Scrollbar   scrollBarBoxesInRow=    new Scrollbar(Scrollbar.HORIZONTAL, boxes, 10, 10, 1000+10);



    // ------------------------------------------------------------------------
    // Tato metoda provede inicializaci horniho panelu s rolovacimi list-boxy.
    // Metoda je zavolana behem inicializace aplikace ci appletu.
    // ------------------------------------------------------------------------
    private void initPanelUp() {
        panelUp.setBackground(Color.white);         // nastaveni barvy pozadi

        panelUp.add(labelPointShape);               // pridani vsech textovych navesti
        panelUp.add(labelSeedShape);                // do horniho panelu
        panelUp.add(labelNeighbourHoodType);
        panelUp.add(labelFilterType);

        panelUp.add(choicePointShape);              // pridani vsech list-boxu
        panelUp.add(choiceSeedShape);
        panelUp.add(choiceNeigbourhoodType);
        panelUp.add(choiceFilter);

        // prace s list-boxem pointShape
        choicePointShape.setEnabled(true);          // naplneni list-boxu texty a povoleni list-boxu
        choicePointShape.add("1 pixel");
        choicePointShape.add("Cross 3x3 pixels");
        choicePointShape.add("X cross 3x3 pixels");
        choicePointShape.add("Diamond 3x3 pixels");
        choicePointShape.add("Block 3x3 pixels");
        choicePointShape.add("Cross 5x5 pixels");
        choicePointShape.add("X cross 5x5 pixels");
        choicePointShape.add("Diamond 5x5 pixels");
        choicePointShape.add("Block 5x5 pixels");
        choicePointShape.add("3 pixels horizontal");
        choicePointShape.add("5 pixels horizontal");
        choicePointShape.add("3 pixels vertical");
        choicePointShape.add("5 pixels vertical");
        choicePointShape.select(pointShape);        // vyber aktivni polozky z list-boxu
        choicePointShape.addItemListener(this);     // nastaveni zpracovani udalosti od list-boxu

        // prace s list-boxem NeighbourhoodType
        choiceNeigbourhoodType.setEnabled(true);    // naplneni list-boxu s typem okoli pixelu
        choiceNeigbourhoodType.add("4 pixels");
        choiceNeigbourhoodType.add("8 pixels");
        choiceNeigbourhoodType.select(0);           // vyber aktivni polozky z list-boxu
        choiceNeigbourhoodType.addItemListener(this);// nastaveni zpracovani udalosti od list-boxu

        // prace s list-boxem SeedShape
        choiceSeedShape.setEnabled(true);           // naplneni list-boxu texty a povoleni list-boxu
        choiceSeedShape.add("One point");
        choiceSeedShape.add("Two points");
        choiceSeedShape.add("Three points");
        choiceSeedShape.add("Four points");
        choiceSeedShape.add("Short bottom line");
        choiceSeedShape.add("Bottom line");
        choiceSeedShape.add("Square");
        choiceSeedShape.add("Border");
        choiceSeedShape.add("Small circle");
        choiceSeedShape.add("Normal circle");
        choiceSeedShape.add("Big circle");
        choiceSeedShape.select(seedShape);          // vyber aktivni polozky z list-boxu
        choiceSeedShape.addItemListener(this);      // nastaveni zpracovani udalosti od list-boxu

        // prace s list-boxem StopCondition
        choiceStopCondition.setEnabled(true);       // naplneni list-boxu texty a povoleni list-boxu
        choiceStopCondition.add("maxiter");
        choiceStopCondition.add("borders");
        choiceStopCondition.add("maxiter and borders");
        choiceStopCondition.add("maxiter or borders");
        choiceStopCondition.select(0);
        choiceStopCondition.addItemListener(this);  // nastaveni zpracovani udalosti od list-boxu

        // prace s list-boxem Filter
        choiceFilter.setEnabled(true);              // naplneni list-boxu texty a povoleni list-boxu
        choiceFilter.add("none");
        choiceFilter.add("2x2 smooth");
        choiceFilter.add("3x3 diamond");
        choiceFilter.add("3x3 cross");
        choiceFilter.add("3x3 X cross");
        choiceFilter.add("3x3 block");
        choiceFilter.add("5x5 diamond");
        choiceFilter.add("5x5 cross");
        choiceFilter.add("5x5 X cross");
        choiceFilter.add("5x5 block");
        choiceFilter.add("3 pixels horizontal");
        choiceFilter.add("5 pixels horizontal");
        choiceFilter.add("3 pixels vertical");
        choiceFilter.add("5 pixels vertical");
        choiceFilter.select(filterType);            // vyber aktivni polozky z list-boxu
        choiceFilter.addItemListener(this);         // nastaveni zpracovani udalosti od list-boxu
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede inicializaci dolniho panelu se slidery.
    // Metoda je zavolana behem inicializace aplikace ci appletu.
    // ------------------------------------------------------------------------
    private void initPanelDown() {
        panelDown.setBackground(Color.white);       // nastaveni barvy pozadi
        panelDown.add(labelPointsInBox);            // pridani vsech textovych navesti
        panelDown.add(labelBoxWidth);
        panelDown.add(labelBoxHeight);
        panelDown.add(labelBoxesInRow);
        panelDown.add(scrollBarPoints);             // pridani vsech slideru
        panelDown.add(scrollBarBoxWidth);
        panelDown.add(scrollBarBoxHeight);
        panelDown.add(scrollBarBoxesInRow);
        scrollBarBoxHeight.setBlockIncrement(1);    // nastaveni miry posuvu slideru
        scrollBarPoints.addAdjustmentListener(this);// nastaveni reakci na udalosti slideru
        scrollBarBoxWidth.addAdjustmentListener(this);
        scrollBarBoxHeight.addAdjustmentListener(this);
        scrollBarBoxesInRow.addAdjustmentListener(this);
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede nastaveni praveho panelu s tlacitky (buttony).
    // Metoda je zavolana behem inicializace aplikace ci appletu.
    // ------------------------------------------------------------------------
    private void initPanelRight() {
        panelRight.setBackground(Color.white);      // nastaveni barvy pozadi
        panelRight.add(buttonRecalc);               // pridani vsech textovych tlacitek
        panelRight.add(buttonRedraw);
        panelRight.add(new Label(""));              // volna polozka pro oddeleni tlacitek
        panelRight.add(buttonAbout);
        panelRight.add(buttonInfo);
        panelRight.add(buttonHelp);
        buttonRedraw.addActionListener(this);       // nastaveni reakce na udalosti od tlacitek
        buttonRecalc.addActionListener(this);
        buttonAbout.addActionListener(this);
        buttonInfo.addActionListener(this);
        buttonHelp.addActionListener(this);
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede inicializaci appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public void init() {
        this.setBackground(Color.white);            // nastaveni barvy pozadi
        setLayout(new BorderLayout(5,5));           // nastaveni layoutu aplikace
        initPanelUp();                              // nastavit horni panel
        initPanelDown();                            // nastavit dolni panel
        initPanelRight();                           // nastavit pravy panel
        add("North",  panelUp);                     // pridat horni panel do plochy aplikace
        add("South",  panelDown);                   // pridat dolni panel do plochy aplikace
        add("East",   panelRight);                  // pridat pravy panel do plochy aplikace
        add("Center", panelCenter);                 // pridat centralni panel do plochy aplikace
        add("West",   panelLeft);
    }



    // ------------------------------------------------------------------------
    // Tato metoda se zavola pri destrukci appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM)
    // ------------------------------------------------------------------------
    public void destroy() {
        remove(panelLeft);
        remove(panelRight);                         // zrusit pravy panel
        remove(panelUp);                            // zrusit horni panel
        remove(panelDown);                          // zrusit dolni panel
        remove(panelCenter);                        // zrusit centralni panel
    }



    // ------------------------------------------------------------------------
    // Tato metoda se zavola vzdy pri nastartovani appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public void start() {
    }



    // ------------------------------------------------------------------------
    // Tato metoda se zavola pri kazdem zastaveni appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public void stop() {
    }



    // ------------------------------------------------------------------------
    // Tato metoda se zavola pri nastartovani appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public void run() {
        repaint();                                  // prvotni vykresleni plochy appletu
    }



    // ------------------------------------------------------------------------
    // Tato metoda se zavola vzdy, kdyz je nutno prekreslit plochu appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public void update(Graphics g) {
        paint(g);                                   // povolit prekresleni appletu
    }



    // ------------------------------------------------------------------------
    // Tato metoda se zavola kdyz je potreba prekreslit applet.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public void paint(Graphics g) {
    }



    // ------------------------------------------------------------------------
    // Nastaveni vnitrnich okraju v okne appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public Insets getInsets() {
        return new Insets(5, 5, 5, 5);
    }



    // ------------------------------------------------------------------------
    // Tato metoda je zavolana v pripade, ze je stlaceno nektere tlacitko
    // umistene na plose appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public void actionPerformed(ActionEvent e) {
        Object o=e.getSource();                     // ktere tlacitko je stlaceno?
        if (o==buttonRedraw) {                      // ma se pouze prekreslit fraktal
            panelLeft.redraw(false);
            applyFilter();
            panelCenter.redraw(false);
        }
        if (o==buttonRecalc) {                      // prepocitani celeho fraktalu
            recalcFractal();
        }
        if (o==buttonAbout) {                       // text s informacemi o autorech
            if (!WindowAbout.visible) {
                WindowAbout window=new WindowAbout();
            }
        }
        if (o==buttonHelp) {                        // text s napovedou
            if (!WindowHelp.visible) {
                WindowHelp window=new WindowHelp();
            }
        }
        if (o==buttonInfo) {                        // text s informacemi o aplikaci
            if (!WindowInfo.visible) {
                WindowInfo window=new WindowInfo();
            }
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda je zavolana v pripade, ze je vybran prvek z list-boxu
    // umisteneho na plose appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public void itemStateChanged(ItemEvent e) {
        Object o=e.getSource();                     // ziskat informace, ktery list-box je zmenen
        if (o==choicePointShape) {
            pointShape=choicePointShape.getSelectedIndex();
        }
        if (o==choiceSeedShape) {
            seedShape=choiceSeedShape.getSelectedIndex();
        }
        if (o==choiceFilter) {                      // uzivatel zmenil filtr aplikovany na obrazek
            filterType=choiceFilter.getSelectedIndex();// ziskat index vybraneho filtru
            applyFilter();
            panelCenter.redraw(false);
        }
        if (o==choiceNeigbourhoodType) {            // uzivatel zmenil typ okoli pixelu
            neighboorType=(choiceNeigbourhoodType.getSelectedIndex()==1);
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda je zavolana v pripade, ze uzivatel zmenil polohu nektereho
    // posuvniku (slideru) umisteneho na plose appletu.
    // Metoda je volana z virtualniho stroje Javy (JVM).
    // ------------------------------------------------------------------------
    public void adjustmentValueChanged(AdjustmentEvent e) {
        Object o=e.getSource();                     // ziskat slider, ktery byl zmenen
        if (o==scrollBarPoints) {                   // zmena poctu bodu generovanych v boxu
            points=scrollBarPoints.getValue();      // ziskat pocet bodu
            labelPointsInBox.setText("Points: "+String.valueOf(points));
        }
        if (o==scrollBarBoxWidth) {                 // zmena sirky boxu
            boxWidth=scrollBarBoxWidth.getValue();  // ziskat novou hodnotu
            labelBoxWidth.setText("Box width: "+String.valueOf(boxWidth)+" px");
        }
        if (o==scrollBarBoxHeight) {                // zmena vysky boxu
            boxHeight=scrollBarBoxHeight.getValue();// ziskat novou hodnotu
            labelBoxHeight.setText("Box height: "+String.valueOf(boxHeight)+" px");
        }
        if (o==scrollBarBoxesInRow) {               // zmena poctu generovanych boxu
            boxes=scrollBarBoxesInRow.getValue();   // ziskat novou hodnotu
            labelBoxesInRow.setText("Boxes in row: "+String.valueOf(boxes));
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda zmeni aktualni filtr.
    // ------------------------------------------------------------------------
    public void applyFilter() {
        switch (filterType) {
            case FilterType.None:       filter.filterNone();       break; // zadny filtr
            case FilterType.Smooth2x2:  filter.filter2x2smooth();  break; // filtr typu 2x2 smooth
            case FilterType.Diamond3x3: filter.filter3x3diamond(); break; // filtr typu 3x3 diamond
            case FilterType.Cross3x3:   filter.filter3x3cross();   break; // filtr typu 3x3 cross
            case FilterType.XCross3x3:  filter.filter3x3Xcross();  break; // filtr typu 3x3 X cross
            case FilterType.Block3x3:   filter.filter3x3block();   break; // filtr typu 3x3 block
            case FilterType.Diamond5x5: filter.filter5x5diamond(); break; // filtr typu 5x5 diamond
            case FilterType.Cross5x5:   filter.filter5x5cross();   break; // filtr typu 5x5 cross
            case FilterType.XCross5x5:  filter.filter5x5Xcross();  break; // filtr typu 5x5 X cross
            case FilterType.Block5x5:   filter.filter5x5block();   break; // filtr typu 5x5 block
            case FilterType.Horizontal3:filter.filter3pixelsH();   break; // filtr typu 3 pixels horizontal
            case FilterType.Horizontal5:filter.filter5pixelsH();   break; // filtr typu 5 pixels horizontal
            case FilterType.Vertical3:  filter.filter3pixelsV();   break; // filtr typu 3 pixels vertical
            case FilterType.Vertical5:  filter.filter5pixelsV();   break; // filtr typu 5 pixels vertical
            default:                                               break; // tato volba by nemela nikdy nastat
        }
    }



    // ------------------------------------------------------------------------
    // Tato metoda provede prepocet fraktalu.
    // ------------------------------------------------------------------------
    private void recalcFractal() {
        if (diffuser!=null) {
            if (diffuser.isAlive())
                return;
        }
        diffuser=new Diffuser();                // vytvorit diffuser
        diffuser.setPixels(panelLeft.pixels);   // nastavit jeho parametry
        diffuser.setSize(ImageWidth, ImageHeight);
        diffuser.setMaxPoints(points);
        diffuser.setBoxWidth(boxWidth);
        diffuser.setBoxHeight(boxHeight);
        diffuser.setBoxesInRow(boxes);
        diffuser.setPointShape(pointShape);
        diffuser.setSeedShape(seedShape);
        diffuser.setNeighbourhoodType(neighboorType);
        diffuser.setObject(this);
        diffuser.start();                       // a spustit ho
    }



    /*
    // -----------------------------------------------------------------------
    // Metoda main, ktera neni v appletu vyuzita.
    // Muze se definovat v pripade, ze se ma vytvorit samostatne spustitelna
    // aplikace interpretovana virtualnim strojem jazyja Java, nikoli applet.
    // V tomto pripade se vsak vytvori dalsi soubor .class s anonymni tridou
    // se jmenem Listener.
    // -----------------------------------------------------------------------
    public static void main(String[] args) {
        Frame frame=new Frame("Diffuse4");
        Applet applet=new Diffuse4();
        frame.add(applet);
        applet.init();
        frame.setSize(640, 480);
        frame.setVisible(true);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
            }
        );
    }
    */
}
// ----------------------------------------------------------------------------
// Konec tridy Diffuse4.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// Trida, ve krere je implementovan algoritmus simulace difuze.
// ----------------------------------------------------------------------------
class Diffuser extends Thread {
    Frame      frame=null;                          // okno pro vypis prubehu prace
    Label      label=null;                          // do tohoto labelu se bude provadet vypis
    int        pixelSrc[];                          // pixmapa pro vykreslovani
    int        width;                               // velikost pixmapy
    int        height;
    int        boxWidth;                            // velikost boxu, ve kterem se body generuji
    int        boxHeight;
    int        maxPoints;                           // max. pocet bodu
    int        pointShape;                          // typ vykreslovych bodu
    int        seedShape;                           // tvar seminka
    int        boxesInRow;                          // pocet boxu generovanych v jednom radku
    boolean    neighboorType;                       // typ okoli pixelu
    boolean    pixels[][];                          // pomocna mrizka, ve ktere se bude generovat
    Diffuse4   object;                              // objekt s panely, do kterych se kresli



    // -----------------------------------------------------------------------
    // Konstruktor, ve kterem se nastavi vhodne implicitni hodnoty.
    // -----------------------------------------------------------------------
    public Diffuser() {
        pixelSrc=null;
        width=height=100;
        maxPoints=10000;
        pointShape=seedShape=0;
        boxesInRow=30;
        neighboorType=false;
        pixels=null;
    }



    // -----------------------------------------------------------------------
    // Nastaveni pixmapy, do ktere se bude provadet vykreslovani
    // -----------------------------------------------------------------------
    public void setPixels(int pixels[]) {
        pixelSrc=pixels;
    }



    // -----------------------------------------------------------------------
    // Nastaveni rozmeru generovane pixmapy.
    // -----------------------------------------------------------------------
    public void setSize(int width, int height) {
        this.width=width;
        this.height=height;
    }



    // -----------------------------------------------------------------------
    // Nastaveni maximalniho poctu bodu v pixmape.
    // -----------------------------------------------------------------------
    public void setMaxPoints(int maxPoints) {
        this.maxPoints=maxPoints;
    }



    // -----------------------------------------------------------------------
    // Zmena sirky boxu.
    // -----------------------------------------------------------------------
    public void setBoxWidth(int boxWidth) {
        this.boxWidth=boxWidth;
    }



    // -----------------------------------------------------------------------
    // Zmena vysky boxu.
    // -----------------------------------------------------------------------
    public void setBoxHeight(int boxHeight) {
        this.boxHeight=boxHeight;
    }



    // -----------------------------------------------------------------------
    // Nastaveni poctu boxu, ktere jsou generovane v jednom radku.
    // -----------------------------------------------------------------------
    public void setBoxesInRow(int boxesInRow) {
        this.boxesInRow=boxesInRow;
    }



    // -----------------------------------------------------------------------
    // Nastaveni typu okoli pixelu, na kterem se provadi testy.
    // -----------------------------------------------------------------------
    public void setNeighbourhoodType(boolean neighboorType) {
        this.neighboorType=neighboorType;
    }



    // -----------------------------------------------------------------------
    // Nastaveni tvaru, ktery se bude ukladat do pracovni bitmapy.
    // -----------------------------------------------------------------------
    public void setPointShape(int pointShape) {
        this.pointShape=pointShape;
    }



    // -----------------------------------------------------------------------
    // Nastaveni seminka - pocatecnich bodu fraktalniho obrazce.
    // -----------------------------------------------------------------------
    public void setSeedShape(int seedShape) {
        this.seedShape=seedShape;
    }



    // -----------------------------------------------------------------------
    // Predani reference hlavniho GUI objektu.
    // -----------------------------------------------------------------------
    public void setObject(Diffuse4 o) {
        object=o;
    }



    // -----------------------------------------------------------------------
    // Vytvoreni a zobrazeni pomocneho okna, ve kterem se zobrazuje prubeh prace.
    // -----------------------------------------------------------------------
    private void prepareGUI() {
        frame=new Frame("Computing diffuse");
        label=new Label("Points:");
        frame.add(label);
        label.setAlignment(Label.CENTER);           // vlastnosti napisu
        label.setVisible(true);
        frame.setSize(200, 100);                    // vlastnosti okna
        frame.setVisible(true);
    }



    // -----------------------------------------------------------------------
    // Tato metoda se zavola po dokonceni generovani fraktalu.
    // -----------------------------------------------------------------------
    private void finishGUI() {
        label.setText("Filtering bitmaps");
        object.panelLeft.redraw(false);
        object.applyFilter();                       // aplikace filtru na bitmapu
        object.panelCenter.redraw(false);
        frame.setVisible(false);                    // a zruseni pomocneho okna
        frame.dispose();
    }



    // -----------------------------------------------------------------------
    // Vytvoreni a inicializace pomocneho pole - plosne mrizky.
    // -----------------------------------------------------------------------
    private void initBitmap() {
        pixels=new boolean[height][width];
        for (int j=0; j<height; j++) {
            for (int i=0; i<width; i++) {
                pixels[j][i]=false;                 // vsechny pixely nastavit
            }                                       // na stejnou hodnotu false
        }
    }



    // -----------------------------------------------------------------------
    // Kopie dat z pomocne bitmapy do pixmapy, ktera se bude zobrazovat.
    // -----------------------------------------------------------------------
    private void copyBitmapToPixmap() {
        int pos=0;
        for (int j=0; j<height; j++) {
            for (int i=0; i<width; i++) {           // pixel je bud cerny nebo bily
                pixelSrc[pos]=pixels[j][i] ? 0xff000000: 0xffffffff;
                pos++;                              // index do cilove pixmapy
            }
        }
    }



    // -----------------------------------------------------------------------
    // Inicializace seminka - pocatecnich bodu ve fraktalnim objektu.
    // -----------------------------------------------------------------------
    private void initSeed() {
        int wh=width/2;
        int hh=height/2;
        int wh1=width/3;
        int wh2=2*width/3;
        int hh2=2*height/3;
        switch (seedShape) {
            case SeedShape.OnePoint:                // generuje se pouze jeden bod
                pixels[height-1][wh]=true;
                break;
            case SeedShape.TwoPoints:               // generuji se dva symetricky postavene body
                pixels[height-1][wh1]=true;
                pixels[height-1][wh2]=true;
                break;
            case SeedShape.ThreePoints:             // generuji se tri symetricky postavene body
                pixels[height-1][wh]=true;
                pixels[height-1][wh1]=true;
                pixels[height-1][wh2]=true;
                break;
            case SeedShape.FourPoints:              // generuji se ctyri
                pixels[height-1][width/5]=true;     // symetricky postavene body
                pixels[height-1][2*width/5]=true;
                pixels[height-1][3*width/5]=true;
                pixels[height-1][4*width/5]=true;
                break;
            case SeedShape.ShortBottomLine:         // generuje se kontiualni
                for (int i=wh1; i<=wh2; i++)        // usecka uprostred bitmapy
                    pixels[height-1][i]=true;
                break;
            case SeedShape.BottomLine:              // usecka na spodnim okraji bitmapy
                for (int i=0; i<width; i++)
                    pixels[height-1][i]=true;
                break;
            case SeedShape.Square:                  // ctverec v dolni casti bitmapy
                for (int i=wh1; i<=wh2; i++) {
                    pixels[hh2][i]=true;
                    pixels[height-1][i]=true;
                }
                for (int i=hh2; i<=height-1; i++) {
                    pixels[i][wh1]=true;
                    pixels[i][wh2]=true;
                }
                break;
            case SeedShape.Border:                  // generuje se okraj z pixelu
                for (int i=0; i<width; i++) {       // okolo cele bitmapy
                    pixels[0][i]=true;
                    pixels[height-1][i]=true;
                }
                for (int i=0; i<height; i++) {
                    pixels[i][0]=true;
                    pixels[i][width-1]=true;
                }
                break;
            case SeedShape.SmallCircle:             // mala kruznice uprostred bitmapy
                {
                double r=wh/4.0;
                for (int i=0; i<1000; i++) {
                    double x=wh+r*Math.cos((double)i);
                    double y=height-r-1+r*Math.sin((double)i);
                    pixels[(int)y][(int)x]=true;
                }
                pixels[height-1][wh]=true;          // pro jistotu (zaokrouhleni) zapsat i nejspodnejsi bod
                }
                break;
            case SeedShape.NormalCircle:            // kruznice uprostred bitmapy
                {
                double r=wh/2.0;
                for (int i=0; i<1000; i++) {
                    double x=wh+r*Math.cos((double)i);
                    double y=height-r+r*Math.sin((double)i);
                    pixels[(int)y][(int)x]=true;
                }
                pixels[height-1][wh]=true;          // pro jistotu (zaokrouhleni) zapsat i nejspodnejsi bod
                }
                break;
            case SeedShape.BigCircle:               // velka kruznice uprostred bitmapy
                {
                double r=wh-9.0;
                for (int i=0; i<1000; i++) {
                    double x=wh+r*Math.cos((double)i);
                    double y=height-r+r*Math.sin((double)i);
                    pixels[(int)y][(int)x]=true;
                }
                pixels[height-1][wh]=true;          // pro jistotu (zaokrouhleni) zapsat i nejspodnejsi bod
                }
                break;
            default:
                pixels[hh][wh]=true;
                break;
        }
    }



    // -----------------------------------------------------------------------
    // Tato metoda vrati hodnotu true, pokud se v okoli pixelu vyskytuje
    // pixel, jez nalezi do vytvareneho fraktalniho objektu.
    // -----------------------------------------------------------------------
    private boolean neighboor(boolean type, int i, int j) {
        return type ?
               pixels[j-1][i-1] |                   // osmiokoli pixelu
               pixels[j-1][i]   |
               pixels[j-1][i+1] |
               pixels[j][i-1]   |
               pixels[j][i+1]   |
               pixels[j+1][i-1] |
               pixels[j+1][i]   |
               pixels[j+1][i+1]
               :
               pixels[j-1][i]   |                   // ctyrokoli pixelu
               pixels[j][i-1]   |
               pixels[j][i+1]   |
               pixels[j+1][i]
               ;
    }



    // -----------------------------------------------------------------------
    // Vykresleni bodu -jednoho pixelu ci nekolika pixelu - do temporalni
    // bitmapy (plosne rastrove bitove mrizky) podle zvoleneho tvaru.
    // -----------------------------------------------------------------------
    private void putPoint(int x, int y) {
        if (x<3) x=3;                               // zabranit zapisum
        if (x>=width-3) x=width-4;                  // mimo pole
        if (y<3) y=3;
        if (y>=height-3) y=height-3;
        if (pointShape!=PointShape.Diamond3x3 &&    // krome dvou specialnich tvaru
            pointShape!=PointShape.Diamond5x5) {
            pixels[y][x]=true;                      // vykreslit prostredni pixel
        }
        if (pointShape==PointShape.Cross3x3 ||
            pointShape==PointShape.Diamond3x3 ||
            pointShape==PointShape.Block3x3 ||
            pointShape==PointShape.Cross5x5 ||
            pointShape==PointShape.Block5x5 ||
            pointShape==PointShape.Horizontal3 ||
            pointShape==PointShape.Horizontal5) {
            pixels[y][x-1]=true;                    // pixel nalevo
            pixels[y][x+1]=true;                    // pixel napravo
        }
        if (pointShape==PointShape.Horizontal5 ||
            pointShape==PointShape.Cross5x5 ||
            pointShape==PointShape.Diamond5x5 ||
            pointShape==PointShape.Block5x5) {
            pixels[y][x-2]=true;                    // druhy pixel nalevo
            pixels[y][x+2]=true;                    // druhy pixel napravo
        }
        if (pointShape==PointShape.Cross3x3 ||
            pointShape==PointShape.Diamond3x3 ||
            pointShape==PointShape.Block3x3 ||
            pointShape==PointShape.Cross5x5 ||
            pointShape==PointShape.Block5x5 ||
            pointShape==PointShape.Vertical3 ||
            pointShape==PointShape.Vertical5) {
            pixels[y-1][x]=true;                    // pixel nahore
            pixels[y+1][x]=true;                    // pixel dole
        }
        if (pointShape==PointShape.Vertical5 ||
            pointShape==PointShape.Cross5x5 ||
            pointShape==PointShape.Diamond5x5 ||
            pointShape==PointShape.Block5x5) {
            pixels[y-1][x]=true;                    // druhy pixel nahore
            pixels[y+1][x]=true;                    // druhy pixel dole
        }
        if (pointShape==PointShape.XCross3x3 ||
            pointShape==PointShape.Block3x3 ||
            pointShape==PointShape.XCross5x5 ||
            pointShape==PointShape.Diamond5x5 ||
            pointShape==PointShape.Block5x5) {
            pixels[y-1][x-1]=true;                  // diagonalni pixely
            pixels[y+1][x-1]=true;
            pixels[y-1][x+1]=true;
            pixels[y+1][x+1]=true;
        }
        if (pointShape==PointShape.XCross5x5 ||
            pointShape==PointShape.Block5x5) {
            pixels[y-2][x-2]=true;                  // diagonalni pixely
            pixels[y+2][x-2]=true;                  // ve vzdalenosti 2
            pixels[y-2][x+2]=true;
            pixels[y+2][x+2]=true;
        }
        if (pointShape==PointShape.Block5x5) {
            pixels[y-2][x-1]=true;
            pixels[y+2][x-1]=true;
            pixels[y-2][x+1]=true;
            pixels[y+2][x+1]=true;
            pixels[y-1][x-2]=true;
            pixels[y+1][x-2]=true;
            pixels[y-1][x+2]=true;
            pixels[y+1][x+2]=true;
        }
    }



    // -----------------------------------------------------------------------
    // Tato metoda provadi vlastni aplikaci ctvrteho algoritmu difuze, jez je
    // zalozen na postupne zmene polohy posuvneho boxu.
    // -----------------------------------------------------------------------
    private void applyDiffuse() {
        boolean  doneInnerLoop;                     // priznak ukonceni vnitrni smycky
        int      counter=0;                         // pocet pruchodu vnejsi smyckou
        int      points=0;                          // pocet vytvorenych bodu
        int      xi, yi;                            // pocatecni pozice posuvneho boxu
        int      x, y;                              // relativni souradnice bodu uvnitr boxu
        int      i, j, d;                           // pocitadla vnitrnich smycek

        // posuvny box postupne projde vsemi radky v pomocne rastrove mrizce
        // s temporalni bitmapou
        for (yi=height-boxHeight-1; yi>10; yi--) {  // postupna zmena polohy posuvneho boxu
            for (d=0; d<50; d++) {                  // smycka, ve ktere se vytvari sub-boxy
                xi=(int)(Math.random()*(double)(width-boxWidth-2)+1);
                i=0;
                j=0;
                do {
                    x=(int)(Math.random()*(double)(boxWidth));  // vypocet relativnich souradnic
                    y=(int)(Math.random()*(double)(boxHeight)); // bodu uvnitr posuvneho boxu
                    if (neighboor(neighboorType, xi+x, yi+y)) {
                        putPoint(x+xi, y+yi);       // pridat novy bod ke stavajicimu objektu
                        i++;
                        points++;
                        break;
                    }
                    j++;
                    if (j>maxPoints) break;         // po zadanem poctu bodu ukoncit vnitrni smycku
                } while (i<boxesInRow);             // kontrola maximalniho poctu vytvorenych sub-boxu
                counter++;
                if (counter==50) {                  // prubezny vypis prace programu
                    label.setText("Points: "+String.valueOf(points)+"  y: "+String.valueOf(yi));
                    counter=0;
                }                                   // end if
            }                                       // end for point
        }                                           // end for
    }



    // -----------------------------------------------------------------------
    // Funkce, ktera rozbehne cele vypocetni vlakno.
    // -----------------------------------------------------------------------
    public void run() {
        prepareGUI();                               // vytvoreni vsech GUI prvku
        label.setText("Initializing");
        initBitmap();                               // inicializace bitmapy
        initSeed();                                 // inicializace seminka
        applyDiffuse();                             // aplikace algoritmu difuze
        label.setText("Finishing");
        copyBitmapToPixmap();                       // kopie pracovni bitmapy do vysledne pixmapy
        finishGUI();                                // fitrace a zavreni pomocneho okna
    }
}
// ----------------------------------------------------------------------------
// Konec tridy Diffuser.
// ----------------------------------------------------------------------------



// ----------------------------------------------------------------------------
// finito
// ----------------------------------------------------------------------------