In Part
4, an image was drawn into a double buffer and shown
in the applet
window. One thing you may have noticed is the
degraded image quality in the
applet compared to the frames
of animation displayed on the tutorial page.
My incredibly
rotating man lost his good looks and became rather
ruddy.
Art imitating life?
I wanted to demonstrate that Java dithers images down to a
palette of
256 colors while browsers handle millions of
colors easily. It is possible
to draw true color images
with Java but only desirable for some users which
takes
away from general graphics use.
For the time being, to reduce the effects of dithering, you
can use a
screen capture utility to catch the applet web page
and edit your images to
fit Java's palette decisions better.
As always with graphics, the end
result is what matters most
and patchworks methods can help considerably.
I talked about images in Part 3
but this is getting to know
them better. Our intimacy with them begins with
the fact
that an image is just an array of dots called pixels.
Imagine
each row of the image strung first to last in a single entity
as
a longer row of values.
Each value is an integer composed of four bytes forming the
pixel to be
drawn by Java. These are extracted to be three
intensity values; red,
green, and blue which combine to make
the colour you see onscreen. The
fourth byte is called the
alpha channel and is a value of transparency for
the pixel.
A value of 0 would make the pixel appear transparent as
a
value of 255 would indicate an opaque pixel. Values between
make
pixels partially transparent.
I have created a special image class to deal with the internal
elements
of Java images. This code can be used without any
modification but I will
explain all that is happening inside.
Click here to learn about the internal Java code of FXImage.class
And now I'll go through the main applet code:
public class FXCycle extends Applet {
Note here how my special effects class is declared as a
variable
instance which will instruct the compiler to
virtually bind it to
FXCycle.class which also means you can
declare my class in your own applet
loops and utilize its
black box functionality without learning the internal
workings.
FXImage fxi;
If you do this, you will require your class (or FXCycle.class)
and
definitely the FXImage.class in the same directory or path
for this to
work. Below are the other variable declarations,
including one defined
constant - FX_MAX.
Image img; int effect = 0; static final int FX_MAX = 7;
Here, the image is initialized (see previous tutorials) as
usual. The
new instance of FXImage takes the image class
as a parameter. It may seem
superfluous to convert the image
here but it affects the color display.
Returning it back to
its origin image class means an initially smoother
picture.
Trust me.
public void init() { img = getImage(getCodeBase(),getParameter("IMAGENAME") + ".gif"); fxi = new FXImage(img); fxi.save(); img = fxi.create(); }
This function handles your mouse clicks on the image.
public boolean mouseDown(Event evt,int x,int y) {
The restore function is called here to normalize the
image before doing
another special effect. It works
better this way, due to the FX algorithms.
fxi.restore();
This part selects a special effect to perform based
on the counter
effect. This appears to be inefficient
code but it didn't work as a case
statement. Trust me.
if(effect==0) fxi.negative(); else if(effect==1) fxi.lighting(50,50,50); else if(effect==2) fxi.lighting(170,170,170); else if(effect==3) fxi.fuzzy(90); else if(effect==4) fxi.border(50,50,30); else if(effect==5) fxi.grey(); else if(effect==6) fxi.stone(45,2,100,100,100); else if(effect==7) {} if(++effect > FX_MAX) effect = 0;
Observe here how a new image must be created each time.
img = fxi.create();
Now call repaint to trigger the paint method's image drawing.
repaint(); return true; }
The paint method below will draw the current image onscreen.
public void paint(Graphics g) { g.drawImage(img,0,0,this.size().width,this.size().height,this); } }
And that's it. This might seem slow because of the necessary
allocation
used by FXImage.Create but another intention of mine
is that you use the FXImage
class to generate all kinds of warped
images when your applet loads and
save each in an image loop as
I taught you in the slideshow program (Part 3).
Here is an example of modifying your code to build FX animation arrays:
Image img; Image imgs[]; FXImage fxi; public void init() { imgs = new Image[CONSTANT_COUNT]; img = getImage(getCodeBase(),getParameter("IMAGENAME") + ".gif"); fxi = new FXImage(img); for(int count=0; count<CONSTANT_COUNT; count++) { fxi.save(); fxi.lighting(50+(count*3),50+(count*3),50+(count*3)); imgs[count] = fxi.create(); fxi.restore(); } }
The special effects will be explained in the next tutorial part
along
with their respective prototypes. In the meantime, play
around with the FXImage
class. It should be useful to generate
animations, banners, fade to
black, etc...
For clarity and not brevity, here is the entire code listing:
// FXCycle.java // by Garry Morse import java.awt.*; import java.applet.*; public class FXCycle extends Applet { // special effects image class FXImage fxi; Image img; int effect = 0; static final int FX_MAX = 7; // initializes applet public void init() { // load image from file img = getImage(getCodeBase(),getParameter("IMAGENAME") + ".gif"); // create a new image class fxi = new FXImage(img); // save its initial contents fxi.save(); img = fxi.create(); } // handler for mouse click events on image public boolean mouseDown(Event evt,int x,int y) { // restore image to initial state before next alteration fxi.restore(); // perform special effect based on cycle counter if(effect==0) fxi.negative(); else if(effect==1) fxi.lighting(50,50,50); else if(effect==2) fxi.lighting(170,170,170); else if(effect==3) fxi.fuzzy(90); else if(effect==4) fxi.border(50,50,30); else if(effect==5) fxi.grey(); else if(effect==6) fxi.stone(45,2,100,100,100); else if(effect==7) {} // reloop if finished cycle if(++effect > FX_MAX) effect = 0; // re-create image class from special effect class img = fxi.create(); // draw image with new special effect alteration repaint(); return true; } // paints image in applet window public void paint(Graphics g) { g.drawImage(img,0,0,this.size().width,this.size().height,this); } }
Below are the HTML parameters:
<APPLET CODE="FXCycle.class" WIDTH=100 HEIGHT=100>
<PARAM
NAME="IMAGENAME" VALUE="../garry">
</APPLET>
Click here to see the Image Filter applet in action!
The Java Game Programming Tutorial and all tutorials within are created by Garry Morse, Copyright 1997