Home : Course Map : Chapter 11 : Java :
Pixels and Transparency
JavaTech
Course Map
Chapter 11

Introduction
Image Class
Image Loading
  Demo 1 Demo 2  
Pixels/Transparency
  Demo 3
Pixel Handling
  Demo 4  
Demo 5
Exercises

    Supplements
Java 2D Imaging
BufferedImage
Creating Buf.Image
Pixel Handling
  Demo 1 Demo 2
Filters
  Convolutions
     Demo 3
  AffineTransforms
     Demo 4
  LookupTable
     Demo 5 Demo 6
  Rescale
     Demo 7
  Color Conversion
     Demo 8
  Custom
     Demo 9
Exercises
Java Adv Imaging
AWT Flicker:
  Override Update
     Demo 1  Demo 2
  Clipping
     Demo 3
  Double Buffer
     Demo 4

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

As discussed in Chapter 6: Java : Colors the default ARGB color model in Java uses red, green, and blue components plus an alpha transparency factor (discussed below.) A color can be obtained as a Color object. However, with images you usually deal with an array of pixels in which each pixel is a 32-bit int value with the four components packed each as an 8-bit value. Chapter 10: Tech : Bits shows how to access and modify the four color components in a int value.

The RGB model implies a monitor pixel. RGB is an additive color model (e.g. equal parts of red, green, and blue combine to display gray up to white depending on the intensities) . However, when an image is sent to a printer, the image dots in that case will be translated for you into the pigment color combinations that provide similar, if not an exact, reproduction of the monitor colors.

In the Pixel Handling section, we show how to access and modify the pixels of an image.

Transparency

The fourth component of the color model used above is the alpha or transparency component.

alpha - 8 bits in top byte of the 32 bit pixel value.

This is used when an image is overlaid above a background color or another image. The transparency determines how the background color combines with the foreground color in the resulting combined pixel value.

This can be useful for various image manipulation such as when overlaying an icon on a component. Typically you want the blank areas of the icon to show the background component.

The program TransparencyApplet below demonstrates the effect of the alpha transparency factor in pixel values. The user selects a color for a large rectangle and also selects both the color and transparency of a smaller rectangle drawn over the larger one. The drawing is done first on an off-screen image and then the image is drawn on a JPanel.

If the small rectangle color is opaque, i.e. the alpha component equals 255, then only its RGB color will be display. Or, if the alpha equals 0, then only the big rectangle color will be seen. However, things get more interesting when you set alpha to an intermediate value.

From the image we can obtain the pixels that result from combining the two colors with an intermediate alpha setting. We display the pixel value on the applet .(To access the pixesl we use the PixelGrabber class that is discussed in the Pixel Handling section.)

TransparencyApplet
+ BgControlPanel + FgControlPanel + OutputPanel

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

/**
  * Demonstrate effect of the alpha transparency factor in pixel
  * values. The user selects via the BgControlPanel a color for a
  * large rectangle. Similarly, the user selects via the FgControlPanel
  * both the color and transparency factor of a small rectangle painted
  * over the larger one. The rectangles are displayed on the OutputPanel.
  * The resulting pixel value in the overlay area is displayed on
  * the output
 **/
public class TransparencyApplet extends JApplet
{
  /** Create the user interface with OutputPanel and two control panels.**/
  public void init () {

    setLayout (new GridLayout (2,1));

    // Create an instance of OutputPanel
    OutputPanel output_panel = new OutputPanel ();

    // Create an instance of the background color control panel
    BgControlPanel bg_control_panel = new BgControlPanel (output_panel);

    // Create an instance of the foreground color control panel
    FgControlPanel fg_control_panel = new FgControlPanel (output_panel);

    JPanel controls_panel = new JPanel (new GridLayout (1,2));

    controls_panel.add(bg_control_panel);
    controls_panel.add(fg_control_panel);

    // Add the panels to applet's pane.
    add (output_panel);
    add (controls_panel);
  } // init

} // class TransparencyApplet

 

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;

/**
  * This JPanel subclass displays one large rectangle
  * with a background color plus a smaller rectangle
  * drawn over the first one with a foreground color. The
  * background and foreground colors can be set with the
  * setBgColor and setFgColor methods respectively.
  *
  * The drawing is first done on an offscreen image so that
  * we can obtain the pixel that results from the combination
  * of the two colors. The alpha factor selected for the
  * foreground will affect the combination color.
 **/
public class OutputPanel extends JPanel {
  Color fBgColor = Color.RED;
  Color fFgColor = Color.BLUE;

  /**
    * Set the background color by passing the 3 RGB component
    * values  (with ranges 0-255).
   **/
  void setBgColor (int cr, int cg, int cb) {
    fBgColor = new Color (cr,cg,cb);
    repaint ();
  }

