Java InputStream mark() and reset()

You can use the method mark to mark a position in the inputstream and the method reset to return to that mark. It allows you to read ahead in the inputstream to determine what to do next. The mark method accepts an limit (integer), which denotes the maximum number of bytes that are to be read ahead. If you read more than this limit, you cannot return to this mark.
Before you can use the mark and reset, you need to test out whether these operations are supported on the inputstream you’re reading off. You can do that with markSupported.

The following program reads in a file once and the second half of the file again using the same inputstream.

Main.java:

import java.io.*;
  
public class Main {
   public static void main(String args[]) throws Exception {
      if (args.length != 1) {
         System.err.println("Usage: java Main <file.txt>");
         System.exit(1);
      }
 
      File file = new File(args[0]);
      BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
      if (bis.markSupported()) {
         int b, count=0;
         int half = (int) file.length() / 2;
         System.out.println("Complete file:");
         while ((b = bis.read()) > 0) {
            System.out.print((char) b);
            if (++count == half+1) 
               bis.mark(half);
         }
 
         System.out.println("---------------------------");
 
         bis.reset();
 
         System.out.println("Read in second half of file again:");
         while ((b = bis.read()) > 0) {
            System.out.print((char) b);
         }
      }
   }

To read-ahead, you can also use the PushBackInputStream.

Performance gain of a BufferedInputStream over an InputStream

IO happens a lot faster if you wrap your original InputStream using BufferedInputStream. Internally, it uses a default buffer size of 2048 bytes. For example, wrapping a FileInputStream in a BufferedInputStream will result in a significant performance gain.

Main.java:

import java.io.*;
  
public class Main {
   public static void main(String args[]) {
      if (args.length != 1) {
         System.err.println("Usage: java Main <file.txt>");
         System.exit(1);
      }
 
      long start1 = System.currentTimeMillis();
      readFileIS(args[0]);
      long end1 = System.currentTimeMillis();
      System.out.println("Reading using FileInputStream: " + (end1 - start1) + " ms.");
  
      long start2 = System.currentTimeMillis();
      readFileBIS(args[0]);
      long end2 = System.currentTimeMillis();
      System.out.println("Reading using BufferedInputStream: " + (end2 - start2) + " ms.");
   }  
 
   public static void readFileIS(String filename) {
      try {
         FileInputStream fis = new FileInputStream(filename);
         while (fis.read() > 0) ;
      }
      catch(Exception e) {
         System.err.println(e);
         System.exit(1);
      }
   }
 
   public static void readFileBIS(String filename) {
      try {
         BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename));
         while (bis.read() > 0) ;
      }
      catch(Exception e) {
         System.err.println(e);
         System.exit(1);
      }
   }
}

Make the speaker beep in Java

The first example simply beeps the speaker through an ASCII code:

public class Main {
   public static void main(String args[]) {
      System.out.print("7");
      System.out.flush();
   }
}

The second example makes use of the AWT Toolkit’s method beep. Note that even though we only use the AWT to make a beep, it automatically creates a non-daemon thread that keeps the program alive when it reaches the end of the main method. This is why there is a call to System.exit.

import java.awt.*;
 
public class beep {
   public static void main(String args[]) {
      Toolkit.getDefaultToolkit().beep();     
      System.exit(1);
   }
}

Use double-buffering for animation in Swing

Look at the performance between these two examples. The first one (Main1.java) will directly write to the graphics context and results in lots of flickering. The second one (Main2.java) uses instead to an intermediate buffer.

Main1.java:

import java.awt.image.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main1 extends JFrame implements Runnable {
   int pos = 0;
   int WIDTH = 300;
   int HEIGHT = 150;
  
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      setSize(WIDTH, HEIGHT);
   } 
 
   public void update(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      g.setColor(Color.white);
      g.fillRect(0, 0, WIDTH, HEIGHT);
 
      g.setColor(Color.black);
      g.fillRect(10 + pos, 50, 50, 50);
   }
 
   public void run() {
      setResizable(false); 
 
      while (true) {
         pos++;
         if (pos > 220) pos = 0;
         repaint();
 
         try {
            Thread.sleep(10);
         }
         catch(InterruptedException e) {
         }
      }
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
 
      Thread t = new Thread(main);
      t.start();
   }
}

Main2.java:

import java.awt.image.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
 
