Images can also be created from scratch by creating,
loading and accessing pixel arrays. The 32-bit pixel arrays typically
use an ARGB
color model discussed previously.
Below we show
Creating
an Image from a Pixel Array
MemoryImageSource
is a convenient class for creating images directly from pixel arrays
and for doing simple animations. Below we show the example program
CreateImageApplet
and the JPanel
subclassImagePanel,
which is displayed on the applet. An image is created and displayed
on the panel.
In the init()
method in the ImagePanel
class, an array large enough to hold the pixels for the applet's
panel is created with :
fWidth =
getSize ().width;
fHeight = getSize ().height;
fPixels = new int [fWidth * fHeight];
Then two loops fill the pixels with a spectrum of
red, green, and blue values plus an opaque alpha value (255).
fPixels[i++]
= (alpha << 24) | (red << 16)
| (green
<< 8 ) | blue;
We then use the createImage(ImageProducer
producer) method in the Component
class to create the image. The MemoryImageSource
implements the ImageProducer
interface and its constructor takes the pixel array as follows:
fImage
= createImage (
new MemoryImageSource
(fWidth, fHeight, fPixels, 0, fWidth));
The first three arguments in the MemoryImageSource
constructor are the width and height of the image and the pixel
array. The fourth argument is the offset into the array where the
data begins and in this case is simply 0. The last argument is the
length of the scan line in the pixel array that corresponds to the
horizontal line in the image and in this case is simply the width
of the panel.
CreateImageApplet.java
|
import
javax.swing.*;
import java.awt.*;
import java.awt.image.*;
/** Create an image from a pixel array. **/
public class CreateImageApplet extends JApplet
{
ImagePanel fImagePanel;
public void init () {
Container content_pane = getContentPane
();
// Create an instance of ImagePanel
fImagePanel = new ImagePanel ();
// Add the ImagePanel to the contentPane.
content_pane.add (fImagePanel);
} // init
// Tell the panel to create and display the
image.
public void start () {
fImagePanel.init ();
}
} // class CreateImageApplet
/** Create an image from a pixel array. **/
class ImagePanel extends JPanel
{
Image fImage;
int fWidth = 0, fHeight = 0;
int [] fPixels;
/**
* Create an image from a pixel array
and MemoryImageSource.
*
* Do the image building in this
method rather
* than in a constructor so that
it will know
* the size of the panel after it
has been added
* to the applet.
**/
void init () {
fWidth = getSize ().width;
fHeight = getSize ().height;
fPixels = new int [fWidth * fHeight];
int i=0;
int half_width = fWidth/2;
// Build the array of pixels with
the color components.
for (int y = 0; y < fHeight;
y++) {
for ( int x = 0; x <
fWidth; x++) {
// Start
red on left and decrease to zero at center
int red
= 255 - (512 * x)/fWidth;
if (red
< 0 ) red = 0;
// Green
peaks in center
int green;
if (x <
half_width )
green
= (512 * x)/fWidth;
else
green
= 255 - (255 * (x - half_width))/half_width;
// Blue
starts from center and peaks at right side.
int blue
= 0;
if (x >
half_width)
blue
= (255 * (x - half_width))/half_width;
int alpha
= 255; // non-transparent
fPixels[i++]
= (alpha << 24) | (red << 16)
| (green
<< 8 ) | blue;
}
}
// Now create the image from the
pixel array.
fImage = createImage (
new MemoryImageSource
(fWidth, fHeight, fPixels, 0, fWidth));
} // init
/** Paint the image on the panel. **/
public void paintComponent (Graphics g) {
super.paintComponent (g);
g.drawImage (fImage, 0, 0, this
);
}
} // class ImagePanel
|
Creating
an Animation from a Pixel Array
MemoryImageSource
can also provide an animation as shown below with the example program
AnimationApplet
. By invoking the setAnimate(true)
method, the MemoryImageSource
object will respond to an invocation of the newPixels()
method by repainting the image.
AnimationApplet
implements Runnable
and a loop in the run()
method periodically invokes the newFrame()
method in the DrawingPanel
object, which is displayed on the applet. This method shifts the
color components in the pixel array and then invokes the method
newPixels (0, 0,
fWidth, fHeight) for the MemoryImageSource
object. This will cause the image to be repainted and thus create
an animated effect.
AnimationApplet.java
|
import
javax.swing.*;
import java.awt.*;
import java.awt.image.*;
/** Use MemoryImageSource to create an animated image. **/
public class AnimationApplet extends JApplet
implements Runnable
{
// Will use thread reference as a flag
Thread fThread;
//msecs of sleep time
int fDeltaT = 10;
// Need a reference to the panel on which animation
appears
DrawingPanel fDrawingPanel;
/** Create a simple interface to draw the animation.**/
public void init () {
Container content_pane = getContentPane
();
// Create an instance of DrawingPanel
fDrawingPanel = new DrawingPanel
();
// Add the DrawingPanel to the contentPane.
content_pane.add (fDrawingPanel);
} // init
/** Start the thread that controls the animation.**/
public void start () {
// Tell the panel to create the
image source.
fDrawingPanel.init ();
// If the thread reference not null
then a
// thread is already running. Otherwise,
create
// a thread and start it.
if (fThread == null) {
fThread
= new Thread (this);
fThread.start
();
}
} // start
/** Stop thread by setting flag. **/
public void stop () {
fThread = null;
}
public void run () {
// Loop through sleep periods until
flag set to null
while (fThread != null) {
try {
Thread.sleep
(fDeltaT);
} catch (InterruptedException
e) {}
// Send request for
create new image
fDrawingPanel.newFrame
();
}
} // run
} //class AnimationApplet
/** Display the animation on this panel. **/
class DrawingPanel extends JPanel
{
Image fImage;
int fWidth, fHeight;
int [] fPixels;
MemoryImageSource fSource;
int fFrame=0;
/**
* Do the image building in this
method rather
* than in a constructor so that
it will know
* the size of the panel after it
has been added
* to the applet.
**/
void init () {
fWidth = getSize ().width;
fHeight = getSize ().height;
// Create an array to hold the color
of each pixel
fPixels = new int [fWidth * fHeight];
// The MemoryImageSource creates
an image from the array.
fSource = new MemoryImageSource
(fWidth, fHeight,
fPixels, 0, fWidth);
// Set the flag for animations.
fSource.setAnimated (true);
fImage = createImage (fSource);
} // init
/** Modify the pixel color parameters for each
frame. **/
void newFrame () {
int index = 0;
// Create a mask from the current
frame number
byte mask = (byte) (fFrame
& 0xff);
int alpha = 255;
for (int y = 0; y < fHeight; y++)
{
for (int
x = 0; x < fWidth; x++) {
//
Modify the color components each frame.
int
red = (y * 255) / (fWidth - 1);
red
= red & mask;
int
green = (x * 255) / (fHeight - 1);
green
= green & mask;
int
blue = 255 - (255 * ( x - fWidth))/fWidth;
blue
= blue & mask;
fPixels[index++]
=
(alpha << 24) | (red << 16) | (green << 8) | blue;
}
}
fFrame++;
// Push out the new data for a new
frame.
fSource.newPixels (0, 0, fWidth,
fHeight);
} // newFrame
/** Draw the image on the panel. **/
public void paintComponent (Graphics g) {
g.drawImage ( fImage, 0, 0, this
);
}
}// class DrawingPanel
|
Obtaining
a Pixel Array from an Image
We can obtain pixels from an existing image as follows.
First create an array large enough to hold the pixels
int [] pixels
= new int[width * height];
for an image of dimensions width
x height. Then create an instance of the PixelGrabber
class from the constructor
PixelGrabber
pGrab = new PixelGrabber(image, x, y,
width,height,
pixels,
offset,
scansize);
where x,y
give the coordinates of the upper left corner of the rectangle
area within the image where the pixels are to obtained. The width,height
arguments give the dimensions of the rectangle. The offset gives
the starting point in the pixels array where to start putting the
data and scansize is defined as the distance from one row of pixels
to the next in the array.
Invoking the grabPixels()
method:
pGrab.grabPixels();
will result in the filling of the pixels
array.
Note that this method can return before the pixel
array has finished filling. The status of the pixel grabbing can
be obtained with
if((pg.getStatus()
& ImageObserver.ALLBITS) != 0)) gotPixels = true;
Once we have the pixels we can do various manipulations
on the pixels such as color filtering, edge finding, etc.
See the example program TransparencyApplet
and the OutputPanel
class in the transparency discussion for a demonstration of PixelGrabber.
References & Web Resources
Last update: May.24, 2006
|