  /**
    * Set the color of the foreground overlpay
    * by passing the 3 RGB component values
    * plus the alpha value (with ranges 0-255).
   **/
  void setFgColor (int cr, int cg, int cb, int ca) {
    fFgColor = new Color (cr,cg,cb,ca);
    repaint ();
  }

  /**
    * Use an offscreen image to draw a rectangle with the
    * background color and then overlay a smaller rectangle
    * with the foreground color amd  alpha factor selected
    * by the user. This image is then drawn on the panel.
    *
    * To find out the pixel value that results from this
    * combination of the background color plus the overlay color,
    * we use a PixelGrabber object to get the pixel array.
    * The resulting pixel value is drawn on the center of the panel.
   **/
  public void paintComponent (Graphics g) {
    super.paintComponent (g);

    int panelWd = getWidth ();
    int panelHt = getHeight ();

    Image img = createImage (panelWd,panelHt);
    Graphics img_gc = img.getGraphics ();

    // Now we fill a rectangle the size of the
    // panel with the chosen color.
    img_gc.setColor (fBgColor);
    img_gc.fillRect (0, 0, panelWd, panelHt);

    // Now overlay a rectanagular patch over the panel
    // and fill it with the foreground color.
    int x = (int)(0.20 * panelWd);
    int y = (int)(0.20 * panelHt);

    int patchWd = (int)(0.60 * panelWd);
    int patchHt = (int)(0.60 * panelHt);

    img_gc.setColor (fFgColor);
    img_gc.fillRect (x, y, patchWd, patchHt);

    g.drawImage (img, 0, 0, this);

    // To determine the color of the combination of background
    // and foreground overlay, we grab the pixels from the overlay
    // region of the offscreen image.
    int [] pixels = new int[patchWd * patchHt];
    PixelGrabber pg =
      new PixelGrabber (img, x, y, patchWd, patchHt, pixels, 0, patchWd);

    // The grabPixels method will cause the filling of the
    // pixels array.
    try {
      pg.grabPixels ();
    }
    catch (InterruptedException e) {
        System.err.println ("Interrupted while waiting for pixels!");
        return;
    }
    // Pixel filling isn't instantaneous so check here to
    // see that it finished.
    if ((pg.getStatus () & ImageObserver.ABORT) != 0) {
        System.err.println ("Image fetch abort or error occurred");
        return;
    }

    // Look at one of the pixels (they should all have the identical
    // value except perhaps at the edge.
    int color_value = pixels[pixels.length / 2];

    // Get the value in hex format and draw it at the center
    //
of the panel.
    String color_value_str = Integer.toHexString (color_value);
    g.setColor(Color.BLACK);
    drawStringInCenter(g, color_value_str);

  } // paintComponent

  /** Use FontMetrics classes to draw a string at
    * the center of a panel.
   **/
  void drawStringInCenter(Graphics g, String msg) {

    // Create the font and pass it to the  Graphics context
    g.setFont (new Font ("Monospaced",Font.BOLD,18));

    // Get measures needed to center the message
    FontMetrics fm = g.getFontMetrics ();

    // How many pixels wide is the string
    int msg_width = fm.stringWidth (msg);

    // How far above the baseline can the font go?
    int ascent = fm.getMaxAscent ();

    // How far below the baseline?
    int descent= fm.getMaxDescent ();

    // Use the string width to find the starting point
    int msg_x = getSize ().width/2 - msg_width/2;

    // Use the vertical height of this font to find
    // the vertical starting coordinate
    int msg_y = getSize ().height/2 - descent/2 + ascent/2;

    g.drawString (msg, msg_x, msg_y);

   } // drawStringInCenter

} // class OutputPanel

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

