Using the Algoritharium libraries in your programs.

To access it, put algoritharium.jar in the same directory as the program you are writing (Right-click and select Save Target As...). Then, compile and execute as follows.

OS X / Linux
------------
% javac -cp .:algoritharium.jar MyImageAlgorithms.java
% java  -jar algoritharium.jar

Windows
------------
% javac -cp .;algoritharium.jar MyImageAlgorithms.java
% java  -jar algoritharium.jar

The -cp flag sets the classpath. The . tells Java to look in the current directory for .java and .class files (such as MyImageAlgorithms.java and MyImageAlgorithms.class). On OS X, the : separates directories in the classpath; on Windows the ; separates directories.

  1.  Modify a single pixel in an image: Write your first image processing code. For example create a class named MyImageAlgorithms with the method oneRedDot as shown below. Compile your saved code using the javac tool.

    import  algoritharium.*;
    import java.awt.Color;

    public class MyImageAlgorithms {
       public void oneRedDot ( ) {
          Image img = ImageViewer.getImage( ) ;
          img.setPixelColor(20, 20, Color .RED) ;
       }
    }
     

    Run the Algoritharium program using  the java tool or double click on the jar file.

    1. Select File-New to get a small yellow image.
    2. Select Code-Load, navigate to and open your MyImageAlgorithms.class file in the file chooser window.
    3. Select MyOps-oneRedDot.
     
  2. Modify several adjacent pixels in one row of the image: Add another method to your MyImageAlgorithms class definition called manyRedDots

    public void manyRedDots ( ) {
          Image img = ImageViewer.getImage( ) ;
          img.setPixelColor(20, 20, Color .RED) ;
          img.setPixelColor(21, 20, Color .RED) ;
          img.setPixelColor(22, 20, Color .RED) ;
          img.setPixelColor(23, 20, Color .RED) ;
    }
     

    Save and compile your program.

    1. Select Code-Reload.
    2. Select MyOps-manyRedDots
       
  3. Use iteration to modify several adjacent pixels in one row of the image: Add another method to your MyImageAlgorithms class definition called loopRedDots

    public void loopRedDots ( ) {
          Image img = ImageViewer.getImage( ) ;
          for(int i = 20; i <= 23; i++)
             img.setPixelColor(i, 20, Color .RED);
    }
     

    Save and compile your program.

    1. Select File-New to get a clean yellow image
    2. Select Code-Reload.
    3. Select MyOps-loopRedDots
       
  4. Make entire image red: Add another method to your MyImageAlgorithms class definition called turnImageRed

    public void turnImageRed ( ) {
          Image img = ImageViewer.getImage( ) ;
          for(int i = 0; i < img.getWidth(); i++)
             for(int j = 0; j < img.getHeight(); j++)
                img.setPixelColor(i, j, Color .RED);
    }
     

    Save and compile your program.

    1. Select Code-Reload.
    2. Select MyOps-turnImageRed
       
  5. Red/green checkerboard: Add two methods to your MyImageAlgorithms class definition called redGreenCheckerboard and changeColor

    public void redGreenCheckerboard ( ) {
       Image img = ImageViewer.getImage( ) ;
       Color[][] c = img.getPixelColors();
       Color currentColor = Color.red;
       for (int i = 0; i < c.length; i++) {
          if (i %20 == 0) currentColor = changeColor(currentColor);
          for (int j = 0; j < c[i].length; j++) {
             if (j %20 == 0) currentColor = changeColor(currentColor);
             c[i][j] = currentColor;
          }
       }
       img.setPixelColors(c);
    }

    public Color changeColor (Color c ) {
          if (c == Color.GREEN)
             return Color.red;
          else
             return Color.green;
    }
     

    Save and compile your program.

    1. Select Code-Reload.
    2. Select MyOps-redGreenCheckerboard
       
  6. Implement a red filter: Add another method to your MyImageAlgorithms class definition called redFilter

    public void redFilter ( ) {
          Image img = ImageViewer.getImage( ) ;
          Color c1, c2;

          for(int i = 0; i < img.getWidth(); i++)
             for(int j = 0; j < img.getHeight(); j++) {
                c1 = img.getPixelColor (i, j);
                c2 = new Color (c1.getRed(), 0, 0);
                img.setPixelColor(i, j, c2);
             }  
    }
     

    Save and compile your program.

    1. Select Code-Reload.
    2. Select MyOps-redFilter
    3. For a more stunning effect save MtCastle.ppm (Right-click and select Save Target As...)
    4. Select File-Open, then select and open MtCastle in your viewer, then apply redFilter
     
  7. Image algorithms involving multiple images: Add another method to your MyImageAlgorithms class definition called multipleImages
    A more robust approach to multiple images involves using the  viewer ID. Here we open a new image viewer using the current viewer's image as the source for our target image viewer. In this way we can manipulate the target image and see the differences between the original (source) image and modified (target) image. Note: Selecting File-Exit will shutdown that image viewer, but clicking on the red X in the corner of any image viewer opened in the same session will shutdown all of the viewers.

    public void multipleImages()  {

          Image source = ImageViewer.getImage();

          ImageViewer iv = new ImageViewer();

          ImageViewer.setImage(iv.getViewerId(), source);

          Image target = ImageViewer.getImage(iv.getViewerId());

          Color[][] c = source.getPixelColors();

          //Some code to modify c

          target.setPixelColors(c);
    }


    Save and compile your program.

    1. Select File-New or File-Open to place an image in the viewer
    2. Select Code-Reload.following each modification to your compiled source code
    3. Select MyOps-multipleImages
     
  8. Image algorithms involving multiple images and include an update to the Title Bar: Add another method to your MyImageAlgorithms class definition called removeOneOfRGB. Here we create multiple images using the  viewer ID. Additionally, the title bar is updated in the instanctiated image viewers keeping the Viewer ID while adding additional information regarding the average of the red, green, and blue pixel intensities across the entire image in the title bar.

    public void removeOneOfRGB() {
       Image source = ImageViewer.getImage();
       ImageViewer ivR = new ImageViewer();
       ImageViewer ivG = new ImageViewer();
       ImageViewer ivB = new ImageViewer();
       ImageViewer.setImage(ivR.getViewerId(), source);
       ImageViewer.setImage(ivG.getViewerId(), source);
       ImageViewer.setImage(ivB.getViewerId(), source);

       removeImageRed(ImageViewer.getImage(ivR.getViewerId()));
       removeImageGreen(ImageViewer.getImage(ivG.getViewerId()));
       removeImageBlue(ImageViewer.getImage(ivB.getViewerId()));

       int[] data = pixelIntensities(ImageViewer.getImage(ivR.getViewerId()).getPixelColors());
       ivR.setTitle(ivR.getTitle()+ " - Red removed - R:"+data[0]+" G:"+data[1]+" B:"+data[2]);

       data = pixelIntensities(ImageViewer.getImage(ivG.getViewerId()).getPixelColors());
       ivG.setTitle(ivG.getTitle()+ " - Green removed - R:"+data[0]+" G:"+data[1]+" B:"+data[2]);

       data = pixelIntensities(ImageViewer.getImage(ivB.getViewerId()).getPixelColors());
       ivB.setTitle(ivB.getTitle()+ " - Blue removed - R:"+data[0]+" G:"+data[1]+" B:"+data[2]);
    }
    private int[] pixelIntensities(Color[][] c) {
       int p, r, g, b, w, h, sumR, sumG, sumB;
       int[] rGBSignature = new int[3];
       w = c[0].length;
       h = c.length;

       for (int x = 0; x < w; x++) {
          sumR = sumG = sumB = 0;

          for (int y = 0; y < h; y++) {
             p = c[y][x].getRGB();
             r = (p >> 16) & 0xff;
             g = (p >> 8) & 0xff;
             b = (p & 0xff);
             sumR += r;
             sumG += g;
             sumB += b;
          }

          rGBSignature[0]+=sumR/h;
          rGBSignature[1]+=sumG/h;
          rGBSignature[2]+=sumB/h;
       }

       rGBSignature[0]/=w;
       rGBSignature[1]/=w;
       rGBSignature[2]/=w;

       return rGBSignature;
    }

  9. Collecting user input: An easy way to collect user input while the program is running is to use the Scanner class. This works if your MyImageAlgorithms has a main method that launches a viewer per the previous step. Here is a sample function that copies a rectangle in one image and places it in another. This code depends on the user to duplicate the ImageViewer and open an image in each.

    public void copyRectangle() {
       Scanner s = 
    new Scanner(System.in);
       System.
    out.println("Enter top left x:");
       
    int startX = s.nextInt();
       System.
    out.println("Enter top left y:");
       int startY = s.nextInt();
       System.
    out.println("Enter bottom right x:");
       
    int endX = s.nextInt();
       System.
    out.println("Enter bottom right y: ");
       
    int endY = s.nextInt();
       Image srcImg = ImageViewer.getImage(2);
       Image destImg = ImageViewer.getImage();
       Color[][] c = srcImg.getRectangle(startX, startY, endX - startX, endY- startY);
       System.
    out.println("Enter destination top left x:");
       
    int destX = s.nextInt();
       System.
    out.println("Enter destinatino top left y:");
       
    int destY = s.nextInt();
       destImg.setRectangle(destX, destY, c);
    }

    My program runs out of memory, but my system should have more than enough. What's going on?  The java heap is the area of RAM reserved for use by the Java virtual machine. You can specifically ask for more (assuming your system has enough) with the following command:
    % java -Xmx300m -Xms300m -jar algoritharium.jar

    In this case, we are asking for 300 MB of memory (note no space between the switch and size and correct units are none for bytes,  k for kilobytes,  m for megabytes,M for megabytes, or g for gigabytes.) The -Xmx sets the maximum heap size, the -Xms flag sets the initial heap size. The operating system determines whether physical ram or paging will be used to achieve the requested memory.