Making a RGB Histogram

Other Articles

Applets and Native Methods.

Swing tiled backgrounds.

RGB Histograms

The javax.swing.undo package provides rudimentary support for undo/redo operations for text. But this package is useless for image processing. Fortunately, if you happen to use the Java Advanced Imaging (JAI), a certain feature of RenderedOp can be used to quickly and easily build an undo / redo system.

Most JAI operations produce RenderedOp objects. If the object is a result of a transformation or a filter, it will contain a reference to the source image for that operation. This source image might contain a reference to another image, that was used to produce it and so on. Wehn you reach the root not you will find that it does not have any sources because it has been directly read from the disk (or a URl). The following is an example of how an image can be transformed with JAI.


        pb = new ParameterBlock();
        pb.addSource(image);
        pb.add(0.5f);
        pb.add(0.5f);
        pb.add(0.0F);
        pb.add(0.0F);
        
        image = JAI.create("scale",pb,null);


For the purpose of thie demonstration we read an image from disk and apply three transformations on it. We then create a JFrame to display the image along with Undo / Redo buttons. The code for the undo button's event handler is as follows


        Vector v = image.getSources();
        if(v != null && v.size() != 0)
        {
            redoActions.add(image);
            image = v.firstElement();
            panel.repaint();
            
        }


As already mentioned, a RenderedOp may contain a reference to the image that was used to produce it. If the vector is null or empty that means we are looking at the original image (one that was read from the disk) and we cannot undo any further. If the vector is not empty, we grab the first element from it and update the display with it. The current image had to be preserved in case we have to redo the operation. We use a vector to store these images (redoActions in the above listing). We use this vector in the event handler for the redo button.


        if(redoActions != null && redoActions.size() != 0)
        {
            image = redoActions.lastElement();
            redoActions.remove(image);
            
            panel.repaint();
            
        }


The rest of the coding, which involves of loading the image and building the UI is straight forward and you can look through it by downloading the full source code.