// Written by Albert Lilly
// Alabama School of Mathematics and Science
// email: lilly@olympus.asms.state.k12.al.us
// For presentation at Supercomputing '96

import java.applet.*;
import java.awt.*;
import java.awt.image.*;
public class Snail extends Applet{
        static Image img; // The image to be analyzed
// Set up storage for 256 color values and the corresponding
//      number of pixels with the same color value
        static int[][] NumberofColors = new int[256][2]; 
        static int pointer = 0;  // Points to colors
        static boolean once = true; // Show the results only once
// Get the image
        public void init() {
                String value = this.getParameter("GIF");
                img = this.getImage(this.getDocumentBase(),value);
        }
// Set up the screen
        public void paint(Graphics g) {
                g = this.getGraphics();
                g.drawImage(img,0,0,this);
        }
// Return the width of the image
        public int analyzeWidth()  {
                return img.getWidth(this);
        }
// Return the height of the image
        public int analyzeHeight()  {
                return img.getHeight(this);
        }
// Show the results
        public void update(Graphics g) {
        if (once) {
        int width; // The width of the image
        int height; // The height of the image
// Draw the snail shell bitmap     
                paint(g);
// Get the width and height of the image
                width = analyzeWidth();
                height = analyzeHeight();
// Analyze the pixels
                handlepixels(img,0,0,width,height,g);
                for (int i = 0; i < pointer; i++) {
                g.setColor(Color.black);
                g.drawString(Integer.toString((NumberofColors[i][0]*100+50)/
                            (width*height))+"%",width+60,30+50*i);
// Translate the 24-bit color into red, green, and blue components
                Color temp = new Color(
                                ((NumberofColors[i][1] << 8) >>> 24),
                                ((NumberofColors[i][1] << 16) >>> 24),
                                ((NumberofColors[i][1] << 24) >>> 24));
                g.setColor(temp);
                g.fillRect(width + 100 , 5 + 50 * i, 
                        NumberofColors[i][0]/10, 40 );
                }
// Stop processing
                once = false;
             System.exit(0);
            }               
        }
// Get, sort, and count the pixel values
public void handlepixels(Image img2, int x, int y, int w, int h,
                        Graphics g) {
        int[] pixels = new int[w * h]; // Used to get the pixel values
        int[] sort = new int[w * h];   // Used for sorting the pixel values
// Get the pixel values
        PixelGrabber pg = new PixelGrabber(img2, x, y, w, h, pixels, 0, w);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
            System.err.println("interrupted waiting for pixels!");
            return;
        }
        if ((pg.status() & ImageObserver.ABORT) != 0) {
            System.err.println("image fetch aborted or errored");
            return;
        }
// Put the values in an array
        int count = 0;
        for (int j = 0; j < h; j++) {
            for (int i = 0; i < w; i++) {
                  sort[count] = pixels[j * w + i];
                  count = count + 1;
            }
        }

        int temp;
        g.setColor(Color.black);
        g.drawString("Pixels to process : " ,w+100,165);
        g.drawString("" + (w*h),w+220,165);
        g.drawString("Processing pixel #: ",w+100,185);
// Sort the values
        for (int j = 0; j < (w * h); j++) {
          g.setColor(Color.white);
          g.drawString(Integer.toString(j),w+220,185);
          g.setColor(Color.black);
          g.drawString(Integer.toString(j+1),w+220,185);
            for (int i = (w * h - 1); i > j; i--) {
                if(sort[i - 1] < sort[i])
                {
                 temp = sort[i - 1];
                 sort[i - 1] = sort[i];
                 sort[i] = temp;
                }
            }
        }
// Count the sorted pixel values
            count = 0;  // Used to count the pixels with a given color value
            for (int i = 1; i < (w * h); i++) {
                if(sort[i - 1] == sort[i])
                 count = count + 1;
                else
                  {
                  count = count + 1;
                  NumberofColors[pointer][0] = count;
                  NumberofColors[pointer][1] = sort[i - 1];
                  pointer = pointer + 1;
                  count = 0;
                  }
            }
                  count = count + 1;
                  NumberofColors[pointer][0] = count;
                  NumberofColors[pointer][1] = sort[w * h - 1];
                  pointer = pointer + 1;
        }
}