/**
  * The FgControlPanel holds four JSlider widgets that set
  * the color and transparency of the foreground rectangle
  * patch drawn on the OutputPanel.
 **/
 public class FgControlPanel extends JPanel
                          implements ChangeListener {

  OutputPanel fOutputPanel;
  JLabel fRedLabel,fGreenLabel,fBlueLabel,fAlphaLabel;
  JSlider fRed,fGreen,fBlue,fAlpha;

  FgControlPanel (OutputPanel output_panel) {

    fOutputPanel = output_panel;

    setLayout (new GridLayout (4, 2));

    add (fRedLabel = new JLabel ("Red 0  ",SwingConstants.RIGHT) );

    // The JSlider constructor parameters:
    //
    //   orientation, minimum, maximum, inital value
    //
    // The sliders are set horizontally.
    // The values range from 0 to 255.
    // Set the blue slider to max initially to match the
    // initial blue color for the output panel overlay.
    //
    add (fRed = new JSlider (JSlider.HORIZONTAL, 0, 255, 0));
    fRed.addChangeListener (this);

    add (fGreenLabel = new JLabel ("Green 0  ",SwingConstants.RIGHT) );
    add (fGreen = new JSlider (Adjustable.HORIZONTAL, 0, 255, 0));
    fGreen.addChangeListener (this);

    add (fBlueLabel = new JLabel ("Blue 0  ",SwingConstants.RIGHT) );
    add (fBlue = new JSlider (Adjustable.HORIZONTAL, 0, 255, 255));
    fBlue.addChangeListener (this);

    add (fAlphaLabel = new JLabel ("Alpha 0  ",SwingConstants.RIGHT) );
    add (fAlpha = new JSlider (Adjustable.HORIZONTAL, 0, 255, 255));
    fAlpha.addChangeListener (this);

    // Initialize to opaque blue.
    fOutputPanel.setFgColor(0,0,255,255);

  } // ctor

  /** This class is the AdjustmentListener for the
    * scroll bar. So the events come here when the
    * scroll bar is moved.
   **/
  public void stateChanged (ChangeEvent evt){

    // Use the labels to show the numerical values of the
    // scroll bar settings.
    fRedLabel.setText ("Red " +
                       Integer.toHexString (fRed.getValue ()));
    fGreenLabel.setText ("Green " +
                         Integer.toHexString (fGreen.getValue ()));
    fBlueLabel.setText ("Blue " +
                        Integer.toHexString (fBlue.getValue ()));
    fAlphaLabel.setText ("Alpha "+
                         Integer.toHexString (fAlpha.getValue ()));

    // Get the values from each scroll bar and pass
    // them as the color component values.
    fOutputPanel.setFgColor (fRed.getValue (), fGreen.getValue (),
                           fBlue.getValue (),fAlpha.getValue ());

    fOutputPanel.repaint ();
  } // stateChanged

} // class FgControlPanel
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

/**
  * The FBControlPanel holds four JSlider widgets that set
  * the color of the large background rectangle drawn on
  * the OutputPanel.
 **/
public class BgControlPanel extends JPanel
                          implements ChangeListener {

  OutputPanel fOutputPanel;
  JLabel fRedLabel,fGreenLabel,fBlueLabel;
  JSlider fRed,fGreen,fBlue;

  BgControlPanel (OutputPanel output_panel) {

    fOutputPanel = output_panel;

    setLayout (new GridLayout (3, 2));

    add (fRedLabel = new JLabel ("Red 0  ",SwingConstants.RIGHT) );

    // The JSlider constructor parameters:
    //
    //   orientation, minimum, maximum, inital value
    //
    // The sliders are set horizontally.
    // The values range from 0 to 255.
    // Set the red slider to max initially to match the
    // initial Red color for the output panel.
    //
    add (fRed = new JSlider (JSlider.HORIZONTAL, 0, 255, 255));
    fRed.addChangeListener (this);

    add (fGreenLabel = new JLabel ("Green 0  ",SwingConstants.RIGHT) );
    add (fGreen = new JSlider (Adjustable.HORIZONTAL, 0, 255, 0));
    fGreen.addChangeListener (this);

    add (fBlueLabel = new JLabel ("Blue 0  ",SwingConstants.RIGHT) );
    add (fBlue = new JSlider (Adjustable.HORIZONTAL, 0, 255, 0));
    fBlue.addChangeListener (this);

  } // ctor

  /**
    * This class is the AdjustmentListener for the
    * scroll bar. So the events come here when the
    * scroll bar is moved.
   **/
  public void stateChanged (ChangeEvent evt) {

    // Use the labels to show the numerical values of the
    // scroll bar settings.
    fRedLabel.setText ("Red "+
                       Integer.toHexString (fRed.getValue ()));
    fGreenLabel.setText ("Green " +
                         Integer.toHexString (fGreen.getValue ()));
    fBlueLabel.setText ("Blue " +
                        Integer.toHexString (fBlue.getValue ()));

    // Get the values from each scroll bar and pass
    // them as the color component values.
    fOutputPanel.setBgColor (fRed.getValue (), fGreen.getValue (),
                             fBlue.getValue ());

    fOutputPanel.repaint ();

  } // stateChanged

} // class BgControlPanel

 

If you play with the color component values for the background and the foreground areas and with the alpha value, you will see that each of the RGB components are combined in a linear manner. Lets define the transparency fraction as

frac = alpha/255

We also define an individual red, green, or blue component for the background color as Cbg and as Cfg for the foreground color component. Then the color components are combined as follows:

Ccombo = (1 - frac) * Cbg + frac * Cfg

This approach approximates the transparency effect that you would see if you put a glass tinted with the foreground color in front of a light with the background color.

References & Web Resources

 

Last update: Dec. 2, 2004

              Tech
Fractals
Fractal Drawing
   Demo 1
Fractal Draw Code
Fractal Images
  Demo 2
Image Processing
  Demo 3
Histogram Image
  Demo 4
Exercises

           Physics
Calibration/SysError
SimWithCal/SysErr
  Demo 1
Analysis
  Demo 2
Examples

Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.