public class Main2 extends JFrame implements Runnable {
   BufferedImage buffer;
   Graphics bufferGraphics;
   int pos = 0;
   int WIDTH = 300;
   int HEIGHT = 150;
  
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      });
 
      setSize(WIDTH, HEIGHT);
   } 
 
   public void update(Graphics g) {
      Graphics2D g2d = (Graphics2D) g;
 
      bufferGraphics.setColor(Color.white);
      bufferGraphics.fillRect(0, 0, WIDTH, HEIGHT);
 
      bufferGraphics.setColor(Color.black);
      bufferGraphics.fillRect(10 + pos, 50, 50, 50);
 
      g2d.drawImage(buffer, 0, 0, this);
   }
 
   public void run() {
      buffer = (BufferedImage) createImage(WIDTH, HEIGHT);
      bufferGraphics = buffer.createGraphics();
      setResizable(false); 
 
      while (true) {
         pos++;
         if (pos > 220) pos = 0;
         repaint();
 
         try {
            Thread.sleep(10);
         }
         catch(InterruptedException e) {
         }
      }
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
 
      Thread t = new Thread(main);
      t.start();
   }
}

Morphing one image into another in Swing

Morphing is short for metamorphosing, it refers to an animation technique in which one image is gradually turned into another.

This example morphs one image into another (with same width and height). It first precalculates R G and B array that contains for each pixel the change that should be applied to a (x, y) pixel in image 1 to get to the (x, y) pixel in image 2 after iterating for nFrames steps.
Then it loops through the pixelvalues of the source image and adds the RGB change to it. After nFrames steps, the resulting image is image 2.

import java.awt.event.*;
import java.awt.image.*;
import java.awt.color.*;
import javax.swing.*;
import java.awt.*;
                           
public class Main extends JFrame
{
   int width, height; 
 
   int source[];
   int dest[];
 
   double dalpha[], dred[], dgreen[], dblue[];
 
   int nFrames;
 
   JLabel jlabel;
 
   public Main(String image1, String image2, int nFrames) throws Exception {
      BufferedImage bi1 = createBufferedImage(image1);
      BufferedImage bi2 = createBufferedImage(image2);
 
      width = bi1.getWidth();
      height = bi1.getHeight();
 
      source = new int[width*height];
      dest = new int[width*height];
 
      dalpha = new double[width*height];
      dred = new double[width*height];
      dgreen = new double[width*height];
      dblue = new double[width*height];
 
      this.nFrames = nFrames;
 
      PixelGrabber grabber1 = new PixelGrabber(bi1,0,0,width,height,source,0,width);
      grabber1.grabPixels();
 
      PixelGrabber grabber2 = new PixelGrabber(bi2,0,0,width,height,dest,0,width);
      grabber2.grabPixels();
 
      calcIntervals();
 
      // add the image inside a JLabel component to the window
      jlabel = new JLabel(new ImageIcon(bi1));
      getContentPane().add(jlabel);
      pack();
                          
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
            System.exit(0);
         }
      });
   }
 
   public void calcIntervals() {
      for (int i=0; i<source.length; i++) {
         int sourcePixel = source[i];
         int sourceAlpha = (sourcePixel >> 24) & 0xff;
         int sourceRed   = (sourcePixel >> 16) & 0xff;
         int sourceGreen = (sourcePixel >>  8) & 0xff;
         int sourceBlue  = (sourcePixel      ) & 0xff;
          
         int destPixel = dest[i];
         int destAlpha = (destPixel >> 24) & 0xff;
         int destRed   = (destPixel >> 16) & 0xff;
         int destGreen = (destPixel >>  8) & 0xff;
         int destBlue  = (destPixel      ) & 0xff;
 
         dalpha[i] = (double) (destAlpha - sourceAlpha) / nFrames;
         dred[i] = (double) (destRed - sourceRed) / nFrames;
         dgreen[i] = (double) (destGreen - sourceGreen) / nFrames;
         dblue[i] = (double) (destBlue - sourceBlue) / nFrames;
      }
   }
 
   public int[] calcFrame(int frame) {
      int result[] = new int1;
      for (int i=0; i<source.length; i++) {
         int sourcePixel = source[i];
         int sourceAlpha = (int) (((sourcePixel >> 24) & 0xff) + (dalpha[i] * frame));
         int sourceRed   = (int) (((sourcePixel >> 16) & 0xff) + (dred[i] * frame));
         int sourceGreen = (int) (((sourcePixel >>  8) & 0xff) + (dgreen[i] * frame));
         int sourceBlue  = (int) (((sourcePixel      ) & 0xff) + (dblue[i] * frame));
          
         result[i] = argb2p(sourceAlpha, sourceRed, sourceGreen, sourceBlue);
      }
 
      return result;
   }
 
   public int argb2p(int alpha, int red, int green, int blue) {
      int t = 0;
 
      t |= (alpha << 24);
      t |= (red << 16);
      t |= (green << 8);
      t |= blue;
 
      return t;
   }         
 
   public void startMorphing(int delay) {
      for (int i=0; i<nFrames+1; i++) {
         int result[] = calcFrame(i);
         Image img = createImage(new MemoryImageSource(width, height, result, 0, width));
         jlabel.setIcon(new ImageIcon(img));
 
         try {
            Thread.sleep(delay);
         }
         catch(InterruptedException e) { }
      }
   }
 
   public BufferedImage createBufferedImage(String filename) {
      Image img = Toolkit.getDefaultToolkit().getImage(filename);
      try {
         MediaTracker tracker = new MediaTracker(this);
         tracker.addImage(img, 0);
         tracker.waitForID(0);
      }
      catch ( Exception e ) {} 
  
      BufferedImage bi = 
         new BufferedImage(img.getWidth(this), img.getHeight(this),
                        BufferedImage.TYPE_INT_RGB);
      Graphics2D g2d = bi.createGraphics();
      g2d.drawImage(img, 0, 0, this);
  
      return bi;
   }
  
   public static void main(String args[]) throws Exception {
      if (args.length != 4) {
         System.out.println("usage: Java Main image1 image2 framecount delay");
         System.exit(1);
      }
 
      Main main = new Main(args[0], args[1], Integer.parseInt(args[2]));
      main.show();
      main.startMorphing(Integer.parseInt(args[3]));
   }
}

