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
|