Test it out with:

java Main ally.jpg lion.jpg 200 10

Where
ally.jpg is the source image
lion.jpg is the destination image
200 is the number of frames in between
10 the delay in milliseconds between showing each frame

ally.jpg:

lion.jpg:

Performing edge detection of an image in Swing

Apply an edge detection filter using the class ConvolveOp.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         Kernel kernel = new Kernel(3, 3, new float[] 
                                            { 1, 1, 1,
                                              1,-2, 1,
                                             -1,-1,-1 });
         ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
         cOp.filter(sourceBi, destBi);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing,
check out this expensive but excellent book:

Posterizing an image in Swing


Will reduce the number of colors used!

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
  
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         short[] posterize = new short[256];
         for(int i=0; i<256; i++) {
            posterize[i] = (short) (i - (i % 32));
         }
  
         ShortLookupTable slt = new ShortLookupTable(0, posterize);
         LookupOp op = new LookupOp(slt, null);
         destBi = op.filter(sourceBi, null);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Blurring an Image in Swing

Use the class ConvolveOp and apply a blur filter.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         Kernel kernel = new Kernel(3, 3, new float[] 
                                            {  1f/9f, 1f/9f, 1f/9f,
                                               1f/9f, 1f/9f, 1f/9f,
                                               1f/9f, 1f/9f, 1f/9f });
         ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
         cOp.filter(sourceBi, destBi);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing,
check out this expensive but excellent book:

Sharpening an Image in Swing

Use the class ConvolveOp and apply a sharpen filter.

Main.java:

import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
 
public class Main extends JFrame {
   private boolean firstTime = true;
   private BufferedImage sourceBi;
   private BufferedImage destBi;
 
   public Main() {
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent we) {
            System.exit(1);
         }
      }); 
   } 
 
   public void paint(Graphics graphics) {
      Graphics2D g2d = (Graphics2D) graphics;
  
      if (firstTime) {
         Image img = new javax.swing.ImageIcon("djkrush.jpg").getImage(); 
         sourceBi = toBufferedImage(img);
         destBi = new BufferedImage(sourceBi.getWidth(), sourceBi.getHeight(), 
                                    BufferedImage.TYPE_INT_RGB);
         setSize(sourceBi.getWidth(), sourceBi.getHeight()*2);
 
         Kernel kernel = new Kernel(3, 3, new float[] 
                                            { -1, -1, -1,
                                              -1,  9, -1,
                                              -1, -1, -1 });
         ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
         cOp.filter(sourceBi, destBi);
 
         firstTime = false;
      }
 
      g2d.drawImage(sourceBi, 0, 0, this);
      g2d.drawImage(destBi, 0, sourceBi.getHeight(), this);
   }
 
   public static BufferedImage toBufferedImage(Image image) {
      BufferedImage bi = new BufferedImage(image.getWidth(null), image.getHeight(null), 
                                           BufferedImage.TYPE_INT_RGB); 
 
      // copy the original image
      Graphics g = bi.createGraphics();
    
      g.drawImage(image, 0, 0, null);
      g.dispose();
 
      return bi;
   }
 
   public static void main(String []args) {
      Main main = new Main();
      main.setVisible(true);
      main.setSize(300, 150);
   }
}

Image used:

To learn more about image processing,
check out this expensive but excellent book: